Lashtw commited on
Commit
ccaf7a8
·
verified ·
1 Parent(s): 3ee0101

Upload 9 files

Browse files
Files changed (2) hide show
  1. src/services/classroom.js +24 -24
  2. src/views/StudentView.js +10 -3
src/services/classroom.js CHANGED
@@ -131,6 +131,7 @@ export async function submitPrompt(userId, roomCode, challengeId, prompt) {
131
  await updateDoc(docRef, {
132
  status: "completed",
133
  submission_prompt: text,
 
134
  timestamp: serverTimestamp()
135
  });
136
  } else {
@@ -258,13 +259,8 @@ export function subscribeToRoom(roomCode, callback) {
258
  */
259
  export async function getPeerPrompts(roomCode, challengeId) {
260
  const progressRef = collection(db, PROGRESS_COLLECTION);
261
- // We need nickname too. progress collection only has userId.
262
- // We might need to fetch user info or store nickname in progress (denormalization).
263
- // Let's store nickname in progress for easier read? Or fetch users.
264
- // For now, let's fetch matching progress, then unique userIds, then fetch those users.
265
 
266
- // Simplified query for prototype: Fetch ALL completions for this challenge, then filter in memory.
267
- // This avoids needing complex Composite Indexes for every room/challenge combination.
268
  const q = query(
269
  progressRef,
270
  where("challengeId", "==", challengeId),
@@ -278,27 +274,31 @@ export async function getPeerPrompts(roomCode, challengeId) {
278
  for (const docSnapshot of snapshot.docs) {
279
  const data = docSnapshot.data();
280
 
281
- // In-Memory Filtering for Room Code
282
- // Note: Older data might not have roomCode. If undefined and we are in a room, maybe exclude?
283
- // Or include if we want to share across global (but user said "this classroom").
284
- // Let's strict check: Must match roomCode.
285
- if (String(data.roomCode) !== String(roomCode)) {
 
 
 
 
 
 
 
 
286
  continue;
287
  }
288
 
289
- // Fetch nickname
290
- const userSnap = await getDoc(doc(db, USERS_COLLECTION, data.userId));
291
- if (userSnap.exists()) {
292
- entries.push({
293
- id: docSnapshot.id,
294
- userId: data.userId,
295
- nickname: userSnap.data().nickname,
296
- prompt: data.submission_prompt,
297
- timestamp: data.timestamp,
298
- likes: data.likes || 0,
299
- likedBy: data.likedBy || []
300
- });
301
- }
302
  }
303
  return entries;
304
 
 
131
  await updateDoc(docRef, {
132
  status: "completed",
133
  submission_prompt: text,
134
+ roomCode: roomCode, // Ensure roomCode is updated for legacy docs
135
  timestamp: serverTimestamp()
136
  });
137
  } else {
 
259
  */
260
  export async function getPeerPrompts(roomCode, challengeId) {
261
  const progressRef = collection(db, PROGRESS_COLLECTION);
 
 
 
 
262
 
263
+ // Query completions (filtered by challenge, status)
 
264
  const q = query(
265
  progressRef,
266
  where("challengeId", "==", challengeId),
 
274
  for (const docSnapshot of snapshot.docs) {
275
  const data = docSnapshot.data();
276
 
277
+ // Fetch nickname & user room info
278
+ // We fetch user first to verify room if needed
279
+ const userSnap = await getDoc(doc(db, USERS_COLLECTION, data.userId));
280
+ if (!userSnap.exists()) continue;
281
+
282
+ const userData = userSnap.data();
283
+
284
+ // Room Code Check
285
+ // 1. Check direct reference in progress (Fastest)
286
+ // 2. Fallback to user's current room (Legacy support)
287
+ const targetRoom = data.roomCode || userData.current_room;
288
+
289
+ if (String(targetRoom) !== String(roomCode)) {
290
  continue;
291
  }
292
 
293
+ entries.push({
294
+ id: docSnapshot.id,
295
+ userId: data.userId,
296
+ nickname: userData.nickname,
297
+ prompt: data.submission_prompt,
298
+ timestamp: data.timestamp,
299
+ likes: data.likes || 0,
300
+ likedBy: data.likedBy || []
301
+ });
 
 
 
 
302
  }
303
  return entries;
304
 
src/views/StudentView.js CHANGED
@@ -57,7 +57,7 @@ function renderTaskCard(c, userProgress) {
57
 
58
  ${!isStarted ? `
59
  <!-- Not Started State -->
60
- <div class="mt-4">
61
  <button onclick="window.startLevel('${c.id}', '${c.link}')"
62
  class="w-full sm:w-auto bg-gray-700 hover:bg-cyan-600 hover:text-white text-gray-200 font-bold py-3 px-6 rounded-xl transition-all flex items-center justify-center space-x-2 shadow-lg">
63
  <span>🚀 開始任務 (Start Task)</span>
@@ -668,7 +668,11 @@ window.triggerEvolution = async (currentStage, nextStage, likes, classSize, curr
668
  // DB Update with Monster ID
669
  const userId = localStorage.getItem('vibecoding_user_id');
670
  await updateUserMonster(userId, nextStage, nextMonster.id);
671
- window.location.reload();
 
 
 
 
672
  }, 1200);
673
  }, 1000);
674
  }, 300);
@@ -678,8 +682,11 @@ window.triggerEvolution = async (currentStage, nextStage, likes, classSize, curr
678
  playFlicker();
679
 
680
  } catch (e) {
 
681
  console.error(e);
682
  alert("進化失敗...");
683
- window.location.reload();
 
 
684
  }
685
  };
 
57
 
58
  ${!isStarted ? `
59
  <!-- Not Started State -->
60
+ <div class="mt-4 flex justify-center">
61
  <button onclick="window.startLevel('${c.id}', '${c.link}')"
62
  class="w-full sm:w-auto bg-gray-700 hover:bg-cyan-600 hover:text-white text-gray-200 font-bold py-3 px-6 rounded-xl transition-all flex items-center justify-center space-x-2 shadow-lg">
63
  <span>🚀 開始任務 (Start Task)</span>
 
668
  // DB Update with Monster ID
669
  const userId = localStorage.getItem('vibecoding_user_id');
670
  await updateUserMonster(userId, nextStage, nextMonster.id);
671
+
672
+ // Soft refresh to prevent screen flicker
673
+ const app = document.querySelector('#app');
674
+ if (app) app.innerHTML = await renderStudentView();
675
+ // Also need to ensure monster container is updated (handle in renderStudentView)
676
  }, 1200);
677
  }, 1000);
678
  }, 300);
 
682
  playFlicker();
683
 
684
  } catch (e) {
685
+ console.error(e);
686
  console.error(e);
687
  alert("進化失敗...");
688
+ // Re-render instead of reload to keep state
689
+ const app = document.querySelector('#app');
690
+ if (app) app.innerHTML = await renderStudentView();
691
  }
692
  };