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;