Skip to content

Commit

Permalink
feat: 태그 검색 기능 구현 (#64)
Browse files Browse the repository at this point in the history
* refactor: 검색 api에서 태그 검색일때의 endpoint 추가

* feat: 태그 검색 기능 구현

* feat: 검색결과 없을 때 화면 구현

* feat: 태그 검색 결과 리스트 컴포넌트 구현

* feat: Text 컴포넌트에서 외부 className을 받을 수 있게 수정

* feat: 검색 페이지에서 태그 검색 결과일 경우 분기처리

* feat: 더보기 버튼을 리스트 컴포넌트로 위치 이동

* feat: 태그 검색을 일반 검색과 분리

* feat: 상품 검색 더보기 페이지 구현

* feat: 태그 검색을 했을 때 input value 스타일 변경

* style: 사용 안하는 코드 import 제거

* feat: ProductSearchResultList 스토리북 추가

* fix: 검색이 되었을 때 resetQuery를 하도록 수정

* style: fix lint error

* feat: 태그 검색 페이지 분리

* feat: 말풍선 아이콘 교체

* feat: ProductItem 디자인 수정

* feat: ProductSearchResultList -> ProductSearchResultPreviewList로 이름 변경

* feat: 버튼 스타일 변경

* feat: ProductOverviewList로 교체

* fix: 상품 상세 경로 수정

* refactor: 인자로 endpoint를 넘겨주게끔 변경
  • Loading branch information
xodms0309 authored Apr 11, 2024
1 parent 0c61323 commit ae36aa8
Show file tree
Hide file tree
Showing 30 changed files with 546 additions and 119 deletions.
51 changes: 45 additions & 6 deletions .storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,55 @@
</clipPath>
</defs>
</symbol>
<symbol id="review2" viewBox="0 0 14 14">
<g strokeLinecap="round" strokeLinejoin="round" clipPath="url(#clip0_1222_34401)">
<symbol id="review2" viewBox="0 0 12 12" fill="none">
<g clip-path="url(#clip0_4627_11650)">
<path
d="M7.002 7.25a.25.25 0 0 1 0-.5m0 .5a.25.25 0 0 0 0-.5m-2.75.5a.25.25 0 0 1 0-.5m0 .5a.25.25 0 0 0 0-.5m5.5.5a.25.25 0 0 1 0-.5m0 .5a.25.25 0 1 0 0-.5"
d="M6.04793 0.650025C5.13272 0.650311 4.23471 0.898835 3.44956 1.36913C2.66442 1.83943 2.02154 2.51387 1.5894 3.32065C1.15725 4.12742 0.952032 5.0363 0.99559 5.95048C1.03915 6.86467 1.32985 7.74991 1.83675 8.51192L0.988281 10.7694L3.82947 10.2556C4.51362 10.5899 5.2644 10.7655 6.02586 10.7693C6.78732 10.7731 7.53981 10.6049 8.22724 10.2773C8.91465 9.94986 9.51934 9.47136 9.99603 8.87759C10.4728 8.28391 10.8095 7.5902 10.9808 6.84826C11.1521 6.10633 11.1539 5.33528 10.9857 4.59261C10.8176 3.84993 10.484 3.15477 10.0099 2.55897C9.53568 1.96315 8.93311 1.48206 8.24714 1.15153C7.56115 0.821004 6.8094 0.649576 6.04793 0.650025Z"
fill="#DDDDDD"
stroke="#DDDDDD"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M6.04799 5.90604C5.93951 5.90604 5.85156 5.8181 5.85156 5.70961C5.85156 5.60113 5.93951 5.51318 6.04799 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M6.04688 5.90604C6.15536 5.90604 6.2433 5.8181 6.2433 5.70961C6.2433 5.60113 6.15536 5.51318 6.04688 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M3.89174 5.90604C3.78326 5.90604 3.69531 5.8181 3.69531 5.70961C3.69531 5.60113 3.78326 5.51318 3.89174 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M3.89062 5.90604C3.99911 5.90604 4.08705 5.8181 4.08705 5.70961C4.08705 5.60113 3.99911 5.51318 3.89062 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M8.21205 5.90604C8.10357 5.90604 8.01562 5.8181 8.01562 5.70961C8.01562 5.60113 8.10357 5.51318 8.21205 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M8.21094 5.90604C8.31942 5.90604 8.40741 5.8181 8.40741 5.70961C8.40741 5.60113 8.31942 5.51318 8.21094 5.51318"
stroke="white"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path d="M6.998.56a6.44 6.44 0 0 0-5.36 10.007L.558 13.44l3.617-.654A6.44 6.44 0 1 0 6.998.56z" />
</g>
<defs>
<clipPath id="clip0_1222_34401">
<path fill="#fff" d="M0 0h14v14H0z" />
<clipPath id="clip0_4627_11650">
<rect width="11" height="11" fill="white" transform="translate(0.550781 0.209595)" />
</clipPath>
</defs>
</symbol>
Expand Down
Binary file added src/assets/search-notfound.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
53 changes: 47 additions & 6 deletions src/components/Common/Svg/SvgSprite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,55 @@ const SvgSprite = () => {
</clipPath>
</defs>
</symbol>
<symbol id="review2" viewBox="0 0 14 14">
<g strokeLinecap="round" strokeLinejoin="round" clipPath="url(#clip0_1222_34401)">
<path d="M7.002 7.25a.25.25 0 0 1 0-.5m0 .5a.25.25 0 0 0 0-.5m-2.75.5a.25.25 0 0 1 0-.5m0 .5a.25.25 0 0 0 0-.5m5.5.5a.25.25 0 0 1 0-.5m0 .5a.25.25 0 1 0 0-.5" />
<path d="M6.998.56a6.44 6.44 0 0 0-5.36 10.007L.558 13.44l3.617-.654A6.44 6.44 0 1 0 6.998.56z" />
<symbol id="review2" viewBox="0 0 12 12" fill="none">
<g clipPath="url(#clip0_4627_11650)">
<path
d="M6.04793 0.650025C5.13272 0.650311 4.23471 0.898835 3.44956 1.36913C2.66442 1.83943 2.02154 2.51387 1.5894 3.32065C1.15725 4.12742 0.952032 5.0363 0.99559 5.95048C1.03915 6.86467 1.32985 7.74991 1.83675 8.51192L0.988281 10.7694L3.82947 10.2556C4.51362 10.5899 5.2644 10.7655 6.02586 10.7693C6.78732 10.7731 7.53981 10.6049 8.22724 10.2773C8.91465 9.94986 9.51934 9.47136 9.99603 8.87759C10.4728 8.28391 10.8095 7.5902 10.9808 6.84826C11.1521 6.10633 11.1539 5.33528 10.9857 4.59261C10.8176 3.84993 10.484 3.15477 10.0099 2.55897C9.53568 1.96315 8.93311 1.48206 8.24714 1.15153C7.56115 0.821004 6.8094 0.649576 6.04793 0.650025Z"
fill="#DDDDDD"
stroke="#DDDDDD"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.04799 5.90604C5.93951 5.90604 5.85156 5.8181 5.85156 5.70961C5.85156 5.60113 5.93951 5.51318 6.04799 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M6.04688 5.90604C6.15536 5.90604 6.2433 5.8181 6.2433 5.70961C6.2433 5.60113 6.15536 5.51318 6.04688 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3.89174 5.90604C3.78326 5.90604 3.69531 5.8181 3.69531 5.70961C3.69531 5.60113 3.78326 5.51318 3.89174 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M3.89062 5.90604C3.99911 5.90604 4.08705 5.8181 4.08705 5.70961C4.08705 5.60113 3.99911 5.51318 3.89062 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M8.21205 5.90604C8.10357 5.90604 8.01562 5.8181 8.01562 5.70961C8.01562 5.60113 8.10357 5.51318 8.21205 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M8.21094 5.90604C8.31942 5.90604 8.40741 5.8181 8.40741 5.70961C8.40741 5.60113 8.31942 5.51318 8.21094 5.51318"
stroke="white"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_1222_34401">
<path fill="#fff" d="M0 0h14v14H0z" />
<clipPath id="clip0_4627_11650">
<rect width="11" height="11" fill="white" transform="translate(0.550781 0.209595)" />
</clipPath>
</defs>
</symbol>
Expand Down
5 changes: 4 additions & 1 deletion src/components/Common/Text/Text.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import cx from 'classnames';

import { text } from './text.css';
import type { TextElement, TextVariants, OverridableComponentPropsWithoutRef } from './text.types';

Expand All @@ -9,12 +11,13 @@ const Text = <T extends TextElement = 'p'>({
weight = 'regular',
color = 'default',
as,
className,
...props
}: TextProps<T>) => {
const Component = as || 'p';

return (
<Component className={text({ color, size, weight })} {...props}>
<Component className={cx(text({ color, size, weight }), className)} {...props}>
{children}
</Component>
);
Expand Down
5 changes: 3 additions & 2 deletions src/components/Product/ProductItem/ProductItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from './productItem.css';

import { SvgIcon } from '@/components/Common';
import { vars } from '@/styles/theme.css';
import type { Product } from '@/types/product';

interface ProductItemProps {
Expand Down Expand Up @@ -44,13 +45,13 @@ const ProductItem = ({ product }: ProductItemProps) => {
<div style={{ height: '8px' }} />
<div className={summaryWrapper}>
<div className={previewWrapper}>
<SvgIcon variant="star2" width={11} height={11} fill="none" stroke="#999" />
<SvgIcon variant="star2" width={11} height={11} fill={vars.colors.gray2} />
<span className={preview} aria-label={`${averageRating}점`}>
{averageRating.toFixed(1)}
</span>
</div>
<div className={previewWrapper}>
<SvgIcon variant="review2" width={11} height={11} fill="none" stroke="#999" />
<SvgIcon variant="review2" width={11} height={11} />
<span className={preview} aria-label={`리뷰 ${reviewCount}개`}>
{reviewCount}
</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,23 @@ import type { Product } from '@/types/product';

interface ProductOverviewListProps {
products: Product[];
isSearchPage?: boolean;
}

const ProductOverviewList = ({ products }: ProductOverviewListProps) => {
const ProductOverviewList = ({ products, isSearchPage = false }: ProductOverviewListProps) => {
return (
<ul className={container}>
{products.map(({ id, image, name, price, averageRating }) => (
<li key={id}>
<Link to={`${PATH.PRODUCT_LIST}/detail/${id}`}>
<ProductOverviewItem image={image} name={name} price={price} rate={averageRating} />
</Link>
{isSearchPage && (
<>
<div style={{ height: '20px' }} />
<hr style={{ border: '0.5px solid #e6e6e6' }} />
</>
)}
</li>
))}
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,16 @@ export const container = style({
flexDirection: 'column',
gap: 20,
});

export const showMoreButton = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: 38,
padding: '9px 0',
margin: '20px 0',
background: '#efefef',
fontSize: 14,
borderRadius: 6,
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from '@storybook/react';

import ProductSearchResultPreviewList from './ProductSearchResultPreviewList';

const meta: Meta<typeof ProductSearchResultPreviewList> = {
title: 'search/ProductSearchResultPreviewList',
component: ProductSearchResultPreviewList,
args: {
searchQuery: '꼬북칩',
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { useRef } from 'react';
import { Link } from 'react-router-dom';

import { showMoreLink } from './productSearchResultPreivewList.css';
import SearchNotFound from '../SearchNotFound/SearchNotFound';

import { Text } from '@/components/Common';
import { ProductOverviewList } from '@/components/Product';
import { PATH } from '@/constants/path';
import { useIntersectionObserver } from '@/hooks/common';
import { useInfiniteProductSearchResultsQuery } from '@/hooks/queries/search';
import displaySlice from '@/utils/displaySlice';

interface ProductSearchResultPreviewListProps {
searchQuery: string;
}

const ProductSearchResultPreviewList = ({ searchQuery }: ProductSearchResultPreviewListProps) => {
const {
data: searchResponse,
fetchNextPage,
hasNextPage,
} = useInfiniteProductSearchResultsQuery(searchQuery, 'products');
const scrollRef = useRef<HTMLDivElement>(null);
useIntersectionObserver<HTMLDivElement>(fetchNextPage, scrollRef, hasNextPage);

if (!searchResponse) {
return null;
}

const products = searchResponse.pages.flatMap((page) => page.products);
const productToDisplay = displaySlice(true, products);

if (products.length === 0) {
return <SearchNotFound />;
}

return (
<>
<ProductOverviewList products={productToDisplay} />
<Link to={`${PATH.SEARCH}/products?query=${searchQuery}`} className={showMoreLink}>
<Text size="caption1" weight="medium" color="info">
더보기
</Text>
</Link>
<div ref={scrollRef} aria-hidden />
</>
);
};

export default ProductSearchResultPreviewList;
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const showMoreLink = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: 44,
padding: '12px 0',
margin: '20px 0',
border: `1px solid ${vars.colors.border.default}`,
fontSize: 14,
borderRadius: 6,
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Link, Text } from '@fun-eat/design-system';
import { useRef } from 'react';
import { Link as RouterLink } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { styled } from 'styled-components';

import SearchNotFound from '../SearchNotFound/SearchNotFound';

import { RecipeItem } from '@/components/Recipe';
import { PATH } from '@/constants/path';
import { useIntersectionObserver } from '@/hooks/common';
Expand All @@ -20,15 +21,15 @@ const RecipeSearchResultList = ({ searchQuery }: RecipeSearchResultListProps) =>
const recipes = searchResponse.pages.flatMap((page) => page.recipes);

if (recipes.length === 0) {
return <Text>검색한 꿀조합을 찾을 수 없습니다.</Text>;
return <SearchNotFound />;
}

return (
<>
<RecipeSearchResultListContainer>
{recipes.map((recipe) => (
<li key={recipe.id}>
<Link as={RouterLink} to={`${PATH.RECIPE}/${recipe.id}`}>
<Link to={`${PATH.RECIPE}/${recipe.id}`}>
<RecipeItem recipe={recipe} />
</Link>
</li>
Expand Down
Loading

0 comments on commit ae36aa8

Please sign in to comment.