@schoolio/player 1.4.3 → 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.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +448 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +448 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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);
|
|
@@ -1316,6 +1325,13 @@ var defaultStyles = {
|
|
|
1316
1325
|
backgroundColor: "#fef2f2",
|
|
1317
1326
|
borderColor: "#ef4444"
|
|
1318
1327
|
},
|
|
1328
|
+
feedbackNeutral: {
|
|
1329
|
+
backgroundColor: "#f0f9ff",
|
|
1330
|
+
borderColor: "#0ea5e9"
|
|
1331
|
+
},
|
|
1332
|
+
feedbackTitleNeutral: {
|
|
1333
|
+
color: "#0369a1"
|
|
1334
|
+
},
|
|
1319
1335
|
feedbackTitle: {
|
|
1320
1336
|
fontSize: "16px",
|
|
1321
1337
|
fontWeight: "600",
|
|
@@ -1336,6 +1352,290 @@ var defaultStyles = {
|
|
|
1336
1352
|
lineHeight: "1.5"
|
|
1337
1353
|
}
|
|
1338
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
|
+
}
|
|
1339
1639
|
function Spinner({ size = 16, color = "#ffffff" }) {
|
|
1340
1640
|
return /* @__PURE__ */ jsx3(
|
|
1341
1641
|
"span",
|
|
@@ -2212,14 +2512,123 @@ function QuizPlayer({
|
|
|
2212
2512
|
},
|
|
2213
2513
|
idx
|
|
2214
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
|
+
})() }),
|
|
2215
2624
|
showFeedback && currentAnswerDetail && /* @__PURE__ */ jsxs3("div", { style: {
|
|
2216
2625
|
...defaultStyles.feedback,
|
|
2217
|
-
...currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
|
|
2626
|
+
...currentQuestion.type === "assessment" ? defaultStyles.feedbackNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
|
|
2218
2627
|
}, children: [
|
|
2219
2628
|
/* @__PURE__ */ jsx3("div", { style: {
|
|
2220
2629
|
...defaultStyles.feedbackTitle,
|
|
2221
|
-
...currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
|
|
2222
|
-
}, 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" }),
|
|
2223
2632
|
currentQuestion.explanation && /* @__PURE__ */ jsx3("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
|
|
2224
2633
|
] })
|
|
2225
2634
|
] }),
|
|
@@ -2541,7 +2950,7 @@ function QuizPlayer({
|
|
|
2541
2950
|
lessonId,
|
|
2542
2951
|
courseId,
|
|
2543
2952
|
answerResult: showFeedback && currentAnswerDetail ? {
|
|
2544
|
-
wasIncorrect: !currentAnswerDetail.isCorrect,
|
|
2953
|
+
wasIncorrect: currentQuestion.type !== "assessment" && !currentAnswerDetail.isCorrect,
|
|
2545
2954
|
selectedAnswer: typeof selectedAnswer === "string" ? selectedAnswer : Array.isArray(selectedAnswer) ? selectedAnswer.join(", ") : void 0,
|
|
2546
2955
|
correctAnswer: typeof currentQuestion.correctAnswer === "string" ? currentQuestion.correctAnswer : Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer.join(", ") : void 0,
|
|
2547
2956
|
explanation: currentQuestion.explanation
|
|
@@ -2749,10 +3158,31 @@ var spinnerKeyframes = `
|
|
|
2749
3158
|
to { transform: rotate(360deg); }
|
|
2750
3159
|
}
|
|
2751
3160
|
`;
|
|
2752
|
-
function formatAnswer(answer) {
|
|
3161
|
+
function formatAnswer(answer, questionType, items, leftItems) {
|
|
2753
3162
|
if (answer === null || answer === void 0) {
|
|
2754
3163
|
return "No answer";
|
|
2755
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
|
+
}
|
|
2756
3186
|
if (typeof answer === "string") {
|
|
2757
3187
|
return answer;
|
|
2758
3188
|
}
|
|
@@ -2764,6 +3194,15 @@ function formatAnswer(answer) {
|
|
|
2764
3194
|
}
|
|
2765
3195
|
return String(answer);
|
|
2766
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
|
+
}
|
|
2767
3206
|
function AttemptViewer({
|
|
2768
3207
|
attemptId,
|
|
2769
3208
|
apiBaseUrl,
|
|
@@ -2900,11 +3339,11 @@ function AttemptViewer({
|
|
|
2900
3339
|
/* @__PURE__ */ jsx4("div", { style: defaultStyles2.questionText, children: answer.questionText }),
|
|
2901
3340
|
/* @__PURE__ */ jsxs4("div", { style: defaultStyles2.answerSection, children: [
|
|
2902
3341
|
/* @__PURE__ */ jsx4("span", { style: defaultStyles2.answerLabel, children: "Your answer:" }),
|
|
2903
|
-
/* @__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) })
|
|
2904
3343
|
] }),
|
|
2905
3344
|
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ jsxs4("div", { style: defaultStyles2.answerSection, children: [
|
|
2906
3345
|
/* @__PURE__ */ jsx4("span", { style: defaultStyles2.answerLabel, children: "Correct answer:" }),
|
|
2907
|
-
/* @__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) })
|
|
2908
3347
|
] }),
|
|
2909
3348
|
/* @__PURE__ */ jsxs4("div", { style: defaultStyles2.points, children: [
|
|
2910
3349
|
answer.pointsEarned,
|