From 9c075e8965725f97987dab86f64aac59a031b3cf Mon Sep 17 00:00:00 2001 From: hojin Date: Tue, 27 Aug 2024 19:10:34 +0900 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20search=201=EC=B0=A8=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/search/search_icon.svg | 6 +++ src/app/layout.tsx | 3 +- src/app/report/[id]/layout.tsx | 2 +- src/app/search/layout.tsx | 11 ++++++ src/app/search/page.tsx | 8 ++++ src/components/common/Gnb.tsx | 5 ++- src/components/search/SearchIndex.tsx | 29 +++++++++++++++ src/components/search/SearchRank.tsx | 37 +++++++++++++++++++ .../skeleton/SearchRankSkeleton.tsx | 23 ++++++++++++ src/providers/ModalProvider.tsx | 7 +--- 10 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 public/images/search/search_icon.svg create mode 100644 src/app/search/layout.tsx create mode 100644 src/app/search/page.tsx create mode 100644 src/components/search/SearchIndex.tsx create mode 100644 src/components/search/SearchRank.tsx create mode 100644 src/components/skeleton/SearchRankSkeleton.tsx diff --git a/public/images/search/search_icon.svg b/public/images/search/search_icon.svg new file mode 100644 index 0000000..5a0d915 --- /dev/null +++ b/public/images/search/search_icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/app/layout.tsx b/src/app/layout.tsx index fde1ed0..c044ec2 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -57,7 +57,8 @@ export default function RootLayout({ src={`//dapi.kakao.com/v2/maps/sdk.js?appkey=${process.env.NEXT_PUBLIC_MAP_KEY}&autoload=false`} /> - {children} + {children} +
diff --git a/src/app/report/[id]/layout.tsx b/src/app/report/[id]/layout.tsx index 57c5653..2640bb5 100644 --- a/src/app/report/[id]/layout.tsx +++ b/src/app/report/[id]/layout.tsx @@ -1,4 +1,4 @@ -export default function ProductLayout({ +export default function ReportLayout({ children }: Readonly<{ children: React.ReactNode; diff --git a/src/app/search/layout.tsx b/src/app/search/layout.tsx new file mode 100644 index 0000000..0134cf8 --- /dev/null +++ b/src/app/search/layout.tsx @@ -0,0 +1,11 @@ +export default function SearchLayout({ + children +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( +
+
{children}
+
+ ); +} diff --git a/src/app/search/page.tsx b/src/app/search/page.tsx new file mode 100644 index 0000000..aad680a --- /dev/null +++ b/src/app/search/page.tsx @@ -0,0 +1,8 @@ +import SearchIndex from '@/components/search/SearchIndex'; +import React from 'react'; + +const SearchPage = () => { + return ; +}; + +export default SearchPage; diff --git a/src/components/common/Gnb.tsx b/src/components/common/Gnb.tsx index 930ea43..51f2900 100644 --- a/src/components/common/Gnb.tsx +++ b/src/components/common/Gnb.tsx @@ -1,7 +1,7 @@ 'use client'; import Link from 'next/link'; -import { usePathname } from 'next/navigation'; +import { usePathname, useRouter } from 'next/navigation'; import React, { useEffect, useState } from 'react'; import { useAuthStore } from '@/store/userAuth.store'; @@ -9,6 +9,7 @@ const Gnb = () => { const pathname = usePathname(); const { isLoggedIn, setIsLoggedIn } = useAuthStore(); const [isLoading, setIsLoading] = useState(true); + const router = useRouter(); useEffect(() => { const accessToken = localStorage.getItem('access_token'); @@ -36,7 +37,7 @@ const Gnb = () => { logo
-
+
router.push('/search')} className="cursor-pointer"> search_icon
diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx new file mode 100644 index 0000000..507050a --- /dev/null +++ b/src/components/search/SearchIndex.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import SearchRank from './SearchRank'; + +const SearchIndex = () => { + return ( +
+
+ 찾으시는 상품이 있으신가요? +
+
+
+ + +
+
+ +
+
실시간 검색
+ +
+
+ ); +}; + +export default SearchIndex; diff --git a/src/components/search/SearchRank.tsx b/src/components/search/SearchRank.tsx new file mode 100644 index 0000000..cc128ea --- /dev/null +++ b/src/components/search/SearchRank.tsx @@ -0,0 +1,37 @@ +'use client'; +import { getRealtimeRank } from '@/factory/RealtimeRank'; +import React from 'react'; +import RealtimeRankSkeleton from '../skeleton/RealtimeSkeleton'; +import { RealtimeRankType } from '@/types/homeComponentsType'; +import SearchRankSkeleton from '../skeleton/SearchRankSkeleton'; + +const SearchRank = () => { + const { data, isLoading } = getRealtimeRank(); + + if (isLoading) { + return ; + } + return ( +
+
+
    + {data?.map((item: RealtimeRankType, i: number) => ( +
  • +
    + {item.rank}위 +
    +
    {item.keyword}
    + {/* todo : 돋보기 누르면 그대로 검색 쿼리에 keyword가 들어가게하기 */} +
    + search +
    +
  • + ))} +
+
+
+ ); +}; + +export default SearchRank; diff --git a/src/components/skeleton/SearchRankSkeleton.tsx b/src/components/skeleton/SearchRankSkeleton.tsx new file mode 100644 index 0000000..bb4685b --- /dev/null +++ b/src/components/skeleton/SearchRankSkeleton.tsx @@ -0,0 +1,23 @@ +import React from 'react'; + +const SearchRankSkeleton = () => { + return ( +
+
+
+
    + {Array.from({ length: 5 }).map((_, i) => ( +
  • +
    +
    +
    +
  • + ))} +
+
+
+
+ ); +}; + +export default SearchRankSkeleton; diff --git a/src/providers/ModalProvider.tsx b/src/providers/ModalProvider.tsx index 4af00cc..c172347 100644 --- a/src/providers/ModalProvider.tsx +++ b/src/providers/ModalProvider.tsx @@ -5,7 +5,7 @@ import React from 'react'; import { createPortal } from 'react-dom'; import Quitmodal from '@/components/modal/Quitmodal'; -const ModalProvider = ({ children }: { children: React.ReactNode }) => { +const ModalProvider = () => { const { open, modalType } = useModalStore(); const [mounted, setMounted] = useState(false); @@ -21,10 +21,7 @@ const ModalProvider = ({ children }: { children: React.ReactNode }) => { if (!$portalRoot) return null; return createPortal( -
- {children} - {open && modalType === 'secession' && } -
, +
{open && modalType === 'secession' && }
, $portalRoot ); }; From e1ba7309f6db2ab04bc080aa445a01390059585c Mon Sep 17 00:00:00 2001 From: hojin Date: Tue, 27 Aug 2024 19:34:31 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20search=202=EC=B0=A8=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/images/search/xcircle.svg | 7 ++++ src/components/search/SearchIndex.tsx | 59 +++++++++++++++++++++------ 2 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 public/images/search/xcircle.svg diff --git a/public/images/search/xcircle.svg b/public/images/search/xcircle.svg new file mode 100644 index 0000000..eaa2ead --- /dev/null +++ b/public/images/search/xcircle.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx index 507050a..afdb60d 100644 --- a/src/components/search/SearchIndex.tsx +++ b/src/components/search/SearchIndex.tsx @@ -1,27 +1,62 @@ -import React from 'react'; +'use client'; +import React, { ChangeEvent, useCallback, useRef, useState } from 'react'; import SearchRank from './SearchRank'; const SearchIndex = () => { + const [isFocused, setIsFocused] = useState(false); + const [keyWord, setKeyWord] = useState(''); + const inputRef = useRef(null); + + const handleKeyword = useCallback((e: ChangeEvent) => { + setKeyWord(e.target.value); + }, []); + + const handleClear = useCallback(() => { + setKeyWord(''); + if (inputRef.current) { + inputRef.current.focus(); + } + }, []); + return (
-
- 찾으시는 상품이 있으신가요? -
+ {keyWord ? null : ( +
+ 찾으시는 상품이 있으신가요? +
+ )} +
-
+
setIsFocused(true)} + onBlur={() => setIsFocused(false)} + value={keyWord} + onChange={handleKeyword} + type="text" placeholder="조각투자 상품 검색" className="w-full outline-none text-body2 " /> - + {keyWord && ( +
+ +
+ )} +
+ +
- -
-
실시간 검색
- -
+ {keyWord ? null : ( +
+
실시간 검색
+ +
+ )}
); }; From ecf2c98a7f785457e9b1bec7956a3cb5a782b41d Mon Sep 17 00:00:00 2001 From: hojin Date: Thu, 29 Aug 2024 17:50:46 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20search=203=EC=B0=A8=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/home/MainListItem.tsx | 13 ++++--- src/components/recentlyIssue/CategoryNews.tsx | 2 +- src/components/search/SearchIndex.tsx | 19 +++++++++- src/components/search/SearchRank.tsx | 2 +- src/components/search/SearchedResultItem.tsx | 11 ++++++ src/factory/SearchItem.tsx | 35 +++++++++++++++++++ src/types/homeComponentsType.ts | 11 ++++-- 7 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 src/components/search/SearchedResultItem.tsx create mode 100644 src/factory/SearchItem.tsx diff --git a/src/components/home/MainListItem.tsx b/src/components/home/MainListItem.tsx index 1b9cf86..927de73 100644 --- a/src/components/home/MainListItem.tsx +++ b/src/components/home/MainListItem.tsx @@ -1,6 +1,7 @@ import type { MainProductItem } from '@/types/homeComponentsType'; import { formatCategory } from '@/utils/formatCategory'; +import { useRouter } from 'next/navigation'; import React from 'react'; const MainListItem = ({ @@ -14,8 +15,12 @@ const MainListItem = ({ dividend, lastDivide_rate }: MainProductItem) => { + const router = useRouter(); + return ( -
+
router.push(`/product/detail/${product_Id}`)} + className="mt-5 pb-5 border-b border-gray100 cursor-pointer">
{/* 이미지 */}
@@ -35,10 +40,10 @@ const MainListItem = ({
{name}
-
{price.toLocaleString()}
-
+
{price.toLocaleString()}원
+
0 ? 'text-error' : 'text-success'}`}> {'('} - {'+'} {priceRate}%{')'} + {`${priceRate > 0 ? '+' : ''}`} {priceRate}%{')'}
diff --git a/src/components/recentlyIssue/CategoryNews.tsx b/src/components/recentlyIssue/CategoryNews.tsx index d24ba37..dfa476c 100644 --- a/src/components/recentlyIssue/CategoryNews.tsx +++ b/src/components/recentlyIssue/CategoryNews.tsx @@ -7,7 +7,7 @@ import CategoryNewsItemSkeleton from '../skeleton/CategoryNewsItemSkeleton'; import { Virtuoso } from 'react-virtuoso'; const CategoryNews = () => { - const [category, setCategory] = useState('building'); + const [category, setCategory] = useState('all'); const [sort, setSort] = useState('latest'); const { data, fetchNextPage, hasNextPage, isFetching, isFetchingNextPage, isLoading } = diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx index afdb60d..a866fed 100644 --- a/src/components/search/SearchIndex.tsx +++ b/src/components/search/SearchIndex.tsx @@ -1,11 +1,16 @@ 'use client'; import React, { ChangeEvent, useCallback, useRef, useState } from 'react'; import SearchRank from './SearchRank'; +import useDebounce from '@/hook/useDebounce'; +import { getSearchItem } from '@/factory/SearchItem'; const SearchIndex = () => { const [isFocused, setIsFocused] = useState(false); const [keyWord, setKeyWord] = useState(''); const inputRef = useRef(null); + const debouncedKeyword = useDebounce(keyWord); + + const { data, isLoading } = getSearchItem(debouncedKeyword); const handleKeyword = useCallback((e: ChangeEvent) => { setKeyWord(e.target.value); @@ -46,17 +51,29 @@ const SearchIndex = () => {
)} -
+
+ {keyWord ? null : (
실시간 검색
)} + + {keyWord && ( +
+
+ 검색 결과{' '} + {keyWord && !isLoading && data && ( + {data?.length}개 + )} +
+
+ )}
); }; diff --git a/src/components/search/SearchRank.tsx b/src/components/search/SearchRank.tsx index cc128ea..4004330 100644 --- a/src/components/search/SearchRank.tsx +++ b/src/components/search/SearchRank.tsx @@ -13,7 +13,7 @@ const SearchRank = () => { } return (
-
+
    {data?.map((item: RealtimeRankType, i: number) => (
  • diff --git a/src/components/search/SearchedResultItem.tsx b/src/components/search/SearchedResultItem.tsx new file mode 100644 index 0000000..aad30e8 --- /dev/null +++ b/src/components/search/SearchedResultItem.tsx @@ -0,0 +1,11 @@ +import React from 'react'; + +const SearchedResultItem = () => { + return ( +
    +
    asdad
    +
    + ); +}; + +export default SearchedResultItem; diff --git a/src/factory/SearchItem.tsx b/src/factory/SearchItem.tsx new file mode 100644 index 0000000..9ef2fa1 --- /dev/null +++ b/src/factory/SearchItem.tsx @@ -0,0 +1,35 @@ +import type { SearchedItem } from '@/types/homeComponentsType'; + +import { useQuery } from '@tanstack/react-query'; +import axios from 'axios'; + +const fetchSearchItem = async (keyword: string) => { + try { + const { data } = await axios.get( + `https://api.moaguide.com/search?keyword=${keyword}` + ); + return data; + } catch (e) { + throw new Error('Failed to fetch'); + } +}; + +export const getSearchItem = (keyword: string) => { + const queryKey = ['SearchItem', keyword]; + + const { data, error, ...queryProps } = useQuery({ + queryKey, + queryFn: () => fetchSearchItem(keyword), + enabled: !!keyword + }); + + if (error) { + console.error(error); + } + + return { + data, + error, + ...queryProps + }; +}; diff --git a/src/types/homeComponentsType.ts b/src/types/homeComponentsType.ts index c6a2ebe..9651e6c 100644 --- a/src/types/homeComponentsType.ts +++ b/src/types/homeComponentsType.ts @@ -36,9 +36,9 @@ export interface MainProductItem { category: string; platform: string; name: string; - price: string; + price: number; priceRate: number; - totalPrice: string; + totalPrice: number; dividend: number; lastDivide_rate: number; } @@ -50,3 +50,10 @@ export interface ReportListsItem { category: string; date: string; } + +export interface SearchedItem { + productId: string; + name: string; + platform: string; + category: string; +} From 8f45738e02b7985ab2cf40b7dca2ccef7c346ed0 Mon Sep 17 00:00:00 2001 From: hojin Date: Mon, 2 Sep 2024 13:02:43 +0900 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20search=204=EC=B0=A8=20=EB=A0=88?= =?UTF-8?q?=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/search/SearchIndex.tsx | 9 +++++---- src/components/skeleton/CircleSkeleton.tsx | 7 +++++++ 2 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 src/components/skeleton/CircleSkeleton.tsx diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx index a866fed..8dcdd61 100644 --- a/src/components/search/SearchIndex.tsx +++ b/src/components/search/SearchIndex.tsx @@ -3,6 +3,7 @@ import React, { ChangeEvent, useCallback, useRef, useState } from 'react'; import SearchRank from './SearchRank'; import useDebounce from '@/hook/useDebounce'; import { getSearchItem } from '@/factory/SearchItem'; +import CircleSkeleton from '../skeleton/CircleSkeleton'; const SearchIndex = () => { const [isFocused, setIsFocused] = useState(false); @@ -64,14 +65,14 @@ const SearchIndex = () => {
)} - {keyWord && ( + {keyWord && isLoading && } + {keyWord && !isLoading && data && (
검색 결과{' '} - {keyWord && !isLoading && data && ( - {data?.length}개 - )} + {data?.length}개
+
    )}
    diff --git a/src/components/skeleton/CircleSkeleton.tsx b/src/components/skeleton/CircleSkeleton.tsx new file mode 100644 index 0000000..6bfce59 --- /dev/null +++ b/src/components/skeleton/CircleSkeleton.tsx @@ -0,0 +1,7 @@ +export default function CircleSkeleton({ className = '' }) { + return ( +
    +
    +
    + ); +} From ea327c7fc69eec9fac358ad40f9d1bba0223dd7f Mon Sep 17 00:00:00 2001 From: hojin Date: Mon, 2 Sep 2024 13:51:26 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20search=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/search/layout.tsx | 2 +- src/components/search/SearchIndex.tsx | 9 +++-- src/components/search/SearchRank.tsx | 19 +++++++-- src/components/search/SearchedResultItem.tsx | 41 ++++++++++++++++++-- 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/src/app/search/layout.tsx b/src/app/search/layout.tsx index 0134cf8..2096e45 100644 --- a/src/app/search/layout.tsx +++ b/src/app/search/layout.tsx @@ -5,7 +5,7 @@ export default function SearchLayout({ }>) { return (
    -
    {children}
    +
    {children}
    ); } diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx index 8dcdd61..970650d 100644 --- a/src/components/search/SearchIndex.tsx +++ b/src/components/search/SearchIndex.tsx @@ -4,6 +4,7 @@ import SearchRank from './SearchRank'; import useDebounce from '@/hook/useDebounce'; import { getSearchItem } from '@/factory/SearchItem'; import CircleSkeleton from '../skeleton/CircleSkeleton'; +import SearchedResultItem from './SearchedResultItem'; const SearchIndex = () => { const [isFocused, setIsFocused] = useState(false); @@ -35,7 +36,7 @@ const SearchIndex = () => {
    { {keyWord ? null : (
    실시간 검색
    - +
    )} @@ -72,7 +73,9 @@ const SearchIndex = () => { 검색 결과{' '} {data?.length}개
    -
      +
        + {data?.map((item, i) => )} +
      )}
      diff --git a/src/components/search/SearchRank.tsx b/src/components/search/SearchRank.tsx index 4004330..7b4c6cd 100644 --- a/src/components/search/SearchRank.tsx +++ b/src/components/search/SearchRank.tsx @@ -1,16 +1,25 @@ 'use client'; import { getRealtimeRank } from '@/factory/RealtimeRank'; -import React from 'react'; +import React, { Dispatch } from 'react'; import RealtimeRankSkeleton from '../skeleton/RealtimeSkeleton'; import { RealtimeRankType } from '@/types/homeComponentsType'; import SearchRankSkeleton from '../skeleton/SearchRankSkeleton'; -const SearchRank = () => { +interface SearchRankType { + setKeyWord: Dispatch>; +} + +const SearchRank = ({ setKeyWord }: SearchRankType) => { const { data, isLoading } = getRealtimeRank(); + const handleClick = (keyword: string) => { + setKeyWord(keyword); + }; + if (isLoading) { return ; } + return (
      @@ -24,7 +33,11 @@ const SearchRank = () => {
      {item.keyword}
      {/* todo : 돋보기 누르면 그대로 검색 쿼리에 keyword가 들어가게하기 */}
      - search + handleClick(item.keyword)} + src="/images/home/search.svg" + alt="search" + />
      ))} diff --git a/src/components/search/SearchedResultItem.tsx b/src/components/search/SearchedResultItem.tsx index aad30e8..094d3ac 100644 --- a/src/components/search/SearchedResultItem.tsx +++ b/src/components/search/SearchedResultItem.tsx @@ -1,10 +1,43 @@ +import type { SearchedItem } from '@/types/homeComponentsType'; + +import { formatCategory } from '@/utils/formatCategory'; +import { useRouter } from 'next/navigation'; import React from 'react'; -const SearchedResultItem = () => { +const SearchedResultItem = ({ productId, name, platform, category }: SearchedItem) => { + const router = useRouter(); + return ( -
      -
      asdad
      -
      +
    • router.push(`/product/detail/${productId}`)} + className="p-5 cursor-pointer bg-white rounded-[12px]"> +
      + {/* 이미지 */} +
      + +
      + {/* 메인정보 */} +
      +
      +
      + {formatCategory(category)} +
      +
      {platform}
      +
      +
      {name}
      +
      + {/* 부가정보 */} +
      +
      + +
      +
      +
      +
    • ); }; From 9b7ba83320159b074eab0b6797a18c85e552ec7b Mon Sep 17 00:00:00 2001 From: hojin Date: Mon, 2 Sep 2024 14:04:36 +0900 Subject: [PATCH 6/6] =?UTF-8?q?feat:=20=ED=99=88=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=8B=A4=EC=8B=9C=EA=B0=84=20=EA=B2=80=EC=83=89?= =?UTF-8?q?=EC=96=B4=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/home/RealtimeRank.tsx | 13 +++++++++++-- src/components/search/SearchIndex.tsx | 4 +++- src/store/search.store.ts | 19 +++++++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 src/store/search.store.ts diff --git a/src/components/home/RealtimeRank.tsx b/src/components/home/RealtimeRank.tsx index b96ad90..31b4148 100644 --- a/src/components/home/RealtimeRank.tsx +++ b/src/components/home/RealtimeRank.tsx @@ -3,8 +3,12 @@ import type { RealtimeRankType } from '@/types/homeComponentsType'; import { getRealtimeRank } from '@/factory/RealtimeRank'; import React from 'react'; import RealtimeRankSkeleton from '../skeleton/RealtimeSkeleton'; +import { useSearchStore } from '@/store/search.store'; +import { useRouter } from 'next/navigation'; const RealtimeRank = () => { + const router = useRouter(); + const { setKeyword } = useSearchStore(); const { data, isLoading } = getRealtimeRank(); if (isLoading) { @@ -28,8 +32,13 @@ const RealtimeRank = () => {
      {item.keyword}
      - {/* todo : 돋보기 누르면 그대로 검색 쿼리에 keyword가 들어가게하기 */} -
      + +
      { + setKeyword(item.keyword); + router.push('/search'); + }} + className="w-6 h-6 rounded-full bg-gray100 flex items-center justify-center cursor-pointer"> search
      diff --git a/src/components/search/SearchIndex.tsx b/src/components/search/SearchIndex.tsx index 970650d..de3898e 100644 --- a/src/components/search/SearchIndex.tsx +++ b/src/components/search/SearchIndex.tsx @@ -5,10 +5,12 @@ import useDebounce from '@/hook/useDebounce'; import { getSearchItem } from '@/factory/SearchItem'; import CircleSkeleton from '../skeleton/CircleSkeleton'; import SearchedResultItem from './SearchedResultItem'; +import { useSearchStore } from '@/store/search.store'; const SearchIndex = () => { + const { currentKeyword } = useSearchStore(); const [isFocused, setIsFocused] = useState(false); - const [keyWord, setKeyWord] = useState(''); + const [keyWord, setKeyWord] = useState(currentKeyword); // 전역 currentKeyword가 존재한다면 우선사용 const inputRef = useRef(null); const debouncedKeyword = useDebounce(keyWord); diff --git a/src/store/search.store.ts b/src/store/search.store.ts new file mode 100644 index 0000000..bc85706 --- /dev/null +++ b/src/store/search.store.ts @@ -0,0 +1,19 @@ +import { create } from 'zustand'; + +/** + * 메인페이지에서 실시간 검색 순위 키워드(검색어)를 클릭 할 시 + * 해당 키워드를 search 페이지의 keyword(검색어)로 넘겨주는 역할의 store입니다. + */ + +interface useSearchStoreType { + currentKeyword: string; + setKeyword: (payload: string) => void; +} + +export const useSearchStore = create((set) => ({ + currentKeyword: '', + setKeyword: (payload: string) => + set(() => ({ + currentKeyword: payload + })) +}));