From 9c57867d83753c615fbaacecb2acea3d8f7ffc0a Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 7 Sep 2023 12:59:57 +0900 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20=EA=B2=80=EC=83=89=20=ED=83=AD=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 57658282f..bafad3bf8 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -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: '목록', From a3715027e2a3a581d7b925b87764cf836935bb25 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 7 Sep 2023 13:00:24 +0900 Subject: [PATCH 02/12] =?UTF-8?q?feat:=20=EC=83=81=ED=92=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D,=20=EA=BF=80=EC=A1=B0=ED=95=A9=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EC=97=90=20=EA=B2=80=EC=83=89=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Common/Title/Title.tsx | 29 ++++++++----------- frontend/src/pages/RecipePage.tsx | 4 +-- frontend/src/pages/SearchPage.tsx | 23 +++++++++++++-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/Common/Title/Title.tsx b/frontend/src/components/Common/Title/Title.tsx index b0e9b941d..8ff965be0 100644 --- a/frontend/src/components/Common/Title/Title.tsx +++ b/frontend/src/components/Common/Title/Title.tsx @@ -1,11 +1,9 @@ -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 { PATH } from '@/constants/path'; - interface TitleProps { headingTitle: string; routeDestination: string; @@ -14,15 +12,13 @@ interface TitleProps { const Title = ({ headingTitle, routeDestination }: TitleProps) => { return ( - - - - - {headingTitle} - + {headingTitle} + + + ); }; @@ -32,20 +28,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)` diff --git a/frontend/src/pages/RecipePage.tsx b/frontend/src/pages/RecipePage.tsx index ead971e6d..a7c061c76 100644 --- a/frontend/src/pages/RecipePage.tsx +++ b/frontend/src/pages/RecipePage.tsx @@ -41,9 +41,7 @@ const RecipePage = () => { return ( <> - - {RECIPE_PAGE_TITLE} - + {RECIPE_PAGE_TITLE} diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index 05c3192dd..f32746989 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -1,4 +1,4 @@ -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'; @@ -7,7 +7,7 @@ import styled from 'styled-components'; import { ErrorBoundary, ErrorComponent, Input, Loading, SvgIcon, TabMenu } from '@/components/Common'; import { RecommendList, ProductSearchResultList, RecipeSearchResultList } from '@/components/Search'; import { SEARCH_PAGE_TABS } from '@/constants'; -import { useDebounce } from '@/hooks/common'; +import { useDebounce, useRoutePage } from '@/hooks/common'; import { useSearch } from '@/hooks/search'; const isProductSearchTab = (tabMenu: string) => tabMenu === SEARCH_PAGE_TABS[0]; @@ -28,6 +28,8 @@ const SearchPage = () => { const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery || ''); const [selectedTabMenu, setSelectedTabMenu] = useState(SEARCH_PAGE_TABS[0]); const { reset } = useQueryErrorResetBoundary(); + const { routeBack } = useRoutePage(); + const theme = useTheme(); const handleTabMenuSelect: MouseEventHandler = (event) => { setSelectedTabMenu(event.currentTarget.value); @@ -50,6 +52,13 @@ const SearchPage = () => { return ( <> + + + {selectedTabMenu} 검색 + +
theme.backgroundColors.default}; font-weight: ${({ theme }) => theme.fontWeights.bold}; From 14631b7ccb43e41225a2e75cc5e182a0d479b8bf Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Fri, 8 Sep 2023 15:49:58 +0900 Subject: [PATCH 03/12] =?UTF-8?q?refactor:=20Title=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=EB=A5=BC=20Common=EC=97=90=EC=84=9C=20Produc?= =?UTF-8?q?t=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Common/index.ts | 1 - .../components/{Common => Product}/Title/Title.stories.tsx | 0 frontend/src/components/{Common => Product}/Title/Title.tsx | 4 ++-- frontend/src/components/Product/index.ts | 1 + frontend/src/pages/ProductListPage.tsx | 3 +-- 5 files changed, 4 insertions(+), 5 deletions(-) rename frontend/src/components/{Common => Product}/Title/Title.stories.tsx (100%) rename frontend/src/components/{Common => Product}/Title/Title.tsx (90%) diff --git a/frontend/src/components/Common/index.ts b/frontend/src/components/Common/index.ts index 395277010..e48a05d20 100644 --- a/frontend/src/components/Common/index.ts +++ b/frontend/src/components/Common/index.ts @@ -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'; diff --git a/frontend/src/components/Common/Title/Title.stories.tsx b/frontend/src/components/Product/Title/Title.stories.tsx similarity index 100% rename from frontend/src/components/Common/Title/Title.stories.tsx rename to frontend/src/components/Product/Title/Title.stories.tsx diff --git a/frontend/src/components/Common/Title/Title.tsx b/frontend/src/components/Product/Title/Title.tsx similarity index 90% rename from frontend/src/components/Common/Title/Title.tsx rename to frontend/src/components/Product/Title/Title.tsx index 8ff965be0..541e1bb47 100644 --- a/frontend/src/components/Common/Title/Title.tsx +++ b/frontend/src/components/Product/Title/Title.tsx @@ -2,7 +2,7 @@ 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'; interface TitleProps { headingTitle: string; @@ -16,7 +16,7 @@ const Title = ({ headingTitle, routeDestination }: TitleProps) => { {headingTitle} - + diff --git a/frontend/src/components/Product/index.ts b/frontend/src/components/Product/index.ts index 4038ee740..656af6a7a 100644 --- a/frontend/src/components/Product/index.ts +++ b/frontend/src/components/Product/index.ts @@ -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'; diff --git a/frontend/src/pages/ProductListPage.tsx b/frontend/src/pages/ProductListPage.tsx index 8e7da4b50..43f2bb4d6 100644 --- a/frontend/src/pages/ProductListPage.tsx +++ b/frontend/src/pages/ProductListPage.tsx @@ -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'; From 929bebb165fe488f8f7ed01de1fc94fbf561db00 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Fri, 8 Sep 2023 16:29:57 +0900 Subject: [PATCH 04/12] =?UTF-8?q?refactor:=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=ED=83=AD=20=EC=82=AD=EC=A0=9C=20=ED=9B=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Product/Title/Title.tsx | 4 +- frontend/src/constants/index.ts | 2 +- frontend/src/pages/RecipePage.tsx | 3 +- frontend/src/pages/SearchPage.tsx | 37 ++++++++----------- frontend/src/router/index.tsx | 6 ++- 5 files changed, 27 insertions(+), 25 deletions(-) diff --git a/frontend/src/components/Product/Title/Title.tsx b/frontend/src/components/Product/Title/Title.tsx index 541e1bb47..a9872cee9 100644 --- a/frontend/src/components/Product/Title/Title.tsx +++ b/frontend/src/components/Product/Title/Title.tsx @@ -4,6 +4,8 @@ import styled from 'styled-components'; import SvgIcon from '../../Common/Svg/SvgIcon'; +import { PATH } from '@/constants/path'; + interface TitleProps { headingTitle: string; routeDestination: string; @@ -16,7 +18,7 @@ const Title = ({ headingTitle, routeDestination }: TitleProps) => { {headingTitle} - + diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index bafad3bf8..fabc13a99 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -53,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', diff --git a/frontend/src/pages/RecipePage.tsx b/frontend/src/pages/RecipePage.tsx index a7c061c76..0e6eeb7c1 100644 --- a/frontend/src/pages/RecipePage.tsx +++ b/frontend/src/pages/RecipePage.tsx @@ -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'; @@ -42,7 +43,7 @@ const RecipePage = () => { return ( <> {RECIPE_PAGE_TITLE} - + diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index f32746989..f6f85a115 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -1,18 +1,20 @@ 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 { useLocation } 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 { 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 { @@ -26,14 +28,13 @@ const SearchPage = () => { handleAutocompleteClose, } = useSearch(); const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery || ''); - const [selectedTabMenu, setSelectedTabMenu] = useState(SEARCH_PAGE_TABS[0]); const { reset } = useQueryErrorResetBoundary(); const { routeBack } = useRoutePage(); - const theme = useTheme(); - const handleTabMenuSelect: MouseEventHandler = (event) => { - setSelectedTabMenu(event.currentTarget.value); - }; + const { pathname } = useLocation(); + const [, , currentPath] = pathname.split('/'); + + const theme = useTheme(); useDebounce( () => { @@ -56,13 +57,13 @@ const SearchPage = () => { - {selectedTabMenu} 검색 + {SEARCH_PAGE_VARIANTS[currentPath as SearchPageType]} 검색 @@ -85,12 +86,6 @@ const SearchPage = () => { )} - - {isSubmitted && debouncedSearchQuery ? ( <> @@ -100,7 +95,7 @@ const SearchPage = () => { }> - {isProductSearchTab(selectedTabMenu) ? ( + {isProductSearchPage(currentPath) ? ( ) : ( @@ -109,7 +104,7 @@ const SearchPage = () => { ) : ( - {selectedTabMenu}을 검색해보세요. + {SEARCH_PAGE_VARIANTS[currentPath as SearchPageType]}을 검색해보세요. )} diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 8391765a3..81b613aa8 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -54,7 +54,11 @@ const router = createBrowserRouter([ ), }, { - path: PATH.SEARCH, + path: `${PATH.SEARCH}/products`, + element: , + }, + { + path: `${PATH.SEARCH}/recipes`, element: , }, { From 87b3942c6ea0344af75c1ed423d4f9544a09e323 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Mon, 11 Sep 2023 14:48:52 +0900 Subject: [PATCH 05/12] =?UTF-8?q?refactor:=20dynamic=20segment=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=B4=EC=84=9C=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=EC=B2=B4=ED=82=B9=EC=9D=84=20=ED=95=98=EB=8A=94=20=EB=B0=A9?= =?UTF-8?q?=EB=B2=95=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/pages/SearchPage.tsx | 23 +++++++++++++++-------- frontend/src/router/index.tsx | 6 +----- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index f6f85a115..c89dc908c 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -1,7 +1,7 @@ import { Button, Heading, Spacing, Text, useTheme } from '@fun-eat/design-system'; import { useQueryErrorResetBoundary } from '@tanstack/react-query'; import { Suspense, useEffect, useState } from 'react'; -import { useLocation } from 'react-router-dom'; +import { useParams } from 'react-router-dom'; import styled from 'styled-components'; import { ErrorBoundary, ErrorComponent, Input, Loading, SvgIcon } from '@/components/Common'; @@ -31,11 +31,18 @@ const SearchPage = () => { const { reset } = useQueryErrorResetBoundary(); const { routeBack } = useRoutePage(); - const { pathname } = useLocation(); - const [, , currentPath] = pathname.split('/'); - const theme = useTheme(); + const { searchVariant } = useParams(); + + const isSearchVariant = (value: string): value is SearchPageType => { + return value === 'products' || value === 'recipes'; + }; + + if (!searchVariant || !isSearchVariant(searchVariant)) { + return null; + } + useDebounce( () => { setDebouncedSearchQuery(searchQuery); @@ -57,13 +64,13 @@ const SearchPage = () => { - {SEARCH_PAGE_VARIANTS[currentPath as SearchPageType]} 검색 + {SEARCH_PAGE_VARIANTS[searchVariant]} 검색 @@ -95,7 +102,7 @@ const SearchPage = () => { }> - {isProductSearchPage(currentPath) ? ( + {isProductSearchPage(searchVariant) ? ( ) : ( @@ -104,7 +111,7 @@ const SearchPage = () => { ) : ( - {SEARCH_PAGE_VARIANTS[currentPath as SearchPageType]}을 검색해보세요. + {SEARCH_PAGE_VARIANTS[searchVariant]}을 검색해보세요. )} diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 81b613aa8..9f0fab017 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -54,11 +54,7 @@ const router = createBrowserRouter([ ), }, { - path: `${PATH.SEARCH}/products`, - element: , - }, - { - path: `${PATH.SEARCH}/recipes`, + path: `${PATH.SEARCH}/:searchVariant`, element: , }, { From 4ec1fbdb2324d86402765decc54e1ffb2d9113d1 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 11:02:47 +0900 Subject: [PATCH 06/12] =?UTF-8?q?chore:=20msw=20=EB=B2=84=EC=A0=84?= =?UTF-8?q?=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/public/mockServiceWorker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/public/mockServiceWorker.js b/frontend/public/mockServiceWorker.js index 36a992745..d8bc3ace3 100644 --- a/frontend/public/mockServiceWorker.js +++ b/frontend/public/mockServiceWorker.js @@ -2,7 +2,7 @@ /* tslint:disable */ /** - * Mock Service Worker (1.2.3). + * Mock Service Worker (1.3.0). * @see https://github.com/mswjs/msw * - Please do NOT modify this file. * - Please do NOT serve this file on production. From 1b9dfabea547e125819a076d4107fe5fa1538bb8 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 12:50:55 +0900 Subject: [PATCH 07/12] =?UTF-8?q?feat:=20=EC=83=88=EB=A1=9C=EC=9A=B4=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/Common/Header/Header.tsx | 32 +++++++++++++++++-- .../components/Layout/SimpleHeaderLayout.tsx | 31 ++++++++++++++++++ frontend/src/components/Layout/index.ts | 1 + .../src/components/Product/Title/Title.tsx | 5 +-- 4 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 frontend/src/components/Layout/SimpleHeaderLayout.tsx diff --git a/frontend/src/components/Common/Header/Header.tsx b/frontend/src/components/Common/Header/Header.tsx index a52adaf21..ae2431ed8 100644 --- a/frontend/src/components/Common/Header/Header.tsx +++ b/frontend/src/components/Common/Header/Header.tsx @@ -2,14 +2,33 @@ import { Link } from '@fun-eat/design-system'; import { Link as RouterLink } from 'react-router-dom'; import styled from 'styled-components'; +import SvgIcon from '../Svg/SvgIcon'; + import Logo from '@/assets/logo.svg'; import { PATH } from '@/constants/path'; -const Header = () => { +interface HeaderProps { + hasSearch?: boolean; +} + +const Header = ({ hasSearch = true }: HeaderProps) => { + if (hasSearch) { + return ( + + + + + + + + + ); + } + return ( - + ); @@ -17,6 +36,15 @@ const Header = () => { export default Header; +const HeaderWithSearchContainer = styled.header` + display: flex; + justify-content: space-between; + align-items: center; + width: calc(100% - 40px); + height: 60px; + margin: 0 auto; +`; + const HeaderContainer = styled.header` display: flex; justify-content: center; diff --git a/frontend/src/components/Layout/SimpleHeaderLayout.tsx b/frontend/src/components/Layout/SimpleHeaderLayout.tsx new file mode 100644 index 000000000..c6c469169 --- /dev/null +++ b/frontend/src/components/Layout/SimpleHeaderLayout.tsx @@ -0,0 +1,31 @@ +import type { PropsWithChildren } from 'react'; +import styled from 'styled-components'; + +import Header from '../Common/Header/Header'; +import NavigationBar from '../Common/NavigationBar/NavigationBar'; + +const SimpleHeaderLayout = ({ children }: PropsWithChildren) => { + return ( + +
+ {children} + + + ); +}; + +export default SimpleHeaderLayout; + +const SimpleHeaderLayoutContainer = styled.div` + height: 100%; + max-width: 600px; + margin: 0 auto; +`; + +const MainWrapper = styled.main` + position: relative; + height: calc(100% - 120px); + padding: 20px; + overflow-x: hidden; + overflow-y: auto; +`; diff --git a/frontend/src/components/Layout/index.ts b/frontend/src/components/Layout/index.ts index 32a1e00e0..69ec1a40c 100644 --- a/frontend/src/components/Layout/index.ts +++ b/frontend/src/components/Layout/index.ts @@ -2,3 +2,4 @@ export { default as DefaultLayout } from './DefaultLayout'; export { default as MinimalLayout } from './MinimalLayout'; export { default as HeaderOnlyLayout } from './HeaderOnlyLayout'; export { default as AuthLayout } from './AuthLayout'; +export { default as SimpleHeaderLayout } from './SimpleHeaderLayout'; diff --git a/frontend/src/components/Product/Title/Title.tsx b/frontend/src/components/Product/Title/Title.tsx index 34b713583..0bbf1c636 100644 --- a/frontend/src/components/Product/Title/Title.tsx +++ b/frontend/src/components/Product/Title/Title.tsx @@ -31,14 +31,15 @@ const TitleContainer = styled.div` position: relative; display: flex; flex-direction: row; - align-items: center; justify-content: space-between; + align-items: center; `; const TitleLink = styled(Link)` display: flex; gap: 20px; - margin-left: 40%; + align-items: center; + margin-left: 36%; `; const HeadingTitle = styled(Heading)` From f48cec85855cb61803e297e7b8200a4ea72bbec9 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 12:51:39 +0900 Subject: [PATCH 08/12] =?UTF-8?q?feat:=20=EA=B2=80=EC=83=89=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EC=99=80=20=ED=86=B5=ED=95=A9=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/constants/index.ts | 3 +- frontend/src/pages/IntegratedSearchPage.tsx | 123 ++++++++++++++++++++ frontend/src/pages/RecipePage.tsx | 22 ++-- frontend/src/pages/SearchPage.tsx | 18 +-- frontend/src/router/App.tsx | 16 ++- frontend/src/router/index.tsx | 36 ++++-- 6 files changed, 184 insertions(+), 34 deletions(-) create mode 100644 frontend/src/pages/IntegratedSearchPage.tsx diff --git a/frontend/src/constants/index.ts b/frontend/src/constants/index.ts index 9ee468126..66e733697 100644 --- a/frontend/src/constants/index.ts +++ b/frontend/src/constants/index.ts @@ -53,7 +53,8 @@ export const TAG_TITLE = { export const MIN_DISPLAYED_TAGS_LENGTH = 3; -export const SEARCH_PAGE_VARIANTS = { products: '상품', recipes: '꿀조합' } as const; +export const SEARCH_TAB_VARIANTS = ['상품', '꿀조합']; +export const SEARCH_PAGE_VARIANTS = { products: '상품', recipes: '꿀조합', integrated: '통합' } as const; export const CATEGORY_TYPE = { FOOD: 'food', diff --git a/frontend/src/pages/IntegratedSearchPage.tsx b/frontend/src/pages/IntegratedSearchPage.tsx new file mode 100644 index 000000000..64d66d155 --- /dev/null +++ b/frontend/src/pages/IntegratedSearchPage.tsx @@ -0,0 +1,123 @@ +import { Button, Heading, Spacing, Text } from '@fun-eat/design-system'; +import { useQueryErrorResetBoundary } from '@tanstack/react-query'; +import type { MouseEventHandler } from 'react'; +import { Suspense, useEffect, useState } from 'react'; +import styled from 'styled-components'; + +import { ErrorBoundary, ErrorComponent, Input, Loading, SvgIcon, TabMenu } from '@/components/Common'; +import { RecommendList, ProductSearchResultList, RecipeSearchResultList } from '@/components/Search'; +import { SEARCH_TAB_VARIANTS } from '@/constants'; +import { useDebounce } from '@/hooks/common'; +import { useSearch } from '@/hooks/search'; + +const isProductSearchTab = (tabMenu: string) => tabMenu === SEARCH_TAB_VARIANTS[0]; +const getInputPlaceholder = (tabMenu: string) => + isProductSearchTab(tabMenu) ? '상품 이름을 검색해보세요.' : '꿀조합에 포함된 상품을 입력해보세요.'; + +const IntegratedSearchPage = () => { + const { + inputRef, + searchQuery, + isSubmitted, + isAutocompleteOpen, + handleSearchQuery, + handleSearch, + handleSearchClick, + handleAutocompleteClose, + } = useSearch(); + const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery || ''); + const [selectedTabMenu, setSelectedTabMenu] = useState(SEARCH_TAB_VARIANTS[0]); + const { reset } = useQueryErrorResetBoundary(); + + const handleTabMenuSelect: MouseEventHandler = (event) => { + setSelectedTabMenu(event.currentTarget.value); + }; + + useDebounce( + () => { + setDebouncedSearchQuery(searchQuery); + }, + 200, + [searchQuery] + ); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.focus(); + } + }, []); + + return ( + <> + + + + + + } + value={searchQuery} + onChange={handleSearchQuery} + ref={inputRef} + /> + + {!isSubmitted && debouncedSearchQuery && isAutocompleteOpen && ( + + }> + + + + )} + + + + + {isSubmitted && debouncedSearchQuery ? ( + <> + + '{searchQuery}'에 대한 검색결과입니다. + + + }> + + {isProductSearchTab(selectedTabMenu) ? ( + + ) : ( + + )} + + + + ) : ( + {selectedTabMenu}을 검색해보세요. + )} + + + ); +}; + +export default IntegratedSearchPage; + +const SearchSection = styled.section` + position: relative; +`; + +const SearchResultSection = styled.section` + margin-top: 30px; +`; + +const Mark = styled.mark` + font-weight: ${({ theme }) => theme.fontWeights.bold}; + background-color: ${({ theme }) => theme.backgroundColors.default}; +`; diff --git a/frontend/src/pages/RecipePage.tsx b/frontend/src/pages/RecipePage.tsx index 6e4065eb7..706e6b941 100644 --- a/frontend/src/pages/RecipePage.tsx +++ b/frontend/src/pages/RecipePage.tsx @@ -42,10 +42,12 @@ const RecipePage = () => { return ( <> - {RECIPE_PAGE_TITLE} - - - + + {RECIPE_PAGE_TITLE} + + + + }> @@ -83,14 +85,14 @@ const RecipePage = () => { export default RecipePage; -const Title = styled(Heading)` - font-size: 24px; +const TitleWrapper = styled.div` + display: flex; + justify-content: space-between; + align-items: center; `; -const SearchPageLink = styled(Link)` - position: absolute; - top: 24px; - right: 20px; +const Title = styled(Heading)` + font-size: 24px; `; const SortButtonWrapper = styled.div` diff --git a/frontend/src/pages/SearchPage.tsx b/frontend/src/pages/SearchPage.tsx index 743aad0f3..6a1c9f892 100644 --- a/frontend/src/pages/SearchPage.tsx +++ b/frontend/src/pages/SearchPage.tsx @@ -35,14 +35,6 @@ const SearchPage = () => { const { searchVariant } = useParams(); - const isSearchVariant = (value: string): value is SearchPageType => { - return value === 'products' || value === 'recipes'; - }; - - if (!searchVariant || !isSearchVariant(searchVariant)) { - return null; - } - useDebounce( () => { setDebouncedSearchQuery(searchQuery); @@ -57,6 +49,14 @@ const SearchPage = () => { } }, []); + const isSearchVariant = (value: string): value is SearchPageType => { + return value === 'products' || value === 'recipes'; + }; + + if (!searchVariant || !isSearchVariant(searchVariant)) { + return null; + } + return ( <> @@ -130,8 +130,8 @@ const SearchResultSection = styled.section` const TitleWrapper = styled.div` display: flex; - align-items: center; gap: 12px; + align-items: center; `; const HeadingTitle = styled(Heading)` diff --git a/frontend/src/router/App.tsx b/frontend/src/router/App.tsx index b4428b177..a8c4bfd10 100644 --- a/frontend/src/router/App.tsx +++ b/frontend/src/router/App.tsx @@ -3,11 +3,11 @@ import { Suspense } from 'react'; import { Outlet } from 'react-router-dom'; import { ErrorBoundary, ErrorComponent, Loading } from '@/components/Common'; -import { MinimalLayout, DefaultLayout, HeaderOnlyLayout } from '@/components/Layout'; +import { MinimalLayout, DefaultLayout, HeaderOnlyLayout, SimpleHeaderLayout } from '@/components/Layout'; import { useRouteChangeTracker } from '@/hooks/common'; interface AppProps { - layout?: 'default' | 'headerOnly' | 'minimal'; + layout?: 'default' | 'headerOnly' | 'minimal' | 'simpleHeader'; } const App = ({ layout = 'default' }: AppProps) => { @@ -39,6 +39,18 @@ const App = ({ layout = 'default' }: AppProps) => { ); } + if (layout === 'simpleHeader') { + return ( + + }> + + + + + + ); + } + return ( }> diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 9f0fab017..37e75caaa 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -7,6 +7,7 @@ import { PATH } from '@/constants/path'; import CategoryProvider from '@/contexts/CategoryContext'; import AuthPage from '@/pages/AuthPage'; import HomePage from '@/pages/HomePage'; +import IntegratedSearchPage from '@/pages/IntegratedSearchPage'; import LoginPage from '@/pages/LoginPage'; import MemberModifyPage from '@/pages/MemberModifyPage'; import MemberPage from '@/pages/MemberPage'; @@ -33,18 +34,6 @@ const router = createBrowserRouter([ ), }, - { - path: `${PATH.PRODUCT_LIST}/:category`, - element: ( - - - - ), - }, - { - path: PATH.RECIPE, - element: , - }, { path: `${PATH.RECIPE}/:recipeId`, element: ( @@ -57,6 +46,10 @@ const router = createBrowserRouter([ path: `${PATH.SEARCH}/:searchVariant`, element: , }, + { + path: `${PATH.SEARCH}/integrated`, + element: , + }, { path: PATH.MEMBER, element: ( @@ -117,6 +110,25 @@ const router = createBrowserRouter([ }, ], }, + { + path: '/', + element: , + errorElement: , + children: [ + { + path: `${PATH.PRODUCT_LIST}/:category`, + element: ( + + + + ), + }, + { + path: PATH.RECIPE, + element: , + }, + ], + }, ]); export default router; From 2ddb8e18ab97237864aa3bec6f4589f44175e800 Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 12:55:45 +0900 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=EA=B2=80=EC=83=89=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=ED=97=A4=EB=8D=94=20ui=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/router/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index 37e75caaa..da53fc95d 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -42,10 +42,6 @@ const router = createBrowserRouter([ ), }, - { - path: `${PATH.SEARCH}/:searchVariant`, - element: , - }, { path: `${PATH.SEARCH}/integrated`, element: , @@ -127,6 +123,10 @@ const router = createBrowserRouter([ path: PATH.RECIPE, element: , }, + { + path: `${PATH.SEARCH}/:searchVariant`, + element: , + }, ], }, ]); From a9cd4f6d97d0bad3249c0692290a8beb4a6d2edf Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 16:01:13 +0900 Subject: [PATCH 10/12] =?UTF-8?q?refactor:=20=EA=B2=80=EC=83=89=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=97=A4=EB=8D=94=20ui=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/router/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/router/index.tsx b/frontend/src/router/index.tsx index da53fc95d..0eaa96fb6 100644 --- a/frontend/src/router/index.tsx +++ b/frontend/src/router/index.tsx @@ -42,10 +42,6 @@ const router = createBrowserRouter([ ), }, - { - path: `${PATH.SEARCH}/integrated`, - element: , - }, { path: PATH.MEMBER, element: ( @@ -123,6 +119,10 @@ const router = createBrowserRouter([ path: PATH.RECIPE, element: , }, + { + path: `${PATH.SEARCH}/integrated`, + element: , + }, { path: `${PATH.SEARCH}/:searchVariant`, element: , From 73c89873d3587aba1268815363a53d6552c87e5f Mon Sep 17 00:00:00 2001 From: TaeeunKim Date: Thu, 14 Sep 2023 16:07:46 +0900 Subject: [PATCH 11/12] =?UTF-8?q?refactor:=20Title->ProductTitle=EB=A1=9C?= =?UTF-8?q?=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ProductTitle/ProductTitle.stories.tsx | 16 ++++++++++++++ .../ProductTitle.tsx} | 22 +++++++++---------- .../Product/Title/Title.stories.tsx | 16 -------------- frontend/src/components/Product/index.ts | 2 +- frontend/src/pages/ProductListPage.tsx | 6 ++--- 5 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 frontend/src/components/Product/ProductTitle/ProductTitle.stories.tsx rename frontend/src/components/Product/{Title/Title.tsx => ProductTitle/ProductTitle.tsx} (65%) delete mode 100644 frontend/src/components/Product/Title/Title.stories.tsx diff --git a/frontend/src/components/Product/ProductTitle/ProductTitle.stories.tsx b/frontend/src/components/Product/ProductTitle/ProductTitle.stories.tsx new file mode 100644 index 000000000..f4e210607 --- /dev/null +++ b/frontend/src/components/Product/ProductTitle/ProductTitle.stories.tsx @@ -0,0 +1,16 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import ProductTitle from './ProductTitle'; + +const meta: Meta = { + title: 'common/ProductTitle', + component: ProductTitle, + args: { + headingTitle: '상품 목록', + }, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/frontend/src/components/Product/Title/Title.tsx b/frontend/src/components/Product/ProductTitle/ProductTitle.tsx similarity index 65% rename from frontend/src/components/Product/Title/Title.tsx rename to frontend/src/components/Product/ProductTitle/ProductTitle.tsx index 0bbf1c636..be0e499f1 100644 --- a/frontend/src/components/Product/Title/Title.tsx +++ b/frontend/src/components/Product/ProductTitle/ProductTitle.tsx @@ -6,28 +6,28 @@ import SvgIcon from '../../Common/Svg/SvgIcon'; import { PATH } from '@/constants/path'; -interface TitleProps { - headingTitle: string; +interface ProductTitleProps { + content: string; routeDestination: string; } -const Title = ({ headingTitle, routeDestination }: TitleProps) => { +const ProductTitle = ({ content, routeDestination }: ProductTitleProps) => { return ( - - - {headingTitle} + + + {content} - + - + ); }; -export default Title; +export default ProductTitle; -const TitleContainer = styled.div` +const ProductTitleContainer = styled.div` position: relative; display: flex; flex-direction: row; @@ -35,7 +35,7 @@ const TitleContainer = styled.div` align-items: center; `; -const TitleLink = styled(Link)` +const ProductTitleLink = styled(Link)` display: flex; gap: 20px; align-items: center; diff --git a/frontend/src/components/Product/Title/Title.stories.tsx b/frontend/src/components/Product/Title/Title.stories.tsx deleted file mode 100644 index 9f455c1a5..000000000 --- a/frontend/src/components/Product/Title/Title.stories.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react'; - -import Title from './Title'; - -const meta: Meta = { - title: 'common/Title', - component: Title, - args: { - headingTitle: '상품 목록', - }, -}; - -export default meta; -type Story = StoryObj; - -export const Default: Story = {}; diff --git a/frontend/src/components/Product/index.ts b/frontend/src/components/Product/index.ts index 656af6a7a..47ce2703d 100644 --- a/frontend/src/components/Product/index.ts +++ b/frontend/src/components/Product/index.ts @@ -4,4 +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'; +export { default as ProductTitle } from './ProductTitle/ProductTitle'; diff --git a/frontend/src/pages/ProductListPage.tsx b/frontend/src/pages/ProductListPage.tsx index 43f2bb4d6..32ecc5475 100644 --- a/frontend/src/pages/ProductListPage.tsx +++ b/frontend/src/pages/ProductListPage.tsx @@ -13,7 +13,7 @@ import { ErrorBoundary, ErrorComponent, } from '@/components/Common'; -import { Title, ProductList } from '@/components/Product'; +import { ProductTitle, ProductList } from '@/components/Product'; import { PRODUCT_SORT_OPTIONS } from '@/constants'; import { PATH } from '@/constants/path'; import { useSortOption } from '@/hooks/common'; @@ -39,8 +39,8 @@ const ProductListPage = () => { return ( <>
- <Spacing size={30} /> From c956881be96bc1ef25c835f9b83631f707c435db Mon Sep 17 00:00:00 2001 From: TaeeunKim <xodms0309@naver.com> Date: Thu, 14 Sep 2023 16:15:29 +0900 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20AuthLayout=20=EC=97=90=EB=9F=AC=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/Layout/AuthLayout.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/Layout/AuthLayout.tsx b/frontend/src/components/Layout/AuthLayout.tsx index e65109b6b..0cc0570c2 100644 --- a/frontend/src/components/Layout/AuthLayout.tsx +++ b/frontend/src/components/Layout/AuthLayout.tsx @@ -1,10 +1,13 @@ -import type { PropsWithChildren } from 'react'; import { Navigate } from 'react-router-dom'; import { PATH } from '@/constants/path'; import { useMemberQuery } from '@/hooks/queries/members'; -const AuthLayout = ({ children }: PropsWithChildren) => { +interface AuthLayoutProps { + children: JSX.Element; +} + +const AuthLayout = ({ children }: AuthLayoutProps) => { const { data: member } = useMemberQuery(); if (!member) {