From fadf6ded3093ee7619e8e82dd2929864a2fc1ab4 Mon Sep 17 00:00:00 2001 From: Jungu Lee <100949102+jobkaeHenry@users.noreply.github.com> Date: Tue, 7 Nov 2023 04:28:35 +0900 Subject: [PATCH] =?UTF-8?q?=ED=8F=AC=EC=8A=A4=ED=8A=B8-=EB=94=94=ED=85=8C?= =?UTF-8?q?=EC=9D=BC-=ED=8E=98=EC=9D=B4=EC=A7=80-=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=EC=85=89=ED=8A=B8=EB=9D=BC=EC=9A=B0=ED=8A=B8=EA=B5=AC=ED=98=84?= =?UTF-8?q?=20(#12)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * New : 포스트 디테일 페이지 인터셉트 라우트 구현 * New : 포스트 디테일 페이지 인터셉트 라우트 구현 * New : 포스트 디테일 URL 함수로 관리 * Minor : 해시태그 모킹 추가 * Minor : Fixme 추가 --- client/src/__test__/post/PostCard.test.tsx | 1 + .../@Modal/(.)post/[userId]/[postId]/page.tsx | 24 +++ client/src/app/@Modal/default.tsx | 5 + client/src/app/layout.tsx | 3 + .../src/app/post/[userId]/[postId]/page.tsx | 21 ++- client/src/components/ModalWrapper.tsx | 50 ++++++ client/src/components/post/PostCard.tsx | 156 +++++++++--------- client/src/components/post/PostDetail.tsx | 15 ++ client/src/utils/createPostDetailPath.test.ts | 10 ++ client/src/utils/createPostDetailPath.ts | 14 ++ 10 files changed, 222 insertions(+), 77 deletions(-) create mode 100644 client/src/app/@Modal/(.)post/[userId]/[postId]/page.tsx create mode 100644 client/src/app/@Modal/default.tsx create mode 100644 client/src/components/ModalWrapper.tsx create mode 100644 client/src/components/post/PostDetail.tsx create mode 100644 client/src/utils/createPostDetailPath.test.ts create mode 100644 client/src/utils/createPostDetailPath.ts diff --git a/client/src/__test__/post/PostCard.test.tsx b/client/src/__test__/post/PostCard.test.tsx index 413bcea..df38304 100644 --- a/client/src/__test__/post/PostCard.test.tsx +++ b/client/src/__test__/post/PostCard.test.tsx @@ -11,6 +11,7 @@ const mockData = { content: "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.", image: ["https://source.unsplash.com/random?wallpapers"], + tags: [], }; describe("버튼 컴포넌트 스펙", () => { diff --git a/client/src/app/@Modal/(.)post/[userId]/[postId]/page.tsx b/client/src/app/@Modal/(.)post/[userId]/[postId]/page.tsx new file mode 100644 index 0000000..9bb2c25 --- /dev/null +++ b/client/src/app/@Modal/(.)post/[userId]/[postId]/page.tsx @@ -0,0 +1,24 @@ +import ModalWrapper from "@/components/ModalWrapper"; +import PostDetail from "@/components/post/PostDetail"; + +const mockData = { + id: "123458", + createdAt: "Mon Nov 06 2023 00:13:07", + nickname: "testNick", + userId: "userID", + userImage: "https://source.unsplash.com/random?wallpapers", + content: + "Lorem ipsum dolor, sit amet consectetur adipisicing elit. Eos ullam aut minus aliquam quis officia, non dolore omnis, magnam totam tenetur ad harum? Mollitia omnis odit atque blanditiis exercitationem! Voluptatum.", + image: ["https://source.unsplash.com/random?wallpapers"], + tags: ["해시태그1", "해시태그2"], +}; + +const page = () => { + return ( + + + + ); +}; + +export default page; diff --git a/client/src/app/@Modal/default.tsx b/client/src/app/@Modal/default.tsx new file mode 100644 index 0000000..395785b --- /dev/null +++ b/client/src/app/@Modal/default.tsx @@ -0,0 +1,5 @@ +const Default = () => { + return null; +}; + +export default Default; diff --git a/client/src/app/layout.tsx b/client/src/app/layout.tsx index 8e1f6ea..b445a08 100644 --- a/client/src/app/layout.tsx +++ b/client/src/app/layout.tsx @@ -17,13 +17,16 @@ export const viewport: Viewport = { export default function RootLayout({ children, + Modal, }: { children: React.ReactNode; + Modal: React.ReactNode; }) { return ( + {Modal} { + // FIXME @로 시작되는 경우만 슬라이스 하도록 추후에 고치고, 함수화 해야함 const parsedUserId = params.userId.slice(1, params.userId.length); - const parsedPostId = params.postId.slice(1, params.postId.length); + const parsedPostId = params.postId; return (
userId:{parsedUserId} -
postId:{parsedPostId} + postId:{parsedPostId} +
+
); }; diff --git a/client/src/components/ModalWrapper.tsx b/client/src/components/ModalWrapper.tsx new file mode 100644 index 0000000..3e82ab1 --- /dev/null +++ b/client/src/components/ModalWrapper.tsx @@ -0,0 +1,50 @@ +"use client"; +import { Box, Modal, ModalProps } from "@mui/material"; +import { useRouter } from "next/navigation"; + +import { ReactNode } from "react"; + +interface ModalInterface + extends Omit { + children?: ReactNode; + /** + * 기본으로 설정된 의 패딩, 배경색 속성을 제거 + */ + disableBox?: boolean; +} + +/** + * MUI 를 랩핑해놓은 글로벌 모달 + */ +const ModalWrapper = ({ children, disableBox }: ModalInterface) => { + const { back } = useRouter(); + + return ( + back()} + disablePortal + sx={{ + alignItems: "center", + justifyContent: "center", + display: "flex", + }} + > + { + + {children} + + } + + ); +}; + +export default ModalWrapper; diff --git a/client/src/components/post/PostCard.tsx b/client/src/components/post/PostCard.tsx index 16a5f15..c943acd 100644 --- a/client/src/components/post/PostCard.tsx +++ b/client/src/components/post/PostCard.tsx @@ -1,5 +1,6 @@ "use client"; import { PostInterface } from "@/types/post/PostInterface"; +import createPostDetailPath from "@/utils/createPostDetailPath"; import { MoreVertOutlined } from "@mui/icons-material"; import { Avatar, @@ -11,6 +12,7 @@ import { Typography, ButtonBase, } from "@mui/material"; +import Link from "next/link"; const PostCard = ({ image, @@ -20,98 +22,102 @@ const PostCard = ({ content, userImage, tags, + id, }: PostInterface) => { return ( - - - {userImage || userId[0].toUpperCase()} - - - {/* Header */} - + + + {userImage || userId[0].toUpperCase()} + + + {/* Header */} - {nickname} - {`@${userId}`} - {createdAt} - - - - - - - - {/* Contents */} - - {content} - {/* Hash tags */} - {tags?.length > 0 && ( - {tags.map((tag, i) => ( - - {`#${tag}`} - - ))} + {nickname} + {`@${userId}`} + {createdAt} + + + + + + + {/* Contents */} + + {content} + {/* Hash tags */} + {tags?.length > 0 && ( + + {tags.map((tag, i) => ( + + {`#${tag}`} + + ))} + + )} + + {/* image */} + {image.length !== 0 && ( + )} - - {/* image */} - {image.length !== 0 && ( - - )} - {/* CTA */} - - - 댓글 - - - 좋아요 - - - 공유하기 - - - - + {/* CTA */} + + + 댓글 + + + 좋아요 + + + 공유하기 + + + + + ); }; diff --git a/client/src/components/post/PostDetail.tsx b/client/src/components/post/PostDetail.tsx new file mode 100644 index 0000000..87a9ae5 --- /dev/null +++ b/client/src/components/post/PostDetail.tsx @@ -0,0 +1,15 @@ +import { PostInterface } from "@/types/post/PostInterface"; + +const PostDetail = ({ + image, + createdAt, + userId, + nickname, + content, + userImage, + tags, + id, +}: PostInterface) => { + return <>{userId}; +}; +export default PostDetail; diff --git a/client/src/utils/createPostDetailPath.test.ts b/client/src/utils/createPostDetailPath.test.ts new file mode 100644 index 0000000..6cc24c5 --- /dev/null +++ b/client/src/utils/createPostDetailPath.test.ts @@ -0,0 +1,10 @@ +import createPostDetailPath from "@/utils/createPostDetailPath"; + +describe("createPostDetailPath 함수 테스트", () => { + it("postId=1 userId=thisUser 가 입력되었을 때 ", () => { + expect(createPostDetailPath("thisUser", "1")).toEqual("/@thisUser/1"); + }); + it("공백을 자동으로 Trim 하는지 여부", () => { + expect(createPostDetailPath(" thisUser", "1 ")).toEqual("/@thisUser/1"); + }); +}); diff --git a/client/src/utils/createPostDetailPath.ts b/client/src/utils/createPostDetailPath.ts new file mode 100644 index 0000000..508263b --- /dev/null +++ b/client/src/utils/createPostDetailPath.ts @@ -0,0 +1,14 @@ +/** + * 유저아이디와 게시글 아이디를 입력받아 /@userId/postId 형태의 String을 리턴 + * @param userId 유저ID + * @param postId 게시글ID + * @returns + */ +const createPostUrl = (userId: string, postId: string) => { + const trimmedUserId = userId.trim(); + const trimmedPostId = postId.trim(); + + return `/@${trimmedUserId}/${trimmedPostId}`; +}; + +export default createPostUrl;