@schoolio/player 1.4.2 → 1.4.4

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.mjs CHANGED
@@ -158,15 +158,16 @@ function checkAnswer(question, selectedAnswer) {
158
158
  return { isCorrect, pointsEarned: isCorrect ? points : 0 };
159
159
  }
160
160
  case "essay":
161
- case "assessment":
162
161
  return { isCorrect: false, pointsEarned: 0 };
162
+ case "assessment":
163
+ return { isCorrect: true, pointsEarned: points };
163
164
  default:
164
165
  return { isCorrect: false, pointsEarned: 0 };
165
166
  }
166
167
  }
167
168
  function createAnswerDetail(question, selectedAnswer) {
168
169
  const { isCorrect, pointsEarned } = checkAnswer(question, selectedAnswer);
169
- return {
170
+ const detail = {
170
171
  questionId: question.id,
171
172
  questionText: question.question,
172
173
  questionType: question.type,
@@ -178,6 +179,14 @@ function createAnswerDetail(question, selectedAnswer) {
178
179
  explanation: question.explanation,
179
180
  hint: question.hint
180
181
  };
182
+ if (question.type === "sorting") {
183
+ detail.items = question.items;
184
+ detail.correctOrder = question.correctOrder;
185
+ } else if (question.type === "matrix") {
186
+ detail.leftItems = question.leftItems;
187
+ detail.rightItems = question.rightItems;
188
+ }
189
+ return detail;
181
190
  }
182
191
  function calculateScore(answers) {
183
192
  const totalPoints = answers.reduce((sum, a) => sum + a.points, 0);
@@ -1021,12 +1030,14 @@ var defaultStyles = {
1021
1030
  fontFamily: "system-ui, -apple-system, sans-serif",
1022
1031
  width: "100%",
1023
1032
  height: "100%",
1033
+ maxHeight: "calc(100vh - 40px)",
1024
1034
  padding: "20px",
1025
1035
  backgroundColor: "#ffffff",
1026
1036
  borderRadius: "12px",
1027
1037
  boxSizing: "border-box",
1028
1038
  display: "flex",
1029
- flexDirection: "column"
1039
+ flexDirection: "column",
1040
+ overflow: "hidden"
1030
1041
  },
1031
1042
  header: {
1032
1043
  marginBottom: "20px",
@@ -1053,8 +1064,7 @@ var defaultStyles = {
1053
1064
  color: "#6b7280"
1054
1065
  },
1055
1066
  progressBar: {
1056
- width: "50%",
1057
- maxWidth: "300px",
1067
+ width: "100%",
1058
1068
  height: "8px",
1059
1069
  backgroundColor: "#e5e7eb",
1060
1070
  borderRadius: "4px",
@@ -1081,6 +1091,7 @@ var defaultStyles = {
1081
1091
  gap: "8px"
1082
1092
  },
1083
1093
  option: {
1094
+ width: "100%",
1084
1095
  padding: "12px 16px",
1085
1096
  border: "2px solid #e5e7eb",
1086
1097
  borderRadius: "8px",
@@ -1090,7 +1101,8 @@ var defaultStyles = {
1090
1101
  boxShadow: "none",
1091
1102
  backgroundColor: "#ffffff",
1092
1103
  WebkitTapHighlightColor: "transparent",
1093
- userSelect: "none"
1104
+ userSelect: "none",
1105
+ boxSizing: "border-box"
1094
1106
  },
1095
1107
  optionSelected: {
1096
1108
  borderColor: "#6721b0",
@@ -1172,18 +1184,22 @@ var defaultStyles = {
1172
1184
  gap: "24px",
1173
1185
  flex: 1,
1174
1186
  minHeight: 0,
1175
- alignItems: "stretch"
1187
+ alignItems: "stretch",
1188
+ overflow: "hidden"
1176
1189
  },
1177
1190
  quizContent: {
1178
1191
  flex: 1,
1179
1192
  minWidth: 0,
1193
+ minHeight: 0,
1180
1194
  overflow: "auto"
1181
1195
  },
1182
1196
  chatPanel: {
1183
1197
  width: "320px",
1184
1198
  flexShrink: 0,
1185
1199
  display: "flex",
1186
- flexDirection: "column"
1200
+ flexDirection: "column",
1201
+ minHeight: 0,
1202
+ overflow: "hidden"
1187
1203
  },
1188
1204
  timer: {
1189
1205
  fontSize: "14px",
@@ -1309,6 +1325,13 @@ var defaultStyles = {
1309
1325
  backgroundColor: "#fef2f2",
1310
1326
  borderColor: "#ef4444"
1311
1327
  },
1328
+ feedbackNeutral: {
1329
+ backgroundColor: "#f0f9ff",
1330
+ borderColor: "#0ea5e9"
1331
+ },
1332
+ feedbackTitleNeutral: {
1333
+ color: "#0369a1"
1334
+ },
1312
1335
  feedbackTitle: {
1313
1336
  fontSize: "16px",
1314
1337
  fontWeight: "600",
@@ -1329,6 +1352,290 @@ var defaultStyles = {
1329
1352
  lineHeight: "1.5"
1330
1353
  }
1331
1354
  };
1355
+ function SortingDragDrop({ items, currentOrder, correctOrder, showFeedback, onOrderChange }) {
1356
+ const [draggedIndex, setDraggedIndex] = useState3(null);
1357
+ const [dragOverIndex, setDragOverIndex] = useState3(null);
1358
+ const handleDragStart = (e, position) => {
1359
+ if (showFeedback) return;
1360
+ setDraggedIndex(position);
1361
+ e.dataTransfer.effectAllowed = "move";
1362
+ e.dataTransfer.setData("text/plain", position.toString());
1363
+ };
1364
+ const handleDragOver = (e, position) => {
1365
+ e.preventDefault();
1366
+ if (showFeedback) return;
1367
+ e.dataTransfer.dropEffect = "move";
1368
+ setDragOverIndex(position);
1369
+ };
1370
+ const handleDragLeave = () => {
1371
+ setDragOverIndex(null);
1372
+ };
1373
+ const handleDrop = (e, toPosition) => {
1374
+ e.preventDefault();
1375
+ if (showFeedback) return;
1376
+ const fromPosition = parseInt(e.dataTransfer.getData("text/plain"), 10);
1377
+ if (fromPosition !== toPosition) {
1378
+ const newOrder = [...currentOrder];
1379
+ const [movedItem] = newOrder.splice(fromPosition, 1);
1380
+ newOrder.splice(toPosition, 0, movedItem);
1381
+ onOrderChange(newOrder);
1382
+ }
1383
+ setDraggedIndex(null);
1384
+ setDragOverIndex(null);
1385
+ };
1386
+ const handleDragEnd = () => {
1387
+ setDraggedIndex(null);
1388
+ setDragOverIndex(null);
1389
+ };
1390
+ return /* @__PURE__ */ jsx3("div", { style: defaultStyles.options, children: currentOrder.map((itemIndex, position) => {
1391
+ const isCorrectPosition = correctOrder?.[position] === itemIndex;
1392
+ const isDragging = draggedIndex === position;
1393
+ const isDragOver = dragOverIndex === position;
1394
+ let itemStyle = {
1395
+ ...defaultStyles.option,
1396
+ display: "flex",
1397
+ alignItems: "center",
1398
+ gap: "12px",
1399
+ cursor: showFeedback ? "default" : "grab",
1400
+ opacity: isDragging ? 0.5 : 1,
1401
+ transition: "all 0.2s ease",
1402
+ transform: isDragOver && !showFeedback ? "scale(1.02)" : "scale(1)"
1403
+ };
1404
+ if (showFeedback) {
1405
+ if (isCorrectPosition) {
1406
+ itemStyle = { ...itemStyle, ...defaultStyles.optionCorrect };
1407
+ } else {
1408
+ itemStyle = { ...itemStyle, ...defaultStyles.optionIncorrect };
1409
+ }
1410
+ } else if (isDragOver) {
1411
+ itemStyle = { ...itemStyle, borderColor: "#6366f1", backgroundColor: "#eef2ff" };
1412
+ }
1413
+ return /* @__PURE__ */ jsxs3(
1414
+ "div",
1415
+ {
1416
+ style: itemStyle,
1417
+ "data-testid": `sorting-item-${position}`,
1418
+ draggable: !showFeedback,
1419
+ onDragStart: (e) => handleDragStart(e, position),
1420
+ onDragOver: (e) => handleDragOver(e, position),
1421
+ onDragLeave: handleDragLeave,
1422
+ onDrop: (e) => handleDrop(e, position),
1423
+ onDragEnd: handleDragEnd,
1424
+ children: [
1425
+ !showFeedback && /* @__PURE__ */ jsx3("div", { style: {
1426
+ cursor: "grab",
1427
+ padding: "4px",
1428
+ display: "flex",
1429
+ alignItems: "center",
1430
+ color: "#9ca3af"
1431
+ }, children: /* @__PURE__ */ jsxs3("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1432
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "5", r: "1" }),
1433
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "12", r: "1" }),
1434
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "19", r: "1" }),
1435
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "5", r: "1" }),
1436
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "12", r: "1" }),
1437
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "19", r: "1" })
1438
+ ] }) }),
1439
+ showFeedback && /* @__PURE__ */ jsx3("div", { style: {
1440
+ display: "flex",
1441
+ alignItems: "center",
1442
+ color: isCorrectPosition ? "#22c55e" : "#ef4444"
1443
+ }, children: isCorrectPosition ? /* @__PURE__ */ jsxs3("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1444
+ /* @__PURE__ */ jsx3("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
1445
+ /* @__PURE__ */ jsx3("polyline", { points: "22 4 12 14.01 9 11.01" })
1446
+ ] }) : /* @__PURE__ */ jsxs3("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1447
+ /* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
1448
+ /* @__PURE__ */ jsx3("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
1449
+ /* @__PURE__ */ jsx3("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
1450
+ ] }) }),
1451
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: items[itemIndex] }),
1452
+ /* @__PURE__ */ jsx3("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx3(TextToSpeech, { text: items[itemIndex], size: "sm" }) })
1453
+ ]
1454
+ },
1455
+ itemIndex
1456
+ );
1457
+ }) });
1458
+ }
1459
+ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatches, showFeedback, onMatchChange }) {
1460
+ const [draggedItem, setDraggedItem] = useState3(null);
1461
+ const [dragOverLeft, setDragOverLeft] = useState3(null);
1462
+ const matchedRightItems = Object.values(currentMatches);
1463
+ const unmatchedRightItems = rightItems.filter((item) => !matchedRightItems.includes(item));
1464
+ const handleDragStart = (e, rightItem) => {
1465
+ if (showFeedback) return;
1466
+ setDraggedItem(rightItem);
1467
+ e.dataTransfer.effectAllowed = "move";
1468
+ e.dataTransfer.setData("text/plain", rightItem);
1469
+ };
1470
+ const handleDragOver = (e, leftItem) => {
1471
+ e.preventDefault();
1472
+ if (showFeedback) return;
1473
+ e.dataTransfer.dropEffect = "move";
1474
+ setDragOverLeft(leftItem);
1475
+ };
1476
+ const handleDragLeave = () => {
1477
+ setDragOverLeft(null);
1478
+ };
1479
+ const handleDrop = (e, leftItem) => {
1480
+ e.preventDefault();
1481
+ if (showFeedback) return;
1482
+ const rightItem = e.dataTransfer.getData("text/plain");
1483
+ if (rightItem) {
1484
+ const newMatches = { ...currentMatches };
1485
+ Object.keys(newMatches).forEach((key) => {
1486
+ if (newMatches[key] === rightItem) {
1487
+ delete newMatches[key];
1488
+ }
1489
+ });
1490
+ newMatches[leftItem] = rightItem;
1491
+ onMatchChange(newMatches);
1492
+ }
1493
+ setDraggedItem(null);
1494
+ setDragOverLeft(null);
1495
+ };
1496
+ const handleDragEnd = () => {
1497
+ setDraggedItem(null);
1498
+ setDragOverLeft(null);
1499
+ };
1500
+ const handleClearMatch = (leftItem) => {
1501
+ if (showFeedback) return;
1502
+ const newMatches = { ...currentMatches };
1503
+ delete newMatches[leftItem];
1504
+ onMatchChange(newMatches);
1505
+ };
1506
+ return /* @__PURE__ */ jsxs3("div", { style: { display: "flex", gap: "24px", flexWrap: "wrap" }, children: [
1507
+ /* @__PURE__ */ jsxs3("div", { style: { flex: 1, minWidth: "200px", display: "flex", flexDirection: "column", gap: "8px" }, children: [
1508
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: "14px", fontWeight: "600", color: "#6b7280", marginBottom: "4px" }, children: "Match these items:" }),
1509
+ leftItems.map((leftItem, idx) => {
1510
+ const matchedRight = currentMatches[leftItem];
1511
+ const correctMatch = correctMatches?.[leftItem];
1512
+ const isCorrect = matchedRight === correctMatch;
1513
+ const isDragOver = dragOverLeft === leftItem;
1514
+ let rowStyle = {
1515
+ display: "flex",
1516
+ alignItems: "center",
1517
+ gap: "12px",
1518
+ padding: "12px 16px",
1519
+ border: "2px dashed #e5e7eb",
1520
+ borderRadius: "8px",
1521
+ backgroundColor: "#ffffff",
1522
+ minHeight: "56px",
1523
+ transition: "all 0.2s ease"
1524
+ };
1525
+ if (showFeedback) {
1526
+ rowStyle.borderStyle = "solid";
1527
+ if (isCorrect) {
1528
+ rowStyle = { ...rowStyle, borderColor: "#22c55e", backgroundColor: "#f0fdf4" };
1529
+ } else {
1530
+ rowStyle = { ...rowStyle, borderColor: "#ef4444", backgroundColor: "#fef2f2" };
1531
+ }
1532
+ } else if (isDragOver) {
1533
+ rowStyle = { ...rowStyle, borderColor: "#6366f1", backgroundColor: "#eef2ff", borderStyle: "solid" };
1534
+ } else if (matchedRight) {
1535
+ rowStyle = { ...rowStyle, borderStyle: "solid", borderColor: "#22c55e" };
1536
+ }
1537
+ return /* @__PURE__ */ jsxs3(
1538
+ "div",
1539
+ {
1540
+ style: rowStyle,
1541
+ "data-testid": `matrix-row-${idx}`,
1542
+ onDragOver: (e) => handleDragOver(e, leftItem),
1543
+ onDragLeave: handleDragLeave,
1544
+ onDrop: (e) => handleDrop(e, leftItem),
1545
+ children: [
1546
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1, fontWeight: "500" }, children: leftItem }),
1547
+ /* @__PURE__ */ jsx3("span", { style: { color: "#6b7280" }, children: "\u2192" }),
1548
+ matchedRight ? /* @__PURE__ */ jsxs3("div", { style: {
1549
+ display: "flex",
1550
+ alignItems: "center",
1551
+ gap: "8px",
1552
+ padding: "6px 12px",
1553
+ backgroundColor: showFeedback ? isCorrect ? "#dcfce7" : "#fee2e2" : "#e0e7ff",
1554
+ borderRadius: "6px",
1555
+ fontSize: "14px"
1556
+ }, children: [
1557
+ /* @__PURE__ */ jsx3("span", { children: matchedRight }),
1558
+ !showFeedback && /* @__PURE__ */ jsx3(
1559
+ "button",
1560
+ {
1561
+ onClick: () => handleClearMatch(leftItem),
1562
+ style: {
1563
+ background: "none",
1564
+ border: "none",
1565
+ cursor: "pointer",
1566
+ padding: "2px",
1567
+ display: "flex",
1568
+ color: "#6b7280"
1569
+ },
1570
+ "aria-label": "Remove match",
1571
+ children: /* @__PURE__ */ jsxs3("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1572
+ /* @__PURE__ */ jsx3("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1573
+ /* @__PURE__ */ jsx3("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1574
+ ] })
1575
+ }
1576
+ ),
1577
+ showFeedback && (isCorrect ? /* @__PURE__ */ jsx3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#22c55e", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx3("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1578
+ /* @__PURE__ */ jsx3("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1579
+ /* @__PURE__ */ jsx3("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
1580
+ ] }))
1581
+ ] }) : /* @__PURE__ */ jsx3("span", { style: { color: "#9ca3af", fontSize: "14px", fontStyle: "italic" }, children: "Drop here" }),
1582
+ showFeedback && !isCorrect && correctMatch && /* @__PURE__ */ jsxs3("span", { style: { color: "#166534", fontSize: "13px", marginLeft: "8px" }, children: [
1583
+ "(Correct: ",
1584
+ correctMatch,
1585
+ ")"
1586
+ ] })
1587
+ ]
1588
+ },
1589
+ idx
1590
+ );
1591
+ })
1592
+ ] }),
1593
+ /* @__PURE__ */ jsxs3("div", { style: { flex: 1, minWidth: "200px", display: "flex", flexDirection: "column", gap: "8px" }, children: [
1594
+ /* @__PURE__ */ jsx3("div", { style: { fontSize: "14px", fontWeight: "600", color: "#6b7280", marginBottom: "4px" }, children: "Drag to match:" }),
1595
+ unmatchedRightItems.length > 0 ? unmatchedRightItems.map((rightItem, idx) => {
1596
+ const isDragging = draggedItem === rightItem;
1597
+ return /* @__PURE__ */ jsxs3(
1598
+ "div",
1599
+ {
1600
+ style: {
1601
+ padding: "12px 16px",
1602
+ border: "2px solid #e5e7eb",
1603
+ borderRadius: "8px",
1604
+ backgroundColor: "#ffffff",
1605
+ cursor: showFeedback ? "default" : "grab",
1606
+ opacity: isDragging ? 0.5 : 1,
1607
+ display: "flex",
1608
+ alignItems: "center",
1609
+ gap: "8px",
1610
+ transition: "all 0.2s ease"
1611
+ },
1612
+ draggable: !showFeedback,
1613
+ onDragStart: (e) => handleDragStart(e, rightItem),
1614
+ onDragEnd: handleDragEnd,
1615
+ "data-testid": `draggable-right-${idx}`,
1616
+ children: [
1617
+ !showFeedback && /* @__PURE__ */ jsx3("div", { style: { color: "#9ca3af", display: "flex" }, children: /* @__PURE__ */ jsxs3("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1618
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "5", r: "1" }),
1619
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "12", r: "1" }),
1620
+ /* @__PURE__ */ jsx3("circle", { cx: "9", cy: "19", r: "1" }),
1621
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "5", r: "1" }),
1622
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "12", r: "1" }),
1623
+ /* @__PURE__ */ jsx3("circle", { cx: "15", cy: "19", r: "1" })
1624
+ ] }) }),
1625
+ /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: rightItem })
1626
+ ]
1627
+ },
1628
+ idx
1629
+ );
1630
+ }) : /* @__PURE__ */ jsx3("div", { style: {
1631
+ padding: "16px",
1632
+ textAlign: "center",
1633
+ color: "#22c55e",
1634
+ fontSize: "14px"
1635
+ }, children: "All items matched!" })
1636
+ ] })
1637
+ ] });
1638
+ }
1332
1639
  function Spinner({ size = 16, color = "#ffffff" }) {
1333
1640
  return /* @__PURE__ */ jsx3(
1334
1641
  "span",
@@ -2205,14 +2512,123 @@ function QuizPlayer({
2205
2512
  },
2206
2513
  idx
2207
2514
  )) }),
2515
+ currentQuestion.type === "sorting" && currentQuestion.items && /* @__PURE__ */ jsx3(
2516
+ SortingDragDrop,
2517
+ {
2518
+ items: currentQuestion.items,
2519
+ currentOrder: Array.isArray(selectedAnswer) ? selectedAnswer : currentQuestion.items.map((_, i) => i),
2520
+ correctOrder: currentQuestion.correctOrder,
2521
+ showFeedback,
2522
+ onOrderChange: handleAnswerChange
2523
+ }
2524
+ ),
2525
+ currentQuestion.type === "matrix" && currentQuestion.leftItems && currentQuestion.rightItems && /* @__PURE__ */ jsx3(
2526
+ MatchingDragDrop,
2527
+ {
2528
+ leftItems: currentQuestion.leftItems,
2529
+ rightItems: currentQuestion.rightItems,
2530
+ currentMatches: typeof selectedAnswer === "object" && selectedAnswer !== null && !Array.isArray(selectedAnswer) ? selectedAnswer : {},
2531
+ correctMatches: currentQuestion.correctMatches,
2532
+ showFeedback,
2533
+ onMatchChange: handleAnswerChange
2534
+ }
2535
+ ),
2536
+ currentQuestion.type === "assessment" && /* @__PURE__ */ jsx3("div", { style: defaultStyles.options, children: (() => {
2537
+ const scaleType = currentQuestion.scaleType || "likert";
2538
+ if (scaleType === "yes-no") {
2539
+ const options = ["Yes", "No"];
2540
+ return options.map((option, idx) => {
2541
+ const isSelected = selectedAnswer === option;
2542
+ let optionStyle = { ...defaultStyles.option };
2543
+ if (isSelected) {
2544
+ optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2545
+ }
2546
+ return /* @__PURE__ */ jsx3(
2547
+ "div",
2548
+ {
2549
+ style: {
2550
+ ...optionStyle,
2551
+ cursor: showFeedback ? "default" : "pointer",
2552
+ display: "flex",
2553
+ alignItems: "center",
2554
+ gap: "8px"
2555
+ },
2556
+ onClick: () => !showFeedback && handleAnswerChange(option),
2557
+ "data-testid": `assessment-option-${option.toLowerCase()}`,
2558
+ children: /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: option })
2559
+ },
2560
+ idx
2561
+ );
2562
+ });
2563
+ }
2564
+ if (scaleType === "rating") {
2565
+ const min = currentQuestion.scaleMin || 1;
2566
+ const max = currentQuestion.scaleMax || 5;
2567
+ const ratings = Array.from({ length: max - min + 1 }, (_, i) => min + i);
2568
+ return /* @__PURE__ */ jsx3("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap", justifyContent: "center" }, children: ratings.map((rating) => {
2569
+ const isSelected = selectedAnswer === rating;
2570
+ return /* @__PURE__ */ jsx3(
2571
+ "button",
2572
+ {
2573
+ onClick: () => !showFeedback && handleAnswerChange(rating),
2574
+ disabled: showFeedback,
2575
+ style: {
2576
+ width: "48px",
2577
+ height: "48px",
2578
+ borderRadius: "50%",
2579
+ border: isSelected ? "2px solid #6721b0" : "2px solid #e5e7eb",
2580
+ backgroundColor: isSelected ? "#f3e8ff" : "#ffffff",
2581
+ cursor: showFeedback ? "not-allowed" : "pointer",
2582
+ fontSize: "18px",
2583
+ fontWeight: "600",
2584
+ color: isSelected ? "#6721b0" : "#374151"
2585
+ },
2586
+ "data-testid": `assessment-rating-${rating}`,
2587
+ children: rating
2588
+ },
2589
+ rating
2590
+ );
2591
+ }) });
2592
+ }
2593
+ const likertOptions = [
2594
+ "Strongly Disagree",
2595
+ "Disagree",
2596
+ "Neutral",
2597
+ "Agree",
2598
+ "Strongly Agree"
2599
+ ];
2600
+ return likertOptions.map((option, idx) => {
2601
+ const isSelected = selectedAnswer === option;
2602
+ let optionStyle = { ...defaultStyles.option };
2603
+ if (isSelected) {
2604
+ optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2605
+ }
2606
+ return /* @__PURE__ */ jsx3(
2607
+ "div",
2608
+ {
2609
+ style: {
2610
+ ...optionStyle,
2611
+ cursor: showFeedback ? "default" : "pointer",
2612
+ display: "flex",
2613
+ alignItems: "center",
2614
+ gap: "8px"
2615
+ },
2616
+ onClick: () => !showFeedback && handleAnswerChange(option),
2617
+ "data-testid": `assessment-likert-${idx}`,
2618
+ children: /* @__PURE__ */ jsx3("span", { style: { flex: 1 }, children: option })
2619
+ },
2620
+ idx
2621
+ );
2622
+ });
2623
+ })() }),
2208
2624
  showFeedback && currentAnswerDetail && /* @__PURE__ */ jsxs3("div", { style: {
2209
2625
  ...defaultStyles.feedback,
2210
- ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
2626
+ ...currentQuestion.type === "assessment" ? defaultStyles.feedbackNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
2211
2627
  }, children: [
2212
2628
  /* @__PURE__ */ jsx3("div", { style: {
2213
2629
  ...defaultStyles.feedbackTitle,
2214
- ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
2215
- }, children: currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
2630
+ ...currentQuestion.type === "assessment" ? defaultStyles.feedbackTitleNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
2631
+ }, children: currentQuestion.type === "assessment" ? "\u2713 Response recorded" : currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
2216
2632
  currentQuestion.explanation && /* @__PURE__ */ jsx3("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
2217
2633
  ] })
2218
2634
  ] }),
@@ -2534,7 +2950,7 @@ function QuizPlayer({
2534
2950
  lessonId,
2535
2951
  courseId,
2536
2952
  answerResult: showFeedback && currentAnswerDetail ? {
2537
- wasIncorrect: !currentAnswerDetail.isCorrect,
2953
+ wasIncorrect: currentQuestion.type !== "assessment" && !currentAnswerDetail.isCorrect,
2538
2954
  selectedAnswer: typeof selectedAnswer === "string" ? selectedAnswer : Array.isArray(selectedAnswer) ? selectedAnswer.join(", ") : void 0,
2539
2955
  correctAnswer: typeof currentQuestion.correctAnswer === "string" ? currentQuestion.correctAnswer : Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer.join(", ") : void 0,
2540
2956
  explanation: currentQuestion.explanation
@@ -2742,10 +3158,31 @@ var spinnerKeyframes = `
2742
3158
  to { transform: rotate(360deg); }
2743
3159
  }
2744
3160
  `;
2745
- function formatAnswer(answer) {
3161
+ function formatAnswer(answer, questionType, items, leftItems) {
2746
3162
  if (answer === null || answer === void 0) {
2747
3163
  return "No answer";
2748
3164
  }
3165
+ if (questionType === "sorting" && Array.isArray(answer)) {
3166
+ const indices = answer;
3167
+ if (items && items.length > 0) {
3168
+ return indices.map((idx, pos) => `${pos + 1}. ${items[idx] ?? `Item ${idx + 1}`}`).join(", ");
3169
+ }
3170
+ return indices.map((idx, pos) => `Position ${pos + 1}: Item ${idx + 1}`).join(", ");
3171
+ }
3172
+ if (questionType === "matrix" && typeof answer === "object" && !Array.isArray(answer)) {
3173
+ const matches = answer;
3174
+ if (leftItems && leftItems.length > 0) {
3175
+ return leftItems.map((left) => {
3176
+ const right = matches[left];
3177
+ return `${left} \u2192 ${right || "No answer"}`;
3178
+ }).join(", ");
3179
+ }
3180
+ const entries = Object.entries(matches);
3181
+ if (entries.length === 0) {
3182
+ return "No answer";
3183
+ }
3184
+ return entries.map(([left, right]) => `${left} \u2192 ${right || "No answer"}`).join(", ");
3185
+ }
2749
3186
  if (typeof answer === "string") {
2750
3187
  return answer;
2751
3188
  }
@@ -2757,6 +3194,15 @@ function formatAnswer(answer) {
2757
3194
  }
2758
3195
  return String(answer);
2759
3196
  }
3197
+ function formatCorrectSortingAnswer(items, correctOrder) {
3198
+ return correctOrder.map((idx, pos) => `${pos + 1}. ${items[idx] ?? `Item ${idx + 1}`}`).join(", ");
3199
+ }
3200
+ function formatCorrectMatrixAnswer(correctMatches, leftItems) {
3201
+ if (leftItems && leftItems.length > 0) {
3202
+ return leftItems.map((left) => `${left} \u2192 ${correctMatches[left] || "N/A"}`).join(", ");
3203
+ }
3204
+ return Object.entries(correctMatches).map(([left, right]) => `${left} \u2192 ${right}`).join(", ");
3205
+ }
2760
3206
  function AttemptViewer({
2761
3207
  attemptId,
2762
3208
  apiBaseUrl,
@@ -2893,11 +3339,11 @@ function AttemptViewer({
2893
3339
  /* @__PURE__ */ jsx4("div", { style: defaultStyles2.questionText, children: answer.questionText }),
2894
3340
  /* @__PURE__ */ jsxs4("div", { style: defaultStyles2.answerSection, children: [
2895
3341
  /* @__PURE__ */ jsx4("span", { style: defaultStyles2.answerLabel, children: "Your answer:" }),
2896
- /* @__PURE__ */ jsx4("span", { style: defaultStyles2.studentAnswer, children: formatAnswer(answer.selectedAnswer) })
3342
+ /* @__PURE__ */ jsx4("span", { style: defaultStyles2.studentAnswer, children: formatAnswer(answer.selectedAnswer, answer.questionType, answer.items, answer.leftItems) })
2897
3343
  ] }),
2898
3344
  !answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ jsxs4("div", { style: defaultStyles2.answerSection, children: [
2899
3345
  /* @__PURE__ */ jsx4("span", { style: defaultStyles2.answerLabel, children: "Correct answer:" }),
2900
- /* @__PURE__ */ jsx4("span", { style: defaultStyles2.correctAnswer, children: formatAnswer(answer.correctAnswer) })
3346
+ /* @__PURE__ */ jsx4("span", { style: defaultStyles2.correctAnswer, children: answer.questionType === "sorting" && answer.items && answer.correctOrder ? formatCorrectSortingAnswer(answer.items, answer.correctOrder) : answer.questionType === "matrix" && answer.correctAnswer && typeof answer.correctAnswer === "object" && !Array.isArray(answer.correctAnswer) ? formatCorrectMatrixAnswer(answer.correctAnswer, answer.leftItems) : formatAnswer(answer.correctAnswer, answer.questionType, answer.items, answer.leftItems) })
2901
3347
  ] }),
2902
3348
  /* @__PURE__ */ jsxs4("div", { style: defaultStyles2.points, children: [
2903
3349
  answer.pointsEarned,