Entry Footer ์์ ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ๋ค๊ณผ ๋๊ธ๋ค์ ๋ณด์ฌ์ค๊ฒ์ด๋ค.
Comment Input ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด ๋๊ธ์ ์ ๋ ฅํ๋ค.
Entry page์์ ๊ฐ์ง๊ณ ์๋ docId ๊ฐ์ผ๋ก ๊ธ์ ๋ง๋ ๋๊ธ๋ค๋ง ๋ถ๋ฌ์ฌ๊ฒ์ด๋ค.
๋๊ธ ์์ ๊ณผ ๋ต๊ธ ๊ธฐ๋ฅ์ ๊ตฌํํ ๊ฒ์ด๋ค.
Comments Database
์ต๋ช ์์ฑ์ ์ํด ์์ฑ์ ์ด๋ฆ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ์ ๋ ฅ๋ฐ์.
๊ธ์ ์์ด๋์ ๋ง๋ ๋๊ธ๋ค์ ๋ถ๋ฌ์ค๊ธฐ ์ํด docId ๋ฅผ ์ ์ฅ.
- nickname(์์ฑ์ ์ด๋ฆ)
- password(์์ /์ญ์ ์ฉ ๋น๋ฐ๋ฒํธ)
- comment(๋๊ธ)
- docId(๊ธ id)
- edited(์์ ๋จ ํ์ ์ฌ๋ถ)
- avatar(๋๊ธ ์๋ฐํ)
//EntryFooter.tsx
const getNotes = async (category: string) => {
try {
const q = query(
collection(dbService, "notes"),
where("category", "==", category as string),
orderBy("createdAt", "desc"),
limit(3)
);
onSnapshot(q, (snapshot) => {
const notesArr: any = snapshot.docs.map((note) => ({
id: note.id + "",
...note.data(),
}));
setNotes(notesArr);
});
} catch (error: any) {}
};
const [selectedCategory, setSelectedCategory] =
useRecoilState<string>(selectedCategoryAtom);
const onOtherNotesClicked = () => {
setSelectedCategory(category);
navigation(`/notes/${encodeURIComponent(selectedCategory).toLowerCase()}`);
};
//CommentInput.tsx
const [nickname, setNickname] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [comment, setComment] = useState<string>("");
Input ์ผ๋ก ๋๋ค์,๋น๋ฐ๋ฒํธ,๋๊ธ์ ์ ๋ ฅ๋ฐ๋๋ค.
//CommentInput.tsx
const onAddButtonClicked = async () => {
if (nickname === "" || password === "" || comment === "") {
toast({
title: "๋น์นธ์ด ์์ต๋๋ค.",
position: "top",
status: "error",
isClosable: true,
});
return;
}
if (nickname.length > 15) {
toast({
title: `๋๋ค์์ด ๋๋ฌด ๊น๋๋ค..( ${nickname.length} / 15 )`,
position: "top",
status: "error",
isClosable: true,
});
return;
}
if (comment.length > 500) {
toast({
title: `๋๊ธ์ด ๋๋ฌด ๊น๋๋ค..( ${comment.length} / 500 )`,
position: "top",
status: "error",
isClosable: true,
});
return;
}
await addDoc(collection(dbService, "comments"), {
docId: docId,
avatar: userIcon.string,
nickname: nickname,
password: password,
comment: comment,
createdAt: Date.now(),
edited: false,
});
toast({
title: "๋๊ธ์์ฑ ์๋ฃ!",
position: "top",
isClosable: true,
});
};
๋๊ธ ์์ฑ ๋ฒํผ์ ํด๋ฆญํ์๋, db ์ฉ๋์ ์ํด ๋๋ค์๊ณผ ๋๊ธ ๊ธ์์์ ์ ํ์ ๋๋ค. ์กฐ๊ฑด์ด ๋ง์ผ๋ฉด addDoc ๋ฉ์๋๋ก comments ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ถ๊ฐํด์ค๋ค.
//Comments.tsx
export default function Comments({ docId }: ICommentsProps) {
const getComments = async (docId: string) => {
try {
const q = query(
collection(dbService, "comments"),
where("docId", "==", docId),
orderBy("createdAt", "desc")
);
onSnapshot(q, (snapshot) => {
const commentsArr: any = snapshot.docs.map((comment) => ({
id: comment.id + "",
...comment.data(),
}));
setComments(commentsArr);
});
} catch (error: any) {}
};
useEffect(() => {
getComments(docId);
}, [docId]);
...
return (
<>
<Center w="full" h={"auto"} flexDir={"column"} gap={4} bgColor={bgColor}>
{comments?.map((comment) => (
<Comment
key={comment.id}
commentId={comment.id}
nickname={comment.nickname}
password={comment.password}
avatar={comment.avatar}
comment={comment.comment}
createdAt={comment.createdAt}
edited={comment.edited}
/>
))}
</Center>
</>
);
}
docId๋ฅผ props๋ก ๋ฐ์ docId๊ฐ ์ผ์นํ๋ ๋๊ธ๋ค๋ง ๋ถ๋ฌ์จ๋ค , comment ์ปดํฌ๋ํธ์ ๋ณด๋ด์ค๋ค.
//Comment.tsx
interface ICommentProps {
nickname: string;
password: string;
avatar: string;
comment: string;
createdAt: number;
commentId: string;
edited: boolean;
}
comment props๋ฅผ ์ค์ ํด์ค๋ค.
commentId๋ ๋ต๊ธ์ ์ํด ๋๊ธ์ Id๋ฅผ ์ ์ฅํด๋๋๋ค.
edit,reply,delete ๊ธฐ๋ฅ์ ์ํด ๋ฒํผ 3๊ฐ๋ฅผ ๊ตฌํํ๋ค.
//Comment.tsx
const [isEdit, setIsEdit] = useState(false);
const [isReply, setIsReply] = useState(false);
//CommentDeleteModal.tsx
const onDeleteClick = async () => {
let commentsRef = null;
if (isReply) {
commentsRef = doc(dbService, "replyComments", commentId!);
} else {
commentsRef = doc(dbService, "comments", commentId!);
}
if (password !== checkPassword) {
toast({
title: "๋น๋ฐ๋ฒํธ๊ฐ ํ๋ฆฝ๋๋ค",
position: "top",
isClosable: true,
status: "error",
});
} else {
await deleteDoc(commentsRef);
toast({
title: "์ญ์ ์๋ฃ!",
position: "top",
isClosable: true,
});
onClose();
}
};
const getReplyComments = async (commentId: string) => {
try {
const q = query(
collection(dbService, "replyComments"),
where("commentId", "==", commentId),
orderBy("createdAt", "asc")
);
onSnapshot(q, (snapshot) => {
const commentsArr: any = snapshot.docs.map((comment) => ({
id: comment.id + "",
...comment.data(),
}));
setReplyComments(commentsArr);
});
} catch (error: any) {}
};
ํด๋น ๋๊ธ id์ ๋ง๋ ๋ต๊ธ๋ค์ ๋ถ๋ฌ์จ๋ค.