From 7cf98ffc358044461fe91e3b6508260cf7aec5fc Mon Sep 17 00:00:00 2001 From: Jungu Lee <1zzangjun@gmail.com> Date: Sun, 7 Jan 2024 00:50:39 +0900 Subject: [PATCH 1/3] =?UTF-8?q?FIX=20:=20Test=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/src/__test__/post/formatTime.test.ts | 8 ++++---- client/src/utils/formatTime.ts | 15 ++++++++------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/client/src/__test__/post/formatTime.test.ts b/client/src/__test__/post/formatTime.test.ts index fdbdfb6..5f0823b 100644 --- a/client/src/__test__/post/formatTime.test.ts +++ b/client/src/__test__/post/formatTime.test.ts @@ -5,7 +5,7 @@ describe("인스타그램 스타일 시간 포매팅 함수", () => { const THREE_DAYS_AGO = "Thu Dec 11 2023 00:50:25 GMT+0900 (한국 표준시)"; const EIGHT_DAYS_AGO = "Thu Dec 6 2023 00:50:25 GMT+0900 (한국 표준시)"; const ONE_MONTH_AGO = "Thu Nov 11 2023 00:50:25 GMT+0900 (한국 표준시)"; - const THREE_MONTH_AGO = "Thu Sep 11 2023 00:50:25 GMT+0900 (한국 표준시)"; + const THREE_MONTH_AGO = "Thu Oct 11 2023 00:50:25 GMT+0900 (한국 표준시)"; const ONE_YEAR_AGO = "Thu Dec 14 2022 00:50:25 GMT+0900 (한국 표준시)"; it("3일 전이 입력되었을때 '3일 전' 이 출력되는지", () => { @@ -14,13 +14,13 @@ describe("인스타그램 스타일 시간 포매팅 함수", () => { it("8일 전이 입력되었을때 '1주 전' 이 출력되는지", () => { expect(formatTime(EIGHT_DAYS_AGO, MOCK_NOW)).toEqual("1주 전"); }); - it("1달전 이 입력되었을때 '1달 전'이 출력되는지 Trim 하는지 여부", () => { + it("1달전 이 입력되었을때 '1달 전'이 출력되는지 여부", () => { expect(formatTime(ONE_MONTH_AGO, MOCK_NOW)).toEqual("1달 전"); }); - it("3달전 이 입력되었을때 '3달 전'이 출력되는지 Trim 하는지 여부", () => { + it("3달전 이 입력되었을때 '3달 전'이 출력되는지 여부", () => { expect(formatTime(THREE_MONTH_AGO, MOCK_NOW)).toEqual("3달 전"); }); - it("1년전 이 입력되었을때 '1년 전'이 출력되는지 Trim 하는지 여부", () => { + it("1년전 이 입력되었을때 '1년 전'이 출력되는지 여부", () => { expect(formatTime(ONE_YEAR_AGO, MOCK_NOW)).toEqual("1년 전"); }); }); diff --git a/client/src/utils/formatTime.ts b/client/src/utils/formatTime.ts index 8cce193..cc616de 100644 --- a/client/src/utils/formatTime.ts +++ b/client/src/utils/formatTime.ts @@ -25,16 +25,17 @@ const formatTime = (timestamp: string, now?: string) => { currentTime.diff(postTime, "day") >= 7 && currentTime.diff(postTime, "month") < 1 ) { - return `${currentTime.diff(postTime, "week")}주 전`; + return `${Math.floor(currentTime.diff(postTime, "week"))}주 전`; } - + + // 1달 전을 한 달 전 이 아닌 1달 전 으로 표기 + if (currentTime.diff(postTime, "month") === 1) { + return "1달 전"; + } + // 1년전을 일 년 전 이 아닌 1년 전 으로 표기 if (currentTime.diff(postTime, "year") === 1) { - return `${currentTime.diff(postTime, "year")}년 전`; - } - // 1년 전을 일 년 전 이 아닌 1년 전 으로 표기 - if (currentTime.diff(postTime, "month") === 1) { - return `${currentTime.diff(postTime, "month")}달 전`; + return "1년 전"; } // 그 외의 경우에는 상대적인 시간 표시 From cae509397312d0b1bed887a5f172a7dab0e88eb4 Mon Sep 17 00:00:00 2001 From: Jungu Lee <1zzangjun@gmail.com> Date: Sun, 7 Jan 2024 02:56:06 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Minor=20:=20=EC=8A=A4=ED=83=80=EC=9D=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD,=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../assets/icons/Alcohol/AllAlcoholIcon.svg | 9 +++++ .../src/components/layout/CustomContainer.tsx | 8 +--- client/src/components/post/PostCard.tsx | 8 +++- client/src/components/wiki/AlcoholNameTag.tsx | 1 + .../components/wiki/WikiAlcoholSelector.tsx | 2 + .../wiki/WikiAlcoholSelectorBtn.tsx | 37 ++++++++++--------- client/src/hooks/wiki/usePushToWikiDetail.ts | 8 +++- 7 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 client/src/assets/icons/Alcohol/AllAlcoholIcon.svg diff --git a/client/src/assets/icons/Alcohol/AllAlcoholIcon.svg b/client/src/assets/icons/Alcohol/AllAlcoholIcon.svg new file mode 100644 index 0000000..7c0834e --- /dev/null +++ b/client/src/assets/icons/Alcohol/AllAlcoholIcon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/client/src/components/layout/CustomContainer.tsx b/client/src/components/layout/CustomContainer.tsx index 7c3d63b..8c18ee3 100644 --- a/client/src/components/layout/CustomContainer.tsx +++ b/client/src/components/layout/CustomContainer.tsx @@ -5,14 +5,10 @@ interface CustomContainerInterface extends ContainerProps { mt?: number; } -const CustomContainer = ({ - sx, - mt, - children, -}: CustomContainerInterface) => { +const CustomContainer = ({ sx, mt, children }: CustomContainerInterface) => { return ( fireToast); const copyToClipboardHander = async () => { @@ -134,6 +137,9 @@ const PostCard = ({ alcoholNo={alcoholNo} alcoholName={alcoholName} alcoholType={alcoholType} + onClick={() => { + onClickElementHandler({ alcoholName, alcoholNo }); + }} /> )} @@ -143,7 +149,7 @@ const PostCard = ({ dangerouslySetInnerHTML={{ __html: sanitize(postContent), }} - onClick={() => openPostDetailPage(id, String(postNo))} + onClick={() => openPostDetailPage(id, String(postNo))} > {/* Hash tags */} diff --git a/client/src/components/wiki/AlcoholNameTag.tsx b/client/src/components/wiki/AlcoholNameTag.tsx index 54a6815..0452af2 100644 --- a/client/src/components/wiki/AlcoholNameTag.tsx +++ b/client/src/components/wiki/AlcoholNameTag.tsx @@ -61,6 +61,7 @@ const WrapperStyle = { border: "1px solid", borderColor: "gray.secondary", backgroundColor: "gray.primary", + cursor: "pointer", display: "flex", flexDirection: "row", alignItems: "center", diff --git a/client/src/components/wiki/WikiAlcoholSelector.tsx b/client/src/components/wiki/WikiAlcoholSelector.tsx index 79aa30a..dfff919 100644 --- a/client/src/components/wiki/WikiAlcoholSelector.tsx +++ b/client/src/components/wiki/WikiAlcoholSelector.tsx @@ -3,6 +3,7 @@ import { useState, useCallback, useMemo } from "react"; import { Stack } from "@mui/material"; import WikiAlcoholSelectorBtn from "./WikiAlcoholSelectorBtn"; import WineIcon from "@/assets/icons/Alcohol/WineIcon.svg"; +import AllAlcoholIcon from "@/assets/icons/Alcohol/AllAlcoholIcon.svg"; import WiskyIcon from "@/assets/icons/Alcohol/WiskyIcon.svg"; import SpiritsIcon from "@/assets/icons/Alcohol/SpiritsIcon.svg"; import TraditionalAlcoholIcon from "@/assets/icons/Alcohol/TraditionalAlcoholIcon.svg"; @@ -11,6 +12,7 @@ import SakeIcon from "@/assets/icons/Alcohol/SakeIcon.svg"; const WikiAlcoholSelector = () => { const btnList = useMemo( () => [ + { title: "전체", iconComponent: }, { title: "포도주", iconComponent: }, { title: "위스키", iconComponent: }, { title: "증류주", iconComponent: }, diff --git a/client/src/components/wiki/WikiAlcoholSelectorBtn.tsx b/client/src/components/wiki/WikiAlcoholSelectorBtn.tsx index 458d589..750e775 100644 --- a/client/src/components/wiki/WikiAlcoholSelectorBtn.tsx +++ b/client/src/components/wiki/WikiAlcoholSelectorBtn.tsx @@ -16,24 +16,27 @@ const WikiAlcoholSelectorBtn = ({ ...buttonBaseProps }: WiciAlcoholSelectorBtnProps) => { return ( - - - - {iconComponent} - - {title} + + + {iconComponent} - + {title} + ); }; diff --git a/client/src/hooks/wiki/usePushToWikiDetail.ts b/client/src/hooks/wiki/usePushToWikiDetail.ts index 9880f16..6e9e803 100644 --- a/client/src/hooks/wiki/usePushToWikiDetail.ts +++ b/client/src/hooks/wiki/usePushToWikiDetail.ts @@ -4,6 +4,12 @@ import { useCallback } from "react"; import useSearchHistory from "../searchHistory/useSearchHistory"; import { ALCOHOL_SEARCH_HISTORY } from "@/const/localstorageKey"; import { WIKI_DETAIL } from "@/const/clientPath"; + +interface OnclickElementHandlerInterface { + alcoholName: AlcoholDetailInterface["alcoholName"]; + alcoholNo: AlcoholDetailInterface["alcoholNo"]; +} + /** * 검색히스토리에 해당 술을 남기고, 디테일페이지로 이동시키는 함수를 리턴하는 훅 * @returns 해당 callback함수 @@ -15,7 +21,7 @@ const usePushToWikiDetail = () => { * 검색히스토리에 해당 술을 남기고, 디테일페이지로 이동시키는 함수를 리턴하는 함수 */ const onClickElementHandler = useCallback( - ({ alcoholName, alcoholNo }: AlcoholDetailInterface) => { + ({ alcoholName, alcoholNo }: OnclickElementHandlerInterface) => { addToSearchHistory(alcoholName); router.push(WIKI_DETAIL(String(alcoholNo))); }, From 20ecd826453add72e60b094a1a9005f7fc0b7835 Mon Sep 17 00:00:00 2001 From: Jungu Lee <1zzangjun@gmail.com> Date: Sun, 7 Jan 2024 03:18:00 +0900 Subject: [PATCH 3/3] =?UTF-8?q?Refactor=20:=20=EC=88=A0=EB=B0=B1=EA=B3=BC?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/newpost/SearchAlcoholInput.tsx | 4 +- client/src/components/wiki/AlcoholList.tsx | 7 +- .../src/components/wiki/AlcoholPagination.tsx | 68 +++++++++++++++++-- .../wiki/searchDrawer/WikiSerachArea.tsx | 4 +- .../alcohol/useGetAlcoholListQuery.tsx | 36 +++++++--- 5 files changed, 99 insertions(+), 20 deletions(-) diff --git a/client/src/components/newpost/SearchAlcoholInput.tsx b/client/src/components/newpost/SearchAlcoholInput.tsx index f2dc595..4f8f5b4 100644 --- a/client/src/components/newpost/SearchAlcoholInput.tsx +++ b/client/src/components/newpost/SearchAlcoholInput.tsx @@ -37,7 +37,9 @@ const SearchAlcoholInput = ({ const [isSearchingAlcohol, setIsSearchingAlCohol] = useState(false); // 검색결과 - const { data, isLoading, isSuccess } = useGetAlcoholListQuery(debouncedValue); + const { data, isLoading, isSuccess } = useGetAlcoholListQuery({ + searchKeyword: debouncedValue, + }); // 유저가 검색후 최종적으로 선택한 값 const [selectedAlcohol, setSelectedAlcohol] = useState< | Pick diff --git a/client/src/components/wiki/AlcoholList.tsx b/client/src/components/wiki/AlcoholList.tsx index 4a54333..1ef8b51 100644 --- a/client/src/components/wiki/AlcoholList.tsx +++ b/client/src/components/wiki/AlcoholList.tsx @@ -5,16 +5,17 @@ import { Typography } from "@mui/material"; import { memo } from "react"; import AlcoholListSkeleton from "./AlcoholListSkeleton"; -interface AlcoholList { +interface AlcoholListInterface { data?: AlcoholDetailInterface[]; onClickElement?: (data: AlcoholDetailInterface) => void; + size?:number } /** * 술 정보 Array 를 입력받아 List로 맵핑해주는 컴포넌트 * onClickElement 속성으로 각 엘리먼트 클릭 시 속성을 지정가능 * @returns */ -const AlcoholList = ({ data: alcohols, onClickElement }: AlcoholList) => { +const AlcoholList = ({ data: alcohols, onClickElement,size=5 }: AlcoholListInterface) => { return alcohols ? ( <> {alcohols.length > 0 ? ( @@ -37,7 +38,7 @@ const AlcoholList = ({ data: alcohols, onClickElement }: AlcoholList) => { )} ) : ( - + ); }; export default memo(AlcoholList); diff --git a/client/src/components/wiki/AlcoholPagination.tsx b/client/src/components/wiki/AlcoholPagination.tsx index 885a65b..1ae2eb8 100644 --- a/client/src/components/wiki/AlcoholPagination.tsx +++ b/client/src/components/wiki/AlcoholPagination.tsx @@ -1,21 +1,79 @@ "use client"; -import useGetAlcoholListQuery from "@/queries/alcohol/useGetAlcoholListQuery"; +import useGetAlcoholListQuery, { + AlcohilListQueryKey, + getAlcoholListByKeyword, +} from "@/queries/alcohol/useGetAlcoholListQuery"; import AlcoholList from "@/components/wiki/AlcoholList"; import { Pagination, Stack } from "@mui/material"; import usePushToWikiDetail from "@/hooks/wiki/usePushToWikiDetail"; +import { useEffect, useState } from "react"; +import { useQueryClient } from "@tanstack/react-query"; const AlcoholPagenation = () => { - const { data: alcohols } = useGetAlcoholListQuery(""); + const [currentPage, setCurrentPage] = useState(1); + const size = 10; + + const { data: alcohols } = useGetAlcoholListQuery({ + searchKeyword: "", + page: currentPage - 1, + size, + }); + + const [totalCount, setTotalCount] = useState(alcohols?.totalCount); + + useEffect(() => { + const isSameWithPreviousValue = + totalCount === alcohols?.totalCount || alcohols?.totalCount === undefined; + + if (isSameWithPreviousValue) return; + setTotalCount(alcohols?.totalCount); + }, [alcohols]); + + const queryClient = useQueryClient(); + + useEffect(() => { + const handler = async () => { + const nextPageParams = { + searchKeyword: "", + size, + page: currentPage + 1, + }; + + const fetchedNextPage = queryClient.getQueryData( + AlcohilListQueryKey.byKeyword(nextPageParams) + ); + + if (fetchedNextPage) return; + const nextPage = await getAlcoholListByKeyword(nextPageParams); + + queryClient.setQueryData( + AlcohilListQueryKey.byKeyword(nextPageParams), + nextPage + ); + }; + + handler(); + }, [currentPage]); + const onClickElementHandler = usePushToWikiDetail(); + return ( - + + onClickElementHandler({ alcoholName, alcoholNo }) + } /> - + setCurrentPage(page)} + /> ); }; diff --git a/client/src/components/wiki/searchDrawer/WikiSerachArea.tsx b/client/src/components/wiki/searchDrawer/WikiSerachArea.tsx index a34e85a..1cfd7ef 100644 --- a/client/src/components/wiki/searchDrawer/WikiSerachArea.tsx +++ b/client/src/components/wiki/searchDrawer/WikiSerachArea.tsx @@ -14,7 +14,9 @@ const WikiSerachArea = () => { const [searchKeyword, setSearchKeyword] = useState(""); const debouncedValue = useDebounce(searchKeyword, 300); - const { data: alcohols } = useGetAlcoholListQuery(debouncedValue); + const { data: alcohols } = useGetAlcoholListQuery({ + searchKeyword: debouncedValue, + }); const onClickElementHandler = usePushToWikiDetail(); diff --git a/client/src/queries/alcohol/useGetAlcoholListQuery.tsx b/client/src/queries/alcohol/useGetAlcoholListQuery.tsx index d5d8a94..f6a4d25 100644 --- a/client/src/queries/alcohol/useGetAlcoholListQuery.tsx +++ b/client/src/queries/alcohol/useGetAlcoholListQuery.tsx @@ -3,31 +3,47 @@ import axios from "@/libs/axios"; import { AlcoholDetailInterface } from "@/types/alcohol/AlcoholInterface"; import { useQuery } from "@tanstack/react-query"; -const useGetAlcoholListQuery = (keyword?: string) => { +export interface useGetAlcoholListQueryInterface { + page?: number; + size?: number; + searchKeyword?: string; +} + +const useGetAlcoholListQuery = ({ + searchKeyword = "", + size = 5, + page = 0, +}: useGetAlcoholListQueryInterface) => { return useQuery({ - queryKey: AlcohilListQueryKey.byKeyword(keyword), - queryFn: async () => await getAlcoholListByKeyword(keyword), - enabled: keyword!=undefined, + queryKey: AlcohilListQueryKey.byKeyword({ page, size, searchKeyword }), + queryFn: async () => + await getAlcoholListByKeyword({ searchKeyword, size, page }), + enabled: searchKeyword != undefined, }); }; -export const getAlcoholListByKeyword = async (keyword?: string) => { +export const getAlcoholListByKeyword = async ({ + searchKeyword, + size, + page, +}: useGetAlcoholListQueryInterface) => { const { data } = await axios.get<{ list: AlcoholDetailInterface[]; totalCount: number; }>(GET_ALCOHOL_LIST, { params: { - page: 0, - size: 5, - searchKeyword: keyword, + page, + size, + searchKeyword, }, - }); + }); return data; }; export const AlcohilListQueryKey = { all: ["alcohol"] as const, - byKeyword: (keyword?: string) => ["alcohol", { keyword }] as const, + byKeyword: ({ searchKeyword, size, page }: useGetAlcoholListQueryInterface) => + ["alcohol", { searchKeyword, size, page }] as const, }; export default useGetAlcoholListQuery;