Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] refactor: 검색 탭 삭제 및 순서 수정 #578

Merged
merged 13 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion frontend/src/components/Common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export { default as SvgSprite } from './Svg/SvgSprite';
export { default as SvgIcon } from './Svg/SvgIcon';
export { default as TabMenu } from './TabMenu/TabMenu';
export { default as TagList } from './TagList/TagList';
export { default as Title } from './Title/Title';
export { default as SectionTitle } from './SectionTitle/SectionTitle';
export { default as ScrollButton } from './ScrollButton/ScrollButton';
export { default as Input } from './Input/Input';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Link, Text, theme } from '@fun-eat/design-system';
import { Heading, Link, theme } from '@fun-eat/design-system';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';

import SvgIcon from '../Svg/SvgIcon';
import SvgIcon from '../../Common/Svg/SvgIcon';

import { PATH } from '@/constants/path';

Expand All @@ -14,15 +14,13 @@ interface TitleProps {
const Title = ({ headingTitle, routeDestination }: TitleProps) => {
return (
<TitleContainer>
<HomeLink as={RouterLink} to={PATH.HOME}>
<SvgIcon variant="arrow" color={theme.colors.gray5} width={20} height={20} />
</HomeLink>
<TitleLink as={RouterLink} to={routeDestination} replace>
<Text as="span" size="xl" weight="bold">
{headingTitle}
</Text>
<HeadingTitle>{headingTitle}</HeadingTitle>
<DropDownIcon variant="arrow" color={theme.colors.black} width={15} height={15} />
</TitleLink>
<Link as={RouterLink} to={`${PATH.SEARCH}/products`}>
<SvgIcon variant="search" />
</Link>
</TitleContainer>
);
};
Expand All @@ -32,20 +30,19 @@ export default Title;
const TitleContainer = styled.div`
display: flex;
flex-direction: row;
justify-content: center;
position: relative;
`;

const HomeLink = styled(Link)`
position: absolute;
top: 8px;
left: 0;
align-items: center;
justify-content: space-between;
`;

const TitleLink = styled(Link)`
display: flex;
align-items: center;
gap: 20px;
margin-left: 40%;
`;

const HeadingTitle = styled(Heading)`
font-size: 2.4rem;
`;

const DropDownIcon = styled(SvgIcon)`
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/Product/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { default as ProductList } from './ProductList/ProductList';
export { default as ProductOverviewItem } from './ProductOverviewItem/ProductOverviewItem';
export { default as PBProductList } from './PBProductList/PBProductList';
export { default as ProductRecipeList } from './ProductRecipeList/ProductRecipeList';
export { default as Title } from './Title/Title';
7 changes: 1 addition & 6 deletions frontend/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@ import { PATH } from './path';
import type { NavigationMenu } from '@/types/common';

export const NAVIGATION_MENU: NavigationMenu[] = [
{
variant: 'search',
name: '검색',
path: PATH.SEARCH,
},
{
variant: 'list',
name: '목록',
Expand Down Expand Up @@ -58,7 +53,7 @@ export const TAG_TITLE = {

export const MIN_DISPLAYED_TAGS_LENGTH = 3;

export const SEARCH_PAGE_TABS = ['상품', '꿀조합'] as const;
export const SEARCH_PAGE_VARIANTS = { products: '상품', recipes: '꿀조합' } as const;

export const CATEGORY_TYPE = {
FOOD: 'food',
Expand Down
3 changes: 1 addition & 2 deletions frontend/src/pages/ProductListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,12 @@ import {
CategoryMenu,
SortButton,
SortOptionList,
Title,
ScrollButton,
Loading,
ErrorBoundary,
ErrorComponent,
} from '@/components/Common';
import { ProductList } from '@/components/Product';
import { Title, ProductList } from '@/components/Product';
import { PRODUCT_SORT_OPTIONS } from '@/constants';
import { PATH } from '@/constants/path';
import { useSortOption } from '@/hooks/common';
Expand Down
7 changes: 3 additions & 4 deletions frontend/src/pages/RecipePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from '@/components/Common';
import { RecipeList, RecipeRegisterForm } from '@/components/Recipe';
import { RECIPE_SORT_OPTIONS } from '@/constants';
import { PATH } from '@/constants/path';
import RecipeFormProvider from '@/contexts/RecipeFormContext';
import { useSortOption } from '@/hooks/common';

Expand All @@ -41,10 +42,8 @@ const RecipePage = () => {

return (
<>
<Title size="xl" weight="bold">
{RECIPE_PAGE_TITLE}
</Title>
<SearchPageLink as={RouterLink} to="/search">
<Title>{RECIPE_PAGE_TITLE}</Title>
<SearchPageLink as={RouterLink} to={`${PATH.SEARCH}/recipes`}>
<SvgIcon variant="search" />
</SearchPageLink>
<ErrorBoundary fallback={ErrorComponent} handleReset={reset}>
Expand Down
61 changes: 41 additions & 20 deletions frontend/src/pages/SearchPage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { Button, Heading, Spacing, Text } from '@fun-eat/design-system';
import { Button, Heading, Spacing, Text, useTheme } from '@fun-eat/design-system';
import { useQueryErrorResetBoundary } from '@tanstack/react-query';
import type { MouseEventHandler } from 'react';
import { Suspense, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import styled from 'styled-components';

import { ErrorBoundary, ErrorComponent, Input, Loading, SvgIcon, TabMenu } from '@/components/Common';
import { ErrorBoundary, ErrorComponent, Input, Loading, SvgIcon } from '@/components/Common';
import { RecommendList, ProductSearchResultList, RecipeSearchResultList } from '@/components/Search';
import { SEARCH_PAGE_TABS } from '@/constants';
import { useDebounce } from '@/hooks/common';
import { SEARCH_PAGE_VARIANTS } from '@/constants';
import { useDebounce, useRoutePage } from '@/hooks/common';
import { useSearch } from '@/hooks/search';

const isProductSearchTab = (tabMenu: string) => tabMenu === SEARCH_PAGE_TABS[0];
const getInputPlaceholder = (tabMenu: string) =>
isProductSearchTab(tabMenu) ? '상품 이름을 검색해보세요.' : '꿀조합에 포함된 상품을 입력해보세요.';
const isProductSearchPage = (path: string) => path === 'products';
const getInputPlaceholder = (path: string) =>
isProductSearchPage(path) ? '상품 이름을 검색해보세요.' : '꿀조합에 포함된 상품을 입력해보세요.';

type SearchPageType = keyof typeof SEARCH_PAGE_VARIANTS;

const SearchPage = () => {
const {
Expand All @@ -26,13 +28,21 @@ const SearchPage = () => {
handleAutocompleteClose,
} = useSearch();
const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery || '');
const [selectedTabMenu, setSelectedTabMenu] = useState<string>(SEARCH_PAGE_TABS[0]);
const { reset } = useQueryErrorResetBoundary();
const { routeBack } = useRoutePage();

const theme = useTheme();

const handleTabMenuSelect: MouseEventHandler<HTMLButtonElement> = (event) => {
setSelectedTabMenu(event.currentTarget.value);
const { searchVariant } = useParams();

const isSearchVariant = (value: string): value is SearchPageType => {
return value === 'products' || value === 'recipes';
};

if (!searchVariant || !isSearchVariant(searchVariant)) {
return null;
}

useDebounce(
() => {
setDebouncedSearchQuery(searchQuery);
Expand All @@ -50,10 +60,17 @@ const SearchPage = () => {
return (
<>
<SearchSection>
<TitleWrapper>
<Button type="button" variant="transparent" onClick={routeBack} aria-label="뒤로 가기">
<SvgIcon variant="arrow" color={theme.colors.gray5} width={15} height={15} />
</Button>
<HeadingTitle>{SEARCH_PAGE_VARIANTS[searchVariant]} 검색</HeadingTitle>
</TitleWrapper>
<Spacing size={16} />
<form onSubmit={handleSearch}>
<Input
customWidth="100%"
placeholder={getInputPlaceholder(selectedTabMenu)}
placeholder={getInputPlaceholder(searchVariant)}
rightIcon={
<Button customHeight="36px" color="white">
<SvgIcon variant="search" />
Expand All @@ -76,12 +93,6 @@ const SearchPage = () => {
</ErrorBoundary>
)}
</SearchSection>
<Spacing size={20} />
<TabMenu
tabMenus={SEARCH_PAGE_TABS}
selectedTabMenu={selectedTabMenu}
handleTabMenuSelect={handleTabMenuSelect}
/>
<SearchResultSection>
{isSubmitted && debouncedSearchQuery ? (
<>
Expand All @@ -91,7 +102,7 @@ const SearchPage = () => {
<ErrorBoundary fallback={ErrorComponent}>
<Suspense fallback={<Loading />}>
<Spacing size={20} />
{isProductSearchTab(selectedTabMenu) ? (
{isProductSearchPage(searchVariant) ? (
<ProductSearchResultList searchQuery={debouncedSearchQuery} />
) : (
<RecipeSearchResultList searchQuery={debouncedSearchQuery} />
Expand All @@ -100,7 +111,7 @@ const SearchPage = () => {
</ErrorBoundary>
</>
) : (
<Text>{selectedTabMenu}을 검색해보세요.</Text>
<Text>{SEARCH_PAGE_VARIANTS[searchVariant]}을 검색해보세요.</Text>
)}
</SearchResultSection>
</>
Expand All @@ -117,6 +128,16 @@ const SearchResultSection = styled.section`
margin-top: 30px;
`;

const TitleWrapper = styled.div`
display: flex;
align-items: center;
gap: 12px;
`;

const HeadingTitle = styled(Heading)`
font-size: 2.4rem;
`;

const Mark = styled.mark`
background-color: ${({ theme }) => theme.backgroundColors.default};
font-weight: ${({ theme }) => theme.fontWeights.bold};
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/router/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const router = createBrowserRouter([
),
},
{
path: PATH.SEARCH,
path: `${PATH.SEARCH}/:searchVariant`,
element: <SearchPage />,
},
{
Expand Down