Skip to content

Commit

Permalink
모임 피드 게시글 신고하기 기능 추가 (#589)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
eunsukimme authored Nov 30, 2023
1 parent c54e887 commit 641f6db
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 39 deletions.
86 changes: 62 additions & 24 deletions pages/post/index.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand Down Expand Up @@ -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) } });

Expand All @@ -84,35 +102,55 @@ export default function PostPage() {
// TODO: loading 스켈레톤 UI가 있으면 좋을 듯
if (!post) return <Loader />;

const isMine = post.user.id === me?.id;

return (
<Container>
<FeedPostViewer
post={post}
isMine={post.user.id === me?.id}
Actions={[
<FeedActionButton
onClick={() =>
overlay.open(({ isOpen, close }) => (
<FeedEditModal isModalOpened={isOpen} postId={String(post.id)} handleModalClose={close} />
))
}
>
수정
</FeedActionButton>,
<FeedActionButton
onClick={() => {
overlay.open(({ isOpen, close }) => (
// eslint-disable-next-line prettier/prettier
// TODO: Actions 합성하는 부분 추상화 한번 더 하자. 너무 verbose 하다.
Actions={
isMine
? [
<FeedActionButton
onClick={() =>
overlay.open(({ isOpen, close }) => (
<FeedEditModal isModalOpened={isOpen} postId={String(post.id)} handleModalClose={close} />
))
}
>
수정
</FeedActionButton>,
<FeedActionButton
onClick={() => {
overlay.open(({ isOpen, close }) => (
// eslint-disable-next-line prettier/prettier
<ConfirmModal isModalOpened={isOpen} message="게시글을 삭제하시겠습니까?" cancelButton="돌아가기" confirmButton="삭제하기"
handleModalClose={close}
handleConfirm={mutateDeletePost}
/>
));
}}
>
삭제
</FeedActionButton>,
]}
handleModalClose={close}
handleConfirm={mutateDeletePost}
/>
));
}}
>
삭제
</FeedActionButton>,
]
: [
<FeedActionButton
onClick={() => {
overlay.open(({ isOpen, close }) => (
// eslint-disable-next-line prettier/prettier
<ConfirmModal isModalOpened={isOpen} message="게시글을 신고하시겠습니까?" cancelButton="돌아가기" confirmButton="신고하기"
handleModalClose={close}
handleConfirm={handleConfirmReportPost({ postId: post.id, callback: close })}
/>
));
}}
>
신고
</FeedActionButton>,
]
}
CommentLikeSection={
<FeedCommentLikeSection
isLiked={post.isLiked}
Expand Down
4 changes: 4 additions & 0 deletions src/components/feed/FeedActionButton/FeedActionButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,8 @@ const MenuItem = styled('button', {
borderRadius: '0 0 14px 14px ',
borderTop: 'none',
},
'&:only-child': {
borderRadius: '14px',
border: '1px solid $gray600',
},
});
24 changes: 10 additions & 14 deletions src/components/feed/FeedPostViewer/FeedPostViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ dayjs.locale('ko');

interface FeedPostViewerProps {
post: paths['/post/v1/{postId}']['get']['responses']['200']['content']['application/json']['data'];
isMine?: boolean;
Actions: React.ReactNode[];
CommentLikeSection: React.ReactNode;
CommentList: React.ReactNode;
Expand All @@ -28,7 +27,6 @@ interface FeedPostViewerProps {

export default function FeedPostViewer({
post,
isMine,
Actions,
CommentLikeSection,
CommentList,
Expand Down Expand Up @@ -59,18 +57,16 @@ export default function FeedPostViewer({
<UpdatedDate>{fromNow(post.updatedDate)}</UpdatedDate>
</AuthorInfo>
</AuthorWrapper>
{isMine && (
<Menu as="div" style={{ position: 'relative' }}>
<Menu.Button>
<MenuIcon />
</Menu.Button>
<MenuItems>
{Actions.map((Action, index) => (
<Menu.Item key={index}>{Action}</Menu.Item>
))}
</MenuItems>
</Menu>
)}
<Menu as="div" style={{ position: 'relative' }}>
<Menu.Button>
<MenuIcon />
</Menu.Button>
<MenuItems>
{Actions.map((Action, index) => (
<Menu.Item key={index}>{Action}</Menu.Item>
))}
</MenuItems>
</Menu>
</ContentHeader>
<ContentBody>
<Title>{post.title}</Title>
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useToast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit 641f6db

Please sign in to comment.