From bde5f3b820bea42f0ddda3ee7b33aa5306f56a76 Mon Sep 17 00:00:00 2001 From: Vanessa Lai Date: Tue, 9 Jul 2024 18:11:19 +0800 Subject: [PATCH] finished css and small bug fixes --- src/components/forumcards/ForumCards.css | 2 +- src/components/forumcards/ForumCards.jsx | 26 +++++ .../header/likecounter/LikeCounter.jsx | 37 +++--- src/pages/forumpost/ForumPost.css | 7 +- src/pages/forumpost/ForumPost.jsx | 108 ++++++++++++------ 5 files changed, 125 insertions(+), 55 deletions(-) diff --git a/src/components/forumcards/ForumCards.css b/src/components/forumcards/ForumCards.css index 3d0dc70..edfb27e 100644 --- a/src/components/forumcards/ForumCards.css +++ b/src/components/forumcards/ForumCards.css @@ -139,7 +139,7 @@ display: inline-block; } - .forum-card-like { + .forum-card-like, .forum-card-comment { display: flex; align-items: center; gap: 2px; diff --git a/src/components/forumcards/ForumCards.jsx b/src/components/forumcards/ForumCards.jsx index 2274312..89efab6 100644 --- a/src/components/forumcards/ForumCards.jsx +++ b/src/components/forumcards/ForumCards.jsx @@ -41,6 +41,7 @@ function ForumCards({ forumDetail }) { const [showResults, setShowResults] = useState(false); const [isLiked, setIsLiked] = useState(false); const [likeCount, setLikeCount] = useState(0); + const [commentCount, setCommentCount] = useState(0); useEffect(() => { const fetchUser = async () => { @@ -52,6 +53,22 @@ function ForumCards({ forumDetail }) { } }; + const fetchAndCountComments = async () => { + const commentsRef = collection(db, 'Forum', forumDetail.id, 'Comments'); + const commentsSnapshot = await getDocs(commentsRef); + + const fetchedComments = await Promise.all(commentsSnapshot.docs.map(async doc => { + const comment = { id: doc.id, ...doc.data() }; + const repliesRef = collection(db, 'Forum', forumDetail.id, 'Comments', doc.id, 'Replies'); + const repliesSnapshot = await getDocs(repliesRef); + comment.replies = repliesSnapshot.docs.map(replyDoc => ({ id: replyDoc.id, ...replyDoc.data() })); + return comment; + })); + + const totalCount = countCommentsAndReplies(fetchedComments); + setCommentCount(totalCount); + }; + const checkLikeStatus = async () => { if (currentUser) { const likesRef = collection(db, 'Forum', forumDetail.id, 'Likes'); @@ -70,6 +87,7 @@ function ForumCards({ forumDetail }) { fetchUser(); checkLikeStatus(); getLikeCount(); + fetchAndCountComments(); if (currentUser) { if (currentUser.uid === forumDetail.userID) { @@ -251,6 +269,12 @@ function ForumCards({ forumDetail }) { } }; + const countCommentsAndReplies = (comments) => { + return comments.reduce((total, comment) => { + return total + 1 + (comment.replies ? countCommentsAndReplies(comment.replies) : 0); + }, 0); + }; + const tagColors = { "Questions": "#FF4B2B", "Modding": "#4CAF50", @@ -360,6 +384,7 @@ function ForumCards({ forumDetail }) {
+ {commentCount}
@@ -370,4 +395,5 @@ function ForumCards({ forumDetail }) {
); } + export default ForumCards; \ No newline at end of file diff --git a/src/components/header/likecounter/LikeCounter.jsx b/src/components/header/likecounter/LikeCounter.jsx index 5639564..2f1e600 100644 --- a/src/components/header/likecounter/LikeCounter.jsx +++ b/src/components/header/likecounter/LikeCounter.jsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useState, useEffect } from 'react'; +import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; import { db } from '../../../lib/firebaseConfig'; import { doc, getDoc, setDoc, onSnapshot, collection } from 'firebase/firestore'; import { useAuth } from '../../../Auth'; @@ -11,28 +11,27 @@ export const LikeCountProvider = ({ children }) => { const { currentUser } = useAuth(); const [likeCount, setLikeCount] = useState(0); - useEffect(() => { + const fetchLikeCount = useCallback(async () => { if (currentUser) { - const fetchLikeCount = async () => { - const likeCountDoc = doc(db, 'Users', currentUser.uid, 'likeCount', 'counter'); + const likeCountDoc = doc(db, 'Users', currentUser.uid, 'likeCount', 'counter'); + try { const likeCountSnapshot = await getDoc(likeCountDoc); - if (likeCountSnapshot.exists()) { setLikeCount(likeCountSnapshot.data().count); } else { - try { - await setDoc(likeCountDoc, { count: 0 }); - setLikeCount(0); - } catch (err) { - console.log(err.message); - } + await setDoc(likeCountDoc, { count: 0 }); + setLikeCount(0); } - }; - - fetchLikeCount(); + } catch (err) { + console.log(err.message); + } } }, [currentUser]); + useEffect(() => { + fetchLikeCount(); + }, [fetchLikeCount]); + useEffect(() => { if (currentUser) { const unsubscribe = onSnapshot(doc(db, 'Users', currentUser.uid, 'likeCount', 'counter'), (doc) => { @@ -52,21 +51,21 @@ export const LikeCountProvider = ({ children }) => { } }; - const increaseLikeCount = () => { + const increaseLikeCount = useCallback(() => { setLikeCount((prevCount) => { const newCount = prevCount + 1; updateLikeCountInFirestore(newCount); return newCount; }); - }; + }, [updateLikeCountInFirestore]); - const decreaseLikeCount = () => { + const decreaseLikeCount = useCallback(() => { setLikeCount((prevCount) => { const newCount = prevCount > 0 ? prevCount - 1 : 0; updateLikeCountInFirestore(newCount); return newCount; }); - }; + }, [updateLikeCountInFirestore]); useEffect(() => { if (currentUser) { @@ -82,7 +81,7 @@ export const LikeCountProvider = ({ children }) => { return () => unsubscribe(); } - }, [currentUser]); + }, [currentUser, decreaseLikeCount]); return ( diff --git a/src/pages/forumpost/ForumPost.css b/src/pages/forumpost/ForumPost.css index b9b2eb4..b0ee399 100644 --- a/src/pages/forumpost/ForumPost.css +++ b/src/pages/forumpost/ForumPost.css @@ -225,7 +225,7 @@ display: inline-block; } - .forum-card-like { + .forum-card-like, .forum-card-comment { display: flex; align-items: center; gap: 2px; @@ -310,7 +310,6 @@ .comment { border-left: 1px solid rgb(194, 194, 194); - margin: 16px; padding: 8px; .comment-header { @@ -323,6 +322,7 @@ .comment-profile { display: flex; + cursor: pointer; flex-direction: row; align-items: center; gap: 4px; @@ -339,6 +339,7 @@ .comment-content { margin: 0; + padding-bottom: 8px; } .comment-reply-button { @@ -363,6 +364,8 @@ } .comment-reply { + margin: 8px 0; + textarea { font-size: 16px; border-radius: 12px; diff --git a/src/pages/forumpost/ForumPost.jsx b/src/pages/forumpost/ForumPost.jsx index d17a415..778b8d4 100644 --- a/src/pages/forumpost/ForumPost.jsx +++ b/src/pages/forumpost/ForumPost.jsx @@ -37,7 +37,7 @@ function timeSincePost(postDate) { } } -const Comment = ({ comment, postID, onReply, currentUser }) => { +const Comment = ({ comment, postID, onReply, currentUser, depth = 0, parentId = '' }) => { const [user, setUser] = useState(null); const [showReplyForm, setShowReplyForm] = useState(false); const [replyContent, setReplyContent] = useState(''); @@ -55,7 +55,8 @@ const Comment = ({ comment, postID, onReply, currentUser }) => { const handleReply = async (e) => { e.preventDefault(); if (replyContent.trim() === '') return; - await onReply(comment.id, replyContent); + const replyId = parentId ? `${parentId}-${comment.id}` : comment.id; + await onReply(replyId, replyContent, depth + 1); setReplyContent(''); setShowReplyForm(false); }; @@ -65,15 +66,19 @@ const Comment = ({ comment, postID, onReply, currentUser }) => { }; return ( -
+
{user && (
- {user.profilePic} + {`${user.username}'s

{user.username}

-

{timeSincePost(post.postDate)}

+

{timeSincePost(comment.timestamp)}

)} @@ -92,7 +97,15 @@ const Comment = ({ comment, postID, onReply, currentUser }) => { )} {comment.replies && comment.replies.map(reply => ( - + ))}
); @@ -113,6 +126,7 @@ function ForumPostPage() { const [replyingTo, setReplyingTo] = useState(null); const commentTextareaRef = useRef(null); const [dropdownOpen, setDropdownOpen] = useState(false); + const [commentCount, setCommentCount] = useState(0); useEffect(() => { const fetchPost = async () => { @@ -133,15 +147,7 @@ function ForumPostPage() { } const fetchComments = async () => { - const commentsQuery = query(collection(db, 'Forum', postID, 'Comments')); - const commentsSnapshot = await getDocs(commentsQuery); - const commentsData = await Promise.all(commentsSnapshot.docs.map(async doc => { - const comment = { id: doc.id, ...doc.data() }; - const repliesQuery = query(collection(db, 'Forum', postID, 'Comments', doc.id, 'Replies')); - const repliesSnapshot = await getDocs(repliesQuery); - comment.replies = repliesSnapshot.docs.map(replyDoc => ({ id: replyDoc.id, ...replyDoc.data() })); - return comment; - })); + const commentsData = await fetchCommentsRecursively(postID); setComments(commentsData); }; @@ -187,7 +193,13 @@ function ForumPostPage() { } }, [postID, currentUser, post]); - const handleComment = async (e, commentId = null, content = null) => { + const countCommentsAndReplies = (comments) => { + return comments.reduce((total, comment) => { + return total + 1 + (comment.replies ? countCommentsAndReplies(comment.replies) : 0); + }, 0); + }; + + const handleComment = async (e, commentId = null, content = null, depth = 0) => { e.preventDefault(); if (!currentUser) { alert('Please log in to comment.'); @@ -195,18 +207,33 @@ function ForumPostPage() { } const commentContent = content || newComment; if (commentContent.trim() === '') return; - + const commentData = { content: commentContent, userId: currentUser.uid, timestamp: new Date() }; - + try { + let commentRef; if (commentId) { - await addDoc(collection(db, 'Forum', postID, 'Comments', commentId, 'Replies'), commentData); + const replyChain = commentId.split('-'); + let currentRef = collection(db, 'Forum', postID, 'Comments'); + for (let i = 0; i < replyChain.length; i++) { + if (i === replyChain.length - 1) { + currentRef = doc(currentRef, replyChain[i]); + } else { + currentRef = collection(currentRef, replyChain[i], 'Replies'); + } + } + commentRef = collection(currentRef, 'Replies'); } else { - await addDoc(collection(db, 'Forum', postID, 'Comments'), commentData); + commentRef = collection(db, 'Forum', postID, 'Comments'); + } + + const newCommentRef = await addDoc(commentRef, commentData); + + if (!commentId) { await addDoc(collection(db, 'Notifications'), { recipientID: post.userID, senderID: currentUser.uid, @@ -216,24 +243,38 @@ function ForumPostPage() { timestamp: new Date() }); } - + setNewComment(''); setReplyingTo(null); - const commentsQuery = query(collection(db, 'Forum', postID, 'Comments')); - const commentsSnapshot = await getDocs(commentsQuery); - const commentsData = await Promise.all(commentsSnapshot.docs.map(async doc => { - const comment = { id: doc.id, ...doc.data() }; - const repliesQuery = query(collection(db, 'Forum', postID, 'Comments', doc.id, 'Replies')); - const repliesSnapshot = await getDocs(repliesQuery); - comment.replies = repliesSnapshot.docs.map(replyDoc => ({ id: replyDoc.id, ...replyDoc.data() })); - return comment; - })); - setComments(commentsData); + + const updatedComments = await fetchCommentsRecursively(postID); + setComments(updatedComments); + setCommentCount(countCommentsAndReplies(updatedComments)); } catch (error) { console.error("Error adding comment:", error); } }; + const fetchCommentsRecursively = async (postID, parentRef = null) => { + const commentsQuery = parentRef + ? query(collection(parentRef, 'Replies')) + : query(collection(db, 'Forum', postID, 'Comments')); + const commentsSnapshot = await getDocs(commentsQuery); + + const fetchedComments = await Promise.all(commentsSnapshot.docs.map(async doc => { + const comment = { id: doc.id, ...doc.data() }; + comment.replies = await fetchCommentsRecursively(postID, doc.ref); + return comment; + })); + + if (!parentRef) { + const totalCount = countCommentsAndReplies(fetchedComments); + setCommentCount(totalCount); + } + + return fetchedComments; + }; + const handleLike = async (e) => { e.stopPropagation(); @@ -245,7 +286,7 @@ function ForumPostPage() { try { await addDoc(collection(db, 'Forum', postID, 'Likes'), { userID: currentUser.uid, - timestamp: new Date() + timestamp: new Date().toISOString() }); setIsLiked(true); setLikeCount(prevCount => prevCount + 1); @@ -256,7 +297,7 @@ function ForumPostPage() { listingID: postID, type: 'forum-like', read: false, - timestamp: new Date() + timestamp: new Date().toISOString() }); } catch (err) { console.error("Error liking post:", err.message); @@ -502,6 +543,7 @@ function ForumPostPage() {
+ {commentCount}