@schoolio/player 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +7 -2
- package/dist/index.d.ts +7 -2
- package/dist/index.js +799 -184
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +733 -143
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
2
19
|
|
|
3
|
-
|
|
4
|
-
var
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
AttemptViewer: () => AttemptViewer,
|
|
24
|
+
QuizApiClient: () => QuizApiClient,
|
|
25
|
+
QuizPlayer: () => QuizPlayer,
|
|
26
|
+
calculateScore: () => calculateScore,
|
|
27
|
+
checkAnswer: () => checkAnswer,
|
|
28
|
+
createAnswerDetail: () => createAnswerDetail,
|
|
29
|
+
formatTime: () => formatTime
|
|
30
|
+
});
|
|
31
|
+
module.exports = __toCommonJS(index_exports);
|
|
5
32
|
|
|
6
33
|
// src/QuizPlayer.tsx
|
|
34
|
+
var import_react = require("react");
|
|
7
35
|
|
|
8
36
|
// src/api.ts
|
|
9
37
|
var QuizApiClient = class {
|
|
@@ -143,14 +171,17 @@ function formatTime(seconds) {
|
|
|
143
171
|
const secs = seconds % 60;
|
|
144
172
|
return `${mins}:${secs.toString().padStart(2, "0")}`;
|
|
145
173
|
}
|
|
174
|
+
|
|
175
|
+
// src/QuizPlayer.tsx
|
|
176
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
146
177
|
var defaultStyles = {
|
|
147
178
|
container: {
|
|
148
179
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
149
|
-
|
|
150
|
-
margin: "0 auto",
|
|
180
|
+
width: "100%",
|
|
151
181
|
padding: "20px",
|
|
152
182
|
backgroundColor: "#ffffff",
|
|
153
|
-
borderRadius: "12px"
|
|
183
|
+
borderRadius: "12px",
|
|
184
|
+
boxSizing: "border-box"
|
|
154
185
|
},
|
|
155
186
|
header: {
|
|
156
187
|
marginBottom: "20px",
|
|
@@ -180,7 +211,8 @@ var defaultStyles = {
|
|
|
180
211
|
transition: "width 0.3s ease"
|
|
181
212
|
},
|
|
182
213
|
question: {
|
|
183
|
-
marginBottom: "24px"
|
|
214
|
+
marginBottom: "24px",
|
|
215
|
+
minHeight: "280px"
|
|
184
216
|
},
|
|
185
217
|
questionText: {
|
|
186
218
|
fontSize: "18px",
|
|
@@ -197,18 +229,31 @@ var defaultStyles = {
|
|
|
197
229
|
border: "2px solid #e5e7eb",
|
|
198
230
|
borderRadius: "8px",
|
|
199
231
|
cursor: "pointer",
|
|
200
|
-
transition: "all 0.2s ease"
|
|
232
|
+
transition: "all 0.2s ease",
|
|
233
|
+
outline: "none",
|
|
234
|
+
backgroundColor: "#ffffff"
|
|
201
235
|
},
|
|
202
236
|
optionSelected: {
|
|
203
237
|
borderColor: "#6721b0",
|
|
204
238
|
backgroundColor: "#f3e8ff"
|
|
205
239
|
},
|
|
240
|
+
optionCorrect: {
|
|
241
|
+
borderColor: "#22c55e",
|
|
242
|
+
backgroundColor: "#f0fdf4"
|
|
243
|
+
},
|
|
244
|
+
optionIncorrect: {
|
|
245
|
+
borderColor: "#ef4444",
|
|
246
|
+
backgroundColor: "#fef2f2"
|
|
247
|
+
},
|
|
206
248
|
input: {
|
|
207
249
|
width: "100%",
|
|
208
250
|
padding: "12px 16px",
|
|
209
251
|
border: "2px solid #e5e7eb",
|
|
210
252
|
borderRadius: "8px",
|
|
211
|
-
fontSize: "16px"
|
|
253
|
+
fontSize: "16px",
|
|
254
|
+
outline: "none",
|
|
255
|
+
boxSizing: "border-box",
|
|
256
|
+
backgroundColor: "#ffffff"
|
|
212
257
|
},
|
|
213
258
|
buttons: {
|
|
214
259
|
display: "flex",
|
|
@@ -237,24 +282,90 @@ var defaultStyles = {
|
|
|
237
282
|
color: "#9ca3af",
|
|
238
283
|
cursor: "not-allowed"
|
|
239
284
|
},
|
|
285
|
+
buttonAddMore: {
|
|
286
|
+
padding: "12px 24px",
|
|
287
|
+
borderRadius: "8px",
|
|
288
|
+
fontSize: "16px",
|
|
289
|
+
fontWeight: "500",
|
|
290
|
+
cursor: "pointer",
|
|
291
|
+
border: "2px solid #6721b0",
|
|
292
|
+
backgroundColor: "transparent",
|
|
293
|
+
color: "#6721b0",
|
|
294
|
+
transition: "all 0.2s ease",
|
|
295
|
+
display: "flex",
|
|
296
|
+
alignItems: "center",
|
|
297
|
+
justifyContent: "center",
|
|
298
|
+
gap: "8px"
|
|
299
|
+
},
|
|
300
|
+
buttonAddMoreDisabled: {
|
|
301
|
+
border: "2px solid #e5e7eb",
|
|
302
|
+
color: "#9ca3af",
|
|
303
|
+
cursor: "not-allowed"
|
|
304
|
+
},
|
|
305
|
+
buttonsColumn: {
|
|
306
|
+
display: "flex",
|
|
307
|
+
flexDirection: "column",
|
|
308
|
+
gap: "12px",
|
|
309
|
+
marginTop: "24px"
|
|
310
|
+
},
|
|
240
311
|
timer: {
|
|
241
312
|
fontSize: "14px",
|
|
242
313
|
color: "#6b7280",
|
|
243
314
|
marginLeft: "16px"
|
|
244
315
|
},
|
|
245
316
|
results: {
|
|
317
|
+
display: "flex",
|
|
318
|
+
flexDirection: "column",
|
|
319
|
+
alignItems: "center",
|
|
320
|
+
justifyContent: "center",
|
|
321
|
+
padding: "48px 24px",
|
|
246
322
|
textAlign: "center",
|
|
247
|
-
|
|
323
|
+
minHeight: "400px",
|
|
324
|
+
position: "relative",
|
|
325
|
+
overflow: "hidden"
|
|
248
326
|
},
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
327
|
+
resultsBackground: {
|
|
328
|
+
position: "absolute",
|
|
329
|
+
inset: "0",
|
|
330
|
+
borderRadius: "16px",
|
|
331
|
+
zIndex: 0
|
|
332
|
+
},
|
|
333
|
+
resultsContent: {
|
|
334
|
+
position: "relative",
|
|
335
|
+
zIndex: 1,
|
|
336
|
+
display: "flex",
|
|
337
|
+
flexDirection: "column",
|
|
338
|
+
alignItems: "center"
|
|
254
339
|
},
|
|
255
|
-
|
|
340
|
+
resultDetails: {
|
|
256
341
|
fontSize: "18px",
|
|
257
|
-
color: "#6b7280"
|
|
342
|
+
color: "#6b7280",
|
|
343
|
+
marginBottom: "4px"
|
|
344
|
+
},
|
|
345
|
+
resultStars: {
|
|
346
|
+
display: "flex",
|
|
347
|
+
justifyContent: "center",
|
|
348
|
+
gap: "8px",
|
|
349
|
+
marginBottom: "20px"
|
|
350
|
+
},
|
|
351
|
+
resultStar: {
|
|
352
|
+
fontSize: "32px",
|
|
353
|
+
animation: "starPop 0.5s ease-out forwards",
|
|
354
|
+
opacity: 0
|
|
355
|
+
},
|
|
356
|
+
confettiContainer: {
|
|
357
|
+
position: "absolute",
|
|
358
|
+
inset: "0",
|
|
359
|
+
pointerEvents: "none",
|
|
360
|
+
overflow: "hidden",
|
|
361
|
+
zIndex: 0
|
|
362
|
+
},
|
|
363
|
+
confettiPiece: {
|
|
364
|
+
position: "absolute",
|
|
365
|
+
width: "10px",
|
|
366
|
+
height: "10px",
|
|
367
|
+
top: "-10px",
|
|
368
|
+
animation: "confettiFall 3s ease-out forwards"
|
|
258
369
|
},
|
|
259
370
|
loading: {
|
|
260
371
|
textAlign: "center",
|
|
@@ -265,10 +376,84 @@ var defaultStyles = {
|
|
|
265
376
|
textAlign: "center",
|
|
266
377
|
padding: "40px",
|
|
267
378
|
color: "#ef4444"
|
|
379
|
+
},
|
|
380
|
+
intro: {
|
|
381
|
+
display: "flex",
|
|
382
|
+
flexDirection: "column",
|
|
383
|
+
alignItems: "center",
|
|
384
|
+
justifyContent: "center",
|
|
385
|
+
padding: "48px 24px",
|
|
386
|
+
textAlign: "center",
|
|
387
|
+
background: "linear-gradient(135deg, #f3e8ff 0%, #e0e7ff 50%, #fce7f3 100%)",
|
|
388
|
+
borderRadius: "16px",
|
|
389
|
+
minHeight: "320px"
|
|
390
|
+
},
|
|
391
|
+
introTitle: {
|
|
392
|
+
fontSize: "28px",
|
|
393
|
+
fontWeight: "700",
|
|
394
|
+
color: "#4c1d95",
|
|
395
|
+
marginBottom: "12px"
|
|
396
|
+
},
|
|
397
|
+
introSubtitle: {
|
|
398
|
+
fontSize: "16px",
|
|
399
|
+
color: "#6b7280",
|
|
400
|
+
marginBottom: "8px"
|
|
401
|
+
},
|
|
402
|
+
introQuestionCount: {
|
|
403
|
+
fontSize: "14px",
|
|
404
|
+
color: "#8b5cf6",
|
|
405
|
+
marginBottom: "32px",
|
|
406
|
+
fontWeight: "500"
|
|
407
|
+
},
|
|
408
|
+
startButton: {
|
|
409
|
+
padding: "16px 48px",
|
|
410
|
+
fontSize: "18px",
|
|
411
|
+
fontWeight: "600",
|
|
412
|
+
backgroundColor: "#7c3aed",
|
|
413
|
+
color: "#ffffff",
|
|
414
|
+
border: "none",
|
|
415
|
+
borderRadius: "12px",
|
|
416
|
+
cursor: "pointer",
|
|
417
|
+
transition: "all 0.2s ease",
|
|
418
|
+
boxShadow: "0 4px 14px rgba(124, 58, 237, 0.4)"
|
|
419
|
+
},
|
|
420
|
+
feedback: {
|
|
421
|
+
marginTop: "16px",
|
|
422
|
+
padding: "16px",
|
|
423
|
+
borderRadius: "8px",
|
|
424
|
+
backgroundColor: "#f9fafb",
|
|
425
|
+
border: "1px solid #e5e7eb"
|
|
426
|
+
},
|
|
427
|
+
feedbackCorrect: {
|
|
428
|
+
backgroundColor: "#f0fdf4",
|
|
429
|
+
borderColor: "#22c55e"
|
|
430
|
+
},
|
|
431
|
+
feedbackIncorrect: {
|
|
432
|
+
backgroundColor: "#fef2f2",
|
|
433
|
+
borderColor: "#ef4444"
|
|
434
|
+
},
|
|
435
|
+
feedbackTitle: {
|
|
436
|
+
fontSize: "16px",
|
|
437
|
+
fontWeight: "600",
|
|
438
|
+
marginBottom: "8px",
|
|
439
|
+
display: "flex",
|
|
440
|
+
alignItems: "center",
|
|
441
|
+
gap: "8px"
|
|
442
|
+
},
|
|
443
|
+
feedbackTitleCorrect: {
|
|
444
|
+
color: "#16a34a"
|
|
445
|
+
},
|
|
446
|
+
feedbackTitleIncorrect: {
|
|
447
|
+
color: "#dc2626"
|
|
448
|
+
},
|
|
449
|
+
feedbackExplanation: {
|
|
450
|
+
fontSize: "14px",
|
|
451
|
+
color: "#4b5563",
|
|
452
|
+
lineHeight: "1.5"
|
|
268
453
|
}
|
|
269
454
|
};
|
|
270
455
|
function Spinner({ size = 16, color = "#ffffff" }) {
|
|
271
|
-
return /* @__PURE__ */
|
|
456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
272
457
|
"span",
|
|
273
458
|
{
|
|
274
459
|
style: {
|
|
@@ -280,7 +465,7 @@ function Spinner({ size = 16, color = "#ffffff" }) {
|
|
|
280
465
|
borderRadius: "50%",
|
|
281
466
|
animation: "spin 0.8s linear infinite"
|
|
282
467
|
},
|
|
283
|
-
children: /* @__PURE__ */
|
|
468
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
284
469
|
}
|
|
285
470
|
);
|
|
286
471
|
}
|
|
@@ -296,27 +481,34 @@ function QuizPlayer({
|
|
|
296
481
|
onComplete,
|
|
297
482
|
onError,
|
|
298
483
|
onProgress,
|
|
484
|
+
onGenerateMoreQuestions,
|
|
299
485
|
className
|
|
300
486
|
}) {
|
|
301
|
-
const [quiz, setQuiz] =
|
|
302
|
-
const [attempt, setAttempt] =
|
|
303
|
-
const [currentQuestionIndex, setCurrentQuestionIndex] =
|
|
304
|
-
const [answers, setAnswers] =
|
|
305
|
-
const [answersDetail, setAnswersDetail] =
|
|
306
|
-
const [isSubmitting, setIsSubmitting] =
|
|
307
|
-
const [isNavigating, setIsNavigating] =
|
|
308
|
-
const [isCompleted, setIsCompleted] =
|
|
309
|
-
const [result, setResult] =
|
|
310
|
-
const [error, setError] =
|
|
311
|
-
const [isLoading, setIsLoading] =
|
|
312
|
-
const [elapsedSeconds, setElapsedSeconds] =
|
|
313
|
-
const
|
|
314
|
-
const
|
|
315
|
-
const
|
|
316
|
-
|
|
487
|
+
const [quiz, setQuiz] = (0, import_react.useState)(null);
|
|
488
|
+
const [attempt, setAttempt] = (0, import_react.useState)(null);
|
|
489
|
+
const [currentQuestionIndex, setCurrentQuestionIndex] = (0, import_react.useState)(0);
|
|
490
|
+
const [answers, setAnswers] = (0, import_react.useState)(/* @__PURE__ */ new Map());
|
|
491
|
+
const [answersDetail, setAnswersDetail] = (0, import_react.useState)([]);
|
|
492
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
|
|
493
|
+
const [isNavigating, setIsNavigating] = (0, import_react.useState)(false);
|
|
494
|
+
const [isCompleted, setIsCompleted] = (0, import_react.useState)(false);
|
|
495
|
+
const [result, setResult] = (0, import_react.useState)(null);
|
|
496
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
497
|
+
const [isLoading, setIsLoading] = (0, import_react.useState)(true);
|
|
498
|
+
const [elapsedSeconds, setElapsedSeconds] = (0, import_react.useState)(0);
|
|
499
|
+
const [showIntro, setShowIntro] = (0, import_react.useState)(true);
|
|
500
|
+
const [timerStarted, setTimerStarted] = (0, import_react.useState)(false);
|
|
501
|
+
const [showFeedback, setShowFeedback] = (0, import_react.useState)(false);
|
|
502
|
+
const [currentAnswerDetail, setCurrentAnswerDetail] = (0, import_react.useState)(null);
|
|
503
|
+
const [extraQuestions, setExtraQuestions] = (0, import_react.useState)([]);
|
|
504
|
+
const [isGeneratingExtra, setIsGeneratingExtra] = (0, import_react.useState)(false);
|
|
505
|
+
const apiClient = (0, import_react.useRef)(null);
|
|
506
|
+
const timerRef = (0, import_react.useRef)(null);
|
|
507
|
+
const startTimeRef = (0, import_react.useRef)(0);
|
|
508
|
+
(0, import_react.useEffect)(() => {
|
|
317
509
|
apiClient.current = new QuizApiClient({ baseUrl: apiBaseUrl, authToken });
|
|
318
510
|
}, [apiBaseUrl, authToken]);
|
|
319
|
-
|
|
511
|
+
(0, import_react.useEffect)(() => {
|
|
320
512
|
async function initialize() {
|
|
321
513
|
if (!apiClient.current) return;
|
|
322
514
|
try {
|
|
@@ -363,8 +555,8 @@ function QuizPlayer({
|
|
|
363
555
|
}
|
|
364
556
|
initialize();
|
|
365
557
|
}, [quizId, lessonId, assignLessonId, courseId, childId, parentId, onError]);
|
|
366
|
-
|
|
367
|
-
if (
|
|
558
|
+
(0, import_react.useEffect)(() => {
|
|
559
|
+
if (timerStarted && !isCompleted && !error) {
|
|
368
560
|
startTimeRef.current = Date.now();
|
|
369
561
|
timerRef.current = setInterval(() => {
|
|
370
562
|
setElapsedSeconds(Math.floor((Date.now() - startTimeRef.current) / 1e3));
|
|
@@ -375,27 +567,39 @@ function QuizPlayer({
|
|
|
375
567
|
clearInterval(timerRef.current);
|
|
376
568
|
}
|
|
377
569
|
};
|
|
378
|
-
}, [
|
|
379
|
-
|
|
570
|
+
}, [timerStarted, isCompleted, error]);
|
|
571
|
+
const handleStart = (0, import_react.useCallback)(() => {
|
|
572
|
+
setShowIntro(false);
|
|
573
|
+
setTimerStarted(true);
|
|
574
|
+
}, []);
|
|
575
|
+
(0, import_react.useEffect)(() => {
|
|
576
|
+
setShowFeedback(false);
|
|
577
|
+
setCurrentAnswerDetail(null);
|
|
578
|
+
}, [currentQuestionIndex]);
|
|
579
|
+
const allQuestions = quiz ? [...quiz.questions, ...extraQuestions] : [];
|
|
580
|
+
const totalQuestions = allQuestions.length;
|
|
581
|
+
const maxQuestions = 50;
|
|
582
|
+
(0, import_react.useEffect)(() => {
|
|
380
583
|
if (quiz && onProgress) {
|
|
381
584
|
onProgress({
|
|
382
585
|
currentQuestion: currentQuestionIndex + 1,
|
|
383
|
-
totalQuestions
|
|
586
|
+
totalQuestions,
|
|
384
587
|
answeredQuestions: answers.size
|
|
385
588
|
});
|
|
386
589
|
}
|
|
387
|
-
}, [currentQuestionIndex, answers.size, quiz, onProgress]);
|
|
388
|
-
const currentQuestion =
|
|
389
|
-
const handleAnswerChange =
|
|
590
|
+
}, [currentQuestionIndex, answers.size, quiz, onProgress, totalQuestions]);
|
|
591
|
+
const currentQuestion = allQuestions[currentQuestionIndex];
|
|
592
|
+
const handleAnswerChange = (0, import_react.useCallback)((value) => {
|
|
390
593
|
if (!currentQuestion) return;
|
|
391
594
|
setAnswers((prev) => new Map(prev).set(currentQuestion.id, value));
|
|
392
595
|
}, [currentQuestion]);
|
|
393
|
-
const
|
|
596
|
+
const handleCheckAnswer = (0, import_react.useCallback)(async () => {
|
|
394
597
|
if (!quiz || !attempt || !currentQuestion || !apiClient.current) return;
|
|
395
598
|
const selectedAnswer2 = answers.get(currentQuestion.id);
|
|
396
599
|
if (selectedAnswer2 === void 0) return;
|
|
397
600
|
setIsNavigating(true);
|
|
398
601
|
const answerDetail = createAnswerDetail(currentQuestion, selectedAnswer2);
|
|
602
|
+
setCurrentAnswerDetail(answerDetail);
|
|
399
603
|
const newAnswersDetail = [...answersDetail];
|
|
400
604
|
const existingIdx = newAnswersDetail.findIndex((a) => a.questionId === currentQuestion.id);
|
|
401
605
|
if (existingIdx >= 0) {
|
|
@@ -413,16 +617,40 @@ function QuizPlayer({
|
|
|
413
617
|
} finally {
|
|
414
618
|
setIsNavigating(false);
|
|
415
619
|
}
|
|
416
|
-
|
|
620
|
+
setShowFeedback(true);
|
|
621
|
+
}, [quiz, attempt, currentQuestion, answers, answersDetail]);
|
|
622
|
+
const handleContinue = (0, import_react.useCallback)(() => {
|
|
623
|
+
if (!quiz) return;
|
|
624
|
+
setShowFeedback(false);
|
|
625
|
+
setCurrentAnswerDetail(null);
|
|
626
|
+
if (currentQuestionIndex < totalQuestions - 1) {
|
|
417
627
|
setCurrentQuestionIndex((prev) => prev + 1);
|
|
418
628
|
}
|
|
419
|
-
}, [quiz,
|
|
420
|
-
const
|
|
421
|
-
if (
|
|
422
|
-
|
|
629
|
+
}, [quiz, currentQuestionIndex, totalQuestions]);
|
|
630
|
+
const handleAddMoreQuestions = (0, import_react.useCallback)(async () => {
|
|
631
|
+
if (!attempt || !onGenerateMoreQuestions || isGeneratingExtra) return;
|
|
632
|
+
if (totalQuestions >= maxQuestions) return;
|
|
633
|
+
setIsGeneratingExtra(true);
|
|
634
|
+
try {
|
|
635
|
+
const result2 = await onGenerateMoreQuestions(attempt.id, totalQuestions);
|
|
636
|
+
if (result2.extraQuestions && result2.extraQuestions.length > 0) {
|
|
637
|
+
const slotsAvailable = maxQuestions - totalQuestions;
|
|
638
|
+
const questionsToAppend = result2.extraQuestions.slice(0, slotsAvailable);
|
|
639
|
+
if (questionsToAppend.length > 0) {
|
|
640
|
+
setExtraQuestions((prev) => [...prev, ...questionsToAppend]);
|
|
641
|
+
setCurrentQuestionIndex(totalQuestions);
|
|
642
|
+
setShowFeedback(false);
|
|
643
|
+
setCurrentAnswerDetail(null);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
} catch (err) {
|
|
647
|
+
console.error("Failed to generate extra questions:", err);
|
|
648
|
+
onError?.(err instanceof Error ? err : new Error("Failed to generate extra questions"));
|
|
649
|
+
} finally {
|
|
650
|
+
setIsGeneratingExtra(false);
|
|
423
651
|
}
|
|
424
|
-
}, [
|
|
425
|
-
const handleSubmit =
|
|
652
|
+
}, [attempt, onGenerateMoreQuestions, isGeneratingExtra, totalQuestions, maxQuestions, onError]);
|
|
653
|
+
const handleSubmit = (0, import_react.useCallback)(async () => {
|
|
426
654
|
if (!quiz || !attempt || !apiClient.current) return;
|
|
427
655
|
setIsSubmitting(true);
|
|
428
656
|
try {
|
|
@@ -438,7 +666,7 @@ function QuizPlayer({
|
|
|
438
666
|
}
|
|
439
667
|
}
|
|
440
668
|
const scoreData = calculateScore(finalAnswersDetail);
|
|
441
|
-
const timeSpent = Math.floor((Date.now() - startTimeRef.current) / 1e3);
|
|
669
|
+
const timeSpent = timerStarted && startTimeRef.current > 0 ? Math.floor((Date.now() - startTimeRef.current) / 1e3) : elapsedSeconds;
|
|
442
670
|
const updatedAttempt = await apiClient.current.updateAttempt(attempt.id, {
|
|
443
671
|
answers: finalAnswersDetail,
|
|
444
672
|
status: "completed",
|
|
@@ -451,7 +679,7 @@ function QuizPlayer({
|
|
|
451
679
|
attemptId: updatedAttempt.id,
|
|
452
680
|
score: scoreData.score,
|
|
453
681
|
correctAnswers: scoreData.correctAnswers,
|
|
454
|
-
totalQuestions
|
|
682
|
+
totalQuestions,
|
|
455
683
|
answers: finalAnswersDetail,
|
|
456
684
|
timeSpentSeconds: timeSpent
|
|
457
685
|
};
|
|
@@ -467,78 +695,414 @@ function QuizPlayer({
|
|
|
467
695
|
} finally {
|
|
468
696
|
setIsSubmitting(false);
|
|
469
697
|
}
|
|
470
|
-
}, [quiz, attempt, currentQuestion, answers, answersDetail, onComplete, onError]);
|
|
698
|
+
}, [quiz, attempt, currentQuestion, answers, answersDetail, onComplete, onError, totalQuestions, timerStarted, elapsedSeconds]);
|
|
471
699
|
if (isLoading) {
|
|
472
|
-
return /* @__PURE__ */
|
|
700
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.loading, children: "Loading quiz..." }) });
|
|
473
701
|
}
|
|
474
702
|
if (error) {
|
|
475
|
-
return /* @__PURE__ */
|
|
703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.error, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { children: [
|
|
476
704
|
"Error: ",
|
|
477
705
|
error
|
|
478
706
|
] }) }) });
|
|
479
707
|
}
|
|
480
708
|
if (isCompleted && result) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
709
|
+
const percentage = Math.round(result.correctAnswers / result.totalQuestions * 100);
|
|
710
|
+
const getScoreTheme = (pct) => {
|
|
711
|
+
if (pct >= 80) {
|
|
712
|
+
return {
|
|
713
|
+
color: "#22c55e",
|
|
714
|
+
bgGradient: "linear-gradient(135deg, #dcfce7 0%, #bbf7d0 50%, #86efac 100%)",
|
|
715
|
+
badge: "Quiz Champion!",
|
|
716
|
+
badgeColor: "#fbbf24",
|
|
717
|
+
badgeBg: "linear-gradient(135deg, #fef3c7 0%, #fde68a 100%)",
|
|
718
|
+
mascotMood: "celebrating",
|
|
719
|
+
stars: 3
|
|
720
|
+
};
|
|
721
|
+
} else if (pct >= 60) {
|
|
722
|
+
return {
|
|
723
|
+
color: "#f59e0b",
|
|
724
|
+
bgGradient: "linear-gradient(135deg, #fef3c7 0%, #fde68a 50%, #fcd34d 100%)",
|
|
725
|
+
badge: "Rising Star!",
|
|
726
|
+
badgeColor: "#f59e0b",
|
|
727
|
+
badgeBg: "linear-gradient(135deg, #fed7aa 0%, #fdba74 100%)",
|
|
728
|
+
mascotMood: "happy",
|
|
729
|
+
stars: 2
|
|
730
|
+
};
|
|
731
|
+
} else if (pct >= 40) {
|
|
732
|
+
return {
|
|
733
|
+
color: "#3b82f6",
|
|
734
|
+
bgGradient: "linear-gradient(135deg, #dbeafe 0%, #bfdbfe 50%, #93c5fd 100%)",
|
|
735
|
+
badge: "Great Learner!",
|
|
736
|
+
badgeColor: "#3b82f6",
|
|
737
|
+
badgeBg: "linear-gradient(135deg, #bfdbfe 0%, #93c5fd 100%)",
|
|
738
|
+
mascotMood: "encouraging",
|
|
739
|
+
stars: 1
|
|
740
|
+
};
|
|
741
|
+
} else {
|
|
742
|
+
return {
|
|
743
|
+
color: "#8b5cf6",
|
|
744
|
+
bgGradient: "linear-gradient(135deg, #f3e8ff 0%, #e9d5ff 50%, #d8b4fe 100%)",
|
|
745
|
+
badge: "Keep Growing!",
|
|
746
|
+
badgeColor: "#8b5cf6",
|
|
747
|
+
badgeBg: "linear-gradient(135deg, #e9d5ff 0%, #d8b4fe 100%)",
|
|
748
|
+
mascotMood: "supportive",
|
|
749
|
+
stars: 0
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
};
|
|
753
|
+
const theme = getScoreTheme(percentage);
|
|
754
|
+
const confettiColors = ["#f43f5e", "#ec4899", "#8b5cf6", "#3b82f6", "#22c55e", "#f59e0b", "#ef4444"];
|
|
755
|
+
const confettiPieces = Array.from({ length: 50 }, (_, i) => ({
|
|
756
|
+
id: i,
|
|
757
|
+
left: `${Math.random() * 100}%`,
|
|
758
|
+
delay: `${Math.random() * 2}s`,
|
|
759
|
+
duration: `${2 + Math.random() * 2}s`,
|
|
760
|
+
color: confettiColors[Math.floor(Math.random() * confettiColors.length)],
|
|
761
|
+
rotation: Math.random() * 360,
|
|
762
|
+
size: 6 + Math.random() * 8
|
|
763
|
+
}));
|
|
764
|
+
const StarIcon = ({ filled, delay }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
765
|
+
"svg",
|
|
766
|
+
{
|
|
767
|
+
width: "36",
|
|
768
|
+
height: "36",
|
|
769
|
+
viewBox: "0 0 24 24",
|
|
770
|
+
style: {
|
|
771
|
+
animation: "starPop 0.5s ease-out forwards",
|
|
772
|
+
animationDelay: `${delay}s`,
|
|
773
|
+
opacity: 0
|
|
774
|
+
},
|
|
775
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
776
|
+
"path",
|
|
777
|
+
{
|
|
778
|
+
d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z",
|
|
779
|
+
fill: filled ? "#fbbf24" : "#e5e7eb",
|
|
780
|
+
stroke: filled ? "#f59e0b" : "#d1d5db",
|
|
781
|
+
strokeWidth: "1"
|
|
782
|
+
}
|
|
783
|
+
)
|
|
784
|
+
}
|
|
785
|
+
);
|
|
786
|
+
const MascotOwl = ({ mood }) => {
|
|
787
|
+
const getEyeExpression = () => {
|
|
788
|
+
switch (mood) {
|
|
789
|
+
case "celebrating":
|
|
790
|
+
return { leftEye: ">", rightEye: "<", pupilY: 42 };
|
|
791
|
+
// Squinting happy
|
|
792
|
+
case "happy":
|
|
793
|
+
return { leftEye: null, rightEye: null, pupilY: 42 };
|
|
794
|
+
// Normal happy
|
|
795
|
+
case "encouraging":
|
|
796
|
+
return { leftEye: null, rightEye: null, pupilY: 44 };
|
|
797
|
+
// Looking down warmly
|
|
798
|
+
default:
|
|
799
|
+
return { leftEye: null, rightEye: null, pupilY: 42 };
|
|
800
|
+
}
|
|
801
|
+
};
|
|
802
|
+
const eyeExpr = getEyeExpression();
|
|
803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
804
|
+
"svg",
|
|
805
|
+
{
|
|
806
|
+
width: "120",
|
|
807
|
+
height: "120",
|
|
808
|
+
viewBox: "0 0 100 100",
|
|
809
|
+
style: {
|
|
810
|
+
animation: mood === "celebrating" ? "bounce 0.6s ease-in-out infinite" : "gentleBob 2s ease-in-out infinite"
|
|
811
|
+
},
|
|
812
|
+
children: [
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "50", cy: "60", rx: "35", ry: "30", fill: "#8b5cf6" }),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "50", cy: "65", rx: "25", ry: "20", fill: "#c4b5fd" }),
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "50", cy: "35", r: "28", fill: "#a78bfa" }),
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "28,15 35,30 22,28", fill: "#7c3aed" }),
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "72,15 65,30 78,28", fill: "#7c3aed" }),
|
|
818
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "38", cy: "38", rx: "10", ry: "12", fill: "white" }),
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "62", cy: "38", rx: "10", ry: "12", fill: "white" }),
|
|
820
|
+
eyeExpr.leftEye ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("text", { x: "38", y: "44", textAnchor: "middle", fontSize: "16", fill: "#1f2937", children: eyeExpr.leftEye }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "38", cy: eyeExpr.pupilY, r: "5", fill: "#1f2937" }),
|
|
821
|
+
eyeExpr.rightEye ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("text", { x: "62", y: "44", textAnchor: "middle", fontSize: "16", fill: "#1f2937", children: eyeExpr.rightEye }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "62", cy: eyeExpr.pupilY, r: "5", fill: "#1f2937" }),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "50,45 45,52 55,52", fill: "#fbbf24" }),
|
|
823
|
+
(mood === "celebrating" || mood === "happy") && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
824
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "28", cy: "45", rx: "5", ry: "3", fill: "#fda4af", opacity: "0.6" }),
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "72", cy: "45", rx: "5", ry: "3", fill: "#fda4af", opacity: "0.6" })
|
|
826
|
+
] }),
|
|
827
|
+
mood === "celebrating" ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
828
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "18", cy: "55", rx: "8", ry: "15", fill: "#7c3aed", transform: "rotate(-30 18 55)" }),
|
|
829
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "82", cy: "55", rx: "8", ry: "15", fill: "#7c3aed", transform: "rotate(30 82 55)" })
|
|
830
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
831
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "20", cy: "60", rx: "8", ry: "15", fill: "#7c3aed" }),
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "80", cy: "60", rx: "8", ry: "15", fill: "#7c3aed" })
|
|
833
|
+
] }),
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "40", cy: "88", rx: "8", ry: "4", fill: "#fbbf24" }),
|
|
835
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ellipse", { cx: "60", cy: "88", rx: "8", ry: "4", fill: "#fbbf24" })
|
|
836
|
+
]
|
|
837
|
+
}
|
|
838
|
+
);
|
|
839
|
+
};
|
|
840
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: defaultStyles.container, children: [
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
|
|
842
|
+
@keyframes confettiFall {
|
|
843
|
+
0% {
|
|
844
|
+
transform: translateY(-10px) rotate(0deg);
|
|
845
|
+
opacity: 1;
|
|
846
|
+
}
|
|
847
|
+
100% {
|
|
848
|
+
transform: translateY(500px) rotate(720deg);
|
|
849
|
+
opacity: 0;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
@keyframes starPop {
|
|
853
|
+
0% {
|
|
854
|
+
transform: scale(0);
|
|
855
|
+
opacity: 0;
|
|
856
|
+
}
|
|
857
|
+
50% {
|
|
858
|
+
transform: scale(1.3);
|
|
859
|
+
}
|
|
860
|
+
100% {
|
|
861
|
+
transform: scale(1);
|
|
862
|
+
opacity: 1;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
@keyframes bounce {
|
|
866
|
+
0%, 100% {
|
|
867
|
+
transform: translateY(0);
|
|
868
|
+
}
|
|
869
|
+
50% {
|
|
870
|
+
transform: translateY(-10px);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
@keyframes gentleBob {
|
|
874
|
+
0%, 100% {
|
|
875
|
+
transform: translateY(0);
|
|
876
|
+
}
|
|
877
|
+
50% {
|
|
878
|
+
transform: translateY(-5px);
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
@keyframes badgePop {
|
|
882
|
+
0% {
|
|
883
|
+
transform: scale(0) rotate(-10deg);
|
|
884
|
+
opacity: 0;
|
|
885
|
+
}
|
|
886
|
+
60% {
|
|
887
|
+
transform: scale(1.1) rotate(5deg);
|
|
888
|
+
}
|
|
889
|
+
100% {
|
|
890
|
+
transform: scale(1) rotate(0deg);
|
|
891
|
+
opacity: 1;
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
@keyframes scoreSlideIn {
|
|
895
|
+
0% {
|
|
896
|
+
transform: translateY(20px);
|
|
897
|
+
opacity: 0;
|
|
898
|
+
}
|
|
899
|
+
100% {
|
|
900
|
+
transform: translateY(0);
|
|
901
|
+
opacity: 1;
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
` }),
|
|
905
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.results, children: [
|
|
906
|
+
percentage >= 60 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.confettiContainer, children: confettiPieces.map((piece) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
907
|
+
"div",
|
|
908
|
+
{
|
|
909
|
+
style: {
|
|
910
|
+
...defaultStyles.confettiPiece,
|
|
911
|
+
left: piece.left,
|
|
912
|
+
width: `${piece.size}px`,
|
|
913
|
+
height: `${piece.size}px`,
|
|
914
|
+
backgroundColor: piece.color,
|
|
915
|
+
borderRadius: Math.random() > 0.5 ? "50%" : "2px",
|
|
916
|
+
animationDelay: piece.delay,
|
|
917
|
+
animationDuration: piece.duration,
|
|
918
|
+
transform: `rotate(${piece.rotation}deg)`
|
|
919
|
+
}
|
|
920
|
+
},
|
|
921
|
+
piece.id
|
|
922
|
+
)) }),
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...defaultStyles.resultsBackground, background: theme.bgGradient } }),
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.resultsContent, children: [
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.resultStars, children: [
|
|
926
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StarIcon, { filled: theme.stars >= 1, delay: 0.3 }),
|
|
927
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StarIcon, { filled: theme.stars >= 2, delay: 0.5 }),
|
|
928
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(StarIcon, { filled: theme.stars >= 3, delay: 0.7 })
|
|
929
|
+
] }),
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MascotOwl, { mood: theme.mascotMood }) }),
|
|
931
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
932
|
+
"div",
|
|
933
|
+
{
|
|
934
|
+
style: {
|
|
935
|
+
background: theme.badgeBg,
|
|
936
|
+
padding: "12px 28px",
|
|
937
|
+
borderRadius: "50px",
|
|
938
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
939
|
+
marginBottom: "20px",
|
|
940
|
+
animation: "badgePop 0.6s ease-out 0.2s forwards",
|
|
941
|
+
opacity: 0,
|
|
942
|
+
border: `3px solid ${theme.badgeColor}`
|
|
943
|
+
},
|
|
944
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
945
|
+
"span",
|
|
946
|
+
{
|
|
947
|
+
style: {
|
|
948
|
+
fontSize: "22px",
|
|
949
|
+
fontWeight: "700",
|
|
950
|
+
color: "#1f2937",
|
|
951
|
+
textShadow: "0 1px 2px rgba(255,255,255,0.5)"
|
|
952
|
+
},
|
|
953
|
+
children: theme.badge
|
|
954
|
+
}
|
|
955
|
+
)
|
|
956
|
+
}
|
|
957
|
+
),
|
|
958
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
959
|
+
"div",
|
|
960
|
+
{
|
|
961
|
+
style: {
|
|
962
|
+
animation: "scoreSlideIn 0.5s ease-out 0.4s forwards",
|
|
963
|
+
opacity: 0
|
|
964
|
+
},
|
|
965
|
+
children: [
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
967
|
+
"div",
|
|
968
|
+
{
|
|
969
|
+
style: {
|
|
970
|
+
fontSize: "48px",
|
|
971
|
+
fontWeight: "800",
|
|
972
|
+
color: theme.color,
|
|
973
|
+
lineHeight: "1",
|
|
974
|
+
marginBottom: "4px"
|
|
975
|
+
},
|
|
976
|
+
children: [
|
|
977
|
+
result.correctAnswers,
|
|
978
|
+
" of ",
|
|
979
|
+
result.totalQuestions
|
|
980
|
+
]
|
|
981
|
+
}
|
|
982
|
+
),
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
984
|
+
"div",
|
|
985
|
+
{
|
|
986
|
+
style: {
|
|
987
|
+
fontSize: "20px",
|
|
988
|
+
fontWeight: "600",
|
|
989
|
+
color: "#6b7280",
|
|
990
|
+
marginBottom: "12px"
|
|
991
|
+
},
|
|
992
|
+
children: "correct answers"
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
]
|
|
996
|
+
}
|
|
997
|
+
),
|
|
998
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { ...defaultStyles.resultDetails, marginTop: "8px" }, children: [
|
|
999
|
+
"Time: ",
|
|
1000
|
+
formatTime(result.timeSpentSeconds)
|
|
1001
|
+
] })
|
|
1002
|
+
] })
|
|
495
1003
|
] })
|
|
1004
|
+
] });
|
|
1005
|
+
}
|
|
1006
|
+
if (quiz && showIntro) {
|
|
1007
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.intro, children: [
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.introTitle, children: quiz.title }),
|
|
1009
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.introSubtitle, children: "Ready to test your knowledge?" }),
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.introQuestionCount, children: [
|
|
1011
|
+
quiz.questions.length,
|
|
1012
|
+
" question",
|
|
1013
|
+
quiz.questions.length !== 1 ? "s" : "",
|
|
1014
|
+
" to answer"
|
|
1015
|
+
] }),
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1017
|
+
"button",
|
|
1018
|
+
{
|
|
1019
|
+
style: defaultStyles.startButton,
|
|
1020
|
+
onClick: handleStart,
|
|
1021
|
+
onMouseOver: (e) => {
|
|
1022
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
1023
|
+
e.currentTarget.style.boxShadow = "0 6px 20px rgba(124, 58, 237, 0.5)";
|
|
1024
|
+
},
|
|
1025
|
+
onMouseOut: (e) => {
|
|
1026
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
1027
|
+
e.currentTarget.style.boxShadow = "0 4px 14px rgba(124, 58, 237, 0.4)";
|
|
1028
|
+
},
|
|
1029
|
+
"data-testid": "button-start-quiz",
|
|
1030
|
+
children: "Let's Start!"
|
|
1031
|
+
}
|
|
1032
|
+
)
|
|
496
1033
|
] }) });
|
|
497
1034
|
}
|
|
498
1035
|
if (!quiz || !currentQuestion) {
|
|
499
|
-
return /* @__PURE__ */
|
|
1036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.error, children: "No quiz data available" }) });
|
|
500
1037
|
}
|
|
501
1038
|
const selectedAnswer = answers.get(currentQuestion.id);
|
|
502
|
-
const isLastQuestion = currentQuestionIndex ===
|
|
503
|
-
const progressPercent = (currentQuestionIndex + 1) /
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
/* @__PURE__ */
|
|
1039
|
+
const isLastQuestion = currentQuestionIndex === totalQuestions - 1;
|
|
1040
|
+
const progressPercent = (currentQuestionIndex + 1) / totalQuestions * 100;
|
|
1041
|
+
const remainingSlots = maxQuestions - totalQuestions;
|
|
1042
|
+
const questionsToAdd = Math.min(5, remainingSlots);
|
|
1043
|
+
const canAddMore = onGenerateMoreQuestions && remainingSlots > 0;
|
|
1044
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className, style: defaultStyles.container, children: [
|
|
1045
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.header, children: [
|
|
1046
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.title, children: quiz.title }),
|
|
1047
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.progress, children: [
|
|
511
1048
|
"Question ",
|
|
512
1049
|
currentQuestionIndex + 1,
|
|
513
1050
|
" of ",
|
|
514
|
-
|
|
1051
|
+
totalQuestions
|
|
515
1052
|
] }),
|
|
516
|
-
/* @__PURE__ */
|
|
1053
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.progressBar, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...defaultStyles.progressFill, width: `${progressPercent}%` } }) })
|
|
517
1054
|
] }),
|
|
518
|
-
/* @__PURE__ */
|
|
519
|
-
/* @__PURE__ */
|
|
520
|
-
(currentQuestion.type === "single" || currentQuestion.type === "true-false") && /* @__PURE__ */
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.question, children: [
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.questionText, children: currentQuestion.question }),
|
|
1057
|
+
(currentQuestion.type === "single" || currentQuestion.type === "true-false") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
1058
|
+
const isSelected = selectedAnswer === option;
|
|
1059
|
+
const isCorrectOption = currentQuestion.correctAnswer === option;
|
|
1060
|
+
let optionStyle = { ...defaultStyles.option };
|
|
1061
|
+
if (showFeedback) {
|
|
1062
|
+
if (isCorrectOption) {
|
|
1063
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
1064
|
+
} else if (isSelected && !isCorrectOption) {
|
|
1065
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
1066
|
+
}
|
|
1067
|
+
} else if (isSelected) {
|
|
1068
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
1069
|
+
}
|
|
1070
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1071
|
+
"div",
|
|
1072
|
+
{
|
|
1073
|
+
style: {
|
|
1074
|
+
...optionStyle,
|
|
1075
|
+
cursor: showFeedback ? "default" : "pointer"
|
|
1076
|
+
},
|
|
1077
|
+
onClick: () => !showFeedback && handleAnswerChange(option),
|
|
1078
|
+
children: option
|
|
526
1079
|
},
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
)) }),
|
|
532
|
-
currentQuestion.type === "multiple" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
1080
|
+
idx
|
|
1081
|
+
);
|
|
1082
|
+
}) }),
|
|
1083
|
+
currentQuestion.type === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
533
1084
|
const selected = Array.isArray(selectedAnswer) && selectedAnswer.includes(option);
|
|
534
|
-
|
|
1085
|
+
const correctAnswers = Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer : currentQuestion.correctAnswer ? [currentQuestion.correctAnswer] : [];
|
|
1086
|
+
const isCorrectOption = correctAnswers.includes(option);
|
|
1087
|
+
let optionStyle = { ...defaultStyles.option };
|
|
1088
|
+
if (showFeedback) {
|
|
1089
|
+
if (isCorrectOption) {
|
|
1090
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
1091
|
+
} else if (selected && !isCorrectOption) {
|
|
1092
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
1093
|
+
}
|
|
1094
|
+
} else if (selected) {
|
|
1095
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
1096
|
+
}
|
|
1097
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
535
1098
|
"div",
|
|
536
1099
|
{
|
|
537
1100
|
style: {
|
|
538
|
-
...
|
|
539
|
-
|
|
1101
|
+
...optionStyle,
|
|
1102
|
+
cursor: showFeedback ? "default" : "pointer"
|
|
540
1103
|
},
|
|
541
1104
|
onClick: () => {
|
|
1105
|
+
if (showFeedback) return;
|
|
542
1106
|
const current = Array.isArray(selectedAnswer) ? selectedAnswer : [];
|
|
543
1107
|
if (selected) {
|
|
544
1108
|
handleAnswerChange(current.filter((o) => o !== option));
|
|
@@ -551,16 +1115,17 @@ function QuizPlayer({
|
|
|
551
1115
|
idx
|
|
552
1116
|
);
|
|
553
1117
|
}) }),
|
|
554
|
-
(currentQuestion.type === "free" || currentQuestion.type === "essay") && /* @__PURE__ */
|
|
1118
|
+
(currentQuestion.type === "free" || currentQuestion.type === "essay") && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
555
1119
|
"textarea",
|
|
556
1120
|
{
|
|
557
1121
|
style: { ...defaultStyles.input, minHeight: currentQuestion.type === "essay" ? "150px" : "60px" },
|
|
558
1122
|
value: selectedAnswer || "",
|
|
559
1123
|
onChange: (e) => handleAnswerChange(e.target.value),
|
|
560
|
-
placeholder: "Type your answer here..."
|
|
1124
|
+
placeholder: "Type your answer here...",
|
|
1125
|
+
disabled: showFeedback
|
|
561
1126
|
}
|
|
562
1127
|
),
|
|
563
|
-
currentQuestion.type === "fill" && /* @__PURE__ */
|
|
1128
|
+
currentQuestion.type === "fill" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.options, children: currentQuestion.blanks?.map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
564
1129
|
"input",
|
|
565
1130
|
{
|
|
566
1131
|
style: defaultStyles.input,
|
|
@@ -570,50 +1135,93 @@ function QuizPlayer({
|
|
|
570
1135
|
current[idx] = e.target.value;
|
|
571
1136
|
handleAnswerChange(current);
|
|
572
1137
|
},
|
|
573
|
-
placeholder: `Blank ${idx + 1}
|
|
1138
|
+
placeholder: `Blank ${idx + 1}`,
|
|
1139
|
+
disabled: showFeedback
|
|
574
1140
|
},
|
|
575
1141
|
idx
|
|
576
|
-
)) })
|
|
1142
|
+
)) }),
|
|
1143
|
+
showFeedback && currentAnswerDetail && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
1144
|
+
...defaultStyles.feedback,
|
|
1145
|
+
...currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
|
|
1146
|
+
}, children: [
|
|
1147
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
1148
|
+
...defaultStyles.feedbackTitle,
|
|
1149
|
+
...currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
|
|
1150
|
+
}, children: currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
|
|
1151
|
+
currentQuestion.explanation && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
|
|
1152
|
+
] })
|
|
577
1153
|
] }),
|
|
578
|
-
/* @__PURE__ */
|
|
579
|
-
/* @__PURE__ */
|
|
1154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: defaultStyles.buttonsColumn, children: [
|
|
1155
|
+
showFeedback && isLastQuestion && canAddMore && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
580
1156
|
"button",
|
|
581
1157
|
{
|
|
582
1158
|
style: {
|
|
583
|
-
...defaultStyles.
|
|
584
|
-
...
|
|
1159
|
+
...defaultStyles.buttonAddMore,
|
|
1160
|
+
...isGeneratingExtra ? defaultStyles.buttonAddMoreDisabled : {}
|
|
585
1161
|
},
|
|
586
|
-
onClick:
|
|
587
|
-
disabled:
|
|
588
|
-
|
|
1162
|
+
onClick: handleAddMoreQuestions,
|
|
1163
|
+
disabled: isGeneratingExtra,
|
|
1164
|
+
"data-testid": "button-add-more-questions",
|
|
1165
|
+
children: isGeneratingExtra ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: 16, color: "#9ca3af" }),
|
|
1167
|
+
"Generating Questions..."
|
|
1168
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
1169
|
+
"+ Add ",
|
|
1170
|
+
questionsToAdd,
|
|
1171
|
+
" More Question",
|
|
1172
|
+
questionsToAdd !== 1 ? "s" : ""
|
|
1173
|
+
] })
|
|
589
1174
|
}
|
|
590
1175
|
),
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { ...defaultStyles.buttons, justifyContent: "flex-end" }, children: showFeedback ? (
|
|
1177
|
+
// After viewing feedback
|
|
1178
|
+
isLastQuestion ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1179
|
+
"button",
|
|
1180
|
+
{
|
|
1181
|
+
style: {
|
|
1182
|
+
...defaultStyles.button,
|
|
1183
|
+
...isSubmitting || isGeneratingExtra ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
1184
|
+
},
|
|
1185
|
+
onClick: handleSubmit,
|
|
1186
|
+
disabled: isSubmitting || isGeneratingExtra,
|
|
1187
|
+
"data-testid": "button-submit-quiz",
|
|
1188
|
+
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Submit Quiz"
|
|
1189
|
+
}
|
|
1190
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1191
|
+
"button",
|
|
1192
|
+
{
|
|
1193
|
+
style: {
|
|
1194
|
+
...defaultStyles.button,
|
|
1195
|
+
...defaultStyles.buttonPrimary
|
|
1196
|
+
},
|
|
1197
|
+
onClick: handleContinue,
|
|
1198
|
+
"data-testid": "button-continue",
|
|
1199
|
+
children: "Continue"
|
|
1200
|
+
}
|
|
1201
|
+
)
|
|
1202
|
+
) : (
|
|
1203
|
+
// Before checking answer
|
|
1204
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1205
|
+
"button",
|
|
1206
|
+
{
|
|
1207
|
+
style: {
|
|
1208
|
+
...defaultStyles.button,
|
|
1209
|
+
...isNavigating || selectedAnswer === void 0 ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
1210
|
+
},
|
|
1211
|
+
onClick: handleCheckAnswer,
|
|
1212
|
+
disabled: isNavigating || selectedAnswer === void 0,
|
|
1213
|
+
"data-testid": "button-check-answer",
|
|
1214
|
+
children: isNavigating ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Check Answer"
|
|
1215
|
+
}
|
|
1216
|
+
)
|
|
1217
|
+
) })
|
|
614
1218
|
] })
|
|
615
1219
|
] });
|
|
616
1220
|
}
|
|
1221
|
+
|
|
1222
|
+
// src/AttemptViewer.tsx
|
|
1223
|
+
var import_react2 = require("react");
|
|
1224
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
617
1225
|
var defaultStyles2 = {
|
|
618
1226
|
container: {
|
|
619
1227
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -628,6 +1236,12 @@ var defaultStyles2 = {
|
|
|
628
1236
|
borderBottom: "1px solid #e5e7eb",
|
|
629
1237
|
paddingBottom: "20px"
|
|
630
1238
|
},
|
|
1239
|
+
title: {
|
|
1240
|
+
fontSize: "24px",
|
|
1241
|
+
fontWeight: "600",
|
|
1242
|
+
marginBottom: "16px",
|
|
1243
|
+
color: "#111827"
|
|
1244
|
+
},
|
|
631
1245
|
summaryGrid: {
|
|
632
1246
|
display: "grid",
|
|
633
1247
|
gridTemplateColumns: "repeat(auto-fit, minmax(120px, 1fr))",
|
|
@@ -787,11 +1401,11 @@ function AttemptViewer({
|
|
|
787
1401
|
showExplanations = true,
|
|
788
1402
|
title
|
|
789
1403
|
}) {
|
|
790
|
-
const [attempt, setAttempt] =
|
|
791
|
-
const [loading, setLoading] =
|
|
792
|
-
const [error, setError] =
|
|
793
|
-
|
|
794
|
-
new QuizApiClient({
|
|
1404
|
+
const [attempt, setAttempt] = (0, import_react2.useState)(null);
|
|
1405
|
+
const [loading, setLoading] = (0, import_react2.useState)(true);
|
|
1406
|
+
const [error, setError] = (0, import_react2.useState)(null);
|
|
1407
|
+
(0, import_react2.useEffect)(() => {
|
|
1408
|
+
const apiClient = new QuizApiClient({
|
|
795
1409
|
baseUrl: apiBaseUrl,
|
|
796
1410
|
authToken
|
|
797
1411
|
});
|
|
@@ -823,49 +1437,49 @@ function AttemptViewer({
|
|
|
823
1437
|
window.location.reload();
|
|
824
1438
|
};
|
|
825
1439
|
if (loading) {
|
|
826
|
-
return /* @__PURE__ */
|
|
827
|
-
/* @__PURE__ */
|
|
828
|
-
/* @__PURE__ */
|
|
829
|
-
/* @__PURE__ */
|
|
830
|
-
/* @__PURE__ */
|
|
1440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.container, className, children: [
|
|
1441
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: spinnerKeyframes }),
|
|
1442
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.loading, children: [
|
|
1443
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.spinner }),
|
|
1444
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { marginTop: "16px", color: "#6b7280" }, children: "Loading attempt..." })
|
|
831
1445
|
] })
|
|
832
1446
|
] });
|
|
833
1447
|
}
|
|
834
1448
|
if (error || !attempt) {
|
|
835
|
-
return /* @__PURE__ */
|
|
836
|
-
/* @__PURE__ */
|
|
837
|
-
/* @__PURE__ */
|
|
838
|
-
/* @__PURE__ */
|
|
1449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.container, className, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.error, children: [
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: "18px", fontWeight: "500" }, children: "Failed to load attempt" }),
|
|
1451
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { marginTop: "8px", color: "#6b7280" }, children: error }),
|
|
1452
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { style: defaultStyles2.retryButton, onClick: handleRetry, children: "Try Again" })
|
|
839
1453
|
] }) });
|
|
840
1454
|
}
|
|
841
1455
|
const scorePercentage = attempt.score ?? 0;
|
|
842
1456
|
const correctCount = attempt.correctAnswers ?? 0;
|
|
843
1457
|
const totalQuestions = attempt.totalQuestions;
|
|
844
1458
|
const timeSpent = attempt.timeSpentSeconds ?? 0;
|
|
845
|
-
return /* @__PURE__ */
|
|
846
|
-
/* @__PURE__ */
|
|
847
|
-
/* @__PURE__ */
|
|
848
|
-
/* @__PURE__ */
|
|
849
|
-
/* @__PURE__ */
|
|
1459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.container, className, children: [
|
|
1460
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: spinnerKeyframes }),
|
|
1461
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.header, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryGrid, children: [
|
|
1462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
1463
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryValue, children: [
|
|
850
1464
|
scorePercentage,
|
|
851
1465
|
"%"
|
|
852
1466
|
] }),
|
|
853
|
-
/* @__PURE__ */
|
|
1467
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Score" })
|
|
854
1468
|
] }),
|
|
855
|
-
/* @__PURE__ */
|
|
856
|
-
/* @__PURE__ */
|
|
1469
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
1470
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryValue, children: [
|
|
857
1471
|
correctCount,
|
|
858
1472
|
"/",
|
|
859
1473
|
totalQuestions
|
|
860
1474
|
] }),
|
|
861
|
-
/* @__PURE__ */
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Correct" })
|
|
862
1476
|
] }),
|
|
863
|
-
/* @__PURE__ */
|
|
864
|
-
/* @__PURE__ */
|
|
865
|
-
/* @__PURE__ */
|
|
1477
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
1478
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.summaryValue, children: formatTime(timeSpent) }),
|
|
1479
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Time" })
|
|
866
1480
|
] })
|
|
867
1481
|
] }) }),
|
|
868
|
-
/* @__PURE__ */
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.questionsList, children: attempt.answers.map((answer, index) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
869
1483
|
"div",
|
|
870
1484
|
{
|
|
871
1485
|
style: {
|
|
@@ -873,12 +1487,12 @@ function AttemptViewer({
|
|
|
873
1487
|
...answer.isCorrect ? defaultStyles2.questionCardCorrect : defaultStyles2.questionCardIncorrect
|
|
874
1488
|
},
|
|
875
1489
|
children: [
|
|
876
|
-
/* @__PURE__ */
|
|
877
|
-
/* @__PURE__ */
|
|
1490
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.questionHeader, children: [
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: defaultStyles2.questionNumber, children: [
|
|
878
1492
|
"Question ",
|
|
879
1493
|
index + 1
|
|
880
1494
|
] }),
|
|
881
|
-
/* @__PURE__ */
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
882
1496
|
"span",
|
|
883
1497
|
{
|
|
884
1498
|
style: {
|
|
@@ -889,23 +1503,23 @@ function AttemptViewer({
|
|
|
889
1503
|
}
|
|
890
1504
|
)
|
|
891
1505
|
] }),
|
|
892
|
-
/* @__PURE__ */
|
|
893
|
-
/* @__PURE__ */
|
|
894
|
-
/* @__PURE__ */
|
|
895
|
-
/* @__PURE__ */
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: defaultStyles2.questionText, children: answer.questionText }),
|
|
1507
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.answerSection, children: [
|
|
1508
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: defaultStyles2.answerLabel, children: "Your answer:" }),
|
|
1509
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: defaultStyles2.studentAnswer, children: formatAnswer(answer.selectedAnswer) })
|
|
896
1510
|
] }),
|
|
897
|
-
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */
|
|
898
|
-
/* @__PURE__ */
|
|
899
|
-
/* @__PURE__ */
|
|
1511
|
+
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.answerSection, children: [
|
|
1512
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: defaultStyles2.answerLabel, children: "Correct answer:" }),
|
|
1513
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: defaultStyles2.correctAnswer, children: formatAnswer(answer.correctAnswer) })
|
|
900
1514
|
] }),
|
|
901
|
-
/* @__PURE__ */
|
|
1515
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.points, children: [
|
|
902
1516
|
answer.pointsEarned,
|
|
903
1517
|
" / ",
|
|
904
1518
|
answer.points,
|
|
905
1519
|
" points"
|
|
906
1520
|
] }),
|
|
907
|
-
showExplanations && answer.explanation && /* @__PURE__ */
|
|
908
|
-
/* @__PURE__ */
|
|
1521
|
+
showExplanations && answer.explanation && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: defaultStyles2.explanation, children: [
|
|
1522
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("strong", { children: "Explanation:" }),
|
|
909
1523
|
" ",
|
|
910
1524
|
answer.explanation
|
|
911
1525
|
] })
|
|
@@ -915,13 +1529,14 @@ function AttemptViewer({
|
|
|
915
1529
|
)) })
|
|
916
1530
|
] });
|
|
917
1531
|
}
|
|
918
|
-
|
|
919
|
-
exports
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1532
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1533
|
+
0 && (module.exports = {
|
|
1534
|
+
AttemptViewer,
|
|
1535
|
+
QuizApiClient,
|
|
1536
|
+
QuizPlayer,
|
|
1537
|
+
calculateScore,
|
|
1538
|
+
checkAnswer,
|
|
1539
|
+
createAnswerDetail,
|
|
1540
|
+
formatTime
|
|
1541
|
+
});
|
|
927
1542
|
//# sourceMappingURL=index.js.map
|