Lashtw commited on
Commit
4e96de1
·
verified ·
1 Parent(s): 046f2a2

Upload 9 files

Browse files
Files changed (1) hide show
  1. src/views/InstructorView.js +29 -13
src/views/InstructorView.js CHANGED
@@ -124,12 +124,9 @@ export async function renderInstructorView() {
124
  <div class="flex items-center"><div class="w-3 h-3 bg-red-500 animate-pulse rounded-sm mr-1"></div> 卡關 (>5m)</div>
125
  </div>
126
 
127
- <button id="group-photo-btn" class="bg-gradient-to-r from-pink-600 to-purple-600 hover:from-pink-500 hover:to-purple-500 text-white font-bold py-2 px-4 rounded-lg transition-all shadow-lg border border-pink-400/30 flex items-center space-x-2">
128
  <span>📸 大合照</span>
129
  </button>
130
- <button id="btn-open-gallery" class="bg-blue-600 hover:bg-blue-500 text-white font-bold py-2 px-4 rounded-lg transition-all border border-blue-400/30 flex items-center space-x-2">
131
- <span>👾 怪獸圖鑑</span>
132
- </button>
133
  <button id="nav-admin-btn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-all border border-gray-600">
134
  管理題目
135
  </button>
@@ -138,13 +135,20 @@ export async function renderInstructorView() {
138
  <button id="rejoin-room-btn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-2 rounded-lg">重回</button>
139
 
140
  <button id="create-room-btn" class="bg-purple-600 hover:bg-purple-500 text-white font-bold px-4 py-2 rounded-lg shadow-lg">開房</button>
141
- <button id="logout-btn" class="bg-red-800 hover:bg-red-700 text-white font-bold px-4 py-2 rounded-lg shadow-lg border border-red-600/50" title="登出">
142
- 🚪
143
- </button>
144
  </div>
145
  </div>
146
  </header>
147
 
 
 
 
 
 
 
 
 
 
 
148
  <!-- Heatmap Content -->
149
  <div id="dashboard-content" class="hidden overflow-x-auto pb-10">
150
  <table class="w-full border-collapse">
@@ -635,6 +639,7 @@ export function setupInstructorEvents() {
635
  createContainer.classList.add('hidden');
636
  roomInfo.classList.remove('hidden');
637
  dashboardContent.classList.remove('hidden');
 
638
  displayRoomCode.textContent = roomCode;
639
  localStorage.setItem('vibecoding_instructor_room', roomCode);
640
  sessionStorage.setItem('vibecoding_instructor_in_room', 'true');
@@ -786,8 +791,8 @@ function renderTransposedHeatmap(students) {
786
  if (p.status === 'completed') {
787
  statusClass = 'bg-green-500/20 border-green-500/50 hover:bg-green-500/40 cursor-pointer shadow-[0_0_10px_rgba(34,197,94,0.1)]';
788
  content = '✅';
789
- const safePrompt = p.prompt.replace(/"/g, '&quot;').replace(/'/g, "\\'");
790
- action = `onclick = "window.showBroadcastModal('${student.id}', '${c.id}', '${student.nickname}', '${c.title}', '${safePrompt}')"`;
791
  } else if (p.status === 'started') {
792
  // Check stuck
793
  const startedAt = p.timestamp ? p.timestamp.toDate() : new Date();
@@ -833,14 +838,25 @@ function renderTransposedHeatmap(students) {
833
  }
834
 
835
  // Global scope for HTML access
836
- window.showBroadcastModal = (userId, challengeId, nickname, title, prompt) => {
 
 
 
 
 
 
 
 
 
 
837
  const modal = document.getElementById('broadcast-modal');
838
  const content = document.getElementById('broadcast-content');
839
 
840
- document.getElementById('broadcast-avatar').textContent = nickname[0];
841
- document.getElementById('broadcast-author').textContent = nickname;
842
  document.getElementById('broadcast-challenge').textContent = title;
843
- document.getElementById('broadcast-prompt').textContent = prompt;
 
844
 
845
  // Store IDs for actions
846
  modal.dataset.userId = userId;
 
124
  <div class="flex items-center"><div class="w-3 h-3 bg-red-500 animate-pulse rounded-sm mr-1"></div> 卡關 (>5m)</div>
125
  </div>
126
 
127
+ <button id="group-photo-btn" class="hidden bg-gradient-to-r from-pink-600 to-purple-600 hover:from-pink-500 hover:to-purple-500 text-white font-bold py-2 px-4 rounded-lg transition-all shadow-lg border border-pink-400/30 flex items-center space-x-2">
128
  <span>📸 大合照</span>
129
  </button>
 
 
 
130
  <button id="nav-admin-btn" class="bg-gray-700 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg transition-all border border-gray-600">
131
  管理題目
132
  </button>
 
135
  <button id="rejoin-room-btn" class="bg-gray-700 hover:bg-gray-600 text-white px-3 py-2 rounded-lg">重回</button>
136
 
137
  <button id="create-room-btn" class="bg-purple-600 hover:bg-purple-500 text-white font-bold px-4 py-2 rounded-lg shadow-lg">開房</button>
 
 
 
138
  </div>
139
  </div>
140
  </header>
141
 
142
+ <!-- Fixed Bottom Right Controls -->
143
+ <div class="fixed bottom-6 right-6 z-40 flex flex-col space-y-3">
144
+ <button id="btn-open-gallery" class="bg-blue-600 hover:bg-blue-500 text-white p-4 rounded-full shadow-2xl border border-blue-400/50 hover:scale-110 transition-transform flex items-center justify-center group" title="怪獸圖鑑">
145
+ <span class="text-2xl group-hover:animate-bounce">👾</span>
146
+ </button>
147
+ <button id="logout-btn" class="bg-red-800 hover:bg-red-700 text-white p-4 rounded-full shadow-2xl border border-red-600/50 hover:scale-110 transition-transform flex items-center justify-center" title="登出">
148
+ <span class="text-2xl">🚪</span>
149
+ </button>
150
+ </div>
151
+
152
  <!-- Heatmap Content -->
153
  <div id="dashboard-content" class="hidden overflow-x-auto pb-10">
154
  <table class="w-full border-collapse">
 
639
  createContainer.classList.add('hidden');
640
  roomInfo.classList.remove('hidden');
641
  dashboardContent.classList.remove('hidden');
642
+ document.getElementById('group-photo-btn').classList.remove('hidden'); // Show photo button
643
  displayRoomCode.textContent = roomCode;
644
  localStorage.setItem('vibecoding_instructor_room', roomCode);
645
  sessionStorage.setItem('vibecoding_instructor_in_room', 'true');
 
791
  if (p.status === 'completed') {
792
  statusClass = 'bg-green-500/20 border-green-500/50 hover:bg-green-500/40 cursor-pointer shadow-[0_0_10px_rgba(34,197,94,0.1)]';
793
  content = '✅';
794
+ // Pass only IDs, lookup logic is in the modal function now to avoid escaping issues
795
+ action = `onclick = "window.showBroadcastModal('${student.id}', '${c.id}')"`;
796
  } else if (p.status === 'started') {
797
  // Check stuck
798
  const startedAt = p.timestamp ? p.timestamp.toDate() : new Date();
 
838
  }
839
 
840
  // Global scope for HTML access
841
+ // Global scope for HTML access
842
+ window.showBroadcastModal = (userId, challengeId) => {
843
+ const student = currentStudents.find(s => s.id === userId);
844
+ if (!student) return;
845
+
846
+ const p = student.progress?.[challengeId];
847
+ if (!p) return;
848
+
849
+ const challenge = cachedChallenges.find(c => c.id === challengeId);
850
+ const title = challenge ? challenge.title : 'Unknown Challenge'; // Fallback
851
+
852
  const modal = document.getElementById('broadcast-modal');
853
  const content = document.getElementById('broadcast-content');
854
 
855
+ document.getElementById('broadcast-avatar').textContent = student.nickname[0];
856
+ document.getElementById('broadcast-author').textContent = student.nickname;
857
  document.getElementById('broadcast-challenge').textContent = title;
858
+ // content is already just text, but let's be safe
859
+ document.getElementById('broadcast-prompt').textContent = p.prompt || p.code || ''; // robust fallback
860
 
861
  // Store IDs for actions
862
  modal.dataset.userId = userId;