Skip to content

Commit

Permalink
New : 댓글 삭제기능 추가 (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
jobkaeHenry authored Dec 4, 2023
1 parent be8b4c6 commit 75b00ea
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 19 deletions.
18 changes: 17 additions & 1 deletion client/src/components/post/detail/PostComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Stack, Avatar, Typography } from "@mui/material";
import dayjs from "dayjs";
import Link from "next/link";
import PostCommentDropdown from "./PostCommentDropdown";
import useDeleteCommentMutation from "@/queries/post/comment/useDeleteCommentMutation";

type Props = {
content: string;
Expand All @@ -13,6 +14,8 @@ type Props = {
userPk: string;
profileImg?: string;
createdAt: string;
commentPk: string;
postPk: string;
};

const PostComment = ({
Expand All @@ -22,10 +25,13 @@ const PostComment = ({
createdAt,
profileImg,
userPk,
postPk,
commentPk,
}: Props) => {
const { data: myData } = useMyInfoQuery();

const isMyComment = userPk === String(myData?.userNo);
const { mutateAsync: onDelete } = useDeleteCommentMutation();

return (
<Stack direction="row" width="100%" gap={1.25}>
Expand All @@ -50,7 +56,17 @@ const PostComment = ({
{dayjs(createdAt).format("MM.DD")}
</Typography>
</Stack>
{isMyComment && <PostCommentDropdown />}
{isMyComment && (
<PostCommentDropdown
onDelete={() => {
onDelete({
commentPk: String(commentPk),
postPk: String(postPk),
});
}}
onEdit={() => {}}
/>
)}
</Stack>
<Typography>{content}</Typography>
</Stack>
Expand Down
24 changes: 12 additions & 12 deletions client/src/components/post/detail/PostCommentDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ import { ButtonBase, Menu, MenuItem } from "@mui/material";
import { MoreVertOutlined } from "@mui/icons-material";
import { useState } from "react";

const PostCommentDropdown = () => {
interface PostCommentDropdownInterface {
onDelete: () => void;
onEdit: () => void;
}

const PostCommentDropdown = ({
onDelete,
onEdit,
}: PostCommentDropdownInterface) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);

Expand All @@ -13,23 +21,15 @@ const PostCommentDropdown = () => {
const handleClose = () => {
setAnchorEl(null);
};

return (
<>
<ButtonBase aria-label="settings" sx={{ p: 0 }} onClick={handleClick}>
<MoreVertOutlined />
</ButtonBase>
<Menu open={open} anchorEl={anchorEl} onClose={handleClose}>
<MenuItem
onClick={() => {
if (confirm("정말 삭제하시겠습니까?")) {
console.log("눌림");
}
}}
>
삭제
</MenuItem>
<MenuItem>수정</MenuItem>
{onDelete && <MenuItem onClick={onDelete}>삭제</MenuItem>}
{onEdit && <MenuItem onClick={onEdit}>수정</MenuItem>}
</Menu>
</>
);
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/post/detail/PostCommentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ const PostCommentList = ({ postNo }: Props) => {
nickname,
userId,
profileImgUrls,
},
i
}
) => (
<PostComment
content={commentContent}
Expand All @@ -32,6 +31,8 @@ const PostCommentList = ({ postNo }: Props) => {
profileImg={profileImgUrls?.[0]?.attachUrl}
userId={userId}
userPk={String(createdBy)}
commentPk={String(commentNo)}
postPk={postNo}
key={commentNo}
/>
)
Expand Down
15 changes: 11 additions & 4 deletions client/src/const/serverPath.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const MY_INFO = "/user/me" as const;
/**
* 유저정보를 수정하는 path
*/
export const PATCH_USER_INFO = '/user' as const
export const PATCH_USER_INFO = "/user" as const;

/**
* 쿠키를 심어주는 로그인 BFF
Expand All @@ -33,7 +33,16 @@ export const POST_LIST = "/posts" as const;
/**
* 게시물 pk 를 입력받아 댓글을 조회,생성 하는 URL
*/
export const POST_COMMENT = (pk:string) => `${POST_LIST}/${pk}/comments`
export const POST_COMMENT = (pk: string) => `${POST_LIST}/${pk}/comments`;

/**
* 게시글Pk와 댓글 PK를 입력받아 댓글 삭제를 요청하는 URL
* @param postPk
* @param commentPk
* @returns
*/
export const DELETE_COMMENT = (postPk: string, commentPk: string) =>
`${POST_LIST}/${postPk}/comments/${commentPk}`;

/**
* 게시물리스트를 받아오거나, 작성하는 Path 버전2 (Breaking Change)
Expand Down Expand Up @@ -71,8 +80,6 @@ export const REMOVE_FILE = (attachNo: string) => `/attach/${attachNo}` as const;
*/
export const GET_ALCOHOL_LIST = "/alcohols" as const;



/**
* 포스트의 PK를 입력받아 해당 PK의 게시글의 좋아요 취소를 요청
* @param id 게시글의 PK
Expand Down
59 changes: 59 additions & 0 deletions client/src/queries/post/comment/useDeleteCommentMutation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { DELETE_COMMENT } from "@/const/serverPath";
import useAxiosPrivate from "@/hooks/useAxiosPrivate";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { commentQueryKey } from "./useGetCommentQuery";
import PostCommentListInterface from "@/types/post/PostCommentInterface";
import { useErrorHandler } from "@/utils/errorHandler";

const useDeleteCommentMutation = () => {
const queryClient = useQueryClient();
const errorHandler = useErrorHandler();

return useMutation({
mutationFn: ({ postPk, commentPk }: deleteCommentInterface) =>
deleteComment({ postPk, commentPk }),

onMutate({ commentPk,postPk }) {
queryClient.cancelQueries({ queryKey: commentQueryKey.byId(commentPk) });

const querySnapShot = queryClient.getQueryData<PostCommentListInterface>(
commentQueryKey.byId(postPk)
);

queryClient.setQueryData<PostCommentListInterface>(
commentQueryKey.byId(postPk),
(prev) => ({
list: (prev?.list ?? []).filter(
({commentNo}) => String(commentNo) !== String(commentPk)
),
totalCount: (prev?.totalCount ?? 0) - 1,
})
);
return { querySnapShot };
},
onError(err, queryFnParams, context) {
errorHandler(err);
queryClient.setQueryData(
commentQueryKey.byId(queryFnParams.postPk),
context?.querySnapShot
);
},
onSuccess(_data, variables) {
queryClient.invalidateQueries({
queryKey: commentQueryKey.byId(variables.postPk),
});
},
});
};

interface deleteCommentInterface {
postPk: string;
commentPk: string;
}
const deleteComment = async ({ postPk, commentPk }: deleteCommentInterface) => {
const axiosPrivate = useAxiosPrivate();
const { data } = await axiosPrivate.delete(DELETE_COMMENT(postPk, commentPk));
return data;
};

export default useDeleteCommentMutation;

0 comments on commit 75b00ea

Please sign in to comment.