Lashtw commited on
Commit
70d259b
·
verified ·
1 Parent(s): 62917c9

Upload 8 files

Browse files
Files changed (1) hide show
  1. src/services/classroom.js +78 -3
src/services/classroom.js CHANGED
@@ -268,14 +268,16 @@ export async function getPeerPrompts(roomCode, challengeId) {
268
  }
269
 
270
  // Fetch nickname
271
- // Optimization: In a real app, store nickname in 'progress' to avoid N+1 queries.
272
- // For now, fetch user.
273
  const userSnap = await getDoc(doc(db, USERS_COLLECTION, data.userId));
274
  if (userSnap.exists()) {
275
  entries.push({
 
 
276
  nickname: userSnap.data().nickname,
277
  prompt: data.submission_prompt,
278
- timestamp: data.timestamp
 
 
279
  });
280
  }
281
  }
@@ -349,3 +351,76 @@ export async function updateChallenge(id, data) {
349
  export async function deleteChallenge(id) {
350
  await deleteDoc(doc(db, CHALLENGES_COLLECTION, id));
351
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
 
270
  // Fetch nickname
 
 
271
  const userSnap = await getDoc(doc(db, USERS_COLLECTION, data.userId));
272
  if (userSnap.exists()) {
273
  entries.push({
274
+ id: docSnapshot.id,
275
+ userId: data.userId,
276
  nickname: userSnap.data().nickname,
277
  prompt: data.submission_prompt,
278
+ timestamp: data.timestamp,
279
+ likes: data.likes || 0,
280
+ likedBy: data.likedBy || []
281
  });
282
  }
283
  }
 
351
  export async function deleteChallenge(id) {
352
  await deleteDoc(doc(db, CHALLENGES_COLLECTION, id));
353
  }
354
+
355
+ // --- Social Features ---
356
+
357
+ const NOTIFICATIONS_COLLECTION = "notifications";
358
+
359
+ /**
360
+ * Toggles like on a progress submission
361
+ */
362
+ export async function toggleLike(progressId, currentUserId, currentNickname, targetUserId, challengeTitle) {
363
+ const progressRef = doc(db, PROGRESS_COLLECTION, progressId);
364
+ const progressSnap = await getDoc(progressRef);
365
+
366
+ if (!progressSnap.exists()) return;
367
+
368
+ const data = progressSnap.data();
369
+ const likedBy = data.likedBy || [];
370
+ const isLiked = likedBy.includes(currentUserId);
371
+
372
+ if (isLiked) {
373
+ // Unlike
374
+ await updateDoc(progressRef, {
375
+ likes: (data.likes || 1) - 1,
376
+ likedBy: likedBy.filter(id => id !== currentUserId)
377
+ });
378
+ } else {
379
+ // Like
380
+ await updateDoc(progressRef, {
381
+ likes: (data.likes || 0) + 1,
382
+ likedBy: [...likedBy, currentUserId]
383
+ });
384
+
385
+ // Send Notification if not liking self
386
+ if (targetUserId !== currentUserId) {
387
+ await addDoc(collection(db, NOTIFICATIONS_COLLECTION), {
388
+ recipientId: targetUserId,
389
+ senderNickname: currentNickname,
390
+ challengeTitle: challengeTitle,
391
+ type: 'like',
392
+ timestamp: serverTimestamp(),
393
+ read: false
394
+ });
395
+ }
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Listen to notifications for a user
401
+ */
402
+ export function subscribeToNotifications(userId, callback) {
403
+ const q = query(
404
+ collection(db, NOTIFICATIONS_COLLECTION),
405
+ where("recipientId", "==", userId),
406
+ where("read", "==", false),
407
+ orderBy("timestamp", "desc")
408
+ );
409
+
410
+ return onSnapshot(q, (snapshot) => {
411
+ const notifications = [];
412
+ snapshot.forEach(doc => {
413
+ notifications.push({ id: doc.id, ...doc.data() });
414
+ });
415
+ callback(notifications);
416
+ });
417
+ }
418
+
419
+ /**
420
+ * Mark notification as read
421
+ */
422
+ export async function markNotificationRead(notificationId) {
423
+ await updateDoc(doc(db, NOTIFICATIONS_COLLECTION, notificationId), {
424
+ read: true
425
+ });
426
+ }