Lashtw commited on
Commit
8c465da
·
verified ·
1 Parent(s): 5d86f22

Upload 8 files

Browse files
src/views/InstructorView.js CHANGED
@@ -25,11 +25,17 @@ export async function renderInstructorView() {
25
  <span class="text-gray-400">教室代碼</span>
26
  <span id="display-room-code" class="text-3xl font-mono font-bold text-cyan-400 tracking-widest bg-gray-900 px-4 py-2 rounded-lg border border-cyan-500/30 shadow-[0_0_15px_rgba(34,211,238,0.3)]"></span>
27
  </div>
28
- <div class="flex space-x-3">
29
  <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">
30
  管理題目 (Admin)
31
  </button>
32
- <div id="create-room-container">
 
 
 
 
 
 
 
33
  <button id="create-room-btn" class="bg-purple-600 hover:bg-purple-500 text-white font-bold py-2 px-6 rounded-lg transition-all shadow-lg shadow-purple-500/30">
34
  建立新教室
35
  </button>
@@ -82,23 +88,27 @@ export function setupInstructorEvents() {
82
  window.location.hash = 'admin';
83
  });
84
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  createBtn.addEventListener('click', async () => {
86
  try {
87
  createBtn.disabled = true;
88
  createBtn.textContent = "建立中...";
89
 
90
  const roomCode = await createRoom();
91
-
92
- // UI Switch
93
- createContainer.classList.add('hidden');
94
- roomInfo.classList.remove('hidden');
95
- dashboardContent.classList.remove('hidden');
96
- displayRoomCode.textContent = roomCode;
97
-
98
- // Subscribe to updates only after room is created
99
- subscribeToRoom(roomCode, (students) => {
100
- renderStudentCards(students, studentsGrid);
101
- });
102
 
103
  } catch (error) {
104
  console.error(error);
@@ -106,6 +116,22 @@ export function setupInstructorEvents() {
106
  createBtn.disabled = false;
107
  }
108
  });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
110
 
111
  function renderStudentCards(students, container) {
 
25
  <span class="text-gray-400">教室代碼</span>
26
  <span id="display-room-code" class="text-3xl font-mono font-bold text-cyan-400 tracking-widest bg-gray-900 px-4 py-2 rounded-lg border border-cyan-500/30 shadow-[0_0_15px_rgba(34,211,238,0.3)]"></span>
27
  </div>
 
28
  <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">
29
  管理題目 (Admin)
30
  </button>
31
+ <div id="create-room-container" class="flex items-center space-x-2">
32
+ <div class="flex items-center bg-gray-900 rounded-lg border border-gray-700 p-1">
33
+ <input type="text" id="rejoin-room-code" placeholder="輸入舊代碼" class="bg-transparent text-white px-2 py-1 w-24 text-center focus:outline-none text-sm">
34
+ <button id="rejoin-room-btn" class="bg-gray-700 hover:bg-gray-600 text-xs text-white px-2 py-1 rounded transition-colors">
35
+ 重回
36
+ </button>
37
+ </div>
38
+ <span class="text-gray-500">or</span>
39
  <button id="create-room-btn" class="bg-purple-600 hover:bg-purple-500 text-white font-bold py-2 px-6 rounded-lg transition-all shadow-lg shadow-purple-500/30">
40
  建立新教室
41
  </button>
 
88
  window.location.hash = 'admin';
89
  });
90
 
91
+ // Auto-fill room code from local storage
92
+ const savedRoomCode = localStorage.getItem('vibecoding_instructor_room');
93
+ if (savedRoomCode) {
94
+ document.getElementById('rejoin-room-code').value = savedRoomCode;
95
+ }
96
+
97
+ const rejoinBtn = document.getElementById('rejoin-room-btn');
98
+ rejoinBtn.addEventListener('click', () => {
99
+ const code = document.getElementById('rejoin-room-code').value.trim();
100
+ if (!code) return alert('請輸入教室代碼');
101
+
102
+ enterRoom(code);
103
+ });
104
+
105
  createBtn.addEventListener('click', async () => {
106
  try {
107
  createBtn.disabled = true;
108
  createBtn.textContent = "建立中...";
109
 
110
  const roomCode = await createRoom();
111
+ enterRoom(roomCode);
 
 
 
 
 
 
 
 
 
 
112
 
113
  } catch (error) {
114
  console.error(error);
 
116
  createBtn.disabled = false;
117
  }
118
  });
119
+
120
+ function enterRoom(roomCode) {
121
+ // UI Switch
122
+ createContainer.classList.add('hidden');
123
+ roomInfo.classList.remove('hidden');
124
+ dashboardContent.classList.remove('hidden');
125
+ displayRoomCode.textContent = roomCode;
126
+
127
+ // Save to local storage
128
+ localStorage.setItem('vibecoding_instructor_room', roomCode);
129
+
130
+ // Subscribe to updates
131
+ subscribeToRoom(roomCode, (students) => {
132
+ renderStudentCards(students, studentsGrid);
133
+ });
134
+ }
135
  }
136
 
137
  function renderStudentCards(students, container) {
src/views/StudentView.js CHANGED
@@ -91,9 +91,12 @@ export async function renderStudentView() {
91
  return `
92
  <div class="min-h-screen p-4 pb-32 max-w-md mx-auto sm:max-w-4xl">
93
  <header class="flex justify-between items-center mb-8 sticky top-0 bg-slate-900/90 backdrop-blur z-20 py-4 px-2 -mx-2">
94
- <div class="flex items-center space-x-2">
95
- <div class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></div>
96
- <span class="text-gray-400 text-sm truncate max-w-[150px]">${nickname}</span>
 
 
 
97
  </div>
98
  <div>
99
  <h1 class="text-xl font-bold italic text-white tracking-widest">VIBECODING</h1>
 
91
  return `
92
  <div class="min-h-screen p-4 pb-32 max-w-md mx-auto sm:max-w-4xl">
93
  <header class="flex justify-between items-center mb-8 sticky top-0 bg-slate-900/90 backdrop-blur z-20 py-4 px-2 -mx-2">
94
+ <div class="flex flex-col">
95
+ <div class="flex items-center space-x-2">
96
+ <div class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></div>
97
+ <span class="text-gray-400 text-sm truncate max-w-[150px]">${nickname}</span>
98
+ </div>
99
+ <div class="text-xs text-gray-500 mt-1">教室: <span class="font-mono text-cyan-400 font-bold">${roomCode}</span></div>
100
  </div>
101
  <div>
102
  <h1 class="text-xl font-bold italic text-white tracking-widest">VIBECODING</h1>