Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feat/#79' into feat/#31
Browse files Browse the repository at this point in the history
  • Loading branch information
SoRaang committed Dec 9, 2024
2 parents 64c82d3 + ff324fe commit f6bb0f8
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 38 deletions.
57 changes: 55 additions & 2 deletions src/api/threadApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const getArticleMarkers = async (
}
};

// 장소 상세 정보 조회
// 글타래 업체/시설 상세 정보 조회
export const getPlaceDetail = async (articleId) => {
try {
const response = await axiosInstance({
Expand All @@ -87,7 +87,60 @@ export const getPlaceDetail = async (articleId) => {

return response.data;
} catch (error) {
console.error('장소 상세 정보 로드 실패:', error.message);
console.error('업체/시설 상세 정보 로드 실패:', error.message);
throw error;
}
};

// 글타래 댓글 조회
export const getComments = async (articleId) => {
try {
const response = await axiosInstance.get(
`/comments/article/${articleId}`,
);
return response.data;
} catch (error) {
if (error.response?.status === 404) {
return [];
}
throw error;
}
};

// 글타래 댓글 작성
export const postComment = async (commentData) => {
try {
const response = await axiosInstance.post(
'/comments/article',
commentData,
);
return response.data;
} catch (error) {
console.error('댓글 작성 실패:', error);
throw error;
}
};

// 글타래 댓글 수정
export const updateComment = async (commentId, commentData) => {
try {
const response = await axiosInstance.put(
`/comments/${commentId}`,
commentData,
);
return response.data;
} catch (error) {
console.error('댓글 수정 실패:', error);
throw error;
}
};

// 글타래 댓글 삭제
export const deleteComments = async (deleteData) => {
try {
await axiosInstance.delete('/comments', { data: deleteData });
} catch (error) {
console.error('댓글 삭제 실패:', error);
throw error;
}
};
Expand Down
22 changes: 10 additions & 12 deletions src/components/common/ReplyItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,20 @@ import NameTag from './NameTag';
import Remix from './Remix';

const ReplyItem = ({
index = 0,
userObject = { userID: 0, userImage: null, userName: '홍길동' },
replyContent = '작성된 내용이 없어요.',
writtenDateTime = '1970-01-01',
isMyReply = false,
isEditMode = false,
index,
userObject,
replyContent,
writtenDateTime,
isMyReply,
isEditMode,
onEdit,
onDelete,
}) => {
return (
<article className="reply-item">
{isEditMode && (
<div className="reply-item-checkbox-wrapper">
<input type="checkbox" id={`chkReplyItem${index}`} />

<label htmlFor={`chkReplyItem${index}`}>
<div className="toggles-indicator">
<Remix iconName={'check-line'} iconSize={0.6} />
Expand All @@ -28,22 +29,19 @@ const ReplyItem = ({
<div className="reply-item-body">
<div className="reply-item-user">
<NameTag userObject={userObject} />

{isMyReply && (
<div className="reply-item-user-controls">
<p>수정</p>
<p onClick={() => onEdit(replyContent)}>수정</p>
<span>·</span>
<p>삭제</p>
<p onClick={onDelete}>삭제</p>
</div>
)}
</div>

<div className="reply-content-wrapper">
<div className="reply-depth-indicator"></div>

<div className="reply-content-container">
<div className="reply-content-text">{replyContent}</div>

<div className="datetime-row reply-item-datetime">
<p>{dateFormat(writtenDateTime)}</p>
<span>·</span>
Expand Down
136 changes: 112 additions & 24 deletions src/pages/ReplyList.jsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,132 @@
import { useState } from 'react';
import { useState, useEffect } from 'react';
import { useModalStore } from '../stores/modalStatus';
import EmptyList from '../components/common/EmptyList';
import ModalFormInput from '../components/common/ModalFormInput';
import ReplyItem from '../components/common/ReplyItem';
import {
getComments,
postComment,
updateComment,
deleteComments,
} from '../api/threadApi';

const ReplyList = () => {
const [replyArray, setNewReply] = useState([]);

const handleWriteReply = (inputObject) => {
setNewReply([
...replyArray,
{
userObject: { userID: 0, userImage: null, userName: '홍길동' },
replyContent: inputObject.formText,
writtenDateTime: new Date(),
},
]);
const [comments, setComments] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const modalData = useModalStore((state) => state.modalData);

useEffect(() => {
const fetchComments = async () => {
if (!modalData?.setObject?.articleId) return;
try {
const data = await getComments(modalData.setObject.articleId);
setComments(data || []);
} catch (err) {
setError('댓글을 불러오는데 실패했습니다.');
} finally {
setLoading(false);
}
};
fetchComments();
}, [modalData?.setObject?.articleId]);

const handleWriteReply = async (inputObject) => {
if (!inputObject.formText.trim()) return;
try {
const response = await postComment({
memberId: 1,
articleId: modalData.setObject.articleId,
content: inputObject.formText,
});

const newComment = {
...response,
userObject: {
userID: response.memberId,
userImage: response.profileImage,
userName: response.nickname.value,
},
replyContent: response.content,
writtenDateTime: response.createdAt,
};

setComments((prev) => ({
...prev,
content: [...prev.content, newComment],
}));
} catch (err) {
console.error('댓글 작성 실패:', err);
}
};

if (loading) return <div>로딩 중...</div>;
if (error) return <div>{error}</div>;
if (!comments) return <div>댓글을 찾을 수 없습니다.</div>;

const handleEditReply = async (commentId, content) => {
try {
const response = await updateComment(commentId, {
memberId: 1,
content,
});
setComments((prev) => ({
...prev,
content: prev.content.map((comment) =>
comment.commentId === commentId ? response : comment,
),
}));
} catch (err) {
console.error('댓글 수정 실패:', err);
}
};

const handleDeleteReply = async (commentId) => {
try {
await deleteComments({
memberId: 1,
commentIds: [commentId],
});
setComments((prev) => ({
...prev,
content: prev.content.filter(
(comment) => comment.commentId !== commentId,
),
}));
} catch (err) {
console.error('댓글 삭제 실패:', err);
}
};

return (
<div>
<div id="reply-list" className="user-common-item-list">
{replyArray.length > 0 ? (
replyArray.map((item, index) => {
return (
<ReplyItem
index={index}
replyContent={item.replyContent}
writtenDateTime={item.writtenDateTime}
key={index}
/>
);
})
{comments.content?.length > 0 ? (
comments.content.map((item, index) => (
<ReplyItem
key={item.commentId}
index={index}
userObject={{
userID: item.memberId,
userImage: item.profileImage,
userName: item.nickname.value,
}}
replyContent={item.content}
writtenDateTime={item.createdAt}
isMyReply={item.memberId === 1}
onEdit={(content) =>
handleEditReply(item.commentId, content)
}
onDelete={() => handleDeleteReply(item.commentId)}
/>
))
) : (
<EmptyList placeHolderText="아직 댓글이 없어요. 첫 댓글을 작성해 보는 건 어떨까요?" />
)}
</div>

<div id="reply-input-container">
<hr />

<ModalFormInput
isIncludeImage={false}
isHorizontal={true}
Expand Down

0 comments on commit f6bb0f8

Please sign in to comment.