Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

액션 시트 API 연동 및 useActionSheet 구현 #231

Merged
merged 11 commits into from
Feb 23, 2024
39 changes: 38 additions & 1 deletion src/apis/comment/useComment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,17 @@ const reactComment = (commentId: number, reaction: 'like' | 'hate', enable: bool
});
};

const reportComment = (commentId: number) => {
return client.post<CommentReaction>({
path: `/comments/${commentId}/report`,
body: {},
});
};

const deleteComment = (commentId: number) => {
return client.delete<CommentReaction>(`/comments/${commentId}`);
};

const useComments = (topicId: number) => {
return useInfiniteQuery({
queryKey: [COMMENT_KEY, topicId],
Expand Down Expand Up @@ -70,6 +81,18 @@ const useCreateComment = (topicId: number) => {
});
};

const useReportComment = (commentId: number) => {
return useMutation({
mutationFn: () => reportComment(commentId),
});
};

const useDeleteComment = (commentId: number) => {
return useMutation({
mutationFn: () => deleteComment(commentId),
});
};

const useReactComment = (topicId: number, commentId: number) => {
const queryClient = useQueryClient();

Expand Down Expand Up @@ -100,4 +123,18 @@ const useReactComment = (topicId: number, commentId: number) => {
});
};

export { COMMENT_KEY, useComments, useCreateComment, useReactComment, usePreviewComment };
export {
COMMENT_KEY,
getComments,
getCommentPreview,
createComments,
reactComment,
reportComment,
deleteComment,
useComments,
usePreviewComment,
useCreateComment,
useReportComment,
useDeleteComment,
useReactComment,
};
28 changes: 28 additions & 0 deletions src/apis/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,34 @@ class Fetch {
return data;
}

async patch<TData>({
path,
headers,
body,
}: {
path: string;
headers?: HeadersInit;
body: object;
}) {
const response = await fetch(`${this.baseURL}${path}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json;charset=UTF-8',
...(this.accessToken && { Authorization: `Bearer ${this.accessToken}` }),
...headers,
},
body: JSON.stringify(body),
});

const data = await response.json();

if (!response.ok) {
throw new ResponseError(data);
}

return data as TData;
}

setAccessToken(token: string) {
this.accessToken = token;
}
Expand Down
16 changes: 16 additions & 0 deletions src/apis/topic/useHideTopic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useMutation } from '@tanstack/react-query';

import client from '@apis/fetch';

const hideTopic = (topicId: number) => {
return client.patch({
path: `/topics/${topicId}/hide?hide=true`,
body: {},
});
};

const useHideTopic = (topicId: number) => {
return useMutation({ mutationFn: () => hideTopic(topicId) });
};

export default useHideTopic;
4 changes: 4 additions & 0 deletions src/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import ImageIcon from './image-icon.svg?react';
import KakaoIcon from './kakao.svg?react';
import LeftDoubleArrowIcon from './left-double-arrow.svg?react';
import MeatballIcon from './meatball.svg?react';
import PencilIcon from './pencil.svg?react';
import PlusBoxIcon from './plus-box.svg?react';
import ProfileIcon from './profile.svg?react';
import RefreshIcon from './refresh.svg?react';
Expand All @@ -42,6 +43,7 @@ import SelectedTextIcon from './text-icon-selected.svg?react';
import TextIcon from './text-icon.svg?react';
import ThumbsIcon from './thumbs.svg?react';
import TopicCreatBackgrounIcon from './topic-create-background.svg?react';
import TrashCanIcon from './trash-can.svg?react';
import TrashIcon from './trash.svg?react';
import UpDownChevronIcon from './up-down.svg?react';
import WriteBoxIcon from './write-box.svg?react';
Expand Down Expand Up @@ -72,6 +74,7 @@ export {
KakaoIcon,
LeftDoubleArrowIcon,
MeatballIcon,
PencilIcon,
NewAlarmIcon,
PlusBoxIcon,
ProfileIcon,
Expand All @@ -83,6 +86,7 @@ export {
SizeUpIcon,
ThumbsIcon,
TopicCreatBackgrounIcon,
TrashCanIcon,
UpDownChevronIcon,
WriteBoxIcon,
TextIcon,
Expand Down
6 changes: 6 additions & 0 deletions src/assets/icons/pencil.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/assets/icons/refresh.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/icons/trash-can.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 37 additions & 38 deletions src/components/Home/Comment/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { TimeUnits, getDateDistance, getDateDistanceText } from '@toss/date';
import React from 'react';

import { useReactComment } from '@apis/comment/useComment';
import { useDeleteComment, useReactComment, useReportComment } from '@apis/comment/useComment';
import { Col, Row } from '@components/commons/Flex/Flex';
import ProfileImg from '@components/commons/ProfileImg/ProfileImg';
import Text from '@components/commons/Text/Text';
import useModal from '@hooks/useModal/useModal';
import useActionSheet from '@hooks/useModal/useActionSheet';
import { CommentResponse } from '@interfaces/api/comment';
import { Choice } from '@interfaces/api/topic';

import { useAuthStore } from '@store/auth';

import { colors } from '@styles/theme';

import { MeatballIcon, ReportIcon } from '@icons/index';
import { MeatballIcon, PencilIcon, ReportIcon, TrashCanIcon } from '@icons/index';

import Thumbs from './Thumbs';

Expand All @@ -23,8 +23,9 @@ interface CommentProps {
}

const Comment = React.memo(({ comment, choices }: CommentProps) => {
const { Modal, toggleModal } = useModal('action');
const reactMutation = useReactComment(comment.topicId, comment.commentId);
const reportMutation = useReportComment(comment.commentId);
const deleteMutation = useDeleteComment(comment.commentId);
const memberId = useAuthStore((store) => store.memberId);
const likeCount = Math.max(
comment.commentReaction.likeCount - comment.commentReaction.hateCount,
Expand All @@ -44,17 +45,17 @@ const Comment = React.memo(({ comment, choices }: CommentProps) => {
};

const handleCommentModify = () => {
// TODO: 수정하기 기능 구현
// TBD: 1차 스펙 아웃
toggleModal();
};

const handleCommentDelete = () => {
// TODO: 삭제하기 기능 구현
deleteMutation.mutate();
toggleModal();
};

const handleCommentReport = () => {
// TODO: 신고하기 기능 구현
reportMutation.mutate();
toggleModal();
};

Expand All @@ -66,6 +67,34 @@ const Comment = React.memo(({ comment, choices }: CommentProps) => {
reactMutation.mutate({ reaction: 'hate', enable: !comment.commentReaction.hated });
};

const { Modal: CommentModal, toggleModal } = useActionSheet({
actions:
memberId === comment.writer.id
? [
{
icon: <PencilIcon />,
label: '수정',
onClick: handleCommentModify,
},
{
icon: <TrashCanIcon />,
label: '삭제',
confirm: {
description: '내가 작성한 댓글을 삭제합니다.',
label: '삭제하기',
onConfirm: handleCommentDelete,
},
},
]
: [
{
icon: <ReportIcon />,
label: '신고하기',
onClick: handleCommentReport,
},
],
});

return (
<React.Fragment>
<Col padding={'14px 20px 24px'}>
Expand Down Expand Up @@ -119,37 +148,7 @@ const Comment = React.memo(({ comment, choices }: CommentProps) => {
</Row>
</Col>
</Col>
<Modal>
{memberId === comment.writer.id ? (
<Col gap={14}>
<button onClick={handleCommentModify}>
<Row alignItems={'center'} gap={14}>
<ReportIcon />
<Text size={16} weight={500}>
수정
</Text>
</Row>
</button>
<button onClick={handleCommentDelete}>
<Row alignItems={'center'} gap={14}>
<ReportIcon />
<Text size={16} weight={500}>
삭제
</Text>
</Row>
</button>
</Col>
) : (
<button onClick={handleCommentReport}>
<Row alignItems={'center'} gap={14}>
<ReportIcon />
<Text size={16} weight={500}>
신고하기
</Text>
</Row>
</button>
)}
</Modal>
<CommentModal />
</React.Fragment>
);
});
Expand Down
Loading
Loading