humza7656 commited on
Commit
9662fcc
·
verified ·
1 Parent(s): 6d68c5c

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +171 -496
index.html CHANGED
@@ -3,543 +3,218 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>QuizCollab | Pro AI Quiz Platform</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://unpkg.com/lucide@0.263.1/dist/umd/lucide.min.js"></script>
9
- <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
10
  <style>
11
  :root {
12
- --slate-950: #020617;
13
- --slate-900: #0f172a;
14
- --slate-800: #1e293b;
15
- --sky-500: #0ea5e9;
16
- --emerald-500: #10b981;
17
  }
18
-
19
- body {
20
- font-family: 'Plus Jakarta Sans', sans-serif;
21
- background-color: var(--slate-950);
22
- color: #f8fafc;
23
- overflow: hidden;
24
  }
25
 
26
- .glass-panel {
27
- background: rgba(30, 41, 59, 0.7);
28
- backdrop-filter: blur(12px);
29
- border: 1px solid rgba(255, 255, 255, 0.05);
 
 
 
 
 
 
 
 
 
30
  }
31
 
32
- .sidebar-item {
33
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
 
 
34
  }
35
 
36
- .sidebar-item.active {
37
- background: rgba(14, 165, 233, 0.1);
38
- color: var(--sky-500);
39
- border-right: 3px solid var(--sky-500);
 
 
 
 
 
40
  }
41
 
42
- .code-font { font-family: 'JetBrains Mono', monospace; }
 
 
 
 
 
43
 
44
- /* Custom Scrollbar */
45
- ::-webkit-scrollbar { width: 6px; }
46
- ::-webkit-scrollbar-track { background: transparent; }
47
- ::-webkit-scrollbar-thumb { background: #334155; border-radius: 10px; }
48
- ::-webkit-scrollbar-thumb:hover { background: #475569; }
 
49
 
50
- @keyframes slideIn {
51
- from { transform: translateX(20px); opacity: 0; }
52
- to { transform: translateX(0); opacity: 1; }
53
  }
54
- .animate-slide { animation: slideIn 0.4s ease-out forwards; }
55
 
56
- .loader {
57
- width: 20px;
58
- height: 20px;
59
- border: 2px solid rgba(255,255,255,0.1);
60
- border-top: 2px solid white;
61
- border-radius: 50%;
62
- animation: spin 0.8s linear infinite;
63
  }
64
- @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
65
-
66
- .toast {
67
  position: fixed;
68
- top: 2rem;
69
- right: 2rem;
70
- z-index: 9999;
71
- transform: translateY(-100px);
72
- transition: transform 0.3s ease;
 
 
 
 
 
 
 
 
 
 
 
73
  }
74
- .toast.show { transform: translateY(0); }
75
  </style>
76
  </head>
77
- <body class="h-screen w-screen flex">
78
 
79
- <!-- Global Components -->
80
- <div id="toast" class="toast flex items-center gap-3 bg-slate-800 border border-slate-700 px-6 py-4 rounded-xl shadow-2xl">
81
- <div class="p-2 bg-emerald-500/20 rounded-full text-emerald-400" id="toast-icon">
82
- <i data-lucide="check-circle" class="w-5 h-5"></i>
83
- </div>
84
- <div>
85
- <p class="font-bold text-sm text-white" id="toast-title">Success</p>
86
- <p class="text-xs text-slate-400" id="toast-msg">Operation completed.</p>
87
- </div>
88
  </div>
89
 
90
- <!-- Auth Overlay (Full Screen) -->
91
- <div id="view-login" class="absolute inset-0 z-[100] bg-slate-950 flex items-center justify-center p-6">
92
- <div class="max-w-md w-full glass-panel p-8 rounded-3xl border border-white/5 shadow-2xl">
93
- <div class="flex flex-col items-center mb-10">
94
- <div class="w-16 h-16 bg-sky-500/10 text-sky-500 rounded-2xl flex items-center justify-center mb-4">
95
- <i data-lucide="brain-circuit" class="w-10 h-10"></i>
96
- </div>
97
- <h1 class="text-3xl font-extrabold tracking-tight">QuizCollab</h1>
98
- <p class="text-slate-500 mt-2 text-center">The professional grade AI quiz orchestrator</p>
99
- </div>
100
 
101
- <div class="space-y-4">
102
- <div class="space-y-1.5">
103
- <label class="text-[10px] uppercase font-black text-slate-500 tracking-wider">Username</label>
104
- <input type="text" id="login-name" placeholder="Enter your display name" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-3 text-sm focus:border-sky-500 focus:outline-none transition-all">
105
- </div>
106
- <div class="space-y-1.5">
107
- <label class="text-[10px] uppercase font-black text-slate-500 tracking-wider">Access Token / Password</label>
108
- <input type="password" id="login-pass" placeholder="••••••••" class="w-full bg-slate-900/50 border border-slate-700/50 rounded-xl px-4 py-3 text-sm focus:border-sky-500 focus:outline-none transition-all">
109
- </div>
110
- <button onclick="handleLogin()" id="btn-login" class="w-full bg-sky-500 hover:bg-sky-400 text-white font-bold py-4 rounded-xl transition-all shadow-lg shadow-sky-500/20 flex items-center justify-center gap-2 mt-6">
111
- <span>Enter Workspace</span>
112
- <i data-lucide="arrow-right" class="w-4 h-4"></i>
113
- </button>
114
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
 
116
- <!-- Connection Config Toggle -->
117
- <button onclick="toggleConfig()" class="mt-8 w-full text-[10px] text-slate-600 uppercase tracking-widest font-bold hover:text-slate-400">
118
- Configure API Gateway
119
- </button>
120
- <div id="config-panel" class="hidden mt-4 p-4 bg-slate-900 rounded-xl border border-slate-800">
121
- <input type="text" id="base-url" value="https://circus-jake-guarantees-kurt.trycloudflare.com" class="w-full bg-black border border-slate-700 rounded p-2 text-[10px] text-sky-400 code-font">
122
- </div>
123
- </div>
124
- </div>
125
-
126
- <!-- Sidebar Navigation (Desktop) -->
127
- <aside id="main-sidebar" class="hidden w-72 bg-slate-900 border-r border-slate-800 flex flex-col">
128
- <div class="p-8">
129
- <div class="flex items-center gap-3 text-sky-500 font-extrabold text-xl">
130
- <i data-lucide="zap" class="w-6 h-6 fill-sky-500"></i>
131
- QuizCollab
132
- </div>
133
- </div>
134
-
135
- <nav class="flex-1 px-4 space-y-2">
136
- <button onclick="switchView('view-dashboard')" id="nav-dashboard" class="sidebar-item w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold text-slate-400 hover:text-white hover:bg-slate-800">
137
- <i data-lucide="layout-grid" class="w-5 h-5"></i> Dashboard
138
- </button>
139
- <button onclick="switchView('view-create')" id="nav-create" class="sidebar-item w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold text-slate-400 hover:text-white hover:bg-slate-800">
140
- <i data-lucide="plus-circle" class="w-5 h-5"></i> Create Room
141
- </button>
142
- <button onclick="switchView('view-join')" id="nav-join" class="sidebar-item w-full flex items-center gap-3 px-4 py-3 rounded-xl text-sm font-semibold text-slate-400 hover:text-white hover:bg-slate-800">
143
- <i data-lucide="key-round" class="w-5 h-5"></i> Join Session
144
- </button>
145
- </nav>
146
-
147
- <div class="p-6 border-t border-slate-800">
148
- <div class="flex items-center gap-3 bg-slate-950/50 p-4 rounded-2xl border border-slate-800">
149
- <div class="w-10 h-10 bg-gradient-to-br from-sky-500 to-indigo-600 rounded-lg flex items-center justify-center font-bold text-white shadow-lg" id="user-initial">
150
- U
151
- </div>
152
- <div class="flex-1 min-w-0">
153
- <p class="text-xs font-bold text-white truncate" id="display-user-name">User Name</p>
154
- <p class="text-[10px] text-slate-500 truncate" id="display-user-id">ID: ....</p>
155
- </div>
156
- <button onclick="location.reload()" class="text-slate-600 hover:text-red-400 transition">
157
- <i data-lucide="log-out" class="w-4 h-4"></i>
158
- </button>
159
- </div>
160
- </div>
161
- </aside>
162
-
163
- <!-- Main Workspace -->
164
- <main class="flex-1 h-full overflow-hidden flex flex-col relative">
165
-
166
- <!-- Dashboard View -->
167
- <section id="view-dashboard" class="hidden flex-1 overflow-y-auto p-12 animate-slide">
168
- <header class="mb-12">
169
- <h2 class="text-4xl font-extrabold tracking-tight mb-2">Workspace Overview</h2>
170
- <p class="text-slate-500">Welcome back. Ready to orchestrate a new learning session?</p>
171
- </header>
172
-
173
- <div class="grid grid-cols-1 lg:grid-cols-2 gap-8 max-w-5xl">
174
- <div onclick="switchView('view-create')" class="group p-8 glass-panel rounded-3xl border border-white/5 hover:border-sky-500/50 cursor-pointer transition-all hover:shadow-2xl hover:shadow-sky-500/10">
175
- <div class="w-14 h-14 bg-sky-500 text-white rounded-2xl flex items-center justify-center mb-6 shadow-lg shadow-sky-500/30">
176
- <i data-lucide="sparkles" class="w-7 h-7"></i>
177
- </div>
178
- <h3 class="text-2xl font-bold mb-3">AI Quiz Builder</h3>
179
- <p class="text-slate-400 leading-relaxed mb-6">Describe a topic and let our Groq-powered engine synthesize a high-quality assessment instantly.</p>
180
- <div class="flex items-center text-sky-400 font-bold text-sm gap-2">
181
- Start Building <i data-lucide="arrow-right" class="w-4 h-4"></i>
182
- </div>
183
- </div>
184
-
185
- <div onclick="switchView('view-join')" class="group p-8 glass-panel rounded-3xl border border-white/5 hover:border-emerald-500/50 cursor-pointer transition-all hover:shadow-2xl hover:shadow-emerald-500/10">
186
- <div class="w-14 h-14 bg-emerald-500 text-white rounded-2xl flex items-center justify-center mb-6 shadow-lg shadow-emerald-500/30">
187
- <i data-lucide="users" class="w-7 h-7"></i>
188
- </div>
189
- <h3 class="text-2xl font-bold mb-3">Join Session</h3>
190
- <p class="text-slate-400 leading-relaxed mb-6">Have a Share ID from a colleague? Enter the workspace to participate in the assessment.</p>
191
- <div class="flex items-center text-emerald-400 font-bold text-sm gap-2">
192
- Connect Now <i data-lucide="arrow-right" class="w-4 h-4"></i>
193
- </div>
194
- </div>
195
- </div>
196
- </section>
197
-
198
- <!-- Create Room View -->
199
- <section id="view-create" class="hidden flex-1 flex items-center justify-center p-12 animate-slide">
200
- <div class="max-w-xl w-full">
201
- <div class="mb-10 text-center">
202
- <h2 class="text-3xl font-bold mb-4">Initialize New Room</h2>
203
- <p class="text-slate-500">Define the knowledge domain for your AI generation</p>
204
- </div>
205
- <div class="space-y-6">
206
- <div class="space-y-2">
207
- <label class="text-[10px] uppercase font-black text-slate-500 tracking-wider">Subject Area</label>
208
- <input type="text" id="quiz-topic" placeholder="e.g. Quantum Mechanics, Digital Marketing..." class="w-full bg-slate-900 border border-slate-700 rounded-2xl px-6 py-5 text-lg font-medium focus:border-sky-500 focus:outline-none transition-all">
209
- </div>
210
- <button onclick="handleCreateAndGenerate()" id="btn-create" class="w-full bg-sky-500 hover:bg-sky-400 text-white font-black py-5 rounded-2xl transition-all shadow-xl flex items-center justify-center gap-3">
211
- <i data-lucide="wand-2" class="w-5 h-5"></i>
212
- <span>Synthesize Assessment</span>
213
- </button>
214
- </div>
215
- </div>
216
 
217
- <!-- Generation Overlay -->
218
- <div id="creation-loader" class="hidden absolute inset-0 z-50 bg-slate-950/90 backdrop-blur-md flex flex-col items-center justify-center">
219
- <div class="relative w-24 h-24 mb-8">
220
- <div class="absolute inset-0 border-4 border-sky-500/20 rounded-full"></div>
221
- <div class="absolute inset-0 border-4 border-sky-500 border-t-transparent rounded-full animate-spin"></div>
222
- <div class="absolute inset-0 flex items-center justify-center">
223
- <i data-lucide="cpu" class="w-10 h-10 text-sky-400 animate-pulse"></i>
224
- </div>
225
- </div>
226
- <h3 class="text-2xl font-bold text-white mb-2">Synthesizing Questions</h3>
227
- <p class="text-slate-400 animate-pulse">Consulting the Groq LLM Knowledge Base...</p>
228
- </div>
229
- </section>
230
-
231
- <!-- Join Room View -->
232
- <section id="view-join" class="hidden flex-1 flex items-center justify-center p-12 animate-slide">
233
- <div class="max-w-md w-full glass-panel p-10 rounded-3xl">
234
- <h2 class="text-2xl font-bold mb-8 flex items-center gap-3">
235
- <i data-lucide="command" class="w-6 h-6 text-emerald-400"></i> Access Session
236
- </h2>
237
- <div class="space-y-6">
238
- <div class="space-y-2">
239
- <label class="text-[10px] uppercase font-black text-slate-500 tracking-wider">Share Token</label>
240
- <input type="text" id="join-share-id" placeholder="Paste Token..." class="w-full bg-black border border-slate-700 rounded-xl px-4 py-4 code-font text-emerald-400 text-center tracking-widest text-xl focus:border-emerald-500 focus:outline-none transition-all">
241
- </div>
242
- <button onclick="handleJoin()" id="btn-join" class="w-full bg-emerald-500 hover:bg-emerald-400 text-white font-bold py-4 rounded-xl transition-all shadow-lg flex items-center justify-center gap-2">
243
- <span>Initialize Link</span>
244
- <i data-lucide="chevron-right" class="w-4 h-4"></i>
245
- </button>
246
- </div>
247
- </div>
248
- </section>
249
-
250
- <!-- Quiz View (Collab Workspace) -->
251
- <section id="view-quiz" class="hidden flex-1 flex flex-col overflow-hidden animate-slide">
252
- <!-- Workspace Header -->
253
- <div class="px-8 py-4 border-b border-slate-800 flex items-center justify-between bg-slate-900/50">
254
- <div class="flex items-center gap-6">
255
- <div class="flex flex-col">
256
- <span class="text-[10px] uppercase font-black text-slate-500 tracking-widest">Active Session</span>
257
- <h3 class="font-bold text-white flex items-center gap-2">
258
- <i data-lucide="folder" class="w-4 h-4 text-sky-400"></i>
259
- <span id="active-topic">Assessment</span>
260
- </h3>
261
- </div>
262
- <div class="h-8 w-px bg-slate-800"></div>
263
- <div class="flex flex-col">
264
- <span class="text-[10px] uppercase font-black text-slate-500 tracking-widest">Share Token</span>
265
- <button onclick="copyShareToken()" class="group font-mono text-xs text-sky-400 flex items-center gap-2 hover:text-white transition">
266
- <span id="display-share-id">TOKEN</span>
267
- <i data-lucide="copy" class="w-3 h-3 group-hover:scale-125 transition"></i>
268
- </button>
269
- </div>
270
- </div>
271
- <div class="flex items-center gap-3">
272
- <button onclick="copyInviteLink()" class="flex items-center gap-2 px-4 py-2 bg-slate-800 hover:bg-slate-700 rounded-lg text-xs font-bold transition">
273
- <i data-lucide="link" class="w-4 h-4"></i> Invite Link
274
- </button>
275
- <button onclick="switchView('view-dashboard')" class="p-2 text-slate-500 hover:text-white transition">
276
- <i data-lucide="x" class="w-5 h-5"></i>
277
- </button>
278
- </div>
279
- </div>
280
-
281
- <div class="flex-1 flex overflow-hidden">
282
- <!-- Left: Question Content -->
283
- <div class="flex-[3] p-8 overflow-y-auto border-r border-slate-800">
284
- <div class="max-w-3xl mx-auto space-y-8">
285
- <div class="flex items-center gap-4 text-sky-500 bg-sky-500/10 w-fit px-4 py-1.5 rounded-full text-xs font-bold mb-6">
286
- <i data-lucide="info" class="w-4 h-4"></i>
287
- AI Generated Content
288
- </div>
289
- <div id="questions-content" class="text-xl leading-relaxed text-slate-300 whitespace-pre-wrap font-medium">
290
- <!-- Questions Load Here -->
291
- </div>
292
- </div>
293
- </div>
294
-
295
- <!-- Right: Submission Panel -->
296
- <div class="flex-[2] bg-slate-900/30 p-8 flex flex-col">
297
- <div class="flex-1 space-y-6">
298
- <div class="space-y-2">
299
- <label class="text-[10px] uppercase font-black text-slate-400 tracking-widest">Workspace Response</label>
300
- <textarea id="quiz-answer" placeholder="Formulate your structured response here..." class="w-full h-80 bg-slate-900/50 border border-slate-700 rounded-2xl p-6 text-sm text-slate-200 focus:outline-none focus:border-sky-500 focus:ring-4 focus:ring-sky-500/10 transition-all resize-none"></textarea>
301
- </div>
302
- <div class="bg-amber-500/5 border border-amber-500/20 p-4 rounded-xl flex gap-3">
303
- <i data-lucide="alert-triangle" class="w-5 h-5 text-amber-500 flex-shrink-0"></i>
304
- <p class="text-[10px] text-amber-500/80 leading-relaxed font-bold uppercase tracking-tight">
305
- Submission is permanent. Ensure all questions are addressed before transmitting to the AI grading engine.
306
- </p>
307
- </div>
308
- </div>
309
- <button onclick="handleSubmitAnswers()" id="btn-submit" class="w-full bg-sky-500 hover:bg-sky-400 text-white font-black py-5 rounded-2xl transition-all shadow-xl flex items-center justify-center gap-3">
310
- <span>Transmit Submission</span>
311
- <i data-lucide="send" class="w-5 h-5"></i>
312
- </button>
313
- </div>
314
- </div>
315
- </section>
316
-
317
- <!-- Results View -->
318
- <section id="view-results" class="hidden flex-1 flex items-center justify-center p-12 animate-slide">
319
- <div class="max-w-2xl w-full text-center">
320
- <div class="inline-flex p-5 bg-emerald-500/20 rounded-3xl mb-10">
321
- <i data-lucide="award" class="w-16 h-16 text-emerald-400"></i>
322
- </div>
323
- <h2 class="text-5xl font-black mb-4 tracking-tighter">Grading Successful</h2>
324
- <p class="text-slate-500 mb-12">The AI has analyzed your submission. Evaluation result below:</p>
325
-
326
- <div class="bg-slate-900/50 border border-slate-800 p-12 rounded-[3rem] mb-12 flex flex-col items-center">
327
- <span class="text-[10px] uppercase font-black text-slate-500 tracking-[0.3em] mb-4">Calculated Score</span>
328
- <div class="text-9xl font-black text-transparent bg-clip-text bg-gradient-to-br from-sky-400 to-emerald-400 tracking-tighter" id="score-display">--</div>
329
- <div class="h-1 w-24 bg-slate-800 my-8 rounded-full"></div>
330
- <p class="text-slate-400 font-medium">Competency Metric Transmitted to Database</p>
331
- </div>
332
-
333
- <button onclick="switchView('view-dashboard')" class="bg-white text-slate-950 font-black py-4 px-10 rounded-2xl hover:scale-105 transition shadow-2xl">
334
- Return to Hub
335
- </button>
336
- </div>
337
- </section>
338
- </main>
339
-
340
- <script>
341
- const appState = {
342
- user: { name: '', id: '', password: '' },
343
- room: { id: '', shareId: '', topic: '' },
344
- questions: '',
345
- currentView: 'view-login'
346
- };
347
-
348
- function refreshIcons() {
349
- try { if (window.lucide) window.lucide.createIcons(); } catch (e) {}
350
- }
351
-
352
- document.addEventListener('DOMContentLoaded', () => {
353
- refreshIcons();
354
- const urlParams = new URLSearchParams(window.location.search);
355
- const invite = urlParams.get('invite');
356
- if (invite) {
357
- document.getElementById('join-share-id').value = invite;
358
- }
359
- });
360
-
361
- function showToast(title, msg, type = 'success') {
362
- const toast = document.getElementById('toast');
363
- document.getElementById('toast-title').textContent = title;
364
- document.getElementById('toast-msg').textContent = msg;
365
- toast.classList.add('show');
366
- setTimeout(() => toast.classList.remove('show'), 3500);
367
- }
368
-
369
- function toggleConfig() {
370
- document.getElementById('config-panel').classList.toggle('hidden');
371
- }
372
-
373
- function switchView(viewId) {
374
- // Update UI
375
- document.querySelectorAll('section, #view-login').forEach(el => el.classList.add('hidden'));
376
- document.getElementById(viewId).classList.remove('hidden');
377
 
378
- // Sidebar display
379
- document.getElementById('main-sidebar').style.display = (viewId === 'view-login') ? 'none' : 'flex';
 
380
 
381
- // Active Nav state
382
- document.querySelectorAll('.sidebar-item').forEach(el => el.classList.remove('active'));
383
- const navBtn = document.getElementById('nav-' + viewId.replace('view-', ''));
384
- if (navBtn) navBtn.classList.add('active');
385
-
386
- appState.currentView = viewId;
387
- refreshIcons();
388
- }
389
 
390
- async function apiCall(endpoint, method = 'GET', body = null) {
391
- const baseUrl = document.getElementById('base-url').value.trim().replace(/\/$/, '');
392
- const url = `${baseUrl}${endpoint.startsWith('/') ? endpoint : '/' + endpoint}`;
393
 
394
- const options = {
395
- method,
396
- headers: { 'Content-Type': 'application/json' }
397
- };
398
- if (body) options.body = JSON.stringify(body);
399
-
400
- try {
401
- const res = await fetch(url, options);
402
- if (!res.ok) throw new Error(`HTTP ${res.status}`);
403
- return await res.json();
404
- } catch (err) {
405
- console.error("API Error:", err);
406
- showToast("Connection Failure", err.message, "error");
407
- throw err;
408
- }
409
- }
410
-
411
- async function handleLogin() {
412
- const name = document.getElementById('login-name').value;
413
- const pass = document.getElementById('login-pass').value;
414
- const btn = document.getElementById('btn-login');
415
-
416
- if (!name || !pass) return showToast("Required", "Credentials missing", "error");
417
- btn.innerHTML = '<div class="loader"></div>';
418
-
419
- try {
420
- // Using corrected path //QuizzCollab/new_user -> /QuizzCollab/new_user
421
- const data = await apiCall('/QuizzCollab/new_user', 'POST', { name, password: pass });
422
 
423
- if (data.User_id) {
424
- appState.user = { name, password: pass, id: data.User_id };
425
- document.getElementById('display-user-name').textContent = name;
426
- document.getElementById('display-user-id').textContent = `ID: ${data.User_id.slice(0, 8)}...`;
427
- document.getElementById('user-initial').textContent = name.charAt(0).toUpperCase();
428
- switchView('view-dashboard');
429
- showToast("Workspace Active", `Welcome, ${name}`);
430
- }
431
- } catch (e) {
432
- console.error(e);
433
- } finally {
434
- btn.innerHTML = '<span>Enter Workspace</span> <i data-lucide="arrow-right" class="w-4 h-4"></i>';
435
- refreshIcons();
436
- }
437
- }
438
-
439
- async function handleCreateAndGenerate() {
440
- const topic = document.getElementById('quiz-topic').value;
441
- if (!topic) return showToast("Incomplete", "Enter a subject area", "error");
442
-
443
- document.getElementById('creation-loader').classList.remove('hidden');
444
-
445
- try {
446
- // 1. Create Room
447
- const r = await apiCall(`/QuizzCollab/room_create?user_id=${appState.user.id}`, 'GET');
448
- appState.room = { id: r.Room_id, shareId: r.Share_id, topic };
449
-
450
- // 2. Generate Quiz
451
- const q = await apiCall('/QuizzCollab/quizz', 'POST', {
452
- room_id: r.Room_id,
453
- share_id: r.Share_id,
454
- user_id: appState.user.id,
455
- field_name: topic
456
- });
457
-
458
- // Normalizing response key (QuizzColab typo fix)
459
- appState.questions = q.QuizzCollab || q.QuizzColab || "Generated content empty.";
460
 
461
- document.getElementById('active-topic').textContent = topic;
462
- document.getElementById('display-share-id').textContent = r.Share_id;
463
- document.getElementById('questions-content').textContent = appState.questions;
464
 
465
- switchView('view-quiz');
466
- showToast("Session Initialized", "AI synthesized assessment successfully.");
467
- } catch (e) {
468
- console.error(e);
469
- } finally {
470
- document.getElementById('creation-loader').classList.add('hidden');
471
- }
472
- }
473
-
474
- async function handleJoin() {
475
- const sid = document.getElementById('join-share-id').value.trim();
476
- if (!sid) return showToast("Required", "Share Token missing", "error");
477
-
478
- const btn = document.getElementById('btn-join');
479
- btn.innerHTML = '<div class="loader"></div>';
480
-
481
- try {
482
- const data = await apiCall(`/QuizzCollab/join/${sid}`, 'GET');
483
- if (data && data[0]) {
484
- const row = data[0];
485
- appState.questions = row.questions;
486
- appState.room = { id: row.room_id, shareId: sid, topic: "Collaborative Session" };
487
-
488
- document.getElementById('active-topic').textContent = "Collaborative Session";
489
- document.getElementById('display-share-id').textContent = sid;
490
- document.getElementById('questions-content').textContent = appState.questions;
491
-
492
- switchView('view-quiz');
493
- showToast("Session Joined", "Workspace sync complete.");
494
  } else {
495
- showToast("Invalid Token", "Session not found", "error");
496
  }
497
- } catch (e) {
498
- console.error(e);
499
- } finally {
500
- btn.innerHTML = '<span>Initialize Link</span> <i data-lucide="chevron-right" class="w-4 h-4"></i>';
501
- refreshIcons();
502
- }
503
  }
504
 
505
- async function handleSubmitAnswers() {
506
- const responseText = document.getElementById('quiz-answer').value.trim();
507
- if (!responseText) return showToast("Required", "No response provided", "error");
 
508
 
509
- const btn = document.getElementById('btn-submit');
510
- btn.innerHTML = '<div class="loader"></div>';
511
-
512
- try {
513
- const res = await apiCall('/QuizzCollab/join/marks', 'POST', {
514
- room_id: appState.room.id,
515
- share_id: appState.room.shareId,
516
- user_id: appState.user.id,
517
- field_name: appState.room.topic,
518
- data: { student_response: responseText }
519
- });
520
-
521
- document.getElementById('score-display').textContent = res.QuizzCollab ?? "N/A";
522
- switchView('view-results');
523
- } catch (e) {
524
- console.error(e);
525
- } finally {
526
- btn.innerHTML = '<span>Transmit Submission</span> <i data-lucide="send" class="w-5 h-5"></i>';
527
- refreshIcons();
528
  }
529
- }
 
530
 
531
- function copyShareToken() {
532
- const token = appState.room.shareId;
533
- navigator.clipboard.writeText(token);
534
- showToast("Copied", "Share Token saved to clipboard");
535
- }
 
536
 
537
- function copyInviteLink() {
538
- const url = new URL(window.location.href);
539
- url.searchParams.set('invite', appState.room.shareId);
540
- navigator.clipboard.writeText(url.toString());
541
- showToast("Link Copied", "Invite URL saved to clipboard");
542
- }
543
  </script>
544
  </body>
545
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>A Little Surprise for You</title>
 
 
 
7
  <style>
8
  :root {
9
+ --bg-color: #020617;
10
+ --text-color: #f1f5f9;
11
+ --accent-color: #22c55e;
 
 
12
  }
13
+
14
+ * {
15
+ margin: 0;
16
+ padding: 0;
17
+ box-sizing: border-box;
18
+ user-select: none;
19
  }
20
 
21
+ body {
22
+ background-color: var(--bg-color);
23
+ color: var(--text-color);
24
+ font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
25
+ height: 100vh;
26
+ overflow: hidden;
27
+ display: flex;
28
+ flex-direction: column;
29
+ align-items: center;
30
+ justify-content: center;
31
+ cursor: pointer;
32
+ background-image:
33
+ radial-gradient(circle at 50% 50%, #1e293b 0%, #020617 100%);
34
  }
35
 
36
+ .container {
37
+ text-align: center;
38
+ z-index: 10;
39
+ pointer-events: none;
40
  }
41
 
42
+ h1 {
43
+ font-size: 2.5rem;
44
+ margin-bottom: 1rem;
45
+ background: linear-gradient(135deg, #4ade80 0%, #2dd4bf 100%);
46
+ -webkit-background-clip: text;
47
+ -webkit-text-fill-color: transparent;
48
+ opacity: 0;
49
+ animation: fadeIn 2s forwards;
50
+ filter: drop-shadow(0 0 15px rgba(74, 222, 128, 0.3));
51
  }
52
 
53
+ p {
54
+ font-size: 1.2rem;
55
+ color: #94a3b8;
56
+ opacity: 0;
57
+ animation: fadeIn 2s forwards 0.5s;
58
+ }
59
 
60
+ .hint {
61
+ margin-top: 2rem;
62
+ font-size: 0.9rem;
63
+ color: #334155;
64
+ font-style: italic;
65
+ }
66
 
67
+ @keyframes fadeIn {
68
+ from { opacity: 0; transform: translateY(10px); }
69
+ to { opacity: 1; transform: translateY(0); }
70
  }
 
71
 
72
+ .lizard {
73
+ position: absolute;
74
+ width: 80px;
75
+ height: 80px;
76
+ pointer-events: none;
77
+ z-index: 5;
78
+ filter: drop-shadow(0 4px 6px rgba(0,0,0,0.4));
79
  }
80
+
81
+ /* Message Box */
82
+ #message-box {
83
  position: fixed;
84
+ bottom: 30px;
85
+ background: rgba(15, 23, 42, 0.9);
86
+ padding: 12px 24px;
87
+ border-radius: 9999px;
88
+ border: 1px solid rgba(74, 222, 128, 0.2);
89
+ backdrop-filter: blur(8px);
90
+ display: none;
91
+ color: #4ade80;
92
+ font-weight: 500;
93
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
94
+ animation: slideUp 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
95
+ }
96
+
97
+ @keyframes slideUp {
98
+ from { transform: translateY(100px); opacity: 0; }
99
+ to { transform: translateY(0); opacity: 1; }
100
  }
 
101
  </style>
102
  </head>
103
+ <body>
104
 
105
+ <div class="container">
106
+ <h1>Hey, I hope this makes you smile</h1>
107
+ <p>Just a screen full of friends for you.</p>
108
+ <div class="hint">(Click anywhere on the screen)</div>
 
 
 
 
 
109
  </div>
110
 
111
+ <div id="message-box"></div>
 
 
 
 
 
 
 
 
 
112
 
113
+ <script>
114
+ const lizardColors = ['#4ade80', '#2dd4bf', '#84cc16', '#10b981', '#fbbf24', '#f87171'];
115
+ const messages = [
116
+ "You're absolutely wonderful! 🦎",
117
+ "Keep that beautiful smile going.",
118
+ "The lizards are here to cheer you up!",
119
+ "Sending you so much positive energy.",
120
+ "You are stronger than you think. ",
121
+ "I'm always rooting for you!",
122
+ "Just keep crawling forward! 🦎"
123
+ ];
124
+
125
+ // Creates a detailed SVG Lizard
126
+ function getLizardSVG(color) {
127
+ return `
128
+ <svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
129
+ <!-- Tail -->
130
+ <path d="M50 90 Q45 70 50 50" stroke="${color}" stroke-width="4" fill="none" stroke-linecap="round" />
131
+ <!-- Body -->
132
+ <ellipse cx="50" cy="40" rx="8" ry="15" fill="${color}" />
133
+ <!-- Head -->
134
+ <ellipse cx="50" cy="20" rx="6" ry="8" fill="${color}" />
135
+ <!-- Eyes -->
136
+ <circle cx="47" cy="18" r="1.5" fill="black" />
137
+ <circle cx="53" cy="18" r="1.5" fill="black" />
138
+ <!-- Legs -->
139
+ <path d="M42 35 L30 30 M58 35 L70 30" stroke="${color}" stroke-width="3" stroke-linecap="round" />
140
+ <path d="M42 50 L30 55 M58 50 L70 55" stroke="${color}" stroke-width="3" stroke-linecap="round" />
141
+ </svg>`;
142
+ }
143
+
144
+ function createLizard(x, y) {
145
+ const lizard = document.createElement('div');
146
+ lizard.className = 'lizard';
147
+ const color = lizardColors[Math.floor(Math.random() * lizardColors.length)];
148
+ lizard.innerHTML = getLizardSVG(color);
149
 
150
+ const startX = x !== undefined ? x - 40 : Math.random() * window.innerWidth;
151
+ const startY = y !== undefined ? y - 40 : Math.random() * window.innerHeight;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
 
153
+ lizard.style.left = startX + 'px';
154
+ lizard.style.top = startY + 'px';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
 
156
+ const angle = Math.random() * Math.PI * 2;
157
+ const rotation = (angle * 180 / Math.PI) + 90; // Align SVG to movement
158
+ lizard.style.transform = `rotate(${rotation}deg)`;
159
 
160
+ document.body.appendChild(lizard);
 
 
 
 
 
 
 
161
 
162
+ const velocity = 3 + Math.random() * 4;
163
+ let curX = startX;
164
+ let curY = startY;
165
 
166
+ // Wiggle movement simulation
167
+ let frame = 0;
168
+ const animate = () => {
169
+ frame++;
170
+ const wiggle = Math.sin(frame * 0.2) * 2;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ curX += Math.cos(angle) * velocity;
173
+ curY += Math.sin(angle) * velocity;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
 
175
+ // Add a little organic movement
176
+ lizard.style.left = (curX + Math.cos(angle + Math.PI/2) * wiggle) + 'px';
177
+ lizard.style.top = (curY + Math.sin(angle + Math.PI/2) * wiggle) + 'px';
178
 
179
+ if (curX < -150 || curX > window.innerWidth + 150 ||
180
+ curY < -150 || curY > window.innerHeight + 150) {
181
+ lizard.remove();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  } else {
183
+ requestAnimationFrame(animate);
184
  }
185
+ };
186
+
187
+ requestAnimationFrame(animate);
 
 
 
188
  }
189
 
190
+ function showMessage() {
191
+ const box = document.getElementById('message-box');
192
+ box.innerText = messages[Math.floor(Math.random() * messages.length)];
193
+ box.style.display = 'block';
194
 
195
+ clearTimeout(window.msgTimeout);
196
+ window.msgTimeout = setTimeout(() => {
197
+ box.style.display = 'none';
198
+ }, 3000);
199
+ }
200
+
201
+ document.addEventListener('mousedown', (e) => {
202
+ // Burst of lizards on click
203
+ for (let i = 0; i < 6; i++) {
204
+ setTimeout(() => {
205
+ createLizard(e.clientX, e.clientY);
206
+ }, i * 60);
 
 
 
 
 
 
 
207
  }
208
+ showMessage();
209
+ });
210
 
211
+ // Background wanderers for ambiance
212
+ setInterval(() => {
213
+ if (document.querySelectorAll('.lizard').length < 12) {
214
+ createLizard();
215
+ }
216
+ }, 1500);
217
 
 
 
 
 
 
 
218
  </script>
219
  </body>
220
  </html>