From f751e9ec285da2b990562867f99574a4843e7506 Mon Sep 17 00:00:00 2001 From: Taeeun Kim Date: Fri, 19 Apr 2024 23:22:43 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=BF=80=EC=A1=B0=ED=95=A9=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EB=94=94=EC=9E=90=EC=9D=B8=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=A0=90=20=EC=A0=81=EC=9A=A9=20(#91)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 폴더명 변경 * refactor: RecipeSearchResultList -> RecipeSearchResultPreviewList로 이름 변경 * feat: 검색 꿀조합 목록 페이지 추가 * style: RecipeSearchResultPreviewList으로 컴포넌트 변경 * feat: 꿀조합 미리보기 개수를 4개로 수정 * refactor: DefaultRecipeItem 컴포넌트로 교체 * feat: 전체보기 버튼 스타일 수정 * fix: 꿀조합 페이지로 이동하지 않는 문제 해결 * feat: 불필요한 Link 제거 * feat: PageHeader 컴포넌트를 TopBar 컴포넌트로 교체 * refactor: 전체보기 버튼 컴포넌트 추가 * fix: 헤더 디자인 잘못된 부분 수정 --- .../Common/ShowAllButton/ShowAllButton.tsx | 25 +++++++++++ .../Common/ShowAllButton/showAllButton.css.ts | 20 +++++++++ src/components/Common/index.ts | 2 + .../ProductRecipeList/ProductRecipeList.tsx | 21 +++------ .../productRecipeList.css.ts | 23 ---------- .../Recipe/RecipeItem/RecipeItem.tsx | 3 +- ...ProductSearchResultPreviewList.stories.tsx | 0 .../ProductSearchResultPreviewList.tsx | 0 .../productSearchResultPreivewList.css.ts | 0 .../RecipeSearchResultPreviewList.tsx | 43 +++++++++++++++++++ .../recipeSearchResultPreviewList.css.ts | 8 ++++ src/components/Search/index.ts | 4 +- .../ProductDetailPage/ProductDetailPage.tsx | 2 +- .../ProductSearchListPage.tsx | 8 +++- .../RecipeSearchListPage.tsx} | 38 +++++++--------- .../recipeSearchListPage.css.ts | 8 ++++ src/pages/SearchPage/SearchPage.tsx | 4 +- src/router/index.tsx | 9 ++++ 18 files changed, 150 insertions(+), 68 deletions(-) create mode 100644 src/components/Common/ShowAllButton/ShowAllButton.tsx create mode 100644 src/components/Common/ShowAllButton/showAllButton.css.ts rename src/components/Search/{ProductSearchResultList => ProductSearchResultPreviewList}/ProductSearchResultPreviewList.stories.tsx (100%) rename src/components/Search/{ProductSearchResultList => ProductSearchResultPreviewList}/ProductSearchResultPreviewList.tsx (100%) rename src/components/Search/{ProductSearchResultList => ProductSearchResultPreviewList}/productSearchResultPreivewList.css.ts (100%) create mode 100644 src/components/Search/RecipeSearchResultPreviewList/RecipeSearchResultPreviewList.tsx create mode 100644 src/components/Search/RecipeSearchResultPreviewList/recipeSearchResultPreviewList.css.ts rename src/{components/Search/RecipeSearchResultList/RecipeSearchResultList.tsx => pages/RecipeSearchListPage/RecipeSearchListPage.tsx} (50%) create mode 100644 src/pages/RecipeSearchListPage/recipeSearchListPage.css.ts diff --git a/src/components/Common/ShowAllButton/ShowAllButton.tsx b/src/components/Common/ShowAllButton/ShowAllButton.tsx new file mode 100644 index 00000000..b82b31dc --- /dev/null +++ b/src/components/Common/ShowAllButton/ShowAllButton.tsx @@ -0,0 +1,25 @@ +import { Link } from 'react-router-dom'; + +import { moreIconWrapper, linkWrapper } from './showAllButton.css'; + +import { SvgIcon, Text } from '@/components/Common'; +import { vars } from '@/styles/theme.css'; + +interface ShowAllButtonProps { + link: string; +} + +const ShowAllButton = ({ link }: ShowAllButtonProps) => { + return ( + +
+ +
+ + 전체보기 + + + ); +}; + +export default ShowAllButton; diff --git a/src/components/Common/ShowAllButton/showAllButton.css.ts b/src/components/Common/ShowAllButton/showAllButton.css.ts new file mode 100644 index 00000000..200e2c5d --- /dev/null +++ b/src/components/Common/ShowAllButton/showAllButton.css.ts @@ -0,0 +1,20 @@ +import { vars } from '@/styles/theme.css'; +import { style } from '@vanilla-extract/css'; + +export const linkWrapper = style({ + display: 'flex', + flexDirection: 'column', + gap: 12, + alignItems: 'center', + width: 45, +}); + +export const moreIconWrapper = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 40, + height: 40, + borderRadius: '50%', + background: vars.colors.secondary1, +}); diff --git a/src/components/Common/index.ts b/src/components/Common/index.ts index ef1d5042..30b5d588 100644 --- a/src/components/Common/index.ts +++ b/src/components/Common/index.ts @@ -25,3 +25,5 @@ export { default as PageHeader } from './PageHeader/PageHeader'; export { default as Badge } from './Badge/Badge'; export { default as WriteButton } from './WriteButton/WriteButton'; export { default as Text } from './Text/Text'; +export { default as TopBar } from './TopBar/TopBar'; +export { default as ShowAllButton } from './ShowAllButton/ShowAllButton'; diff --git a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx index 8c5f0f24..385d8428 100644 --- a/src/components/Product/ProductRecipeList/ProductRecipeList.tsx +++ b/src/components/Product/ProductRecipeList/ProductRecipeList.tsx @@ -1,18 +1,17 @@ -import { Link } from 'react-router-dom'; +import { container, moreItem } from './productRecipeList.css'; -import { container, moreIcon, moreIconWrapper, moreItem, moreLink } from './productRecipeList.css'; - -import { SvgIcon, Text } from '@/components/Common'; +import { ShowAllButton } from '@/components/Common'; import { DefaultRecipeItem } from '@/components/Recipe'; +import { PATH } from '@/constants/path'; import { useInfiniteProductRecipesQuery } from '@/hooks/queries/product'; -import { vars } from '@/styles/theme.css'; import displaySlice from '@/utils/displaySlice'; interface ProductRecipeListProps { productId: number; + productName: string; } -const ProductRecipeList = ({ productId }: ProductRecipeListProps) => { +const ProductRecipeList = ({ productId, productName }: ProductRecipeListProps) => { // 상품에서 보여줄 꿀조합 정렬 조건 const { data } = useInfiniteProductRecipesQuery(productId, 'favoriteCount,desc'); @@ -32,15 +31,7 @@ const ProductRecipeList = ({ productId }: ProductRecipeListProps) => { ))} {recipeToDisplay.length < recipes.length && (
  • - {/*링크는 상품이 포함된 꿀조합 검색결과로 가는 것이 맞을듯?*/} - -
    - -
    - - 전체보기 - - +
  • )} diff --git a/src/components/Product/ProductRecipeList/productRecipeList.css.ts b/src/components/Product/ProductRecipeList/productRecipeList.css.ts index 5c7824ba..a6930606 100644 --- a/src/components/Product/ProductRecipeList/productRecipeList.css.ts +++ b/src/components/Product/ProductRecipeList/productRecipeList.css.ts @@ -1,4 +1,3 @@ -import { vars } from '@/styles/theme.css'; import { style } from '@vanilla-extract/css'; export const container = style({ @@ -14,25 +13,3 @@ export const moreItem = style({ alignItems: 'center', minWidth: 108, }); - -export const moreLink = style({ - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - alignItems: 'center', -}); - -export const moreIconWrapper = style({ - display: 'flex', - justifyContent: 'center', - alignItems: 'center', - width: 40, - height: 40, - marginBottom: 12, - borderRadius: '50%', - background: vars.colors.secondary1, -}); - -export const moreIcon = style({ - transform: 'rotate(180deg)', -}); diff --git a/src/components/Recipe/RecipeItem/RecipeItem.tsx b/src/components/Recipe/RecipeItem/RecipeItem.tsx index e94712db..6bbf7de6 100644 --- a/src/components/Recipe/RecipeItem/RecipeItem.tsx +++ b/src/components/Recipe/RecipeItem/RecipeItem.tsx @@ -26,6 +26,7 @@ import { RECIPE_CARD_DEFAULT_IMAGE_URL_4, RECIPE_CARD_DEFAULT_IMAGE_URL_5, } from '@/constants/image'; +import { PATH } from '@/constants/path'; import RecipeItemProvider from '@/contexts/RecipeItemContext'; import { useRecipeItemValueContext } from '@/hooks/context'; import type { Recipe } from '@/types/recipe'; @@ -50,7 +51,7 @@ const RecipeItem = ({ recipe, children }: RecipeItemProps) => { return ( - {children} + {children} ); }; diff --git a/src/components/Search/ProductSearchResultList/ProductSearchResultPreviewList.stories.tsx b/src/components/Search/ProductSearchResultPreviewList/ProductSearchResultPreviewList.stories.tsx similarity index 100% rename from src/components/Search/ProductSearchResultList/ProductSearchResultPreviewList.stories.tsx rename to src/components/Search/ProductSearchResultPreviewList/ProductSearchResultPreviewList.stories.tsx diff --git a/src/components/Search/ProductSearchResultList/ProductSearchResultPreviewList.tsx b/src/components/Search/ProductSearchResultPreviewList/ProductSearchResultPreviewList.tsx similarity index 100% rename from src/components/Search/ProductSearchResultList/ProductSearchResultPreviewList.tsx rename to src/components/Search/ProductSearchResultPreviewList/ProductSearchResultPreviewList.tsx diff --git a/src/components/Search/ProductSearchResultList/productSearchResultPreivewList.css.ts b/src/components/Search/ProductSearchResultPreviewList/productSearchResultPreivewList.css.ts similarity index 100% rename from src/components/Search/ProductSearchResultList/productSearchResultPreivewList.css.ts rename to src/components/Search/ProductSearchResultPreviewList/productSearchResultPreivewList.css.ts diff --git a/src/components/Search/RecipeSearchResultPreviewList/RecipeSearchResultPreviewList.tsx b/src/components/Search/RecipeSearchResultPreviewList/RecipeSearchResultPreviewList.tsx new file mode 100644 index 00000000..b188fc6d --- /dev/null +++ b/src/components/Search/RecipeSearchResultPreviewList/RecipeSearchResultPreviewList.tsx @@ -0,0 +1,43 @@ +import { useRef } from 'react'; + +import { listWrapper } from './recipeSearchResultPreviewList.css'; +import SearchNotFound from '../SearchNotFound/SearchNotFound'; + +import { ShowAllButton } from '@/components/Common'; +import { DefaultRecipeItem } from '@/components/Recipe'; +import { PATH } from '@/constants/path'; +import { useIntersectionObserver } from '@/hooks/common'; +import { useInfiniteRecipeSearchResultsQuery } from '@/hooks/queries/search'; +import displaySlice from '@/utils/displaySlice'; + +interface RecipeSearchResultPreviewListProps { + searchQuery: string; +} + +const RecipeSearchResultPreviewList = ({ searchQuery }: RecipeSearchResultPreviewListProps) => { + const { data: searchResponse, fetchNextPage, hasNextPage } = useInfiniteRecipeSearchResultsQuery(searchQuery); + const scrollRef = useRef(null); + useIntersectionObserver(fetchNextPage, scrollRef, hasNextPage); + + const recipes = searchResponse.pages.flatMap((page) => page.recipes); + + if (recipes.length === 0) { + return ; + } + + return ( +
      + {displaySlice(false, recipes, 4).map((recipe, idx) => ( +
    • + {idx < 4 ? ( + + ) : ( + + )} +
    • + ))} +
    + ); +}; + +export default RecipeSearchResultPreviewList; diff --git a/src/components/Search/RecipeSearchResultPreviewList/recipeSearchResultPreviewList.css.ts b/src/components/Search/RecipeSearchResultPreviewList/recipeSearchResultPreviewList.css.ts new file mode 100644 index 00000000..df2e9d1a --- /dev/null +++ b/src/components/Search/RecipeSearchResultPreviewList/recipeSearchResultPreviewList.css.ts @@ -0,0 +1,8 @@ +import { style } from '@vanilla-extract/css'; + +export const listWrapper = style({ + display: 'flex', + gap: 10, + alignItems: 'center', + overflowY: 'scroll', +}); diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts index 2c312d80..0c32f1b8 100644 --- a/src/components/Search/index.ts +++ b/src/components/Search/index.ts @@ -1,5 +1,5 @@ -export { default as ProductSearchResultPreviewList } from './ProductSearchResultList/ProductSearchResultPreviewList'; +export { default as ProductSearchResultPreviewList } from './ProductSearchResultPreviewList/ProductSearchResultPreviewList'; export { default as RecommendList } from './RecommendList/RecommendList'; -export { default as RecipeSearchResultList } from './RecipeSearchResultList/RecipeSearchResultList'; +export { default as RecipeSearchResultPreviewList } from './RecipeSearchResultPreviewList/RecipeSearchResultPreviewList'; export { default as TagSearchResultList } from './TagSearchResultList/TagSearchResultList'; export { default as SearchInput } from './SearchInput/SearchInput'; diff --git a/src/pages/ProductDetailPage/ProductDetailPage.tsx b/src/pages/ProductDetailPage/ProductDetailPage.tsx index 0367084c..889e1abd 100644 --- a/src/pages/ProductDetailPage/ProductDetailPage.tsx +++ b/src/pages/ProductDetailPage/ProductDetailPage.tsx @@ -66,7 +66,7 @@ export const ProductDetailPage = () => {
    }> - + diff --git a/src/pages/ProductSearchListPage/ProductSearchListPage.tsx b/src/pages/ProductSearchListPage/ProductSearchListPage.tsx index 828710b0..fa9f1b8b 100644 --- a/src/pages/ProductSearchListPage/ProductSearchListPage.tsx +++ b/src/pages/ProductSearchListPage/ProductSearchListPage.tsx @@ -3,7 +3,7 @@ import { useSearchParams } from 'react-router-dom'; import { container } from './productSearchListPage.css'; -import { PageHeader } from '@/components/Common'; +import { TopBar } from '@/components/Common'; import { ProductOverviewList } from '@/components/Product'; import { useIntersectionObserver } from '@/hooks/common'; import { useInfiniteProductSearchResultsQuery } from '@/hooks/queries/search'; @@ -24,7 +24,11 @@ export const ProductSearchListPage = () => { return ( <> - + + + + +
    diff --git a/src/components/Search/RecipeSearchResultList/RecipeSearchResultList.tsx b/src/pages/RecipeSearchListPage/RecipeSearchListPage.tsx similarity index 50% rename from src/components/Search/RecipeSearchResultList/RecipeSearchResultList.tsx rename to src/pages/RecipeSearchListPage/RecipeSearchListPage.tsx index bdc5134b..8c0b0e70 100644 --- a/src/components/Search/RecipeSearchResultList/RecipeSearchResultList.tsx +++ b/src/pages/RecipeSearchListPage/RecipeSearchListPage.tsx @@ -1,19 +1,18 @@ import { useRef } from 'react'; -import { Link } from 'react-router-dom'; -import { styled } from 'styled-components'; +import { useSearchParams } from 'react-router-dom'; -import SearchNotFound from '../SearchNotFound/SearchNotFound'; +import { listWrapper } from './recipeSearchListPage.css'; -import { RecipeItem } from '@/components/Recipe'; -import { PATH } from '@/constants/path'; +import { TopBar } from '@/components/Common'; +import { DefaultRecipeItem } from '@/components/Recipe'; +import SearchNotFound from '@/components/Search/SearchNotFound/SearchNotFound'; import { useIntersectionObserver } from '@/hooks/common'; import { useInfiniteRecipeSearchResultsQuery } from '@/hooks/queries/search'; -interface RecipeSearchResultListProps { - searchQuery: string; -} +export const RecipeSearchListPage = () => { + const [searchParams, setSearchParams] = useSearchParams(); + const searchQuery = searchParams.get('query') || ''; -const RecipeSearchResultList = ({ searchQuery }: RecipeSearchResultListProps) => { const { data: searchResponse, fetchNextPage, hasNextPage } = useInfiniteRecipeSearchResultsQuery(searchQuery); const scrollRef = useRef(null); useIntersectionObserver(fetchNextPage, scrollRef, hasNextPage); @@ -26,24 +25,19 @@ const RecipeSearchResultList = ({ searchQuery }: RecipeSearchResultListProps) => return ( <> - + + + + + +
      {recipes.map((recipe) => (
    • - - - +
    • ))} - +
    ); }; - -export default RecipeSearchResultList; - -const RecipeSearchResultListContainer = styled.ul` - & > li + li { - margin-top: 40px; - } -`; diff --git a/src/pages/RecipeSearchListPage/recipeSearchListPage.css.ts b/src/pages/RecipeSearchListPage/recipeSearchListPage.css.ts new file mode 100644 index 00000000..5b47dfb5 --- /dev/null +++ b/src/pages/RecipeSearchListPage/recipeSearchListPage.css.ts @@ -0,0 +1,8 @@ +import { style } from '@vanilla-extract/css'; + +export const listWrapper = style({ + display: 'grid', + gridTemplateColumns: '1fr 1fr', + gap: '16px 10px', + padding: '0 20px', +}); diff --git a/src/pages/SearchPage/SearchPage.tsx b/src/pages/SearchPage/SearchPage.tsx index 9f8562f7..d3b3a001 100644 --- a/src/pages/SearchPage/SearchPage.tsx +++ b/src/pages/SearchPage/SearchPage.tsx @@ -6,7 +6,7 @@ import { badgeContainer, searchWrapper, searchResultTitle, searchSection, subTit import { Text, Badge, ErrorBoundary, ErrorComponent, Loading, PageHeader } from '@/components/Common'; import { ProductSearchResultPreviewList, - RecipeSearchResultList, + RecipeSearchResultPreviewList, RecommendList, SearchInput, } from '@/components/Search'; @@ -87,7 +87,7 @@ export const SearchPage = () => { }> - +
    diff --git a/src/router/index.tsx b/src/router/index.tsx index 8f0e1be1..843fabb2 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -213,6 +213,15 @@ const router = createBrowserRouter([ return { Component: ProductSearchListPage }; }, }, + { + path: `${PATH.SEARCH}/recipes`, + async lazy() { + const { RecipeSearchListPage } = await import( + /* webpackChunkName: "RecipeSearchListPage" */ '@/pages/RecipeSearchListPage/RecipeSearchListPage' + ); + return { Component: RecipeSearchListPage }; + }, + }, ], }, ]);