diff --git a/apps/common/features/src/entities/comment/api/comment-service.ts b/apps/common/features/src/entities/comment/api/comment-service.ts index 7fb0b5655..a4001301d 100644 --- a/apps/common/features/src/entities/comment/api/comment-service.ts +++ b/apps/common/features/src/entities/comment/api/comment-service.ts @@ -2,11 +2,13 @@ import { client } from "@/shared/api"; import { ENDPOINT } from "@/shared/config"; import { commentFormSchema, + commentUpdateFormSchema, type Comment, type CommentService, type CommentList, type CommentParams, type CommentFormData, + type CommentUpdateFormData, } from "../model/comment-interface"; export class CommentApiService implements CommentService { @@ -26,6 +28,32 @@ export class CommentApiService implements CommentService { ); return response.data; } + + public async updateComment( + bbsId: number, + pstNo: number, + cmntNo: number, + data: CommentUpdateFormData, + ): Promise { + const validatedData = commentUpdateFormSchema.parse(data); + const response = await client.put( + `${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}/${bbsId}/${pstNo}/${cmntNo}`, + validatedData, + ); + return response.data; + } + + public async deleteComment( + bbsId: number, + pstNo: number, + cmntNo: number, + cmntPswd: string, + ): Promise { + const response = await client.delete( + `${ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS}/${bbsId}/${pstNo}/${cmntNo}?cmntPswd=${cmntPswd}`, + ); + return response.data; + } } export const CommentApi = new CommentApiService(); diff --git a/apps/common/features/src/entities/comment/index.ts b/apps/common/features/src/entities/comment/index.ts index 376ec62e4..0b3c0f660 100644 --- a/apps/common/features/src/entities/comment/index.ts +++ b/apps/common/features/src/entities/comment/index.ts @@ -6,4 +6,5 @@ export { type CommentList, type CommentParams, type CommentFormData, + type CommentUpdateFormData, } from "./model/comment-interface"; diff --git a/apps/common/features/src/entities/comment/model/comment-interface.ts b/apps/common/features/src/entities/comment/model/comment-interface.ts index ea22af65b..9023346af 100644 --- a/apps/common/features/src/entities/comment/model/comment-interface.ts +++ b/apps/common/features/src/entities/comment/model/comment-interface.ts @@ -18,6 +18,7 @@ export interface Comment { rgtr: string; mdfcnDt: string; mdfr: string; + delYn: string; } export const commentFormSchema = z.object({ @@ -39,16 +40,16 @@ export type CommentUpdateFormData = z.infer; export interface CommentService { getComments(params: CommentParams): Promise; createComment(data: CommentFormData): Promise; - // updateComment( - // bbsId: number, - // pstNo: number, - // cmntNo: number, - // data: CommentUpdateFormData, - // ): Promise; - // deleteComment( - // bbsId: number, - // pstNo: number, - // cmntNo: number, - // cmntPswd: string, - // ): Promise; + updateComment( + bbsId: number, + pstNo: number, + cmntNo: number, + data: CommentUpdateFormData, + ): Promise; + deleteComment( + bbsId: number, + pstNo: number, + cmntNo: number, + cmntPswd: string, + ): Promise; } diff --git a/apps/common/features/src/widgets/post/ui/post-comment.tsx b/apps/common/features/src/widgets/post/ui/post-comment.tsx index b7a55a6ca..0bddc1e81 100644 --- a/apps/common/features/src/widgets/post/ui/post-comment.tsx +++ b/apps/common/features/src/widgets/post/ui/post-comment.tsx @@ -1,21 +1,28 @@ import dayjs from "dayjs"; +import { useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; +import { useConfirm } from "@frontend-opensource/use-react-hooks"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { Button, Input, Textarea } from "@common/components"; import { CommentApi, commentFormSchema, type CommentFormData, + type CommentUpdateFormData, } from "@/entities/comment"; -import { Form, FormControl, FormField, FormItem } from "@/shared/ui/form"; -import { useAlertStore, useUserStore } from "@/shared/lib"; import { ENDPOINT } from "@/shared/config"; +import { useAlertStore, usePrompt, useUserStore } from "@/shared/lib"; +import { Form, FormControl, FormField, FormItem } from "@/shared/ui/form"; -function PostComment({ pstNo }: { pstNo: number }) { +function PostComment({ bbsId, pstNo }: { bbsId: number; pstNo: number }) { + const { prompt } = usePrompt(); + const { confirm } = useConfirm(); const queryClient = useQueryClient(); - const { setMessage: alert } = useAlertStore((state) => state); const { userInfo } = useUserStore((state) => state); + const { setMessage: alert } = useAlertStore((state) => state); + const [editingCmntNo, setEditingCmntNo] = useState(null); + const [editValue, setEditValue] = useState(""); const { data: comments } = useQuery({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS, pstNo], @@ -26,7 +33,7 @@ function PostComment({ pstNo }: { pstNo: number }) { const { mutate: createComment } = useMutation({ mutationFn: (data: CommentFormData) => CommentApi.createComment(data), onSuccess: () => { - alert("댓글이 등록되었습니다."); + alert("등록되었습니다."); form.setValue("cmntCn", ""); queryClient.invalidateQueries({ queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS], @@ -34,6 +41,35 @@ function PostComment({ pstNo }: { pstNo: number }) { }, }); + const { mutate: updateComment } = useMutation({ + mutationFn: ({ + cmntNo, + data, + }: { + cmntNo: number; + data: CommentUpdateFormData; + }) => CommentApi.updateComment(bbsId, pstNo, cmntNo, data), + onSuccess: () => { + alert("수정되었습니다."); + setEditingCmntNo(null); + setEditValue(""); + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS], + }); + }, + }); + + const { mutate: deleteComment } = useMutation({ + mutationFn: ({ cmntNo, cmntPswd }: { cmntNo: number; cmntPswd: string }) => + CommentApi.deleteComment(bbsId, pstNo, cmntNo, cmntPswd), + onSuccess: () => { + alert("삭제되었습니다."); + queryClient.invalidateQueries({ + queryKey: [ENDPOINT.BOARD_SERVICE.POSTS_COMMENTS], + }); + }, + }); + const form = useForm({ resolver: zodResolver(commentFormSchema), values: { @@ -48,6 +84,35 @@ function PostComment({ pstNo }: { pstNo: number }) { createComment(data); }; + const getCommentPassword = async () => { + let cmntPswd = ""; + if (userInfo?.userUnqId) { + cmntPswd = userInfo?.userUnqId; + } else { + cmntPswd = await prompt("비밀번호를 입력해주세요."); + } + return cmntPswd; + }; + + const handleUpdateComment = async (cmntNo: number, wrtrNm: string) => { + if (!(await confirm("수정하시겠습니까?"))) return; + const cmntPswd = await getCommentPassword(); + updateComment({ + cmntNo, + data: { + cmntCn: editValue, + wrtrNm, + cmntPswd, + }, + }); + }; + + const handleDeleteComment = async (cmntNo: number) => { + if (!(await confirm("삭제하시겠습니까?"))) return; + const cmntPswd = await getCommentPassword(); + deleteComment({ cmntNo, cmntPswd }); + }; + return (
@@ -113,32 +178,77 @@ function PostComment({ pstNo }: { pstNo: number }) {
- {comments?.content.map((comment) => ( -
-
-
- - {comment.wrtrNm} - - - {dayjs(comment.regDt).format("YYYY.MM.DD")} - + {comments?.content.map((comment) => { + if (comment.delYn === "Y") return null; + return ( +
+
+
+ + {comment.wrtrNm} + + + {dayjs(comment.regDt).format("YYYY.MM.DD")} + +
+ {editingCmntNo === comment.cmntNo ? ( +
+