Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions my-app/firebase.js
Original file line number Diff line number Diff line change
@@ -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",
Expand Down Expand Up @@ -49,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;
});
}
Expand All @@ -61,16 +60,17 @@ 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
({ userId, favourites, currentSearch }) => {
if (noUpload || !userId)
return;
const userRef = ref(db, `users/${userId}`);
const dataToSync = {
favourites,
currentSearch,
//currentSearch,
};

set(userRef, dataToSync)
Expand Down Expand Up @@ -169,3 +169,35 @@ export async function saveJSONCoursesToFirebase(model, data) {
model.addCourse(course);
});
}


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);
}
}


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;
}




22 changes: 21 additions & 1 deletion my-app/src/model.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { addCourse } from "../firebase";
import { addCourse, addReviewForCourse, getReviewsForCourse } from "../firebase"; // for reviews


export const model = {
user: undefined,
Expand Down Expand Up @@ -65,4 +66,23 @@ export const model = {
this.addCourse(course);
});
},

//for reviews
async addReview(courseCode, review) {
try {
await addReviewForCourse(courseCode, review);

} 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 [];
}
},
};
9 changes: 0 additions & 9 deletions my-app/src/presenters/CourseViewPresenter.jsx

This file was deleted.

8 changes: 6 additions & 2 deletions my-app/src/presenters/ListViewPresenter.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useState } from 'react';
import ListView from "../views/ListView.jsx";
import CoursePagePopup from '../views/Components/CoursePagePopup.jsx';
import PrerequisitePresenter from './PrerequisitePresenter.jsx';
import {ReviewPresenter} from "../presenters/ReviewPresenter.jsx"

const ListViewPresenter = observer(({ model }) => {
const addFavourite = (course) => {
Expand All @@ -22,15 +23,18 @@ const ListViewPresenter = observer(({ model }) => {

const [isPopupOpen, setIsPopupOpen] = useState(false);
const [selectedCourse, setSelectedCourse] = useState(null);
const preP = <PrerequisitePresenter model={model} selectedCourse={selectedCourse} />
const preP = <PrerequisitePresenter model={model} selectedCourse={selectedCourse} />;
const reviewPresenter = <ReviewPresenter model={model} course={selectedCourse}/>;

const popup = <CoursePagePopup
favouriteCourses={model.favourites}
addFavourite={addFavourite}
removeFavourite={removeFavourite}
isOpen={isPopupOpen} onClose={() => setIsPopupOpen(false)}
course={selectedCourse}
prerequisiteTree={preP} />
prerequisiteTree={preP}
reviewPresenter={reviewPresenter}/>



return <ListView
Expand Down
46 changes: 46 additions & 0 deletions my-app/src/presenters/ReviewPresenter.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useEffect, useState } from 'react';
import { observer } from 'mobx-react-lite';
import { ReviewView } from '../views/ReviewView.jsx';


export const ReviewPresenter = 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()) {
const review = {
userName: model.user?.name || "Anonymous",
text: newReview,
timestamp: Date.now(), //timestamp
};
await model.addReview(course.code, review);
//fetch and update the reviews after submitting
const updatedReviews = await model.getReviews(course.code);
setReviews(updatedReviews);
setNewReview(""); //clear text bar
}
};


return (
<ReviewView
course={course}
reviews={reviews}
newReview={newReview}
setNewReview={setNewReview}
handleReviewSubmit={handleReviewSubmit}
/>
);
});

Loading