From aea413d538a48cd59a9ec002fff43d3f4bc652ce Mon Sep 17 00:00:00 2001 From: emyemy89 Date: Wed, 9 Apr 2025 16:49:05 +0200 Subject: [PATCH 1/5] added functions for creating reviews for each course --- my-app/firebase.js | 28 ++++++++++ my-app/src/model.js | 29 ++++++++++- my-app/src/presenters/CourseViewPresenter.jsx | 51 +++++++++++++++++-- my-app/src/views/CourseView.jsx | 43 +++++++++++++--- 4 files changed, 137 insertions(+), 14 deletions(-) diff --git a/my-app/firebase.js b/my-app/firebase.js index 666de8b9..6a14c15d 100644 --- a/my-app/firebase.js +++ b/my-app/firebase.js @@ -137,3 +137,31 @@ export async function saveJSONCoursesToFirebase(model, data){ }); } +// for reviews +export async function addReview(courseCode, review) { + const reviewsRef = ref(db, `reviews/${courseCode}`); + const newReviewRef = push(reviewsRef); // Firebase creates a unique key for each review + await set(newReviewRef, review); // Save the review data to the generated ID +} + + + +export async function getReviewsForCourse(courseCode) { + const reviewsRef = ref(db, `reviews/${courseCode}`); + const snapshot = await get(reviewsRef); + if (!snapshot.exists()) return []; + + const reviews = []; + snapshot.forEach(childSnapshot => { + reviews.push({ + id: childSnapshot.key, // Firebase-generated unique key + userName: childSnapshot.val().userName, + text: childSnapshot.val().text + }); + }); + return reviews; +} + + + + diff --git a/my-app/src/model.js b/my-app/src/model.js index d98c2e5f..0e803dd8 100644 --- a/my-app/src/model.js +++ b/my-app/src/model.js @@ -1,4 +1,5 @@ -import { addCourse } from "../firebase"; +import { addCourse, addReview, getReviewsForCourse } from "../firebase"; // for reviews + export const model = { user: undefined, @@ -76,5 +77,29 @@ export const model = { course.description.toLowerCase().includes(query.toLowerCase()) ); this.setCurrentSearch(searchResults); - } + }, + + + //for reviews + async addReview(courseCode, review) { + try { + await addReview({ ...review, courseCode }); + } catch (error) { + console.error("Error adding review:", error); + } + }, + + async getReviews(courseCode) { + try { + return await getReviewsForCourse(courseCode); + } catch (error) { + console.error("Error fetching reviews:", error); + return []; + } + }, + + + + + }; diff --git a/my-app/src/presenters/CourseViewPresenter.jsx b/my-app/src/presenters/CourseViewPresenter.jsx index 9e520c8d..f6eba684 100644 --- a/my-app/src/presenters/CourseViewPresenter.jsx +++ b/my-app/src/presenters/CourseViewPresenter.jsx @@ -1,9 +1,50 @@ -import React from 'react'; -import { observer } from "mobx-react-lite"; +import React, { useEffect, useState } from 'react'; +import { observer } from 'mobx-react-lite'; import CourseView from "../views/CourseView.jsx"; -const CourseViewPresenter = observer(({ model }) => { - return ; +import { model } from "../model"; //for reviews + + + +const CourseViewPresenter = observer(({ model, course }) => { + const [reviews, setReviews] = useState([]); + const [newReview, setNewReview] = useState(""); + + //fetch reviews when the course code changes + useEffect(() => { + async function fetchReviews() { + const data = await model.getReviews(course.code); + setReviews(data); + } + fetchReviews(); + }, [course.code, model]); + + + const handleReviewSubmit = async () => { + if (newReview.trim()) { + await model.addReview(course.code, { + userName: model.user?.name || "Anonymous", + text: newReview, + timestamp: Date.now(), //timestamp + }); + //fetch and update the reviews after submitting + const updatedReviews = await model.getReviews(course.code); + setReviews(updatedReviews); + setNewReview(""); //clear text bar + } + }; + + + return ( + + ); }); -export { CourseViewPresenter }; \ No newline at end of file +export { CourseViewPresenter }; + diff --git a/my-app/src/views/CourseView.jsx b/my-app/src/views/CourseView.jsx index 545bb1eb..d8186b03 100644 --- a/my-app/src/views/CourseView.jsx +++ b/my-app/src/views/CourseView.jsx @@ -1,10 +1,13 @@ import React from 'react'; import PrerequisiteTree from "./PrerequisiteTree.jsx"; +import { useEffect, useState } from "react"; //for reviews +import { model } from "../model"; //for reviews -// import {model} from '/src/model.js'; -export default function CourseView({ course }) { + +export default function CourseView({ course, reviews, newReview, setNewReview, handleReviewSubmit }) { if (!course) return null; + return ( @@ -44,11 +47,10 @@ export default function CourseView({ course }) {

Prerequisite Graph Tree

Graph tree or prerequisite info will go here...

- {/* Reviews Section */} -
-

Reviews

-

Here would be some reviews of the course...

-
+ + + + {/* Prerequisite Graph Tree Section */} @@ -58,6 +60,33 @@ export default function CourseView({ course }) { + + + {/* Reviews Section */} +
+

Reviews

+
    + {(reviews || []).map((rev, i) => ( +
  • {rev.userName}: {rev.text}
  • + ))} +
+ +
+ setNewReview(e.target.value)} + /> + +
+ ); } From 35933422b545349156be3f2b67f4c1f641366d7c Mon Sep 17 00:00:00 2001 From: Justus Kluge Date: Thu, 10 Apr 2025 13:56:16 +0200 Subject: [PATCH 2/5] Reviews work! --- my-app/firebase.js | 19 +++++++++++-------- my-app/src/model.js | 4 ++-- my-app/src/views/ReviewView.jsx | 21 ++++++++++----------- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/my-app/firebase.js b/my-app/firebase.js index f56e9cc0..0ce66cd9 100644 --- a/my-app/firebase.js +++ b/my-app/firebase.js @@ -1,8 +1,7 @@ import { initializeApp } from "firebase/app"; import { getAuth, GoogleAuthProvider, onAuthStateChanged } from "firebase/auth"; -import { get, getDatabase, ref, set, onValue } from "firebase/database"; +import { get, getDatabase, ref, set, onValue, push} from "firebase/database"; import { reaction, toJS } from "mobx"; -// foo // Your web app's Firebase configuration const firebaseConfig = { apiKey: "AIzaSyCBckVI9nhAP62u5jZJW3F4SLulUv7znis", @@ -70,7 +69,7 @@ export function syncModelToFirebase(model) { const userRef = ref(db, `users/${userId}`); const dataToSync = { favourites, - currentSearch, + //currentSearch, }; set(userRef, dataToSync) @@ -170,11 +169,15 @@ export async function saveJSONCoursesToFirebase(model, data) { }); } -// for reviews -export async function addReview(courseCode, review) { - const reviewsRef = ref(db, `reviews/${courseCode}`); - const newReviewRef = push(reviewsRef); // Firebase creates a unique key for each review - await set(newReviewRef, review); // Save the review data to the generated ID + +export async function addReviewForCourse(courseCode, review) { + try { + const reviewsRef = ref(db, `reviews/${courseCode}`); + const newReviewRef = push(reviewsRef); + await set(newReviewRef, review); + } catch (error) { + console.error("Error when adding a course to firebase:", error); + } } diff --git a/my-app/src/model.js b/my-app/src/model.js index 05d072b7..2ff413e8 100644 --- a/my-app/src/model.js +++ b/my-app/src/model.js @@ -1,4 +1,4 @@ -import { addCourse, addReview, getReviewsForCourse } from "../firebase"; // for reviews +import { addCourse, addReviewForCourse, getReviewsForCourse } from "../firebase"; // for reviews export const model = { @@ -70,7 +70,7 @@ export const model = { //for reviews async addReview(courseCode, review) { try { - await addReview({ ...review, courseCode }); + await addReviewForCourse(courseCode, review); } catch (error) { console.error("Error adding review:", error); } diff --git a/my-app/src/views/ReviewView.jsx b/my-app/src/views/ReviewView.jsx index f040b557..124bc638 100644 --- a/my-app/src/views/ReviewView.jsx +++ b/my-app/src/views/ReviewView.jsx @@ -11,18 +11,8 @@ export function ReviewView({ return (
+

Reviews

{/* Reviews Section */} -
-

Reviews

-
    - {(reviews || []).map((rev, i) => ( -
  • - {rev.userName}: {rev.text} -
  • - ))} -
-
-
+
+
    + {(reviews || []).map((rev, i) => ( +
  • + {rev.userName}: {rev.text} +
  • + ))} +
+
); } From 8bbac250b1083d02c72b4188825ff41d87a1a2a5 Mon Sep 17 00:00:00 2001 From: Justus Kluge Date: Thu, 10 Apr 2025 14:03:37 +0200 Subject: [PATCH 3/5] lint --- my-app/firebase.js | 1 + 1 file changed, 1 insertion(+) diff --git a/my-app/firebase.js b/my-app/firebase.js index 0ce66cd9..8bb60021 100644 --- a/my-app/firebase.js +++ b/my-app/firebase.js @@ -63,6 +63,7 @@ export function syncModelToFirebase(model) { currentSearch: toJS(model.currentSearch), // Add more per-user attributes here }), + // eslint-disable-next-line no-unused-vars ({ userId, favourites, currentSearch }) => { if (noUpload || !userId) return; From 06f578c2cbcfe8887d3d8c3877771d81ed03fcdd Mon Sep 17 00:00:00 2001 From: Justus Kluge Date: Thu, 10 Apr 2025 14:10:51 +0200 Subject: [PATCH 4/5] lint II? --- my-app/firebase.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/my-app/firebase.js b/my-app/firebase.js index 8bb60021..27a4ee7a 100644 --- a/my-app/firebase.js +++ b/my-app/firebase.js @@ -1,6 +1,6 @@ import { initializeApp } from "firebase/app"; import { getAuth, GoogleAuthProvider, onAuthStateChanged } from "firebase/auth"; -import { get, getDatabase, ref, set, onValue, push} from "firebase/database"; +import { get, getDatabase, ref, set, onValue, push } from "firebase/database"; import { reaction, toJS } from "mobx"; // Your web app's Firebase configuration const firebaseConfig = { From 210b443aed1443e6de4c2fa2861d0d2954fde164 Mon Sep 17 00:00:00 2001 From: Justus Kluge Date: Thu, 10 Apr 2025 14:18:30 +0200 Subject: [PATCH 5/5] Remove synching the search... --- my-app/firebase.js | 6 +++--- my-app/src/model.js | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/my-app/firebase.js b/my-app/firebase.js index 27a4ee7a..99cceddd 100644 --- a/my-app/firebase.js +++ b/my-app/firebase.js @@ -48,8 +48,8 @@ async function firebaseToModel(model) { noUpload = true; if (data.favourites) model.setFavourite(data.favourites); - if (data.currentSearch) - model.setCurrentSearch(data.currentSearch); + // if (data.currentSearch) + // model.setCurrentSearch(data.currentSearch); noUpload = false; }); } @@ -60,7 +60,7 @@ export function syncModelToFirebase(model) { () => ({ userId: model?.user, favourites: toJS(model.favourites), - currentSearch: toJS(model.currentSearch), + // currentSearch: toJS(model.currentSearch), // Add more per-user attributes here }), // eslint-disable-next-line no-unused-vars diff --git a/my-app/src/model.js b/my-app/src/model.js index 98d1e0db..3da7c114 100644 --- a/my-app/src/model.js +++ b/my-app/src/model.js @@ -71,6 +71,7 @@ export const model = { async addReview(courseCode, review) { try { await addReviewForCourse(courseCode, review); + } catch (error) { console.error("Error adding review:", error); }