diff --git a/src/apis/api.js b/src/apis/api.js index 41ddee1d..74c2e400 100644 --- a/src/apis/api.js +++ b/src/apis/api.js @@ -113,7 +113,14 @@ export const updateComment = async (id, data) => { }; // 과제 !! -export const deleteComment = async (id) => {}; +export const deleteComment = async (commentId) => { + const response = await instanceWithToken.delete(`/comment/${commentId}/`); + if (response.status === 204) { + console.log("COMMENT DELETED"); + } else { + console.log("[ERROR] error while deleting comment"); + } +}; export const getUser = async () => { const response = await instanceWithToken.get("/account/info/"); diff --git a/src/components/Comment/CommentElement.jsx b/src/components/Comment/CommentElement.jsx index fd48385e..450ca952 100644 --- a/src/components/Comment/CommentElement.jsx +++ b/src/components/Comment/CommentElement.jsx @@ -1,59 +1,88 @@ import { useState, useEffect } from "react"; - +import { getCookie } from "../../utils/cookie"; +import { getUser } from "../../apis/api"; const CommentElement = (props) => { - const { comment, handleCommentDelete, postId } = props; - const [content, setContent] = useState(comment.content); - const [isEdit, setIsEdit] = useState(false); - - const [onChangeValue, setOnChangeValue] = useState(content); // 수정 취소 시 직전 content 값으로 변경을 위한 state - - // comment created_at 전처리 - const date = new Date(comment.created_at); - const year = date.getFullYear(); - let month = date.getMonth() + 1; - month = month < 10 ? `0${month}` : month; - let day = date.getDate(); - day = day < 10 ? `0${day}` : day; - - const handleEditComment = () => { // add api call for editing comment - setContent(onChangeValue); - setIsEdit(!isEdit); - console.log({ - post: postId, - comment: comment.id, - content: content - }); - }; - - useEffect(() => { // add api call to check if user is the author of the comment - }, []); - - return ( -
-
- {isEdit ? ( - setOnChangeValue(e.target.value)} /> - ) : ( -

{content}

- )} - - {year}.{month}.{day} -
- -
- {isEdit ? ( - <> - - - - ) : ( - <> - - - - )} -
-
- ); + const { comment, handleCommentDelete, postId, handleCommentEdit } = props; + const [content, setContent] = useState(comment.content); + const [isEdit, setIsEdit] = useState(false); + const [user, setUser] = useState(); + const [onChangeValue, setOnChangeValue] = useState(content); // 수정 취소 시 직전 content 값으로 변경을 위한 state + + // 유저 확인 + useEffect(() => { + // access_token이 있으면 유저 정보 가져옴 + if (getCookie("access_token")) { + const getUserAPI = async () => { + const user = await getUser(); + setUser(user); + }; + getUserAPI(); + } + }, []); + + // comment created_at 전처리 + const date = new Date(comment.created_at); + const year = date.getFullYear(); + let month = date.getMonth() + 1; + month = month < 10 ? `0${month}` : month; + let day = date.getDate(); + day = day < 10 ? `0${day}` : day; + + const handleEditClick = async () => { + if (isEdit) { + await handleCommentEdit(comment.id, onChangeValue); + } + setIsEdit(!isEdit); + }; + + useEffect(() => { + // add api call to check if user is the author of the comment + }, []); + + console.log("Current User ID:", user?.id); + console.log("Comment Author ID:", comment?.author.id); + + return ( +
+
+ {isEdit ? ( + setOnChangeValue(e.target.value)} + /> + ) : ( +

{content}

+ )} + + + {year}.{month}.{day} + +
+ +
+ {isEdit ? ( + <> + + + + ) : user?.id === comment?.author ? ( + <> + + + + ) : null} +
+
+ ); }; export default CommentElement; diff --git a/src/components/Comment/index.jsx b/src/components/Comment/index.jsx index c8c4a27e..cefd5ff7 100644 --- a/src/components/Comment/index.jsx +++ b/src/components/Comment/index.jsx @@ -1,53 +1,74 @@ -import { useState } from "react"; -import comments from "../../data/comments"; // dummy data +import { useState, useEffect } from "react"; import CommentElement from "./CommentElement"; +import { createComment, getComments } from "../../apis/api"; +import { getCookie } from "../../utils/cookie"; -const Comment = ({ postId }) => { - const [commentList, setCommentList] = useState(comments); // state for comments - const [newContent, setNewContent] = useState(""); // state for new comment +const Comment = ({ + postId, + comments, + handleCommentDelete, + handleCommentEdit, +}) => { + const [commentList, setCommentList] = useState(comments); + const [newContent, setNewContent] = useState(""); + const [isLoggedIn, setIsLoggedIn] = useState(false); - const handleCommentSubmit = (e) => { - e.preventDefault(); - setCommentList([ // TODO: add api call for creating comment - ...commentList, - { - id: commentList.length + 1, - content: newContent, - created_at: new Date().toISOString(), - post: postId, - author: { - id: 1, - username: "user1" - } - } - ]); - console.log({ - post: postId, - content: newContent - }); - setNewContent(""); - }; + useEffect(() => { + // 로그인 여부 확인 + if (getCookie("access_token")) { + setIsLoggedIn(true); + } + }, []); - const handleCommentDelete = (commentId) => { - console.log("comment: ", commentId); - setCommentList(commentList.filter((comment) => comment.id !== commentId)); // TODO: add api call for deleting comment - }; + const handleCommentSubmit = async (e) => { + e.preventDefault(); + try { + const newComment = { + content: newContent, + post: postId, + }; + await createComment(newComment); + setNewContent(""); + const updatedComments = await getComments(postId); // 새 댓글 목록을 가져옴 + setCommentList(updatedComments); // 상태 업데이트 + } catch (error) { + console.error("[ERROR] error while creating comment", error); + } + }; - return ( -
-

Comments

- {commentList.map((comment) => { - return ( - - ); - })} - -
- setNewContent(e.target.value)} /> - -
-
- ); + return ( +
+

Comments

+ {commentList.map((comment) => ( + + ))} + + {isLoggedIn && ( +
+ setNewContent(e.target.value)} + /> + +
+ )} +
+ ); }; export default Comment; diff --git a/src/routes/PostDetailPage.jsx b/src/routes/PostDetailPage.jsx index 9e32f22f..25bddb0d 100644 --- a/src/routes/PostDetailPage.jsx +++ b/src/routes/PostDetailPage.jsx @@ -2,21 +2,20 @@ import { useState, useEffect } from "react"; import { useParams, Link, useNavigate } from "react-router-dom"; import { BigPost } from "../components/Posts"; import Comment from "../components/Comment"; -import { getPost } from "../apis/api"; -import posts from "../data/posts"; +import { + getPost, + getComments, + deleteComment, + updateComment, +} from "../apis/api"; import { getUser, deletePost } from "../apis/api"; import { getCookie } from "../utils/cookie"; const PostDetailPage = () => { const { postId } = useParams(); const [post, setPost] = useState(null); - const [user, setUser] = useState(); - - useEffect(() => { - const post = posts.find((post) => post.id === parseInt(postId)); - setPost(post); - }, [postId]); + const [comments, setComments] = useState([]); useEffect(() => { const getPostAPI = async () => { @@ -38,6 +37,15 @@ const PostDetailPage = () => { } }, []); + // 댓글 데이터 가져옴. + useEffect(() => { + const getCommentsAPI = async () => { + const comments = await getComments(postId); + setComments(comments); + }; + getCommentsAPI(); + }, [postId]); + const navigate = useNavigate(); const onClickDelete = async () => { @@ -50,12 +58,44 @@ const PostDetailPage = () => { } }; + const handleCommentDelete = async (commentId) => { + const confirmDelete = window.confirm("댓글을 삭제하시겠습니까?"); + if (!confirmDelete) return; + try { + await deleteComment(commentId); // API 호출로 댓글 삭제 + setComments(comments.filter((comment) => comment.id !== commentId)); // 로컬 상태에서 댓글 제거 + window.location.reload(); + } catch (error) { + console.error("[ERROR] error while deleting comment", error); + } + }; + + const handleCommentEdit = async (commentId, updatedContent) => { + try { + await updateComment(commentId, { content: updatedContent }); + setComments( + comments.map((comment) => + comment.id === commentId + ? { ...comment, content: updatedContent } + : comment + ) + ); // 로컬 상태에서 댓글 업데이트 + } catch (error) { + console.error("[ERROR] error while updating comment", error); + } + }; + return ( post && (
+ -
{user?.id === post?.author.id ? ( <> @@ -70,6 +110,7 @@ const PostDetailPage = () => { ) : null} + {/* user와 post.author가 동일하면 버튼을 리턴, 아니면 null */}