From 641f6dbd09fdd3343c3c7c09732cd3b3b5930e68 Mon Sep 17 00:00:00 2001 From: "Eunsu(Evan) Kim" Date: Thu, 30 Nov 2023 22:24:00 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AA=A8=EC=9E=84=20=ED=94=BC=EB=93=9C=20?= =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=8B=A0=EA=B3=A0=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#589)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * style: edit ActionButton style * feat: remove isMine props on FeedPostViewer * feat: add conditionally composing Actions and integrate report API * chore: add 'info' to ToastType * feat: add toast after report a post --- pages/post/index.tsx | 86 +++++++++++++------ .../FeedActionButton/FeedActionButton.tsx | 4 + .../feed/FeedPostViewer/FeedPostViewer.tsx | 24 +++--- src/hooks/useToast/Toast.tsx | 2 +- 4 files changed, 77 insertions(+), 39 deletions(-) diff --git a/pages/post/index.tsx b/pages/post/index.tsx index 1b1522ab..9a03dd8c 100644 --- a/pages/post/index.tsx +++ b/pages/post/index.tsx @@ -1,6 +1,7 @@ import FeedPostViewer from '@components/feed/FeedPostViewer/FeedPostViewer'; import Loader from '@components/loader/Loader'; import { useRouter } from 'next/router'; +import useToast from '@hooks/useToast'; import { useMutation } from '@tanstack/react-query'; import { apiV2 } from '@api/index'; import FeedCommentInput from '@components/feed/FeedCommentInput/FeedCommentInput'; @@ -24,6 +25,7 @@ import { useDisplay } from '@hooks/useDisplay'; export default function PostPage() { const overlay = useOverlay(); + const showToast = useToast(); const router = useRouter(); const { isMobile } = useDisplay(); const query = router.query; @@ -64,6 +66,22 @@ export default function PostPage() { onSuccess: () => router.replace(`/detail?id=${post?.meeting.id}`), }); + const { mutateAsync: mutateReportPost } = useMutation({ + mutationFn: (postId: number) => POST('/post/v1/{postId}/report', { params: { path: { postId } } }), + }); + const handleConfirmReportPost = + ({ postId, callback }: { postId: number; callback: () => void }) => + async () => { + const { error } = await mutateReportPost(postId); + if (error) { + showToast({ type: 'error', message: error.message }); + callback(); + return; + } + showToast({ type: 'info', message: '게시글을 신고했습니다' }); + callback(); + }; + const post = postQuery.data; const { data: meeting } = useQueryGetMeeting({ params: { id: String(post?.meeting.id) } }); @@ -84,35 +102,55 @@ export default function PostPage() { // TODO: loading 스켈레톤 UI가 있으면 좋을 듯 if (!post) return ; + const isMine = post.user.id === me?.id; + return ( - overlay.open(({ isOpen, close }) => ( - - )) - } - > - 수정 - , - { - overlay.open(({ isOpen, close }) => ( - // eslint-disable-next-line prettier/prettier + // TODO: Actions 합성하는 부분 추상화 한번 더 하자. 너무 verbose 하다. + Actions={ + isMine + ? [ + + overlay.open(({ isOpen, close }) => ( + + )) + } + > + 수정 + , + { + overlay.open(({ isOpen, close }) => ( + // eslint-disable-next-line prettier/prettier - )); - }} - > - 삭제 - , - ]} + handleModalClose={close} + handleConfirm={mutateDeletePost} + /> + )); + }} + > + 삭제 + , + ] + : [ + { + overlay.open(({ isOpen, close }) => ( + // eslint-disable-next-line prettier/prettier + + )); + }} + > + 신고 + , + ] + } CommentLikeSection={ {fromNow(post.updatedDate)} - {isMine && ( - - - - - - {Actions.map((Action, index) => ( - {Action} - ))} - - - )} + + + + + + {Actions.map((Action, index) => ( + {Action} + ))} + + {post.title} diff --git a/src/hooks/useToast/Toast.tsx b/src/hooks/useToast/Toast.tsx index d620abd9..5e5f21bc 100644 --- a/src/hooks/useToast/Toast.tsx +++ b/src/hooks/useToast/Toast.tsx @@ -2,7 +2,7 @@ import { useEffect } from 'react'; import { styled } from 'stitches.config'; import CautionIcon from '@assets/svg/caution.svg'; -type ToastType = 'error'; +type ToastType = 'error' | 'info'; export interface ToastProps { isOpen: boolean;