From de5b272080e9ab4f5e53cb323f68b9322292039d Mon Sep 17 00:00:00 2001 From: Jungu Lee <100949102+jobkaeHenry@users.noreply.github.com> Date: Thu, 14 Dec 2023 01:23:03 +0900 Subject: [PATCH] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80-=EC=9E=91=EC=84=B1?= =?UTF-8?q?=EC=8B=9C=EA=B0=84-=ED=91=9C=EC=8B=9C-=EB=B3=80=EA=B2=BD=20(#86?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * New : 시간 포맷 스펙 작성 * New : 시간 포맷함수 구현 * Refactor : 인터페이스 변경 * Refactor : 변경된 시간 표기 적용 * Minor : 사용하지 않는 모듈 제거 * Refactor : 해시태그리스트 중복제거 로직 추가, wrap 속성 추가 --- client/src/__test__/post/formatTime.test.ts | 26 +++++++++++++ client/src/components/post/PostCard.tsx | 14 ++----- .../src/components/post/PostHashtagList.tsx | 25 ++++++------- client/src/types/post/PostInterface.ts | 2 +- client/src/utils/formatTime.ts | 37 +++++++++++++++++++ 5 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 client/src/__test__/post/formatTime.test.ts create mode 100644 client/src/utils/formatTime.ts diff --git a/client/src/__test__/post/formatTime.test.ts b/client/src/__test__/post/formatTime.test.ts new file mode 100644 index 0000000..fdbdfb6 --- /dev/null +++ b/client/src/__test__/post/formatTime.test.ts @@ -0,0 +1,26 @@ +import formatTime from "@/utils/formatTime"; + +describe("인스타그램 스타일 시간 포매팅 함수", () => { + const MOCK_NOW = "Thu Dec 14 2023 00:50:25 GMT+0900 (한국 표준시)"; + 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 ONE_YEAR_AGO = "Thu Dec 14 2022 00:50:25 GMT+0900 (한국 표준시)"; + + it("3일 전이 입력되었을때 '3일 전' 이 출력되는지", () => { + expect(formatTime(THREE_DAYS_AGO, MOCK_NOW)).toEqual("3일 전"); + }); + it("8일 전이 입력되었을때 '1주 전' 이 출력되는지", () => { + expect(formatTime(EIGHT_DAYS_AGO, MOCK_NOW)).toEqual("1주 전"); + }); + it("1달전 이 입력되었을때 '1달 전'이 출력되는지 Trim 하는지 여부", () => { + expect(formatTime(ONE_MONTH_AGO, MOCK_NOW)).toEqual("1달 전"); + }); + it("3달전 이 입력되었을때 '3달 전'이 출력되는지 Trim 하는지 여부", () => { + expect(formatTime(THREE_MONTH_AGO, MOCK_NOW)).toEqual("3달 전"); + }); + it("1년전 이 입력되었을때 '1년 전'이 출력되는지 Trim 하는지 여부", () => { + expect(formatTime(ONE_YEAR_AGO, MOCK_NOW)).toEqual("1년 전"); + }); +}); diff --git a/client/src/components/post/PostCard.tsx b/client/src/components/post/PostCard.tsx index d419b21..667f1a9 100644 --- a/client/src/components/post/PostCard.tsx +++ b/client/src/components/post/PostCard.tsx @@ -19,20 +19,18 @@ import ShareIcon from "@/assets/icons/ShareIcon.svg"; import LikeIcon from "@/assets/icons/LikeIcon.svg"; import CommentIcon from "@/assets/icons/CommentIcon.svg"; import AlcoholNameTag from "@/components/wiki/AlcoholNameTag"; -import dayjs from "dayjs"; import useLikePostMutation from "@/queries/post/useLikePostMutation"; import useUnLikePostMutation from "@/queries/post/useUnLikePostMutation"; import "../newpost/quill.mention.css"; import { sanitize } from "isomorphic-dompurify"; import UserAvatar from "../user/info/UserAvatar"; import Link from "next/link"; -import HOME, { USER_PAGE } from "@/const/clientPath"; +import { USER_PAGE } from "@/const/clientPath"; import { useMyInfoQuery } from "@/queries/auth/useMyInfoQuery"; import PostCardOptionDropdown from "./PostCardOptionDropdown"; import { postcardContext } from "@/store/post/PostCardContext"; -import { useDeletePostMutation } from "@/queries/post/useDeletePostMutation"; -import useDeleteAttachMutation from "@/queries/attach/useDeleteAttachMutation"; import { useRouter } from "next/navigation"; +import formatTime from "@/utils/formatTime"; const PostCard = ({ postAttachUrls, @@ -52,7 +50,6 @@ const PostCard = ({ alcoholNo, }: PostInterface) => { const openPostDetailPage = useOpenPostDetailPage(); - const router = useRouter(); const hasImage = useMemo(() => postAttachUrls.length !== 0, [postAttachUrls]); @@ -61,9 +58,6 @@ const PostCard = ({ const { mutate: likeHandler } = useLikePostMutation(searchContext); const { mutate: unLikeHandler } = useUnLikePostMutation(searchContext); - const { mutateAsync: deletePost } = useDeletePostMutation(); - const { mutateAsync: deleteFile } = useDeleteAttachMutation(); - const { data: currentUser } = useMyInfoQuery(); const isMyPost = useMemo( @@ -106,7 +100,7 @@ const PostCard = ({ >{`@${id}`} - {dayjs(lastModifiedDate).format("MM.DD")} + {formatTime(lastModifiedDate)} @@ -149,7 +143,7 @@ const PostCard = ({ borderRadius: 2, bgcolor: "background.default", cursor: "pointer", - aspectRatio: 2.36 + aspectRatio: 2.36, }} /> )} diff --git a/client/src/components/post/PostHashtagList.tsx b/client/src/components/post/PostHashtagList.tsx index f9ed4cb..4bee58c 100644 --- a/client/src/components/post/PostHashtagList.tsx +++ b/client/src/components/post/PostHashtagList.tsx @@ -1,26 +1,25 @@ import { SEARCH_BY_KEYWORD } from "@/const/clientPath"; import { PostInterface } from "@/types/post/PostInterface"; -import { Box, BoxProps, Typography } from "@mui/material"; +import { Stack, StackProps, Typography } from "@mui/material"; import Link from "next/link"; -interface TagListInterface extends BoxProps { - tags: PostInterface['tagList']; +interface TagListInterface extends StackProps { + tags: PostInterface["tagList"]; } const PostHashTagList = ({ tags, ...others }: TagListInterface) => { + const uniqueSet = Array.from(new Set(tags)); return ( <> - {tags?.length > 0 && ( - 0 && ( + - {tags.map((tag,i) => ( + {uniqueSet.map((tag, i) => ( { ))} - + )} ); diff --git a/client/src/types/post/PostInterface.ts b/client/src/types/post/PostInterface.ts index ae1e9c3..14c48b6 100644 --- a/client/src/types/post/PostInterface.ts +++ b/client/src/types/post/PostInterface.ts @@ -11,7 +11,7 @@ export interface PostInterface { /** * 업데이트 된 날짜 */ - lastModifiedDate?: string; + lastModifiedDate: string; /** * 해당 게시글을 생성한유저PK */ diff --git a/client/src/utils/formatTime.ts b/client/src/utils/formatTime.ts new file mode 100644 index 0000000..c69b962 --- /dev/null +++ b/client/src/utils/formatTime.ts @@ -0,0 +1,37 @@ +import dayjs from "dayjs"; +import "dayjs/locale/ko"; +import relativeTime from "dayjs/plugin/relativeTime"; + +// 상대적인 시간을 표시하기 위해 플러그인 추가 +dayjs.extend(relativeTime); +dayjs.locale("ko"); // 로캘을 한국어로 설정 + +/** + * Instagram 스타일의 작성 시간 포맷 함수 + */ +const formatTime = (timestamp: string, now?: string) => { + const postTime = dayjs(timestamp); + const currentTime = dayjs(now || new Date()); + + // 1주 ~ 1달 까지는 n주 전 으로 표기 + if ( + currentTime.diff(postTime, "day") >= 7 && + currentTime.diff(postTime, "month") < 1 + ) { + return `${currentTime.diff(postTime, "week")}주 전`; + } + + // 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 postTime.fromNow(); +}; + +export default formatTime;