Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions src/apis/api.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { instance, instanceWithToken } from "./axios";
import axios from "axios";

// Account 관련 API들
export const signIn = async (data) => {
const response = await instance.post("/account/signin/", data);
if (response.status === 200) {
Expand All @@ -20,6 +20,17 @@ export const signUp = async (data) => {
return response;
};

export const getUser = async () => {
const response = await instanceWithToken.get("/account/info/");
if (response.status === 200) {
console.log("GET USER SUCCESS");
} else {
console.log("[ERROR] error while updating comment");
}
return response.data;
};

// 추가
export const getPosts = async () => {
const response = await instance.get("/post/");
return response.data;
Expand Down Expand Up @@ -64,6 +75,7 @@ export const deletePost = async (id, navigate) => {
// 과제!!
export const likePost = async (postId) => {};

// Tag 관련 API들
export const getTags = async () => {
const response = await instance.get("/tag/");
return response.data;
Expand All @@ -78,6 +90,10 @@ export const createTag = async (data) => {
}
return response; // response 받아서 그 다음 처리
};

// 추가

// Comment 관련 API들
export const getComments = async (postId) => {
const response = await instance.get(`/comment/?post=${postId}`);
return response.data;
Expand All @@ -102,13 +118,14 @@ export const updateComment = async (id, data) => {
console.log("[ERROR] error while updating comment");
}
};
export const deleteComment = async (id) => {};
export const getUser = async () => {
const response = await instanceWithToken.get("/account/info/");
if (response.status === 200) {
console.log("GET USER SUCCESS");

// 과제 !!
export const deleteComment = async (id) => {
const response = await instanceWithToken.delete(`/comment/${id}/`);
if (response.status === 204) {
console.log("DELETE SUCCESS");
window.location.reload();
} else {
console.log("[ERROR] error while updating comment");
console.log("[ERROR] error while deleting post");
}
return response.data;
};
2 changes: 2 additions & 0 deletions src/apis/axios.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const instance = axios.create();
// Token 있어야 접근 가능한 API들 - 얘는 토큰을 넣어줘야 해요
export const instanceWithToken = axios.create();

// ⬇️ 추가
// instanceWithToken에는 쿠키에서 토큰을 찾고 담아줍시다!
instanceWithToken.interceptors.request.use(
// 요청을 보내기전 수행할 일
// 사실상 이번 세미나에 사용할 부분은 이거밖에 없어요
Expand Down
132 changes: 78 additions & 54 deletions src/components/Comment/CommentElement.jsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,83 @@
import { useState, useEffect } from "react";
import { updateComment, getUser } from "../../apis/api";
import { getCookie } from "../../utils/cookie";

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 (
<div className="w-full flex flex-row justify-between items-center mb-5">
<div className="w-3/4 flex flex-col gap-1">
{isEdit ? (
<input className="input mb-2" value={onChangeValue} onChange={(e) => setOnChangeValue(e.target.value)} />
) : (
<p className="text-lg">{content}</p>
)}

<span className="text-base text-gray-300">{year}.{month}.{day}</span>
</div>

<div className="flex flex-row items-center gap-3">
{isEdit ? (
<>
<button onClick={() => { setIsEdit(!isEdit); setOnChangeValue(content); }}>취소</button>
<button onClick={handleEditComment}>완료</button>
</>
) : (
<>
<button onClick={() => handleCommentDelete(comment.id)}>삭제</button>
<button onClick={() => setIsEdit(!isEdit)}>수정</button>
</>
)}
</div>
</div>
);
const { comment, handleCommentDelete, postId } = props;
const [content, setContent] = useState(comment.content);
const [isEdit, setIsEdit] = useState(false);
const [user, setUser] = useState(null); // state for user

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 = async () => {
await updateComment(comment.id, { content: onChangeValue });
setIsEdit(!isEdit);
};

// get user info
useEffect(() => {
if (getCookie("access_token")) {
const getUserAPI = async () => {
const user = await getUser();
setUser(user);
};
getUserAPI();
}
}, []);

return (
<div className="w-full flex flex-row justify-between items-center mb-5">
<div className="w-3/4 flex flex-col gap-1">
{isEdit ? (
<input
className="input mb-2"
value={onChangeValue}
onChange={(e) => setOnChangeValue(e.target.value)}
/>
) : (
<p className="text-lg">{content}</p>
)}

<span className="text-base text-gray-300">
{year}.{month}.{day}
</span>
</div>

<div className="flex flex-row items-center gap-3">
{user?.id === comment.author.id ? (
isEdit ? (
<>
<button
onClick={() => {
setIsEdit(!isEdit);
setOnChangeValue(content);
}}
>
취소
</button>
<button onClick={handleEditComment}>완료</button>
</>
) : (
<>
<button onClick={() => handleCommentDelete(comment.id)}>
삭제
</button>
<button onClick={() => setIsEdit(!isEdit)}>수정</button>
</>
)
) : null}
{}
</div>
</div>
);
};
export default CommentElement;
109 changes: 66 additions & 43 deletions src/components/Comment/index.jsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,76 @@
import { useState } from "react";
import comments from "../../data/comments"; // dummy data
import { useState, useEffect } from "react";
import { getComments, createComment, deleteComment } from "../../apis/api"; // dummy data
import CommentElement from "./CommentElement";
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 [commentList, setCommentList] = useState([]); // state for comments
const [newContent, setNewContent] = useState({
post: postId,
content: "",
});
const [isSignedIn, setIsSignedIn] = useState();

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(() => {
const getCommentsAPI = async () => {
const comments = await getComments(postId);
setCommentList(comments);
};
getCommentsAPI();
const signIn = getCookie("access_token") ? true : false;
setIsSignedIn(signIn);
}, []);

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();
await createComment({ post: postId, content: newContent });
setNewContent("");
};

const handleCommentDelete = async (commentId) => {
const confirmDelete = window.confirm("정말 삭제하시겠습니까?");
if (!confirmDelete) return;
try {
await deleteComment(commentId);
} catch (error) {
console.error(error);
} // TODO: add api call for deleting comment
};

return (
<div className="w-full mt-5 self-start">
<h1 className="text-3xl font-bold my-5">Comments</h1>
{commentList.map((comment) => {
return (
<CommentElement
key={comment.id}
comment={comment}
handleCommentDelete={handleCommentDelete}
postId={postId}
/>
);
})}

return (
<div className="w-full mt-5 self-start">
<h1 className="text-3xl font-bold my-5">Comments</h1>
{commentList.map((comment) => {
return (
<CommentElement key={comment.id} comment={comment} handleCommentDelete={handleCommentDelete} postId={postId} />
);
})}

<form className="flex flex-row mt-10 gap-3" onSubmit={handleCommentSubmit}>
<input type="text" value={newContent} placeholder="댓글을 입력해주세요" className="input" style={{ width: "calc(100% - 100px)" }} onChange={(e) => setNewContent(e.target.value)} />
<button type="submit" className="button">작성</button>
</form>
</div>
);
{isSignedIn ? (
<form
className="flex flex-row mt-10 gap-3"
onSubmit={handleCommentSubmit}
>
<input
type="text"
value={newContent.content}
placeholder="댓글을 입력해주세요"
className="input"
style={{ width: "calc(100% - 100px)" }}
onChange={(e) => setNewContent(e.target.value)}
/>
<button type="submit" className="button">
작성
</button>
</form>
) : null}
</div>
);
};

export default Comment;
14 changes: 8 additions & 6 deletions src/routes/PostDetailPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,30 @@ 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, getUser, deletePost } from "../apis/api";
import { getCookie } from "../utils/cookie";

import posts from "../data/posts";

const PostDetailPage = () => {
const { postId } = useParams();
const [post, setPost] = useState(null);
const [user, setUser] = useState();

const [user, setUser] = useState(null);

useEffect(() => {
const getPostAPI = async () => {
const posts = await getPost(postId);
setPost(posts);
const post = await getPost(postId);
setPost(post);
};
getPostAPI();
}, [postId]);

useEffect(() => {
// access_token이 있으면 유저 정보 가져옴
if (getCookie("access_token")) {
const getUserAPI = async () => {
const user = await getUser();
setUser(user);
console.log(user);
};
getUserAPI();
}
Expand All @@ -34,6 +35,7 @@ const PostDetailPage = () => {
const onClickDelete = async () => {
const confirmDelete = window.confirm("정말 삭제하시겠습니까?");
if (!confirmDelete) return;

try {
await deletePost(postId, navigate);
} catch (error) {
Expand Down