Skip to content

Commit

Permalink
FE: [feat] 커뮤니티 댓글, 대댓글 기능 추가 #148
Browse files Browse the repository at this point in the history
  • Loading branch information
hyeona01 committed Dec 7, 2024
1 parent b4b84de commit 111c640
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 19 deletions.
16 changes: 15 additions & 1 deletion src/frontend/src/apis/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const searchBoard = async (boardName: string, keyword: string) => {
return response.data;
};

export const postBoardLike = async (
export const postBoardCommentLike = async (
boardName: string,
postId: number,
commentId: number
Expand All @@ -47,3 +47,17 @@ export const postBoardLike = async (
);
return response.data;
};

export const postBoardCommemt = async (
boardName: string,
postId: number,
content: string,
parentCommentId: number | null
) => {
const response = await api.post(`/board/${boardName}/${postId}`, {
content: content,
postId: postId,
parentCommentId: parentCommentId,
});
return response.data;
};
29 changes: 24 additions & 5 deletions src/frontend/src/components/common/Comment.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
import { comment } from "@/types/board";
import { CrewGalleryDetailResponse } from "@/types/crew";
import { Dispatch, SetStateAction } from "react";

type CommentProps = {
comment: comment;
selectedComment?: number | null;
setSelectedComment?: Dispatch<SetStateAction<number | null>>;
};

const Comment = ({ comment }: CommentProps) => {
const Comment = ({
comment,
selectedComment,
setSelectedComment,
}: CommentProps) => {
const handleClick = (id: number) => {
if (setSelectedComment) {
if (selectedComment == id) {
setSelectedComment(null);
} else setSelectedComment(id);
}
};

return (
<div className="flex items-center gap-3 py-4">
<div
onClick={() => handleClick(comment.commentId)}
className={`flex items-center gap-3 py-4 ${
selectedComment === comment.commentId ? "bg-[#f7f7f7]" : ""
}`}
>
<div className="w-[40px] h-[40px] rounded-full overflow-hidden">
<img
className="w-full h-full object-cover"
src="https://blog.malcang.com/wp-content/uploads/2024/03/1-1.png"
alt=""
src={comment.profileImage}
alt="프로필"
/>
</div>
<div>
Expand Down
29 changes: 29 additions & 0 deletions src/frontend/src/components/common/CommentInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Dispatch, SetStateAction } from "react";

type CommentInputProps = {
comment: string;
setComment: Dispatch<SetStateAction<string>>;
onSubmit: () => void;
};

const CommentInput = ({ comment, setComment, onSubmit }: CommentInputProps) => {
return (
<div className="fixed bottom-0 left-0 z-[200] w-full bg-white border-t border-gray-300 px-4 py-4 flex items-center gap-2">
<input
type="text"
value={comment}
onChange={(e) => setComment(e.target.value)}
placeholder="댓글을 입력하세요"
className="flex-grow border border-gray-300 rounded-lg px-3 py-2 focus:outline-none focus:ring focus:ring-blue-300"
/>
<button
onClick={onSubmit}
className="bg-blue-500 text-white rounded-lg px-4 py-2 hover:bg-blue-600"
>
등록
</button>
</div>
);
};

export default CommentInput;
11 changes: 8 additions & 3 deletions src/frontend/src/components/common/Reply.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { ReactComponent as ReplyIcon } from "@/assets/icons/ReplyIcon.svg";
import Comment from "@/components/common/Comment";
import { comment, replies } from "@/types/board";
import Comment from "./Comment";

const Reply = () => {
type ReplyProps = {
reply: comment;
};

const Reply = ({ reply }: ReplyProps) => {
return (
<div className="ml-4 flex items-center gap-2">
<ReplyIcon />
{/* <Comment /> */}
<Comment comment={reply} />
</div>
);
};
Expand Down
21 changes: 18 additions & 3 deletions src/frontend/src/components/communityDetail/CommentsList.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
import Comment from "@/components/common/Comment";
import Reply from "@/components/common/Reply";
import { comment } from "@/types/board";
import { Dispatch, SetStateAction } from "react";

type CommentsListProps = {
comments: comment[];
selectedComment: number | null;
setSelectedComment: Dispatch<SetStateAction<number | null>>;
};

const CommentsList = ({ comments }: CommentsListProps) => {
const CommentsList = ({
comments,
selectedComment,
setSelectedComment,
}: CommentsListProps) => {
return (
<div>
{comments.map((comment) => (
<Comment comment={comment} />
<>
<Comment
key={comment.commentId}
comment={comment}
setSelectedComment={setSelectedComment}
selectedComment={selectedComment}
/>
{comment.replies &&
comment.replies.map((reply) => <Reply reply={reply} />)}
</>
))}
{/* <Reply /> */}
</div>
);
};
Expand Down
26 changes: 23 additions & 3 deletions src/frontend/src/hooks/useBoard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import {
getBoardData,
getBoardDetailData,
postBoard,
postBoardLike,
postBoardCommemt,
postBoardCommentLike,
searchBoard,
} from "@/apis/board";
import { boardRequest } from "@/types/board";
Expand Down Expand Up @@ -55,13 +56,13 @@ export const useBoardSearch = (boardName: string, keyword: string) => {
});
};

export const useBoardLike = (
export const useBoardCommentLike = (
boardName: string,
postId: number,
commentId: number
) => {
return useMutation({
mutationFn: () => postBoardLike(boardName, postId, commentId),
mutationFn: () => postBoardCommentLike(boardName, postId, commentId),
onSuccess: () => {
console.log("커뮤니티 좋아요 성공");
},
Expand All @@ -70,3 +71,22 @@ export const useBoardLike = (
},
});
};

export const useBoardCommentPost = (
boardName: string,
postId: number,
content: string,
parentCommentId: number | null
) => {
return useMutation({
mutationFn: () =>
postBoardCommemt(boardName, postId, content, parentCommentId),
onSuccess: () => {
console.log("커뮤니티 댓글 작성 성공");
window.location.reload();
},
onError: () => {
console.log("커뮤니티 댓글 작성 실패");
},
});
};
29 changes: 26 additions & 3 deletions src/frontend/src/pages/CommunityDetail/CommunityDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,27 @@ import { ReactComponent as HeartIcon } from "@/assets/icons/HeartIcon.svg";
import { ReactComponent as BackIcon } from "@/assets/icons/BackIcon.svg";
import { useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useBoardDetailGet } from "@/hooks/useBoard";
import { useBoardCommentPost, useBoardDetailGet } from "@/hooks/useBoard";
import Spinner from "@/components/common/Spinner";
import CommentInput from "@/components/common/CommentInput";

const CommunityDetailPage = () => {
const navigate = useNavigate();
const { id } = useParams();
const { id, board } = useParams();
const [isScrapped, setIsScrapped] = useState(false);
const [comment, setComment] = useState("");
const [selectedComment, setSelectedComment] = useState<number | null>(null);

const { mutate } = useBoardCommentPost(
String(board),
Number(id),
comment,
selectedComment
);
const handleCommentSubmit = () => {
console.log(comment);
mutate();
};

const { data, isLoading } = useBoardDetailGet({
boardName: "FREE",
Expand All @@ -24,6 +38,11 @@ const CommunityDetailPage = () => {
) : (
data && (
<>
<CommentInput
comment={comment}
setComment={setComment}
onSubmit={handleCommentSubmit}
/>
<div className="shadow-sm w-full flex justify-start p-4 mb-6">
<BackIcon onClick={() => navigate("/community")} />
</div>
Expand All @@ -36,7 +55,11 @@ const CommunityDetailPage = () => {
stroke={isScrapped ? "#F17171" : "#afafaf"}
/>
</div>
<CommentsList comments={data.comments} />
<CommentsList
comments={data.comments}
setSelectedComment={setSelectedComment}
selectedComment={selectedComment}
/>
</div>
</>
)
Expand Down
4 changes: 3 additions & 1 deletion src/frontend/src/types/board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@ export type replies = {
commentId: number;
content: string;
writer: string;
profileImage?: string;
createdAt: string;
};

export type comment = {
commentId: number;
content: string;
writer: string;
profileImage?: string;
createdAt: string;
replies: replies[];
replies?: replies[]; // replies와 타입 통일을 위함
};

export type boardDetailResponse = {
Expand Down

0 comments on commit 111c640

Please sign in to comment.