diff --git a/index.html b/index.html index 275b444d..5d34024f 100644 --- a/index.html +++ b/index.html @@ -2,11 +2,9 @@ - Codelabz -
diff --git a/less.config.js b/less.config.js index 5b997099..2faad74d 100644 --- a/less.config.js +++ b/less.config.js @@ -1,4 +1,4 @@ -const lessOptions = { +export const lessOptions = { lessOptions: { javascriptEnabled: true, modifyVars: { @@ -10,7 +10,3 @@ const lessOptions = { } } }; - -module.exports = { - lessOptions -}; diff --git a/src/components/AuthPage/smButton/smButtons.jsx b/src/components/AuthPage/smButton/smButtons.jsx index 226c31f4..2f904102 100644 --- a/src/components/AuthPage/smButton/smButtons.jsx +++ b/src/components/AuthPage/smButton/smButtons.jsx @@ -26,11 +26,11 @@ const SmButtons = () => { }} > - - signInWithGoogle()(firebase, dispatch)} - className={classes.google} - > + signInWithGoogle()(firebase, dispatch)} + > + google diff --git a/src/components/Card/CardWithPicture.jsx b/src/components/Card/CardWithPicture.jsx index e8cd65c2..bb0c37a7 100644 --- a/src/components/Card/CardWithPicture.jsx +++ b/src/components/Card/CardWithPicture.jsx @@ -15,13 +15,11 @@ import ShareOutlinedIcon from "@mui/icons-material/ShareOutlined"; import ChatOutlinedIcon from "@mui/icons-material/ChatOutlined"; import TurnedInNotOutlinedIcon from "@mui/icons-material/TurnedInNotOutlined"; import MoreVertOutlinedIcon from "@mui/icons-material/MoreVertOutlined"; -import { ToggleButton, ToggleButtonGroup } from "@mui/material"; -import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import { Link } from "react-router-dom"; import { useDispatch, useSelector } from "react-redux"; import { useFirebase, useFirestore } from "react-redux-firebase"; import { getUserProfileData } from "../../store/actions"; +import TutorialLikesDislikes from "../ui-helpers/TutorialLikesDislikes"; const useStyles = makeStyles(theme => ({ root: { @@ -73,22 +71,9 @@ const useStyles = makeStyles(theme => ({ export default function CardWithPicture({ tutorial }) { const classes = useStyles(); - const [alignment, setAlignment] = React.useState("left"); - const [count, setCount] = useState(1); const dispatch = useDispatch(); const firebase = useFirebase(); const firestore = useFirestore(); - const handleIncrement = () => { - setCount(count + 1); - }; - - const handleDecrement = () => { - setCount(count - 1); - }; - - const handleAlignment = (event, newAlignment) => { - setAlignment(newAlignment); - }; useEffect(() => { getUserProfileData(tutorial?.created_by)(firebase, firestore, dispatch); @@ -189,32 +174,7 @@ export default function CardWithPicture({ tutorial }) { {"10 min"}
- - - - {count} - - - - - + diff --git a/src/components/Card/CardWithoutPicture.jsx b/src/components/Card/CardWithoutPicture.jsx index abc4ecb0..b5caed3b 100644 --- a/src/components/Card/CardWithoutPicture.jsx +++ b/src/components/Card/CardWithoutPicture.jsx @@ -14,13 +14,11 @@ import ShareOutlinedIcon from "@mui/icons-material/ShareOutlined"; import ChatOutlinedIcon from "@mui/icons-material/ChatOutlined"; import TurnedInNotOutlinedIcon from "@mui/icons-material/TurnedInNotOutlined"; import MoreVertOutlinedIcon from "@mui/icons-material/MoreVertOutlined"; -import ToggleButton from "@mui/lab/ToggleButton"; -import ToggleButtonGroup from "@mui/lab/ToggleButtonGroup"; -import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import { useDispatch, useSelector } from "react-redux"; import { useFirebase, useFirestore } from "react-redux-firebase"; import { getUserProfileData } from "../../store/actions"; +import TutorialLikesDislikes from "../ui-helpers/TutorialLikesDislikes"; + const useStyles = makeStyles(theme => ({ root: { margin: "0.5rem", @@ -67,22 +65,9 @@ const useStyles = makeStyles(theme => ({ export default function CardWithoutPicture({ tutorial }) { const classes = useStyles(); - const [alignment, setAlignment] = React.useState("left"); - const [count, setCount] = useState(1); const dispatch = useDispatch(); const firebase = useFirebase(); const firestore = useFirestore(); - const handleIncrement = () => { - setCount(count + 1); - }; - - const handleDecrement = () => { - setCount(count - 1); - }; - - const handleAlignment = (event, newAlignment) => { - setAlignment(newAlignment); - }; useEffect(() => { getUserProfileData(tutorial?.created_by)(firebase, firestore, dispatch); @@ -178,32 +163,7 @@ export default function CardWithoutPicture({ tutorial }) { {"10 min"}
- - - - {count} - - - - - + diff --git a/src/components/CardTabs/Events/index.jsx b/src/components/CardTabs/Events/index.jsx index 2605b29b..c3042e55 100644 --- a/src/components/CardTabs/Events/index.jsx +++ b/src/components/CardTabs/Events/index.jsx @@ -37,14 +37,14 @@ const EventsCard = props => {
- + {props.title} {props.events.map(function (event, index) { @@ -54,23 +54,23 @@ const EventsCard = props => { container direction="row" spacing={2} - data-testId={index == 0 ? "upEventBox" : ""} + data-testid={index == 0 ? "upEventBox" : ""} > - + {event.name} {event.date} diff --git a/src/components/CardTabs/Tags/index.jsx b/src/components/CardTabs/Tags/index.jsx index 8a566662..4bbd14d2 100644 --- a/src/components/CardTabs/Tags/index.jsx +++ b/src/components/CardTabs/Tags/index.jsx @@ -41,14 +41,14 @@ const TagCard = props => { const classes = useStyles(); return ( -
+
Popular Tags @@ -61,7 +61,7 @@ const TagCard = props => { label={tag} id={index} className={classes.chip} - data-testId={index === 0 ? "TagsChip" : ""} + data-testid={index === 0 ? "TagsChip" : ""} /> ); })} diff --git a/src/components/CardTabs/Users/UserElement.jsx b/src/components/CardTabs/Users/UserElement.jsx index 2a6c2a9c..05fcebe5 100644 --- a/src/components/CardTabs/Users/UserElement.jsx +++ b/src/components/CardTabs/Users/UserElement.jsx @@ -15,7 +15,7 @@ const UserElement = ({ user, index, useStyles }) => { key: "user" + { index }, mb: 1.5 }} - gutterBottom + gutterbottom="true" > - + {/* 750 ? true : undefined} xs={2} className={classes.sideBody}> */} + 750 ? true : undefined} + xs={windowSize.width > 750 ? 2 : undefined} + className={classes.sideBody} + > {windowSize.width > 750 && ( 750 ? true : undefined} className={classes.leftSideCard} direction="column" style={{ @@ -216,17 +222,22 @@ function HomePage({ background = "white", textColor = "black" }) { boxShadow: "none" }} > - + 750 ? true : undefined} + className={classes.outerSideBar} + > )} 750 ? true : undefined} className={classes.mainBody} - data-testId="homepageMainBody" - xs={6} + data-testid="homepageMainBody" + xs={windowSize.width > 750 ? 6 : undefined} > - + 750 ? true : undefined} + sx={{ display: { md: "none" } }} + > {tutorials.map(tutorial => { @@ -257,7 +272,7 @@ function HomePage({ background = "white", textColor = "black" }) { - + 750 ? true : undefined} + className={classes.sideBody} + xs={windowSize.width > 750 ? 3 : undefined} + > 750 ? true : undefined} alignContent="center" direction="column" style={{ width: "100%" }} - data-testId="homepageTagSidebar" + data-testid="homepageTagSidebar" > - + 750 ? true : undefined} + style={{ minWidth: "100%" }} + > @@ -325,9 +349,13 @@ function HomePage({ background = "white", textColor = "black" }) { style={{ width: "100%" }} - data-testId="homepageUpcomingEvents" + data-testid="homepageUpcomingEvents" > - + 750 ? true : undefined} + style={{ minWidth: "100%" }} + > @@ -338,9 +366,13 @@ function HomePage({ background = "white", textColor = "black" }) { style={{ width: "100%" }} - data-testId="homepageUsersToFollow" + data-testid="homepageUsersToFollow" > - + 750 ? true : undefined} + style={{ minWidth: "100%" }} + > @@ -356,9 +388,13 @@ function HomePage({ background = "white", textColor = "black" }) { border: "none", boxShadow: "none" }} - data-testId="homepageContributors" + data-testid="homepageContributors" > - + 750 ? true : undefined} + style={{ minWidth: "100%" }} + > @@ -370,9 +406,13 @@ function HomePage({ background = "white", textColor = "black" }) { style={{ width: "100%" }} - data-testId="homepagePopularEventSidebar" + data-testid="homepagePopularEventSidebar" > - + 750 ? true : undefined} + style={{ minWidth: "100%" }} + > diff --git a/src/components/NavBar/new/MiniNavbar/index.jsx b/src/components/NavBar/new/MiniNavbar/index.jsx index 596e4e5b..ae9579a9 100644 --- a/src/components/NavBar/new/MiniNavbar/index.jsx +++ b/src/components/NavBar/new/MiniNavbar/index.jsx @@ -131,13 +131,12 @@ function MiniNavbar() { - - {window.innerWidth > 960 && ( - toggleDrawer(true)} /> - )} - {window.innerWidth <= 960 && ( - toggleSlider()} /> - )} + + window.innerWidth > 960 ? toggleDrawer(true) : toggleSlider() + } + > + diff --git a/src/components/SideBar/sidelist.jsx b/src/components/SideBar/sidelist.jsx index abc8d879..8d8edd7a 100644 --- a/src/components/SideBar/sidelist.jsx +++ b/src/components/SideBar/sidelist.jsx @@ -91,7 +91,7 @@ const SideList = ({ {menuItems.map(function (item, index) { return (
- +
Activity diff --git a/src/components/Topbar/NewCodelabz/index.jsx b/src/components/Topbar/NewCodelabz/index.jsx index 392d030f..659777b9 100644 --- a/src/components/Topbar/NewCodelabz/index.jsx +++ b/src/components/Topbar/NewCodelabz/index.jsx @@ -34,9 +34,9 @@ function NewCodelabz({ setVisibleModal }) { return ( - + setVisibleModal(true)} > diff --git a/src/components/TutorialPage/components/Commnets/Comment.jsx b/src/components/TutorialPage/components/Commnets/Comment.jsx index 09e486fc..73525816 100644 --- a/src/components/TutorialPage/components/Commnets/Comment.jsx +++ b/src/components/TutorialPage/components/Commnets/Comment.jsx @@ -9,10 +9,6 @@ import { import { makeStyles } from "@mui/styles"; import CardActions from "@mui/material/CardActions"; import MoreVertOutlinedIcon from "@mui/icons-material/MoreVertOutlined"; -import ToggleButton from "@mui/lab/ToggleButton"; -import ToggleButtonGroup from "@mui/lab/ToggleButtonGroup"; -import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import React, { useState, useEffect, @@ -29,6 +25,7 @@ import { getCommentReply, addComment } from "../../../../store/actions/tutorialPageActions"; +import CommentLikesDislikes from "../../../ui-helpers/CommentLikesDislikes"; const useStyles = makeStyles(() => ({ container: { margin: "10px 0", @@ -55,7 +52,6 @@ const useStyles = makeStyles(() => ({ const Comment = ({ id }) => { const classes = useStyles(); const [showReplyfield, setShowReplyfield] = useState(false); - const [alignment, setAlignment] = React.useState("left"); const [count, setCount] = useState(1); const firestore = useFirestore(); const firebase = useFirebase(); @@ -84,25 +80,15 @@ const Comment = ({ id }) => { const [replies] = repliesArray.filter(replies => replies.comment_id == id); - const handleIncrement = () => { - setCount(count + 1); - }; - - const handleDecrement = () => { - setCount(count - 1); - }; - - const handleAlignment = (event, newAlignment) => { - setAlignment(newAlignment); - }; - const handleSubmit = comment => { const commentData = { content: comment, replyTo: data.comment_id, tutorial_id: data.tutorial_id, createdAt: firestore.FieldValue.serverTimestamp(), - userId: "codelabzuser" + userId: "codelabzuser", + likes: 0, + dislikes: 0 }; addComment(commentData)(firebase, firestore, dispatch); }; @@ -129,32 +115,7 @@ const Comment = ({ id }) => { Reply )} - - - - {count} - - - - - + diff --git a/src/components/TutorialPage/components/Commnets/CommentBox.jsx b/src/components/TutorialPage/components/Commnets/CommentBox.jsx index 02f462f9..f5e78950 100644 --- a/src/components/TutorialPage/components/Commnets/CommentBox.jsx +++ b/src/components/TutorialPage/components/Commnets/CommentBox.jsx @@ -41,7 +41,9 @@ const CommentBox = ({ commentsArray, tutorialId }) => { replyTo: tutorialId, tutorial_id: tutorialId, createdAt: firestore.FieldValue.serverTimestamp(), - userId: "codelabzuser" + userId: "codelabzuser", + likes: 0, + dislikes: 0 }; addComment(commentData)(firebase, firestore, dispatch); }; diff --git a/src/components/TutorialPage/components/PostDetails.jsx b/src/components/TutorialPage/components/PostDetails.jsx index 1c46ac63..a3cf9422 100644 --- a/src/components/TutorialPage/components/PostDetails.jsx +++ b/src/components/TutorialPage/components/PostDetails.jsx @@ -8,16 +8,15 @@ import ShareOutlinedIcon from "@mui/icons-material/ShareOutlined"; import ChatOutlinedIcon from "@mui/icons-material/ChatOutlined"; import TurnedInNotOutlinedIcon from "@mui/icons-material/TurnedInNotOutlined"; import MoreVertOutlinedIcon from "@mui/icons-material/MoreVertOutlined"; -import ToggleButton from "@mui/lab/ToggleButton"; -import ToggleButtonGroup from "@mui/lab/ToggleButtonGroup"; -import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp"; -import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown"; import User from "./UserDetails"; import { useDispatch, useSelector } from "react-redux"; import { useFirebase, useFirestore } from "react-redux-firebase"; import { getUserProfileData } from "../../../store/actions"; import { HashLink } from "react-router-hash-link"; import { useParams } from "react-router-dom"; +import TutorialLikesDislikes from "../../ui-helpers/TutorialLikesDislikes.jsx"; +import PropTypes from "prop-types"; + const useStyles = makeStyles(() => ({ container: { padding: "20px", @@ -45,8 +44,6 @@ const PostDetails = ({ details }) => { const dispatch = useDispatch(); const firebase = useFirebase(); const firestore = useFirestore(); - const [alignment, setAlignment] = React.useState("left"); - const [count, setCount] = useState(details.upVote - details.downVote || 0); const { id } = useParams(); useEffect(() => { @@ -65,17 +62,6 @@ const PostDetails = ({ details }) => { return timestamp.toDate().toDateString(); }; - const handleIncrement = () => { - setCount(count + 1); - }; - - const handleDecrement = () => { - setCount(count - 1); - }; - - const handleAlignment = (event, newAlignment) => { - setAlignment(newAlignment); - }; const classes = useStyles(); return ( <> @@ -108,32 +94,7 @@ const PostDetails = ({ details }) => { - - - - {count} - - - - - + @@ -162,4 +123,8 @@ const PostDetails = ({ details }) => { ); }; +PostDetails.propTypes = { + details: PropTypes.object.isRequired +}; + export default PostDetails; diff --git a/src/components/TutorialPage/index.jsx b/src/components/TutorialPage/index.jsx index dd7895c2..d00d680e 100644 --- a/src/components/TutorialPage/index.jsx +++ b/src/components/TutorialPage/index.jsx @@ -54,10 +54,11 @@ function TutorialPage({ background = "white", textColor = "black" }) { title: tutorial?.title, org: tutorial?.owner, user: tutorial?.created_by, - upVote: tutorial?.upVotes, - downVote: tutorial?.downVotes, + like: tutorial?.likes, + dislike: tutorial?.dislikes, published_on: tutorial?.createdAt, - tag: tutorial?.tut_tags + tag: tutorial?.tut_tags, + tutorial_id: tutorial?.tutorial_id }; const steps = useSelector( diff --git a/src/components/ui-helpers/CommentLikesDislikes.jsx b/src/components/ui-helpers/CommentLikesDislikes.jsx new file mode 100644 index 00000000..d1d7dc08 --- /dev/null +++ b/src/components/ui-helpers/CommentLikesDislikes.jsx @@ -0,0 +1,176 @@ +import React, { useState, useEffect } from "react"; +import { ToggleButton, ToggleButtonGroup, Typography } from "@mui/material"; +import { ThumbUp, ThumbDown } from "@mui/icons-material"; +import { db } from "../../config/index"; +import PropTypes from "prop-types"; +import firebase from "../../config/index"; + +const CommentLikesDislikes = ({ comment_id }) => { + const [userChoice, setUserChoice] = useState(null); + const [likesCount, setLikesCount] = useState(0); + const [dislikesCount, setDislikesCount] = useState(0); + + const commentLikesDocRef = db.collection("comment_likes").doc(comment_id); // Reference to the document in the "comment_likes" collection + + const commentLikesDocSnapshot = commentLikesDocRef.get(); + const commentDislikesDocRef = db + .collection("comment_dislikes") + .doc(comment_id); // Reference to the document in the "comment_dislikes" collection + const commentDislikesDocSnapshot = commentDislikesDocRef.get(); + + useEffect(() => { + const fetchData = async () => { + if (!firebase.auth().currentUser) { + // User not authenticated + return; + } + + // Check if the current user has already liked the comment + const likesSnapshot = await commentLikesDocRef.get(); + if (likesSnapshot.exists) { + const userIds = likesSnapshot.data().userIds || []; + if (userIds.includes(firebase.auth().currentUser.uid)) { + setUserChoice("like"); + } + } + + // Check if the current user has already disliked the comment + const dislikesSnapshot = await commentDislikesDocRef.get(); + if (dislikesSnapshot.exists) { + const userIds = dislikesSnapshot.data().userIds || []; + if (userIds.includes(firebase.auth().currentUser.uid)) { + setUserChoice("dislike"); + } + } + + // Subscribe to like/dislike counts in Firestore + const unsubscribeLikes = db + .collection("comment_likes") + .doc(comment_id) + .onSnapshot(doc => { + if (doc.exists) { + setLikesCount(doc.data().userIds.length || 0); + } + }); + + const unsubscribeDislikes = db + .collection("comment_dislikes") + .doc(comment_id) + .onSnapshot(doc => { + if (doc.exists) { + setDislikesCount(doc.data().userIds.length || 0); + } + }); + + // Unsubscribe from snapshot listeners when component unmounts + return () => { + unsubscribeLikes(); + unsubscribeDislikes(); + }; + }; + + fetchData(); + }, [comment_id]); + + async function handleIncrement(newChoice) { + const fieldToUpdate = + newChoice === "like" ? "comment_likes" : "comment_dislikes"; + const countField = newChoice === "like" ? "likes" : "dislikes"; + const addUserId = firebase.firestore.FieldValue.arrayUnion( + firebase.auth().currentUser.uid + ); + + // Update like/dislike count of comments in Firestore + await db + .collection("cl_comments") + .doc(comment_id) + .update({ + [countField]: firebase.firestore.FieldValue.increment(1) + }); + + // Update like/dislike count in Firestore + await db + .collection(fieldToUpdate) + .doc(comment_id) + .update({ + [fieldToUpdate + "_count"]: firebase.firestore.FieldValue.increment(1), + userIds: addUserId + }); + + setUserChoice(newChoice); + if (newChoice === "like") { + setLikesCount(likesCount + 1); + } else { + setDislikesCount(dislikesCount + 1); + } + + // Log the updated array of users + const docSnapshot = await db + .collection(fieldToUpdate) + .doc(comment_id) + .get(); + console.log( + `array of users who are in ${fieldToUpdate}`, + docSnapshot.data().userIds + ); + } + + const handleUserChoice = async (event, newChoice) => { + if (!commentLikesDocSnapshot.exists) { + // Document doesn't exist, create it with initial data + await commentLikesDocRef.set({ + comment_id: comment_id, + userIds: [], + comment_likes_count: 0 + }); + } + + if (!commentDislikesDocSnapshot.exists) { + // Document doesn't exist, create it with initial data + await commentDislikesDocRef.set({ + comment_id: comment_id, + userIds: [], + comment_dislikes_count: 0 + }); + } + + if (newChoice) { + handleIncrement(newChoice); + } + if (userChoice) { + // Update like/dislike count of comments in Firestore + await db + .collection("cl_comments") + .doc(comment_id) + .update({ + [userChoice + "s"]: firebase.firestore.FieldValue.increment(-1) + }); + } + setUserChoice(newChoice); + }; + + return ( + + + + {likesCount} + + + + {dislikesCount} + + + ); +}; + +CommentLikesDislikes.propTypes = { + comment_id: PropTypes.string.isRequired +}; + +export default CommentLikesDislikes; diff --git a/src/components/ui-helpers/TutorialLikesDislikes.jsx b/src/components/ui-helpers/TutorialLikesDislikes.jsx new file mode 100644 index 00000000..dfb920bd --- /dev/null +++ b/src/components/ui-helpers/TutorialLikesDislikes.jsx @@ -0,0 +1,176 @@ +import React, { useState, useEffect } from "react"; +import { ToggleButton, ToggleButtonGroup, Typography } from "@mui/material"; +import { ThumbUp, ThumbDown } from "@mui/icons-material"; +import { db } from "../../config/index"; +import PropTypes from "prop-types"; +import firebase from "../../config/index"; + +const TutorialLikesDislikes = ({ tutorial_id }) => { + const [userChoice, setUserChoice] = useState(null); + const [likesCount, setLikesCount] = useState(0); + const [dislikesCount, setDislikesCount] = useState(0); + + const tutorialLikesDocRef = db.collection("tutorial_likes").doc(tutorial_id); // Reference to the document in the "tutorial_likes" collection + + const tutorialLikesDocSnapshot = tutorialLikesDocRef.get(); + const tutorialDislikesDocRef = db + .collection("tutorial_dislikes") + .doc(tutorial_id); // Reference to the document in the "tutorial_dislikes" collection + const tutorialDislikesDocSnapshot = tutorialDislikesDocRef.get(); + + useEffect(() => { + const fetchData = async () => { + if (!firebase.auth().currentUser) { + // User not authenticated + return; + } + + // Check if the current user has already liked the tutorial + const likesSnapshot = await tutorialLikesDocRef.get(); + if (likesSnapshot.exists) { + const userIds = likesSnapshot.data().userIds || []; + if (userIds.includes(firebase.auth().currentUser.uid)) { + setUserChoice("like"); + } + } + + // Check if the current user has already disliked the tutorial + const dislikesSnapshot = await tutorialDislikesDocRef.get(); + if (dislikesSnapshot.exists) { + const userIds = dislikesSnapshot.data().userIds || []; + if (userIds.includes(firebase.auth().currentUser.uid)) { + setUserChoice("dislike"); + } + } + + // Subscribe to like/dislike counts in Firestore + const unsubscribeLikes = db + .collection("tutorial_likes") + .doc(tutorial_id) + .onSnapshot(doc => { + if (doc.exists) { + setLikesCount(doc.data().userIds.length || 0); + } + }); + + const unsubscribeDislikes = db + .collection("tutorial_dislikes") + .doc(tutorial_id) + .onSnapshot(doc => { + if (doc.exists) { + setDislikesCount(doc.data().userIds.length || 0); + } + }); + + // Unsubscribe from snapshot listeners when component unmounts + return () => { + unsubscribeLikes(); + unsubscribeDislikes(); + }; + }; + + fetchData(); + }, [tutorial_id]); + + async function handleIncrement(newChoice) { + const fieldToUpdate = + newChoice === "like" ? "tutorial_likes" : "tutorial_dislikes"; + const countField = newChoice === "like" ? "likes" : "dislikes"; + const addUserId = firebase.firestore.FieldValue.arrayUnion( + firebase.auth().currentUser.uid + ); + + // Update like/dislike count of tutorials in Firestore + await db + .collection("tutorials") + .doc(tutorial_id) + .update({ + [countField]: firebase.firestore.FieldValue.increment(1) + }); + + // Update like/dislike count in Firestore + await db + .collection(fieldToUpdate) + .doc(tutorial_id) + .update({ + [fieldToUpdate + "_count"]: firebase.firestore.FieldValue.increment(1), + userIds: addUserId + }); + + setUserChoice(newChoice); + if (newChoice === "like") { + setLikesCount(likesCount + 1); + } else { + setDislikesCount(dislikesCount + 1); + } + + // Log the updated array of users + const docSnapshot = await db + .collection(fieldToUpdate) + .doc(tutorial_id) + .get(); + console.log( + `array of users who are in ${fieldToUpdate}`, + docSnapshot.data().userIds + ); + } + + const handleUserChoice = async (event, newChoice) => { + if (!tutorialLikesDocSnapshot.exists) { + // Document doesn't exist, create it with initial data + await tutorialLikesDocRef.set({ + tutorial_id: tutorial_id, + userIds: [], + tutorial_likes_count: 0 + }); + } + + if (!tutorialDislikesDocSnapshot.exists) { + // Document doesn't exist, create it with initial data + await tutorialDislikesDocRef.set({ + tutorial_id: tutorial_id, + userIds: [], + tutorial_dislikes_count: 0 + }); + } + + if (newChoice) { + handleIncrement(newChoice); + } + if (userChoice) { + // Update like/dislike count of tutorials in Firestore + await db + .collection("tutorials") + .doc(tutorial_id) + .update({ + [userChoice + "s"]: firebase.firestore.FieldValue.increment(-1) + }); + } + setUserChoice(newChoice); + }; + + return ( + + + + {likesCount} + + + + {dislikesCount} + + + ); +}; + +TutorialLikesDislikes.propTypes = { + tutorial_id: PropTypes.string.isRequired +}; + +export default TutorialLikesDislikes; \ No newline at end of file diff --git a/src/config/index.js b/src/config/index.js index ee402c72..aefbdce6 100644 --- a/src/config/index.js +++ b/src/config/index.js @@ -29,7 +29,7 @@ export const onlineFirebaseApp = initializeApp(firebaseConfig, "secondary"); // Initialize firebase instance firebase.initializeApp(firebaseConfig); -const db = firebase.firestore(); // <- needed if using firestor +export const db = firebase.firestore(); // <- needed if using firestor if (import.meta.env.VITE_APP_USE_EMULATOR) { firebase.firestore().useEmulator("localhost", 8080); diff --git a/src/helpers/appBar.jsx b/src/helpers/appBar.jsx index 6db7a627..dd0c7364 100644 --- a/src/helpers/appBar.jsx +++ b/src/helpers/appBar.jsx @@ -109,13 +109,13 @@ const CodeLabzAppBar = () => { if (authed) { return ( -
+
); } else { return ( -
+
); diff --git a/src/store/actions/tutorialPageActions.js b/src/store/actions/tutorialPageActions.js index c716765a..d12dea25 100644 --- a/src/store/actions/tutorialPageActions.js +++ b/src/store/actions/tutorialPageActions.js @@ -119,8 +119,7 @@ export const getTutorialData = .collection("tutorials") .doc(tutorialID) .get(); - const tutorial = data.data(); - dispatch({ type: actions.GET_POST_DATA_SUCCESS, payload: tutorial }); + const tutorial = { tutorial_id: tutorialID, ...data.data() }; dispatch({ type: actions.GET_POST_DATA_SUCCESS, payload: tutorial }); } catch (e) { dispatch({ type: actions.GET_POST_DATA_FAIL }); console.log(e); diff --git a/src/store/actions/tutorialsActions.js b/src/store/actions/tutorialsActions.js index 7d273c1d..52953242 100644 --- a/src/store/actions/tutorialsActions.js +++ b/src/store/actions/tutorialsActions.js @@ -144,7 +144,10 @@ export const createTutorial = background_color: "#ffffff", text_color: "#000000", createdAt: firestore.FieldValue.serverTimestamp(), - updatedAt: firestore.FieldValue.serverTimestamp() + updatedAt: firestore.FieldValue.serverTimestamp(), + likes: 0, + dislikes: 0, + views: 0, }); // Adds first step when a tutorial is created