11import { initializeApp } from "firebase/app" ;
22import { getAuth , GoogleAuthProvider , onAuthStateChanged } from "firebase/auth" ;
3- import { get , getDatabase , ref , set , onValue , push } from "firebase/database" ;
3+ import { getFunctions , httpsCallable } from 'firebase/functions' ;
4+ import { get , getDatabase , ref , set , onValue , onChildRemoved , onChildAdded } from "firebase/database" ;
45import { reaction , toJS } from "mobx" ;
56
67// Your web app's Firebase configuration
@@ -17,6 +18,7 @@ const firebaseConfig = {
1718
1819// Initialize Firebase
1920const app = initializeApp ( firebaseConfig ) ;
21+ const functions = getFunctions ( app ) ;
2022export const auth = getAuth ( app ) ;
2123export const db = getDatabase ( app ) ;
2224export const googleProvider = new GoogleAuthProvider ( ) ;
@@ -50,6 +52,7 @@ export function connectToFirebase(model) {
5052 firebaseToModel ( model ) ; // Set up listeners for user-specific data
5153 syncModelToFirebase ( model ) ; // Start syncing changes to Firebase
5254 syncScrollPositionToFirebase ( model ) ;
55+ startAverageRatingListener ( model ) ;
5356 } else {
5457 model . setUser ( null ) ; // If no user, clear user-specific data
5558 }
@@ -123,6 +126,52 @@ export function syncScrollPositionToFirebase(model, containerRef) {
123126 containerRef . current ?. removeEventListener ( "scroll" , handleScroll ) ;
124127}
125128
129+ function startAverageRatingListener ( model ) {
130+ const coursesRef = ref ( db , "reviews" ) ;
131+
132+ // Step 1: One-time fetch if model.avgRating is not initialized
133+ if ( ! model . avgRating || Object . keys ( model . avgRating ) . length === 0 ) {
134+ get ( coursesRef ) . then ( ( snapshot ) => {
135+ if ( ! snapshot . exists ( ) ) return ;
136+
137+ const initialRatings = { } ;
138+
139+ snapshot . forEach ( ( courseSnapshot ) => {
140+ const courseCode = courseSnapshot . key ;
141+ const avgRating = courseSnapshot . child ( "avgRating" ) . val ( ) ;
142+
143+ if ( typeof avgRating === "number" ) {
144+ initialRatings [ courseCode ] = avgRating ;
145+ }
146+ } ) ;
147+
148+ model . setAverageRatings ( initialRatings ) ;
149+ } ) ;
150+ }
151+
152+ // Step 2: listener for each courses avgRating
153+ onChildAdded ( coursesRef , ( courseSnapshot ) => {
154+ const courseCode = courseSnapshot . key ;
155+ const avgRatingRef = ref ( db , `reviews/${ courseCode } /avgRating` ) ;
156+
157+ onValue ( avgRatingRef , ( ratingSnapshot ) => {
158+ if ( ! ratingSnapshot . exists ( ) ) return ;
159+
160+ const rating = ratingSnapshot . val ( ) ;
161+
162+ if ( typeof rating === "number" ) {
163+ model . updateAverageRating ( courseCode , rating ) ;
164+ }
165+ } ) ;
166+ } ) ;
167+
168+ onChildRemoved ( coursesRef , ( courseSnapshot ) => {
169+ const courseCode = courseSnapshot . key ;
170+ model . updateAverageRating ( courseCode , null ) ;
171+ } ) ;
172+ }
173+
174+
126175function saveCoursesToCache ( courses , timestamp ) {
127176 const request = indexedDB . open ( "CourseDB" , 1 ) ;
128177
@@ -288,11 +337,14 @@ async function loadCoursesFromCacheOrFirebase(model) {
288337
289338export async function addReviewForCourse ( courseCode , review ) {
290339 try {
291- const reviewsRef = ref ( db , `reviews/${ courseCode } ` ) ;
292- const newReviewRef = push ( reviewsRef ) ;
293- await set ( newReviewRef , review ) ;
340+ const reviewsRef = ref ( db , `reviews/${ courseCode } /${ review . uid } ` ) ;
341+ await set ( reviewsRef , review ) ;
342+ const updateCourseAvgRating = httpsCallable ( functions , 'updateCourseAvgRating' ) ;
343+ const result = await updateCourseAvgRating ( { courseCode } ) ;
344+
345+ console . log ( 'Average rating updated:' , result . data . avgRating ) ;
294346 } catch ( error ) {
295- console . error ( "Error when adding a course to firebase:" , error ) ;
347+ console . error ( "Error when adding a course to firebase or updating the average :" , error ) ;
296348 }
297349}
298350
@@ -302,6 +354,7 @@ export async function getReviewsForCourse(courseCode) {
302354 if ( ! snapshot . exists ( ) ) return [ ] ;
303355 const reviews = [ ] ;
304356 snapshot . forEach ( ( childSnapshot ) => {
357+ if ( childSnapshot . key != "avgRating" )
305358 reviews . push ( {
306359 id : childSnapshot . key ,
307360 ...childSnapshot . val ( ) ,
0 commit comments