@schoolio/player 1.4.4 → 1.4.6
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 +51 -2
- package/dist/index.d.ts +51 -2
- package/dist/index.js +1857 -781
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1851 -781
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,13 +21,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AttemptViewer: () => AttemptViewer,
|
|
24
|
+
ERROR_DEFINITIONS: () => ERROR_DEFINITIONS,
|
|
25
|
+
ErrorLogsPanel: () => ErrorLogsPanel,
|
|
26
|
+
ErrorTypesPanel: () => ErrorTypesPanel,
|
|
27
|
+
MaintenanceScreen: () => MaintenanceScreen,
|
|
24
28
|
QuizApiClient: () => QuizApiClient,
|
|
25
29
|
QuizPlayer: () => QuizPlayer,
|
|
26
30
|
TextToSpeech: () => TextToSpeech,
|
|
27
31
|
calculateScore: () => calculateScore,
|
|
28
32
|
checkAnswer: () => checkAnswer,
|
|
29
33
|
createAnswerDetail: () => createAnswerDetail,
|
|
30
|
-
formatTime: () => formatTime
|
|
34
|
+
formatTime: () => formatTime,
|
|
35
|
+
getErrorFromHttpStatus: () => getErrorFromHttpStatus,
|
|
36
|
+
getErrorFromMessage: () => getErrorFromMessage
|
|
31
37
|
});
|
|
32
38
|
module.exports = __toCommonJS(index_exports);
|
|
33
39
|
|
|
@@ -136,6 +142,13 @@ var QuizApiClient = class {
|
|
|
136
142
|
}
|
|
137
143
|
return response.blob();
|
|
138
144
|
}
|
|
145
|
+
async logError(params) {
|
|
146
|
+
try {
|
|
147
|
+
await this.request("POST", "/api/external/log-error", params);
|
|
148
|
+
} catch (e) {
|
|
149
|
+
console.warn("[QuizEngine] Failed to log error:", e);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
139
152
|
};
|
|
140
153
|
|
|
141
154
|
// src/utils.ts
|
|
@@ -1056,8 +1069,191 @@ function QuestionChatPanel({
|
|
|
1056
1069
|
] });
|
|
1057
1070
|
}
|
|
1058
1071
|
|
|
1059
|
-
// src/
|
|
1072
|
+
// src/errors.ts
|
|
1073
|
+
var ERROR_DEFINITIONS = {
|
|
1074
|
+
QUIZ_NOT_FOUND: {
|
|
1075
|
+
code: "QUIZ_NOT_FOUND",
|
|
1076
|
+
userMessage: "We couldn't find this quiz",
|
|
1077
|
+
subMessage: "The quiz may have been removed or the link is incorrect.",
|
|
1078
|
+
cause: "The quiz ID does not exist in the database, or the quiz has been deleted.",
|
|
1079
|
+
isBlocking: true
|
|
1080
|
+
},
|
|
1081
|
+
ATTEMPT_NOT_FOUND: {
|
|
1082
|
+
code: "ATTEMPT_NOT_FOUND",
|
|
1083
|
+
userMessage: "We couldn't find this quiz attempt",
|
|
1084
|
+
subMessage: "The attempt may have expired or the link is incorrect.",
|
|
1085
|
+
cause: "The attempt ID does not exist, or the attempt has been deleted/archived.",
|
|
1086
|
+
isBlocking: true
|
|
1087
|
+
},
|
|
1088
|
+
QUIZ_EXPIRED: {
|
|
1089
|
+
code: "QUIZ_EXPIRED",
|
|
1090
|
+
userMessage: "This quiz has expired",
|
|
1091
|
+
subMessage: "The deadline for this quiz has passed.",
|
|
1092
|
+
cause: "The quiz end date/time has passed and submissions are no longer accepted.",
|
|
1093
|
+
isBlocking: true
|
|
1094
|
+
},
|
|
1095
|
+
QUIZ_NOT_STARTED: {
|
|
1096
|
+
code: "QUIZ_NOT_STARTED",
|
|
1097
|
+
userMessage: "This quiz is not available yet",
|
|
1098
|
+
subMessage: "Please check back when the quiz opens.",
|
|
1099
|
+
cause: "The quiz start date/time has not yet been reached.",
|
|
1100
|
+
isBlocking: true
|
|
1101
|
+
},
|
|
1102
|
+
NETWORK_ERROR: {
|
|
1103
|
+
code: "NETWORK_ERROR",
|
|
1104
|
+
userMessage: "Connection problem",
|
|
1105
|
+
subMessage: "Please check your internet connection and try again.",
|
|
1106
|
+
cause: "Unable to reach the server due to network connectivity issues.",
|
|
1107
|
+
isBlocking: true
|
|
1108
|
+
},
|
|
1109
|
+
SERVER_ERROR: {
|
|
1110
|
+
code: "SERVER_ERROR",
|
|
1111
|
+
userMessage: "Something went wrong on our end",
|
|
1112
|
+
subMessage: "Our team has been notified. Please try again later.",
|
|
1113
|
+
cause: "The server encountered an internal error (HTTP 500+).",
|
|
1114
|
+
isBlocking: true
|
|
1115
|
+
},
|
|
1116
|
+
UNAUTHORIZED: {
|
|
1117
|
+
code: "UNAUTHORIZED",
|
|
1118
|
+
userMessage: "Please sign in to continue",
|
|
1119
|
+
subMessage: "You need to be logged in to access this quiz.",
|
|
1120
|
+
cause: "The user is not authenticated (HTTP 401).",
|
|
1121
|
+
isBlocking: true
|
|
1122
|
+
},
|
|
1123
|
+
FORBIDDEN: {
|
|
1124
|
+
code: "FORBIDDEN",
|
|
1125
|
+
userMessage: "You don't have access to this quiz",
|
|
1126
|
+
subMessage: "Contact your instructor if you believe this is a mistake.",
|
|
1127
|
+
cause: "The user does not have permission to access this resource (HTTP 403).",
|
|
1128
|
+
isBlocking: true
|
|
1129
|
+
},
|
|
1130
|
+
TTS_FAILED: {
|
|
1131
|
+
code: "TTS_FAILED",
|
|
1132
|
+
userMessage: "Text-to-speech unavailable",
|
|
1133
|
+
subMessage: "Audio features are temporarily unavailable.",
|
|
1134
|
+
cause: "The text-to-speech service failed or is unreachable.",
|
|
1135
|
+
isBlocking: false
|
|
1136
|
+
},
|
|
1137
|
+
CHAT_FAILED: {
|
|
1138
|
+
code: "CHAT_FAILED",
|
|
1139
|
+
userMessage: "Chat assistance unavailable",
|
|
1140
|
+
subMessage: "The AI helper is temporarily unavailable.",
|
|
1141
|
+
cause: "The chat/AI service failed to initialize or respond.",
|
|
1142
|
+
isBlocking: false
|
|
1143
|
+
},
|
|
1144
|
+
SUBMISSION_FAILED: {
|
|
1145
|
+
code: "SUBMISSION_FAILED",
|
|
1146
|
+
userMessage: "Failed to submit your answer",
|
|
1147
|
+
subMessage: "Please try again. Your progress has been saved.",
|
|
1148
|
+
cause: "The answer submission request failed due to network or server issues.",
|
|
1149
|
+
isBlocking: false
|
|
1150
|
+
},
|
|
1151
|
+
UNKNOWN_ERROR: {
|
|
1152
|
+
code: "UNKNOWN_ERROR",
|
|
1153
|
+
userMessage: "Something unexpected happened",
|
|
1154
|
+
subMessage: "Please try refreshing the page.",
|
|
1155
|
+
cause: "An unclassified error occurred.",
|
|
1156
|
+
isBlocking: true
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
function getErrorFromHttpStatus(status, context) {
|
|
1160
|
+
switch (status) {
|
|
1161
|
+
case 401:
|
|
1162
|
+
return "UNAUTHORIZED";
|
|
1163
|
+
case 403:
|
|
1164
|
+
return "FORBIDDEN";
|
|
1165
|
+
case 404:
|
|
1166
|
+
return context === "attempt" ? "ATTEMPT_NOT_FOUND" : "QUIZ_NOT_FOUND";
|
|
1167
|
+
case 410:
|
|
1168
|
+
return "QUIZ_EXPIRED";
|
|
1169
|
+
case 500:
|
|
1170
|
+
case 502:
|
|
1171
|
+
case 503:
|
|
1172
|
+
case 504:
|
|
1173
|
+
return "SERVER_ERROR";
|
|
1174
|
+
default:
|
|
1175
|
+
if (status >= 400 && status < 500) {
|
|
1176
|
+
return context === "attempt" ? "ATTEMPT_NOT_FOUND" : "QUIZ_NOT_FOUND";
|
|
1177
|
+
}
|
|
1178
|
+
return "UNKNOWN_ERROR";
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function getErrorFromMessage(message, context) {
|
|
1182
|
+
const lowerMessage = message.toLowerCase();
|
|
1183
|
+
if (lowerMessage.includes("network") || lowerMessage.includes("fetch") || lowerMessage.includes("connection")) {
|
|
1184
|
+
return "NETWORK_ERROR";
|
|
1185
|
+
}
|
|
1186
|
+
if (lowerMessage.includes("not found") || lowerMessage.includes("404")) {
|
|
1187
|
+
return context === "attempt" ? "ATTEMPT_NOT_FOUND" : "QUIZ_NOT_FOUND";
|
|
1188
|
+
}
|
|
1189
|
+
if (lowerMessage.includes("unauthorized") || lowerMessage.includes("401")) {
|
|
1190
|
+
return "UNAUTHORIZED";
|
|
1191
|
+
}
|
|
1192
|
+
if (lowerMessage.includes("forbidden") || lowerMessage.includes("403")) {
|
|
1193
|
+
return "FORBIDDEN";
|
|
1194
|
+
}
|
|
1195
|
+
if (lowerMessage.includes("expired")) {
|
|
1196
|
+
return "QUIZ_EXPIRED";
|
|
1197
|
+
}
|
|
1198
|
+
if (lowerMessage.includes("tts") || lowerMessage.includes("speech")) {
|
|
1199
|
+
return "TTS_FAILED";
|
|
1200
|
+
}
|
|
1201
|
+
if (lowerMessage.includes("chat")) {
|
|
1202
|
+
return "CHAT_FAILED";
|
|
1203
|
+
}
|
|
1204
|
+
return "UNKNOWN_ERROR";
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
// src/MaintenanceScreen.tsx
|
|
1060
1208
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1209
|
+
function MaintenanceScreen({ errorCode }) {
|
|
1210
|
+
const errorDef = errorCode ? ERROR_DEFINITIONS[errorCode] : null;
|
|
1211
|
+
const message = errorDef?.userMessage || "Your quiz is on its way...";
|
|
1212
|
+
const subMessage = errorDef?.subMessage || "Please check back soon!";
|
|
1213
|
+
const containerStyle = {
|
|
1214
|
+
display: "flex",
|
|
1215
|
+
flexDirection: "column",
|
|
1216
|
+
alignItems: "center",
|
|
1217
|
+
justifyContent: "center",
|
|
1218
|
+
minHeight: "300px",
|
|
1219
|
+
padding: "40px",
|
|
1220
|
+
background: "linear-gradient(135deg, #f8f7ff 0%, #e8e4f8 50%, #f0ebff 100%)",
|
|
1221
|
+
borderRadius: "16px"
|
|
1222
|
+
};
|
|
1223
|
+
const iconStyle = {
|
|
1224
|
+
fontSize: "48px",
|
|
1225
|
+
marginBottom: "24px",
|
|
1226
|
+
color: "#8b5cf6"
|
|
1227
|
+
};
|
|
1228
|
+
const messageStyle = {
|
|
1229
|
+
fontSize: "20px",
|
|
1230
|
+
fontWeight: "600",
|
|
1231
|
+
color: "#4c1d95",
|
|
1232
|
+
textAlign: "center",
|
|
1233
|
+
marginBottom: "12px"
|
|
1234
|
+
};
|
|
1235
|
+
const submessageStyle = {
|
|
1236
|
+
fontSize: "14px",
|
|
1237
|
+
color: "#7c3aed",
|
|
1238
|
+
textAlign: "center",
|
|
1239
|
+
opacity: 0.8
|
|
1240
|
+
};
|
|
1241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: containerStyle, "data-testid": "maintenance-screen", "data-error-code": errorCode || "none", children: [
|
|
1242
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: iconStyle, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1243
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 8v4" }),
|
|
1245
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 16h.01" })
|
|
1246
|
+
] }) }),
|
|
1247
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: messageStyle, "data-testid": "text-error-message", children: message }),
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: submessageStyle, "data-testid": "text-error-submessage", children: subMessage })
|
|
1249
|
+
] });
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// src/assets/astronautData.ts
|
|
1253
|
+
var astronautImage = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAB4AAAAQ4CAMAAADfDTFxAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAwBQTFRFYGBgsVEZcHBwq6urhYSEkZGRiomJuJsBMxoHJCAhUFBQQEBAXZu4ATtbnp6ev7+/dDURJnqMdnR1enl5ABoqAm2rVSYMamhpLCkqKCUlz8/PMS0uWksA39/fbmxtAViJEBAQAAAAzunzMDAwPDo6qKioj46OgICAoqKiOC8AOTU2oKCgaq3LNDExibbNQD4+mpqaV1RVRUJCZmRlpqampKSkSEVGlpaWUE5OTElKnJycIm5+mJiYXlxdf35+lJSUXFlaU1FSZGFiWFZWAV+UBGaebtLoWlhZqMjWTMjiS0hJc3FyAUlyidvtbGpraGZmb25ujYyMYF5ed3Z2F0lUFw4CAVB+////AUJnLCgpecXVKXyqfHp75eXlT0xN1dXVNzQ1hai8ksXZPzw9qNLlTn6UsOfywMDAICAgASxFwNzsEz1GgH5/R0RFJ1ZwOjc4JiIjNjM0KicoRmt4tra2HhscMi8vXVtbACU5CwsLLisreJ+xKUhWBHS0gYCBOzg5fnx9YmBghIOD/NQBITlHgH9/PMPgWVdYJyQlMCwtESYyIx8gTUtLgoGBPV5qSUdH8m4jg4KCVVNTAA8XfHt7DwcCAAcLAHW4FRQV7+/vr6+vBAwOOLfSDzE4LZKoHmJwRkNEQj9APjs8CyUqCBgcMZ62i4qLj4+P42chfXx8aWdoDw4OUk9QZWNjNavExVkcAGahGlViKYaal0UWjo2NbWtsiYiI1GAfh4aH7McBfmoBl5eXlZWVk5KSn5+fdHNzpaWlnZ2dfn19cW9viD4UkI+Qjo2OeHd33boBnoUBATNQzawBjncBbl0AnuHw7/b63+/3EBcbFH256urqEkpq+vr6mZmZElJ1GhgYU1xeo6OjGG6fm5ubEh4jRVdejIuM9fX1lpWWnp2elJOTICcrnJuboaGhornEE3WtQU5Wv9HaJzg8h5icQZSmz9jeeo+XY2xucHd7EjtTkJ2iBwYGfYqNGV+HMTtAQoWr8/v9v8bIw8vNIi0yZHyHFygs////mvWEFwAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAMcVSURBVHja7L3viyRnuf9f9CRCuhgLtAeTlj5TRcdTwSUkRo+bBDXG2SDoMIkubI/g8Sz4wBow5AdnzczAJsfAYGRXgo7MTPWjGA5pNAr7QEXQVNSQE9hnIsoiHvacj99z/oJ9dJ747brv+v2ju7q7qqa79/V6oMlmd3709vSrr+u+rvet/B0AAABqR+EhAAAAQMAAAAAIGAAAABAwAAAAAgYAAAAEDAAAgIABAAAAAQMAACBgAAAAQMAAAAAIGAAAAAEDAAAAAgaA6dE0zTkQKOqQhvzn4a92eGwAEDAAlE1bOzhQVd0YSVdVDhxMDICAAaCMktc5UC1jItTmQR8NAyBgAJjWvQOla0yLrjawMAACBoDJsPsNNb/CFTTNIfIfcytkqzlo82ACIGAAKFb5NjIKX0tVzIGmdXo5aFrf9XFGKdwcUAkDIGAAGE3HaaYKXsXU2r3CaI6ZKomtRp+HFgABA0CefQeJ0lc1+xOoN6bh5Pmxrjg2jzAAAgaAMfa1lMGU7g2wNTPekm46PMwACBgAIthON3Zs63R6JaGZsY+saDzYAAgYACR9JRqnYbZ75WL3lUiEh3XATBYAAgaAv9sHVrRJ3OlVQrsR/SyMZAEgYIDbHE2J2tfuVUjUwdYBE1kACBjg9sUJh6S6g06vcrSwF60rdKIBEDDAbYntWKEN272aiDi/yUAWAAIGuP30exAUo12nVyedRvCZVRQMgIABblf91lf8RsrgLgoGQMAAtyGBfnXT7p0KWhMFAyBggNuM4OzXck5Jv6ITHcxfNxnHAkDAAMuPFuq3d7qEClZYSgJAwADLTUedF/3GFKwf8FcDgIABlhf7YJ70G1OwxVEwAAIGWFb61imPXmUqWOUoGAABAywzgekac6RfMRHtLSXpA/6S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";
|
|
1254
|
+
|
|
1255
|
+
// src/QuizPlayer.tsx
|
|
1256
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1061
1257
|
var defaultStyles = {
|
|
1062
1258
|
container: {
|
|
1063
1259
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -1126,7 +1322,9 @@ var defaultStyles = {
|
|
|
1126
1322
|
option: {
|
|
1127
1323
|
width: "100%",
|
|
1128
1324
|
padding: "12px 16px",
|
|
1129
|
-
|
|
1325
|
+
borderWidth: "2px",
|
|
1326
|
+
borderStyle: "solid",
|
|
1327
|
+
borderColor: "#e5e7eb",
|
|
1130
1328
|
borderRadius: "8px",
|
|
1131
1329
|
cursor: "pointer",
|
|
1132
1330
|
transition: "all 0.2s ease",
|
|
@@ -1420,7 +1618,7 @@ function SortingDragDrop({ items, currentOrder, correctOrder, showFeedback, onOr
|
|
|
1420
1618
|
setDraggedIndex(null);
|
|
1421
1619
|
setDragOverIndex(null);
|
|
1422
1620
|
};
|
|
1423
|
-
return /* @__PURE__ */ (0,
|
|
1621
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.options, children: currentOrder.map((itemIndex, position) => {
|
|
1424
1622
|
const isCorrectPosition = correctOrder?.[position] === itemIndex;
|
|
1425
1623
|
const isDragging = draggedIndex === position;
|
|
1426
1624
|
const isDragOver = dragOverIndex === position;
|
|
@@ -1443,7 +1641,7 @@ function SortingDragDrop({ items, currentOrder, correctOrder, showFeedback, onOr
|
|
|
1443
1641
|
} else if (isDragOver) {
|
|
1444
1642
|
itemStyle = { ...itemStyle, borderColor: "#6366f1", backgroundColor: "#eef2ff" };
|
|
1445
1643
|
}
|
|
1446
|
-
return /* @__PURE__ */ (0,
|
|
1644
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1447
1645
|
"div",
|
|
1448
1646
|
{
|
|
1449
1647
|
style: itemStyle,
|
|
@@ -1455,34 +1653,34 @@ function SortingDragDrop({ items, currentOrder, correctOrder, showFeedback, onOr
|
|
|
1455
1653
|
onDrop: (e) => handleDrop(e, position),
|
|
1456
1654
|
onDragEnd: handleDragEnd,
|
|
1457
1655
|
children: [
|
|
1458
|
-
!showFeedback && /* @__PURE__ */ (0,
|
|
1656
|
+
!showFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
1459
1657
|
cursor: "grab",
|
|
1460
1658
|
padding: "4px",
|
|
1461
1659
|
display: "flex",
|
|
1462
1660
|
alignItems: "center",
|
|
1463
1661
|
color: "#9ca3af"
|
|
1464
|
-
}, children: /* @__PURE__ */ (0,
|
|
1465
|
-
/* @__PURE__ */ (0,
|
|
1466
|
-
/* @__PURE__ */ (0,
|
|
1467
|
-
/* @__PURE__ */ (0,
|
|
1468
|
-
/* @__PURE__ */ (0,
|
|
1469
|
-
/* @__PURE__ */ (0,
|
|
1470
|
-
/* @__PURE__ */ (0,
|
|
1662
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "5", r: "1" }),
|
|
1664
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "12", r: "1" }),
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "19", r: "1" }),
|
|
1666
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "5", r: "1" }),
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "12", r: "1" }),
|
|
1668
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "19", r: "1" })
|
|
1471
1669
|
] }) }),
|
|
1472
|
-
showFeedback && /* @__PURE__ */ (0,
|
|
1670
|
+
showFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
1473
1671
|
display: "flex",
|
|
1474
1672
|
alignItems: "center",
|
|
1475
1673
|
color: isCorrectPosition ? "#22c55e" : "#ef4444"
|
|
1476
|
-
}, children: isCorrectPosition ? /* @__PURE__ */ (0,
|
|
1477
|
-
/* @__PURE__ */ (0,
|
|
1478
|
-
/* @__PURE__ */ (0,
|
|
1479
|
-
] }) : /* @__PURE__ */ (0,
|
|
1480
|
-
/* @__PURE__ */ (0,
|
|
1481
|
-
/* @__PURE__ */ (0,
|
|
1482
|
-
/* @__PURE__ */ (0,
|
|
1674
|
+
}, children: isCorrectPosition ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "22 4 12 14.01 9 11.01" })
|
|
1677
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1678
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1679
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "15", y1: "9", x2: "9", y2: "15" }),
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "9", y1: "9", x2: "15", y2: "15" })
|
|
1483
1681
|
] }) }),
|
|
1484
|
-
/* @__PURE__ */ (0,
|
|
1485
|
-
/* @__PURE__ */ (0,
|
|
1682
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: items[itemIndex] }),
|
|
1683
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextToSpeech, { text: items[itemIndex], size: "sm" }) })
|
|
1486
1684
|
]
|
|
1487
1685
|
},
|
|
1488
1686
|
itemIndex
|
|
@@ -1536,9 +1734,9 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1536
1734
|
delete newMatches[leftItem];
|
|
1537
1735
|
onMatchChange(newMatches);
|
|
1538
1736
|
};
|
|
1539
|
-
return /* @__PURE__ */ (0,
|
|
1540
|
-
/* @__PURE__ */ (0,
|
|
1541
|
-
/* @__PURE__ */ (0,
|
|
1737
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "24px", flexWrap: "wrap" }, children: [
|
|
1738
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { flex: 1, minWidth: "200px", display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
1739
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "14px", fontWeight: "600", color: "#6b7280", marginBottom: "4px" }, children: "Match these items:" }),
|
|
1542
1740
|
leftItems.map((leftItem, idx) => {
|
|
1543
1741
|
const matchedRight = currentMatches[leftItem];
|
|
1544
1742
|
const correctMatch = correctMatches?.[leftItem];
|
|
@@ -1549,7 +1747,9 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1549
1747
|
alignItems: "center",
|
|
1550
1748
|
gap: "12px",
|
|
1551
1749
|
padding: "12px 16px",
|
|
1552
|
-
|
|
1750
|
+
borderWidth: "2px",
|
|
1751
|
+
borderStyle: "dashed",
|
|
1752
|
+
borderColor: "#e5e7eb",
|
|
1553
1753
|
borderRadius: "8px",
|
|
1554
1754
|
backgroundColor: "#ffffff",
|
|
1555
1755
|
minHeight: "56px",
|
|
@@ -1567,7 +1767,7 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1567
1767
|
} else if (matchedRight) {
|
|
1568
1768
|
rowStyle = { ...rowStyle, borderStyle: "solid", borderColor: "#22c55e" };
|
|
1569
1769
|
}
|
|
1570
|
-
return /* @__PURE__ */ (0,
|
|
1770
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1571
1771
|
"div",
|
|
1572
1772
|
{
|
|
1573
1773
|
style: rowStyle,
|
|
@@ -1576,9 +1776,9 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1576
1776
|
onDragLeave: handleDragLeave,
|
|
1577
1777
|
onDrop: (e) => handleDrop(e, leftItem),
|
|
1578
1778
|
children: [
|
|
1579
|
-
/* @__PURE__ */ (0,
|
|
1580
|
-
/* @__PURE__ */ (0,
|
|
1581
|
-
matchedRight ? /* @__PURE__ */ (0,
|
|
1779
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1, fontWeight: "500" }, children: leftItem }),
|
|
1780
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { color: "#6b7280" }, children: "\u2192" }),
|
|
1781
|
+
matchedRight ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
|
|
1582
1782
|
display: "flex",
|
|
1583
1783
|
alignItems: "center",
|
|
1584
1784
|
gap: "8px",
|
|
@@ -1587,8 +1787,8 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1587
1787
|
borderRadius: "6px",
|
|
1588
1788
|
fontSize: "14px"
|
|
1589
1789
|
}, children: [
|
|
1590
|
-
/* @__PURE__ */ (0,
|
|
1591
|
-
!showFeedback && /* @__PURE__ */ (0,
|
|
1790
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: matchedRight }),
|
|
1791
|
+
!showFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1592
1792
|
"button",
|
|
1593
1793
|
{
|
|
1594
1794
|
onClick: () => handleClearMatch(leftItem),
|
|
@@ -1601,18 +1801,18 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1601
1801
|
color: "#6b7280"
|
|
1602
1802
|
},
|
|
1603
1803
|
"aria-label": "Remove match",
|
|
1604
|
-
children: /* @__PURE__ */ (0,
|
|
1605
|
-
/* @__PURE__ */ (0,
|
|
1606
|
-
/* @__PURE__ */ (0,
|
|
1804
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1805
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1607
1807
|
] })
|
|
1608
1808
|
}
|
|
1609
1809
|
),
|
|
1610
|
-
showFeedback && (isCorrect ? /* @__PURE__ */ (0,
|
|
1611
|
-
/* @__PURE__ */ (0,
|
|
1612
|
-
/* @__PURE__ */ (0,
|
|
1810
|
+
showFeedback && (isCorrect ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#22c55e", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "#ef4444", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1811
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
1812
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
1613
1813
|
] }))
|
|
1614
|
-
] }) : /* @__PURE__ */ (0,
|
|
1615
|
-
showFeedback && !isCorrect && correctMatch && /* @__PURE__ */ (0,
|
|
1814
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { color: "#9ca3af", fontSize: "14px", fontStyle: "italic" }, children: "Drop here" }),
|
|
1815
|
+
showFeedback && !isCorrect && correctMatch && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { style: { color: "#166534", fontSize: "13px", marginLeft: "8px" }, children: [
|
|
1616
1816
|
"(Correct: ",
|
|
1617
1817
|
correctMatch,
|
|
1618
1818
|
")"
|
|
@@ -1623,16 +1823,18 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1623
1823
|
);
|
|
1624
1824
|
})
|
|
1625
1825
|
] }),
|
|
1626
|
-
/* @__PURE__ */ (0,
|
|
1627
|
-
/* @__PURE__ */ (0,
|
|
1826
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { flex: 1, minWidth: "200px", display: "flex", flexDirection: "column", gap: "8px" }, children: [
|
|
1827
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { fontSize: "14px", fontWeight: "600", color: "#6b7280", marginBottom: "4px" }, children: "Drag to match:" }),
|
|
1628
1828
|
unmatchedRightItems.length > 0 ? unmatchedRightItems.map((rightItem, idx) => {
|
|
1629
1829
|
const isDragging = draggedItem === rightItem;
|
|
1630
|
-
return /* @__PURE__ */ (0,
|
|
1830
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
1631
1831
|
"div",
|
|
1632
1832
|
{
|
|
1633
1833
|
style: {
|
|
1634
1834
|
padding: "12px 16px",
|
|
1635
|
-
|
|
1835
|
+
borderWidth: "2px",
|
|
1836
|
+
borderStyle: "solid",
|
|
1837
|
+
borderColor: "#e5e7eb",
|
|
1636
1838
|
borderRadius: "8px",
|
|
1637
1839
|
backgroundColor: "#ffffff",
|
|
1638
1840
|
cursor: showFeedback ? "default" : "grab",
|
|
@@ -1647,20 +1849,20 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1647
1849
|
onDragEnd: handleDragEnd,
|
|
1648
1850
|
"data-testid": `draggable-right-${idx}`,
|
|
1649
1851
|
children: [
|
|
1650
|
-
!showFeedback && /* @__PURE__ */ (0,
|
|
1651
|
-
/* @__PURE__ */ (0,
|
|
1652
|
-
/* @__PURE__ */ (0,
|
|
1653
|
-
/* @__PURE__ */ (0,
|
|
1654
|
-
/* @__PURE__ */ (0,
|
|
1655
|
-
/* @__PURE__ */ (0,
|
|
1656
|
-
/* @__PURE__ */ (0,
|
|
1852
|
+
!showFeedback && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { color: "#9ca3af", display: "flex" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "5", r: "1" }),
|
|
1854
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "12", r: "1" }),
|
|
1855
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "9", cy: "19", r: "1" }),
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "5", r: "1" }),
|
|
1857
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "12", r: "1" }),
|
|
1858
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("circle", { cx: "15", cy: "19", r: "1" })
|
|
1657
1859
|
] }) }),
|
|
1658
|
-
/* @__PURE__ */ (0,
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: rightItem })
|
|
1659
1861
|
]
|
|
1660
1862
|
},
|
|
1661
1863
|
idx
|
|
1662
1864
|
);
|
|
1663
|
-
}) : /* @__PURE__ */ (0,
|
|
1865
|
+
}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
1664
1866
|
padding: "16px",
|
|
1665
1867
|
textAlign: "center",
|
|
1666
1868
|
color: "#22c55e",
|
|
@@ -1670,7 +1872,7 @@ function MatchingDragDrop({ leftItems, rightItems, currentMatches, correctMatche
|
|
|
1670
1872
|
] });
|
|
1671
1873
|
}
|
|
1672
1874
|
function Spinner({ size = 16, color = "#ffffff" }) {
|
|
1673
|
-
return /* @__PURE__ */ (0,
|
|
1875
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1674
1876
|
"span",
|
|
1675
1877
|
{
|
|
1676
1878
|
style: {
|
|
@@ -1682,7 +1884,7 @@ function Spinner({ size = 16, color = "#ffffff" }) {
|
|
|
1682
1884
|
borderRadius: "50%",
|
|
1683
1885
|
animation: "spin 0.8s linear infinite"
|
|
1684
1886
|
},
|
|
1685
|
-
children: /* @__PURE__ */ (0,
|
|
1887
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `@keyframes spin { to { transform: rotate(360deg); } }` })
|
|
1686
1888
|
}
|
|
1687
1889
|
);
|
|
1688
1890
|
}
|
|
@@ -1700,7 +1902,8 @@ function QuizPlayer({
|
|
|
1700
1902
|
onProgress,
|
|
1701
1903
|
onGenerateMoreQuestions,
|
|
1702
1904
|
className,
|
|
1703
|
-
forceNewAttempt = true
|
|
1905
|
+
forceNewAttempt = true,
|
|
1906
|
+
hideScore = false
|
|
1704
1907
|
}) {
|
|
1705
1908
|
const [quiz, setQuiz] = (0, import_react3.useState)(null);
|
|
1706
1909
|
const [attempt, setAttempt] = (0, import_react3.useState)(null);
|
|
@@ -1711,10 +1914,14 @@ function QuizPlayer({
|
|
|
1711
1914
|
const [isNavigating, setIsNavigating] = (0, import_react3.useState)(false);
|
|
1712
1915
|
const [isCompleted, setIsCompleted] = (0, import_react3.useState)(false);
|
|
1713
1916
|
const [result, setResult] = (0, import_react3.useState)(null);
|
|
1714
|
-
const [
|
|
1917
|
+
const [errorCode, setErrorCode] = (0, import_react3.useState)(null);
|
|
1715
1918
|
const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
|
|
1716
1919
|
const [elapsedSeconds, setElapsedSeconds] = (0, import_react3.useState)(0);
|
|
1717
1920
|
const [showIntro, setShowIntro] = (0, import_react3.useState)(true);
|
|
1921
|
+
const [showResumeChoice, setShowResumeChoice] = (0, import_react3.useState)(false);
|
|
1922
|
+
const [hasExistingProgress, setHasExistingProgress] = (0, import_react3.useState)(false);
|
|
1923
|
+
const [existingProgressCount, setExistingProgressCount] = (0, import_react3.useState)(0);
|
|
1924
|
+
const [isStartingFresh, setIsStartingFresh] = (0, import_react3.useState)(false);
|
|
1718
1925
|
const [timerStarted, setTimerStarted] = (0, import_react3.useState)(false);
|
|
1719
1926
|
const [showFeedback, setShowFeedback] = (0, import_react3.useState)(false);
|
|
1720
1927
|
const [currentAnswerDetail, setCurrentAnswerDetail] = (0, import_react3.useState)(null);
|
|
@@ -1728,6 +1935,7 @@ function QuizPlayer({
|
|
|
1728
1935
|
const [showReportModal, setShowReportModal] = (0, import_react3.useState)(false);
|
|
1729
1936
|
const [isReporting, setIsReporting] = (0, import_react3.useState)(false);
|
|
1730
1937
|
const [reportComment, setReportComment] = (0, import_react3.useState)("");
|
|
1938
|
+
const [retryKey, setRetryKey] = (0, import_react3.useState)(0);
|
|
1731
1939
|
const apiClient = (0, import_react3.useRef)(null);
|
|
1732
1940
|
const timerRef = (0, import_react3.useRef)(null);
|
|
1733
1941
|
const startTimeRef = (0, import_react3.useRef)(0);
|
|
@@ -1749,7 +1957,7 @@ function QuizPlayer({
|
|
|
1749
1957
|
if (!apiClient.current) return;
|
|
1750
1958
|
try {
|
|
1751
1959
|
setIsLoading(true);
|
|
1752
|
-
|
|
1960
|
+
setErrorCode(null);
|
|
1753
1961
|
const quizData = await apiClient.current.getQuiz(quizId);
|
|
1754
1962
|
setQuiz(quizData);
|
|
1755
1963
|
const attemptData = await apiClient.current.createAttempt({
|
|
@@ -1762,7 +1970,10 @@ function QuizPlayer({
|
|
|
1762
1970
|
forceNew: forceNewAttempt
|
|
1763
1971
|
});
|
|
1764
1972
|
setAttempt(attemptData);
|
|
1765
|
-
if (!forceNewAttempt && attemptData.answers && attemptData.answers.length > 0) {
|
|
1973
|
+
if (!forceNewAttempt && attemptData.answers && attemptData.answers.length > 0 && attemptData.status === "in_progress") {
|
|
1974
|
+
setHasExistingProgress(true);
|
|
1975
|
+
setExistingProgressCount(attemptData.answers.length);
|
|
1976
|
+
setShowResumeChoice(true);
|
|
1766
1977
|
setAnswersDetail(attemptData.answers);
|
|
1767
1978
|
const answersMap = /* @__PURE__ */ new Map();
|
|
1768
1979
|
attemptData.answers.forEach((a) => {
|
|
@@ -1785,15 +1996,23 @@ function QuizPlayer({
|
|
|
1785
1996
|
setIsLoading(false);
|
|
1786
1997
|
} catch (err) {
|
|
1787
1998
|
const message = err instanceof Error ? err.message : "Failed to load quiz";
|
|
1788
|
-
|
|
1999
|
+
const code = getErrorFromMessage(message, "quiz");
|
|
2000
|
+
setErrorCode(code);
|
|
2001
|
+
apiClient.current?.logError({
|
|
2002
|
+
errorCode: code,
|
|
2003
|
+
context: "quiz",
|
|
2004
|
+
resourceId: quizId,
|
|
2005
|
+
component: "QuizPlayer",
|
|
2006
|
+
message
|
|
2007
|
+
});
|
|
1789
2008
|
setIsLoading(false);
|
|
1790
2009
|
onErrorRef.current?.(err instanceof Error ? err : new Error(message));
|
|
1791
2010
|
}
|
|
1792
2011
|
}
|
|
1793
2012
|
initialize();
|
|
1794
|
-
}, [quizId, lessonId, assignLessonId, courseId, childId, parentId, forceNewAttempt]);
|
|
2013
|
+
}, [quizId, lessonId, assignLessonId, courseId, childId, parentId, forceNewAttempt, retryKey]);
|
|
1795
2014
|
(0, import_react3.useEffect)(() => {
|
|
1796
|
-
if (timerStarted && !isCompleted && !
|
|
2015
|
+
if (timerStarted && !isCompleted && !errorCode) {
|
|
1797
2016
|
startTimeRef.current = Date.now();
|
|
1798
2017
|
timerRef.current = setInterval(() => {
|
|
1799
2018
|
setElapsedSeconds(Math.floor((Date.now() - startTimeRef.current) / 1e3));
|
|
@@ -1804,11 +2023,62 @@ function QuizPlayer({
|
|
|
1804
2023
|
clearInterval(timerRef.current);
|
|
1805
2024
|
}
|
|
1806
2025
|
};
|
|
1807
|
-
}, [timerStarted, isCompleted,
|
|
2026
|
+
}, [timerStarted, isCompleted, errorCode]);
|
|
1808
2027
|
const handleStart = (0, import_react3.useCallback)(() => {
|
|
1809
2028
|
setShowIntro(false);
|
|
2029
|
+
setShowResumeChoice(false);
|
|
1810
2030
|
setTimerStarted(true);
|
|
1811
2031
|
}, []);
|
|
2032
|
+
const handleResumePrevious = (0, import_react3.useCallback)(() => {
|
|
2033
|
+
if (quiz && answers.size > 0) {
|
|
2034
|
+
const answeredIds = new Set(answers.keys());
|
|
2035
|
+
const allQs = [...quiz.questions, ...extraQuestions].filter((q) => !skippedQuestionIds.has(q.id));
|
|
2036
|
+
let resumeIndex = 0;
|
|
2037
|
+
for (let i = 0; i < allQs.length; i++) {
|
|
2038
|
+
if (!answeredIds.has(allQs[i].id)) {
|
|
2039
|
+
resumeIndex = i;
|
|
2040
|
+
break;
|
|
2041
|
+
}
|
|
2042
|
+
resumeIndex = allQs.length - 1;
|
|
2043
|
+
}
|
|
2044
|
+
setCurrentQuestionIndex(resumeIndex);
|
|
2045
|
+
}
|
|
2046
|
+
setShowIntro(false);
|
|
2047
|
+
setShowResumeChoice(false);
|
|
2048
|
+
setTimerStarted(true);
|
|
2049
|
+
}, [quiz, answers, extraQuestions, skippedQuestionIds]);
|
|
2050
|
+
const handleStartFresh = (0, import_react3.useCallback)(async () => {
|
|
2051
|
+
if (!apiClient.current || !attempt) return;
|
|
2052
|
+
setIsStartingFresh(true);
|
|
2053
|
+
try {
|
|
2054
|
+
await apiClient.current.updateAttempt(attempt.id, {
|
|
2055
|
+
status: "abandoned"
|
|
2056
|
+
});
|
|
2057
|
+
const newAttemptData = await apiClient.current.createAttempt({
|
|
2058
|
+
quizId,
|
|
2059
|
+
lessonId,
|
|
2060
|
+
assignLessonId,
|
|
2061
|
+
courseId,
|
|
2062
|
+
childId,
|
|
2063
|
+
parentId,
|
|
2064
|
+
forceNew: true
|
|
2065
|
+
});
|
|
2066
|
+
setAttempt(newAttemptData);
|
|
2067
|
+
setAnswers(/* @__PURE__ */ new Map());
|
|
2068
|
+
setAnswersDetail([]);
|
|
2069
|
+
setCurrentQuestionIndex(0);
|
|
2070
|
+
setHasExistingProgress(false);
|
|
2071
|
+
setExistingProgressCount(0);
|
|
2072
|
+
setShowResumeChoice(false);
|
|
2073
|
+
setShowIntro(false);
|
|
2074
|
+
setTimerStarted(true);
|
|
2075
|
+
} catch (err) {
|
|
2076
|
+
const message = err instanceof Error ? err.message : "Failed to start fresh";
|
|
2077
|
+
onErrorRef.current?.(new Error(message));
|
|
2078
|
+
} finally {
|
|
2079
|
+
setIsStartingFresh(false);
|
|
2080
|
+
}
|
|
2081
|
+
}, [attempt, quizId, lessonId, assignLessonId, courseId, childId, parentId]);
|
|
1812
2082
|
(0, import_react3.useEffect)(() => {
|
|
1813
2083
|
setShowFeedback(false);
|
|
1814
2084
|
setCurrentAnswerDetail(null);
|
|
@@ -1928,7 +2198,15 @@ function QuizPlayer({
|
|
|
1928
2198
|
onCompleteRef.current?.(quizResult);
|
|
1929
2199
|
} catch (err) {
|
|
1930
2200
|
const message = err instanceof Error ? err.message : "Failed to submit quiz";
|
|
1931
|
-
|
|
2201
|
+
const code = getErrorFromMessage(message, "quiz");
|
|
2202
|
+
setErrorCode(code);
|
|
2203
|
+
apiClient.current?.logError({
|
|
2204
|
+
errorCode: code,
|
|
2205
|
+
context: "quiz",
|
|
2206
|
+
resourceId: quizId,
|
|
2207
|
+
component: "QuizPlayer",
|
|
2208
|
+
message
|
|
2209
|
+
});
|
|
1932
2210
|
onErrorRef.current?.(err instanceof Error ? err : new Error(message));
|
|
1933
2211
|
} finally {
|
|
1934
2212
|
setIsSubmitting(false);
|
|
@@ -2006,14 +2284,43 @@ function QuizPlayer({
|
|
|
2006
2284
|
setIsReporting(false);
|
|
2007
2285
|
}
|
|
2008
2286
|
}, [currentQuestion, apiClient, attempt, quiz, childId, parentId, lessonId, courseId, assignLessonId]);
|
|
2287
|
+
const handleRetryQuiz = (0, import_react3.useCallback)(() => {
|
|
2288
|
+
setCurrentQuestionIndex(0);
|
|
2289
|
+
setAnswers(/* @__PURE__ */ new Map());
|
|
2290
|
+
setAnswersDetail([]);
|
|
2291
|
+
setIsCompleted(false);
|
|
2292
|
+
setResult(null);
|
|
2293
|
+
setErrorCode(null);
|
|
2294
|
+
setShowIntro(true);
|
|
2295
|
+
setShowFeedback(false);
|
|
2296
|
+
setCurrentAnswerDetail(null);
|
|
2297
|
+
setTimerStarted(false);
|
|
2298
|
+
setElapsedSeconds(0);
|
|
2299
|
+
startTimeRef.current = 0;
|
|
2300
|
+
setExtraQuestions([]);
|
|
2301
|
+
setSkippedQuestionIds(/* @__PURE__ */ new Set());
|
|
2302
|
+
setAttempt(null);
|
|
2303
|
+
setShowResumeChoice(false);
|
|
2304
|
+
setHasExistingProgress(false);
|
|
2305
|
+
setExistingProgressCount(0);
|
|
2306
|
+
setIsSubmitting(false);
|
|
2307
|
+
setIsNavigating(false);
|
|
2308
|
+
setIsGeneratingExtra(false);
|
|
2309
|
+
setIsStartingFresh(false);
|
|
2310
|
+
setShowSkipModal(false);
|
|
2311
|
+
setIsSkipping(false);
|
|
2312
|
+
setSkipComment("");
|
|
2313
|
+
setSelectedSkipReason(null);
|
|
2314
|
+
setShowReportModal(false);
|
|
2315
|
+
setIsReporting(false);
|
|
2316
|
+
setReportComment("");
|
|
2317
|
+
setRetryKey((prev) => prev + 1);
|
|
2318
|
+
}, []);
|
|
2009
2319
|
if (isLoading) {
|
|
2010
|
-
return /* @__PURE__ */ (0,
|
|
2320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.loading, children: "Loading quiz..." }) });
|
|
2011
2321
|
}
|
|
2012
|
-
if (
|
|
2013
|
-
return /* @__PURE__ */ (0,
|
|
2014
|
-
"Error: ",
|
|
2015
|
-
error
|
|
2016
|
-
] }) }) });
|
|
2322
|
+
if (errorCode) {
|
|
2323
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MaintenanceScreen, { errorCode }) });
|
|
2017
2324
|
}
|
|
2018
2325
|
if (isCompleted && result) {
|
|
2019
2326
|
const percentage = result.totalQuestions > 0 ? Math.round(result.correctAnswers / result.totalQuestions * 100) : 0;
|
|
@@ -2071,7 +2378,7 @@ function QuizPlayer({
|
|
|
2071
2378
|
rotation: Math.random() * 360,
|
|
2072
2379
|
size: 6 + Math.random() * 8
|
|
2073
2380
|
}));
|
|
2074
|
-
const StarIcon = ({ filled, delay }) => /* @__PURE__ */ (0,
|
|
2381
|
+
const StarIcon = ({ filled, delay }) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2075
2382
|
"svg",
|
|
2076
2383
|
{
|
|
2077
2384
|
width: "36",
|
|
@@ -2082,7 +2389,7 @@ function QuizPlayer({
|
|
|
2082
2389
|
animationDelay: `${delay}s`,
|
|
2083
2390
|
opacity: 0
|
|
2084
2391
|
},
|
|
2085
|
-
children: /* @__PURE__ */ (0,
|
|
2392
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2086
2393
|
"path",
|
|
2087
2394
|
{
|
|
2088
2395
|
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",
|
|
@@ -2093,62 +2400,23 @@ function QuizPlayer({
|
|
|
2093
2400
|
)
|
|
2094
2401
|
}
|
|
2095
2402
|
);
|
|
2096
|
-
const
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
case "celebrating":
|
|
2100
|
-
return { leftEye: ">", rightEye: "<", pupilY: 42 };
|
|
2101
|
-
// Squinting happy
|
|
2102
|
-
case "happy":
|
|
2103
|
-
return { leftEye: null, rightEye: null, pupilY: 42 };
|
|
2104
|
-
// Normal happy
|
|
2105
|
-
case "encouraging":
|
|
2106
|
-
return { leftEye: null, rightEye: null, pupilY: 44 };
|
|
2107
|
-
// Looking down warmly
|
|
2108
|
-
default:
|
|
2109
|
-
return { leftEye: null, rightEye: null, pupilY: 42 };
|
|
2110
|
-
}
|
|
2111
|
-
};
|
|
2112
|
-
const eyeExpr = getEyeExpression();
|
|
2113
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2114
|
-
"svg",
|
|
2403
|
+
const Mascot = ({ mood }) => {
|
|
2404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2405
|
+
"img",
|
|
2115
2406
|
{
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2407
|
+
src: astronautImage,
|
|
2408
|
+
alt: "Astronaut mascot",
|
|
2409
|
+
width: "180",
|
|
2410
|
+
height: "180",
|
|
2119
2411
|
style: {
|
|
2120
|
-
animation: mood === "celebrating" ? "bounce 0.6s ease-in-out infinite" : "gentleBob 2s ease-in-out infinite"
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "50", cy: "60", rx: "35", ry: "30", fill: "#8b5cf6" }),
|
|
2124
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "50", cy: "65", rx: "25", ry: "20", fill: "#c4b5fd" }),
|
|
2125
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "50", cy: "35", r: "28", fill: "#a78bfa" }),
|
|
2126
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "28,15 35,30 22,28", fill: "#7c3aed" }),
|
|
2127
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "72,15 65,30 78,28", fill: "#7c3aed" }),
|
|
2128
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "38", cy: "38", rx: "10", ry: "12", fill: "white" }),
|
|
2129
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "62", cy: "38", rx: "10", ry: "12", fill: "white" }),
|
|
2130
|
-
eyeExpr.leftEye ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "38", y: "44", textAnchor: "middle", fontSize: "16", fill: "#1f2937", children: eyeExpr.leftEye }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "38", cy: eyeExpr.pupilY, r: "5", fill: "#1f2937" }),
|
|
2131
|
-
eyeExpr.rightEye ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x: "62", y: "44", textAnchor: "middle", fontSize: "16", fill: "#1f2937", children: eyeExpr.rightEye }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "62", cy: eyeExpr.pupilY, r: "5", fill: "#1f2937" }),
|
|
2132
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "50,45 45,52 55,52", fill: "#fbbf24" }),
|
|
2133
|
-
(mood === "celebrating" || mood === "happy") && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2134
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "28", cy: "45", rx: "5", ry: "3", fill: "#fda4af", opacity: "0.6" }),
|
|
2135
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "72", cy: "45", rx: "5", ry: "3", fill: "#fda4af", opacity: "0.6" })
|
|
2136
|
-
] }),
|
|
2137
|
-
mood === "celebrating" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2138
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "18", cy: "55", rx: "8", ry: "15", fill: "#7c3aed", transform: "rotate(-30 18 55)" }),
|
|
2139
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "82", cy: "55", rx: "8", ry: "15", fill: "#7c3aed", transform: "rotate(30 82 55)" })
|
|
2140
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
2141
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "20", cy: "60", rx: "8", ry: "15", fill: "#7c3aed" }),
|
|
2142
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "80", cy: "60", rx: "8", ry: "15", fill: "#7c3aed" })
|
|
2143
|
-
] }),
|
|
2144
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "40", cy: "88", rx: "8", ry: "4", fill: "#fbbf24" }),
|
|
2145
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ellipse", { cx: "60", cy: "88", rx: "8", ry: "4", fill: "#fbbf24" })
|
|
2146
|
-
]
|
|
2412
|
+
animation: mood === "celebrating" ? "bounce 0.6s ease-in-out infinite" : "gentleBob 2s ease-in-out infinite",
|
|
2413
|
+
objectFit: "contain"
|
|
2414
|
+
}
|
|
2147
2415
|
}
|
|
2148
2416
|
);
|
|
2149
2417
|
};
|
|
2150
|
-
return /* @__PURE__ */ (0,
|
|
2151
|
-
/* @__PURE__ */ (0,
|
|
2418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className, style: defaultStyles.container, children: [
|
|
2419
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
|
|
2152
2420
|
@keyframes confettiFall {
|
|
2153
2421
|
0% {
|
|
2154
2422
|
transform: translateY(-10px) rotate(0deg);
|
|
@@ -2211,9 +2479,19 @@ function QuizPlayer({
|
|
|
2211
2479
|
opacity: 1;
|
|
2212
2480
|
}
|
|
2213
2481
|
}
|
|
2482
|
+
@keyframes buttonFadeIn {
|
|
2483
|
+
0% {
|
|
2484
|
+
opacity: 0;
|
|
2485
|
+
transform: translateY(10px);
|
|
2486
|
+
}
|
|
2487
|
+
100% {
|
|
2488
|
+
opacity: 1;
|
|
2489
|
+
transform: translateY(0);
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2214
2492
|
` }),
|
|
2215
|
-
/* @__PURE__ */ (0,
|
|
2216
|
-
percentage >= 60 && /* @__PURE__ */ (0,
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.results, children: [
|
|
2494
|
+
percentage >= 60 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.confettiContainer, children: confettiPieces.map((piece) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2217
2495
|
"div",
|
|
2218
2496
|
{
|
|
2219
2497
|
style: {
|
|
@@ -2230,15 +2508,70 @@ function QuizPlayer({
|
|
|
2230
2508
|
},
|
|
2231
2509
|
piece.id
|
|
2232
2510
|
)) }),
|
|
2233
|
-
/* @__PURE__ */ (0,
|
|
2234
|
-
/* @__PURE__ */ (0,
|
|
2235
|
-
/* @__PURE__ */ (0,
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2511
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...defaultStyles.resultsBackground, background: theme.bgGradient } }),
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.resultsContent, children: hideScore ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2513
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginBottom: "24px" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Mascot, { mood: "happy" }) }),
|
|
2514
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2515
|
+
"div",
|
|
2516
|
+
{
|
|
2517
|
+
style: {
|
|
2518
|
+
background: "linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%)",
|
|
2519
|
+
padding: "12px 28px",
|
|
2520
|
+
borderRadius: "50px",
|
|
2521
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
|
|
2522
|
+
marginBottom: "20px",
|
|
2523
|
+
animation: "badgePop 0.6s ease-out 0.2s forwards",
|
|
2524
|
+
opacity: 0,
|
|
2525
|
+
border: "3px solid #22c55e"
|
|
2526
|
+
},
|
|
2527
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2528
|
+
"span",
|
|
2529
|
+
{
|
|
2530
|
+
style: {
|
|
2531
|
+
fontSize: "22px",
|
|
2532
|
+
fontWeight: "700",
|
|
2533
|
+
color: "#1f2937",
|
|
2534
|
+
textShadow: "0 1px 2px rgba(255,255,255,0.5)"
|
|
2535
|
+
},
|
|
2536
|
+
children: "All Done!"
|
|
2537
|
+
}
|
|
2538
|
+
)
|
|
2539
|
+
}
|
|
2540
|
+
),
|
|
2541
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2542
|
+
"div",
|
|
2543
|
+
{
|
|
2544
|
+
style: {
|
|
2545
|
+
animation: "scoreSlideIn 0.5s ease-out 0.4s forwards",
|
|
2546
|
+
opacity: 0
|
|
2547
|
+
},
|
|
2548
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2549
|
+
"div",
|
|
2550
|
+
{
|
|
2551
|
+
style: {
|
|
2552
|
+
fontSize: "24px",
|
|
2553
|
+
fontWeight: "600",
|
|
2554
|
+
color: "#22c55e",
|
|
2555
|
+
lineHeight: "1.4",
|
|
2556
|
+
marginBottom: "12px"
|
|
2557
|
+
},
|
|
2558
|
+
children: "The quiz was submitted successfully!"
|
|
2559
|
+
}
|
|
2560
|
+
)
|
|
2561
|
+
}
|
|
2562
|
+
),
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...defaultStyles.resultDetails, marginTop: "8px" }, children: [
|
|
2564
|
+
"Time: ",
|
|
2565
|
+
formatTime(result.timeSpentSeconds)
|
|
2566
|
+
] })
|
|
2567
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.resultStars, children: [
|
|
2569
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StarIcon, { filled: theme.stars >= 1, delay: 0.3 }),
|
|
2570
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StarIcon, { filled: theme.stars >= 2, delay: 0.5 }),
|
|
2571
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StarIcon, { filled: theme.stars >= 3, delay: 0.7 })
|
|
2239
2572
|
] }),
|
|
2240
|
-
/* @__PURE__ */ (0,
|
|
2241
|
-
/* @__PURE__ */ (0,
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginBottom: "16px" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Mascot, { mood: theme.mascotMood }) }),
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2242
2575
|
"div",
|
|
2243
2576
|
{
|
|
2244
2577
|
style: {
|
|
@@ -2251,7 +2584,7 @@ function QuizPlayer({
|
|
|
2251
2584
|
opacity: 0,
|
|
2252
2585
|
border: `3px solid ${theme.badgeColor}`
|
|
2253
2586
|
},
|
|
2254
|
-
children: /* @__PURE__ */ (0,
|
|
2587
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2255
2588
|
"span",
|
|
2256
2589
|
{
|
|
2257
2590
|
style: {
|
|
@@ -2265,7 +2598,7 @@ function QuizPlayer({
|
|
|
2265
2598
|
)
|
|
2266
2599
|
}
|
|
2267
2600
|
),
|
|
2268
|
-
/* @__PURE__ */ (0,
|
|
2601
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2269
2602
|
"div",
|
|
2270
2603
|
{
|
|
2271
2604
|
style: {
|
|
@@ -2273,7 +2606,7 @@ function QuizPlayer({
|
|
|
2273
2606
|
opacity: 0
|
|
2274
2607
|
},
|
|
2275
2608
|
children: [
|
|
2276
|
-
/* @__PURE__ */ (0,
|
|
2609
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2277
2610
|
"div",
|
|
2278
2611
|
{
|
|
2279
2612
|
style: {
|
|
@@ -2290,7 +2623,7 @@ function QuizPlayer({
|
|
|
2290
2623
|
]
|
|
2291
2624
|
}
|
|
2292
2625
|
),
|
|
2293
|
-
/* @__PURE__ */ (0,
|
|
2626
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2294
2627
|
"div",
|
|
2295
2628
|
{
|
|
2296
2629
|
style: {
|
|
@@ -2305,25 +2638,116 @@ function QuizPlayer({
|
|
|
2305
2638
|
]
|
|
2306
2639
|
}
|
|
2307
2640
|
),
|
|
2308
|
-
/* @__PURE__ */ (0,
|
|
2641
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...defaultStyles.resultDetails, marginTop: "8px" }, children: [
|
|
2309
2642
|
"Time: ",
|
|
2310
2643
|
formatTime(result.timeSpentSeconds)
|
|
2311
|
-
] })
|
|
2312
|
-
|
|
2644
|
+
] }),
|
|
2645
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2646
|
+
"button",
|
|
2647
|
+
{
|
|
2648
|
+
style: {
|
|
2649
|
+
marginTop: "24px",
|
|
2650
|
+
padding: "14px 32px",
|
|
2651
|
+
fontSize: "16px",
|
|
2652
|
+
fontWeight: "600",
|
|
2653
|
+
color: "#7c3aed",
|
|
2654
|
+
background: "white",
|
|
2655
|
+
border: "2px solid #7c3aed",
|
|
2656
|
+
borderRadius: "12px",
|
|
2657
|
+
cursor: "pointer",
|
|
2658
|
+
transition: "all 0.2s ease",
|
|
2659
|
+
animation: "buttonFadeIn 0.5s ease-out 0.8s forwards",
|
|
2660
|
+
opacity: 0
|
|
2661
|
+
},
|
|
2662
|
+
onClick: handleRetryQuiz,
|
|
2663
|
+
onMouseOver: (e) => {
|
|
2664
|
+
e.currentTarget.style.background = "#7c3aed";
|
|
2665
|
+
e.currentTarget.style.color = "white";
|
|
2666
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
2667
|
+
},
|
|
2668
|
+
onMouseOut: (e) => {
|
|
2669
|
+
e.currentTarget.style.background = "white";
|
|
2670
|
+
e.currentTarget.style.color = "#7c3aed";
|
|
2671
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
2672
|
+
},
|
|
2673
|
+
"data-testid": "button-retry-quiz",
|
|
2674
|
+
children: "Try Again"
|
|
2675
|
+
}
|
|
2676
|
+
)
|
|
2677
|
+
] }) })
|
|
2313
2678
|
] })
|
|
2314
2679
|
] });
|
|
2315
2680
|
}
|
|
2681
|
+
if (quiz && showIntro && showResumeChoice && hasExistingProgress) {
|
|
2682
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.intro, children: [
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.introTitle, children: "Welcome Back!" }),
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.introSubtitle, children: "You have an unfinished quiz. Would you like to continue or start over?" }),
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.introQuestionCount, children: [
|
|
2686
|
+
existingProgressCount,
|
|
2687
|
+
" of ",
|
|
2688
|
+
quiz.questions.length,
|
|
2689
|
+
" question",
|
|
2690
|
+
quiz.questions.length !== 1 ? "s" : "",
|
|
2691
|
+
" answered"
|
|
2692
|
+
] }),
|
|
2693
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px", marginTop: "8px" }, children: [
|
|
2694
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2695
|
+
"button",
|
|
2696
|
+
{
|
|
2697
|
+
style: defaultStyles.startButton,
|
|
2698
|
+
onClick: handleResumePrevious,
|
|
2699
|
+
onMouseOver: (e) => {
|
|
2700
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
2701
|
+
e.currentTarget.style.boxShadow = "0 6px 20px rgba(124, 58, 237, 0.5)";
|
|
2702
|
+
},
|
|
2703
|
+
onMouseOut: (e) => {
|
|
2704
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
2705
|
+
e.currentTarget.style.boxShadow = "0 4px 14px rgba(124, 58, 237, 0.4)";
|
|
2706
|
+
},
|
|
2707
|
+
"data-testid": "button-continue-quiz",
|
|
2708
|
+
children: "Continue Where I Left Off"
|
|
2709
|
+
}
|
|
2710
|
+
),
|
|
2711
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2712
|
+
"button",
|
|
2713
|
+
{
|
|
2714
|
+
style: {
|
|
2715
|
+
...defaultStyles.startButton,
|
|
2716
|
+
background: "transparent",
|
|
2717
|
+
color: "#7c3aed",
|
|
2718
|
+
border: "2px solid #7c3aed",
|
|
2719
|
+
boxShadow: "none"
|
|
2720
|
+
},
|
|
2721
|
+
onClick: handleStartFresh,
|
|
2722
|
+
disabled: isStartingFresh,
|
|
2723
|
+
onMouseOver: (e) => {
|
|
2724
|
+
if (!isStartingFresh) {
|
|
2725
|
+
e.currentTarget.style.transform = "translateY(-2px)";
|
|
2726
|
+
e.currentTarget.style.background = "rgba(124, 58, 237, 0.1)";
|
|
2727
|
+
}
|
|
2728
|
+
},
|
|
2729
|
+
onMouseOut: (e) => {
|
|
2730
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
2731
|
+
e.currentTarget.style.background = "transparent";
|
|
2732
|
+
},
|
|
2733
|
+
"data-testid": "button-start-fresh",
|
|
2734
|
+
children: isStartingFresh ? "Starting..." : "Start Fresh"
|
|
2735
|
+
}
|
|
2736
|
+
)
|
|
2737
|
+
] })
|
|
2738
|
+
] }) });
|
|
2739
|
+
}
|
|
2316
2740
|
if (quiz && showIntro) {
|
|
2317
|
-
return /* @__PURE__ */ (0,
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
2319
|
-
/* @__PURE__ */ (0,
|
|
2320
|
-
/* @__PURE__ */ (0,
|
|
2741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.intro, children: [
|
|
2742
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.introTitle, children: quiz.title }),
|
|
2743
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.introSubtitle, children: "Ready to test your knowledge?" }),
|
|
2744
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.introQuestionCount, children: [
|
|
2321
2745
|
quiz.questions.length,
|
|
2322
2746
|
" question",
|
|
2323
2747
|
quiz.questions.length !== 1 ? "s" : "",
|
|
2324
2748
|
" to answer"
|
|
2325
2749
|
] }),
|
|
2326
|
-
/* @__PURE__ */ (0,
|
|
2750
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2327
2751
|
"button",
|
|
2328
2752
|
{
|
|
2329
2753
|
style: defaultStyles.startButton,
|
|
@@ -2343,7 +2767,7 @@ function QuizPlayer({
|
|
|
2343
2767
|
] }) });
|
|
2344
2768
|
}
|
|
2345
2769
|
if (!quiz || !currentQuestion) {
|
|
2346
|
-
return /* @__PURE__ */ (0,
|
|
2770
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.error, children: "No quiz data available" }) });
|
|
2347
2771
|
}
|
|
2348
2772
|
const selectedAnswer = answers.get(currentQuestion.id);
|
|
2349
2773
|
const isLastQuestion = currentQuestionIndex === totalQuestions - 1;
|
|
@@ -2351,294 +2775,166 @@ function QuizPlayer({
|
|
|
2351
2775
|
const remainingSlots = maxQuestions - totalQuestions;
|
|
2352
2776
|
const questionsToAdd = Math.min(5, remainingSlots);
|
|
2353
2777
|
const canAddMore = onGenerateMoreQuestions && remainingSlots > 0;
|
|
2354
|
-
return /* @__PURE__ */ (0,
|
|
2355
|
-
/* @__PURE__ */ (0,
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
totalQuestions
|
|
2363
|
-
] }),
|
|
2364
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.progressBar, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...defaultStyles.progressFill, width: `${progressPercent}%` } }) })
|
|
2365
|
-
] }),
|
|
2366
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...defaultStyles.question, position: "relative", paddingBottom: "40px" }, children: [
|
|
2367
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.questionText, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextToSpeech, { text: currentQuestion.question, inline: true, size: "md" }) }),
|
|
2368
|
-
isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2369
|
-
"button",
|
|
2370
|
-
{
|
|
2371
|
-
onClick: () => setShowSkipModal(true),
|
|
2372
|
-
title: "Skip question",
|
|
2373
|
-
style: {
|
|
2374
|
-
position: "absolute",
|
|
2375
|
-
bottom: "8px",
|
|
2376
|
-
left: "0",
|
|
2377
|
-
background: "transparent",
|
|
2378
|
-
border: "none",
|
|
2379
|
-
cursor: "pointer",
|
|
2380
|
-
padding: "6px 10px",
|
|
2381
|
-
borderRadius: "6px",
|
|
2382
|
-
color: "#9ca3af",
|
|
2383
|
-
display: "flex",
|
|
2384
|
-
alignItems: "center",
|
|
2385
|
-
justifyContent: "center",
|
|
2386
|
-
gap: "4px",
|
|
2387
|
-
fontSize: "12px",
|
|
2388
|
-
opacity: 0.6,
|
|
2389
|
-
transition: "opacity 0.2s, color 0.2s"
|
|
2390
|
-
},
|
|
2391
|
-
onMouseEnter: (e) => {
|
|
2392
|
-
e.currentTarget.style.opacity = "1";
|
|
2393
|
-
e.currentTarget.style.color = "#6b7280";
|
|
2394
|
-
},
|
|
2395
|
-
onMouseLeave: (e) => {
|
|
2396
|
-
e.currentTarget.style.opacity = "0.6";
|
|
2397
|
-
e.currentTarget.style.color = "#9ca3af";
|
|
2398
|
-
},
|
|
2399
|
-
"data-testid": "button-skip-question",
|
|
2400
|
-
children: [
|
|
2401
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2402
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "5 4 15 12 5 20 5 4" }),
|
|
2403
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "19", y1: "5", x2: "19", y2: "19" })
|
|
2404
|
-
] }),
|
|
2405
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Skip" })
|
|
2406
|
-
]
|
|
2407
|
-
}
|
|
2408
|
-
),
|
|
2409
|
-
!isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2410
|
-
"button",
|
|
2411
|
-
{
|
|
2412
|
-
onClick: () => setShowReportModal(true),
|
|
2413
|
-
title: "Report an issue with this question",
|
|
2414
|
-
style: {
|
|
2415
|
-
position: "absolute",
|
|
2416
|
-
bottom: "8px",
|
|
2417
|
-
left: "0",
|
|
2418
|
-
background: "transparent",
|
|
2419
|
-
border: "none",
|
|
2420
|
-
cursor: "pointer",
|
|
2421
|
-
padding: "6px 10px",
|
|
2422
|
-
borderRadius: "6px",
|
|
2423
|
-
color: "#9ca3af",
|
|
2424
|
-
display: "flex",
|
|
2425
|
-
alignItems: "center",
|
|
2426
|
-
justifyContent: "center",
|
|
2427
|
-
gap: "4px",
|
|
2428
|
-
fontSize: "12px",
|
|
2429
|
-
opacity: 0.6,
|
|
2430
|
-
transition: "opacity 0.2s, color 0.2s"
|
|
2431
|
-
},
|
|
2432
|
-
onMouseEnter: (e) => {
|
|
2433
|
-
e.currentTarget.style.opacity = "1";
|
|
2434
|
-
e.currentTarget.style.color = "#ef4444";
|
|
2435
|
-
},
|
|
2436
|
-
onMouseLeave: (e) => {
|
|
2437
|
-
e.currentTarget.style.opacity = "0.6";
|
|
2438
|
-
e.currentTarget.style.color = "#9ca3af";
|
|
2439
|
-
},
|
|
2440
|
-
"data-testid": "button-report-question",
|
|
2441
|
-
children: [
|
|
2442
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2443
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" }),
|
|
2444
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "4", y1: "22", x2: "4", y2: "15" })
|
|
2445
|
-
] }),
|
|
2446
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Report" })
|
|
2447
|
-
]
|
|
2778
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className, style: defaultStyles.container, children: [
|
|
2779
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("style", { children: `
|
|
2780
|
+
.quiz-option:focus,
|
|
2781
|
+
.quiz-option:active,
|
|
2782
|
+
.quiz-option:focus-visible,
|
|
2783
|
+
.quiz-option:focus-within {
|
|
2784
|
+
outline: none !important;
|
|
2785
|
+
box-shadow: none !important;
|
|
2448
2786
|
}
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
const isSelected = selectedAnswer === option;
|
|
2452
|
-
const isCorrectOption = currentQuestion.correctAnswer === option;
|
|
2453
|
-
let optionStyle = { ...defaultStyles.option };
|
|
2454
|
-
if (showFeedback) {
|
|
2455
|
-
if (isCorrectOption) {
|
|
2456
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
2457
|
-
} else if (isSelected && !isCorrectOption) {
|
|
2458
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
2459
|
-
}
|
|
2460
|
-
} else if (isSelected) {
|
|
2461
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
2787
|
+
.quiz-option {
|
|
2788
|
+
-webkit-tap-highlight-color: transparent;
|
|
2462
2789
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2790
|
+
` }),
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.mainLayout, children: [
|
|
2792
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.quizContent, children: [
|
|
2793
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.header, children: [
|
|
2794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.title, children: quiz.title }),
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.progress, children: [
|
|
2796
|
+
"Question ",
|
|
2797
|
+
currentQuestionIndex + 1,
|
|
2798
|
+
" of ",
|
|
2799
|
+
totalQuestions
|
|
2800
|
+
] }),
|
|
2801
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.progressBar, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...defaultStyles.progressFill, width: `${progressPercent}%` } }) })
|
|
2802
|
+
] }),
|
|
2803
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { ...defaultStyles.question, position: "relative", paddingBottom: "40px" }, children: [
|
|
2804
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.questionText, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextToSpeech, { text: currentQuestion.question, inline: true, size: "md" }) }),
|
|
2805
|
+
isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2806
|
+
"button",
|
|
2465
2807
|
{
|
|
2808
|
+
onClick: () => setShowSkipModal(true),
|
|
2809
|
+
title: "Skip question",
|
|
2466
2810
|
style: {
|
|
2467
|
-
|
|
2468
|
-
|
|
2811
|
+
position: "absolute",
|
|
2812
|
+
bottom: "8px",
|
|
2813
|
+
left: "0",
|
|
2814
|
+
background: "transparent",
|
|
2815
|
+
border: "none",
|
|
2816
|
+
cursor: "pointer",
|
|
2817
|
+
padding: "6px 10px",
|
|
2818
|
+
borderRadius: "6px",
|
|
2819
|
+
color: "#9ca3af",
|
|
2469
2820
|
display: "flex",
|
|
2470
2821
|
alignItems: "center",
|
|
2471
|
-
|
|
2822
|
+
justifyContent: "center",
|
|
2823
|
+
gap: "4px",
|
|
2824
|
+
fontSize: "12px",
|
|
2825
|
+
opacity: 0.6,
|
|
2826
|
+
transition: "opacity 0.2s, color 0.2s"
|
|
2827
|
+
},
|
|
2828
|
+
onMouseEnter: (e) => {
|
|
2829
|
+
e.currentTarget.style.opacity = "1";
|
|
2830
|
+
e.currentTarget.style.color = "#6b7280";
|
|
2472
2831
|
},
|
|
2473
|
-
|
|
2832
|
+
onMouseLeave: (e) => {
|
|
2833
|
+
e.currentTarget.style.opacity = "0.6";
|
|
2834
|
+
e.currentTarget.style.color = "#9ca3af";
|
|
2835
|
+
},
|
|
2836
|
+
"data-testid": "button-skip-question",
|
|
2474
2837
|
children: [
|
|
2475
|
-
/* @__PURE__ */ (0,
|
|
2476
|
-
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("polygon", { points: "5 4 15 12 5 20 5 4" }),
|
|
2840
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "19", y1: "5", x2: "19", y2: "19" })
|
|
2841
|
+
] }),
|
|
2842
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Skip" })
|
|
2477
2843
|
]
|
|
2478
|
-
},
|
|
2479
|
-
idx
|
|
2480
|
-
);
|
|
2481
|
-
}) }),
|
|
2482
|
-
currentQuestion.type === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
2483
|
-
const selected = Array.isArray(selectedAnswer) && selectedAnswer.includes(option);
|
|
2484
|
-
const correctAnswers = Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer : currentQuestion.correctAnswer ? [currentQuestion.correctAnswer] : [];
|
|
2485
|
-
const isCorrectOption = correctAnswers.includes(option);
|
|
2486
|
-
let optionStyle = { ...defaultStyles.option };
|
|
2487
|
-
if (showFeedback) {
|
|
2488
|
-
if (isCorrectOption) {
|
|
2489
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
2490
|
-
} else if (selected && !isCorrectOption) {
|
|
2491
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
2492
2844
|
}
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
2497
|
-
"div",
|
|
2845
|
+
),
|
|
2846
|
+
!isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2847
|
+
"button",
|
|
2498
2848
|
{
|
|
2849
|
+
onClick: () => setShowReportModal(true),
|
|
2850
|
+
title: "Report an issue with this question",
|
|
2499
2851
|
style: {
|
|
2500
|
-
|
|
2501
|
-
|
|
2852
|
+
position: "absolute",
|
|
2853
|
+
bottom: "8px",
|
|
2854
|
+
left: "0",
|
|
2855
|
+
background: "transparent",
|
|
2856
|
+
border: "none",
|
|
2857
|
+
cursor: "pointer",
|
|
2858
|
+
padding: "6px 10px",
|
|
2859
|
+
borderRadius: "6px",
|
|
2860
|
+
color: "#9ca3af",
|
|
2502
2861
|
display: "flex",
|
|
2503
2862
|
alignItems: "center",
|
|
2504
|
-
|
|
2863
|
+
justifyContent: "center",
|
|
2864
|
+
gap: "4px",
|
|
2865
|
+
fontSize: "12px",
|
|
2866
|
+
opacity: 0.6,
|
|
2867
|
+
transition: "opacity 0.2s, color 0.2s"
|
|
2505
2868
|
},
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
}
|
|
2869
|
+
onMouseEnter: (e) => {
|
|
2870
|
+
e.currentTarget.style.opacity = "1";
|
|
2871
|
+
e.currentTarget.style.color = "#ef4444";
|
|
2872
|
+
},
|
|
2873
|
+
onMouseLeave: (e) => {
|
|
2874
|
+
e.currentTarget.style.opacity = "0.6";
|
|
2875
|
+
e.currentTarget.style.color = "#9ca3af";
|
|
2514
2876
|
},
|
|
2877
|
+
"data-testid": "button-report-question",
|
|
2515
2878
|
children: [
|
|
2516
|
-
/* @__PURE__ */ (0,
|
|
2517
|
-
|
|
2879
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
2880
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" }),
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("line", { x1: "4", y1: "22", x2: "4", y2: "15" })
|
|
2882
|
+
] }),
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Report" })
|
|
2518
2884
|
]
|
|
2519
|
-
}
|
|
2520
|
-
|
|
2521
|
-
)
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
disabled: showFeedback
|
|
2531
|
-
}
|
|
2532
|
-
),
|
|
2533
|
-
currentQuestion.type === "fill" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.blanks?.map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2534
|
-
"input",
|
|
2535
|
-
{
|
|
2536
|
-
style: defaultStyles.input,
|
|
2537
|
-
value: (Array.isArray(selectedAnswer) ? selectedAnswer[idx] : "") || "",
|
|
2538
|
-
onChange: (e) => {
|
|
2539
|
-
const current = Array.isArray(selectedAnswer) ? [...selectedAnswer] : [];
|
|
2540
|
-
current[idx] = e.target.value;
|
|
2541
|
-
handleAnswerChange(current);
|
|
2542
|
-
},
|
|
2543
|
-
placeholder: `Blank ${idx + 1}`,
|
|
2544
|
-
disabled: showFeedback
|
|
2545
|
-
},
|
|
2546
|
-
idx
|
|
2547
|
-
)) }),
|
|
2548
|
-
currentQuestion.type === "sorting" && currentQuestion.items && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2549
|
-
SortingDragDrop,
|
|
2550
|
-
{
|
|
2551
|
-
items: currentQuestion.items,
|
|
2552
|
-
currentOrder: Array.isArray(selectedAnswer) ? selectedAnswer : currentQuestion.items.map((_, i) => i),
|
|
2553
|
-
correctOrder: currentQuestion.correctOrder,
|
|
2554
|
-
showFeedback,
|
|
2555
|
-
onOrderChange: handleAnswerChange
|
|
2556
|
-
}
|
|
2557
|
-
),
|
|
2558
|
-
currentQuestion.type === "matrix" && currentQuestion.leftItems && currentQuestion.rightItems && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2559
|
-
MatchingDragDrop,
|
|
2560
|
-
{
|
|
2561
|
-
leftItems: currentQuestion.leftItems,
|
|
2562
|
-
rightItems: currentQuestion.rightItems,
|
|
2563
|
-
currentMatches: typeof selectedAnswer === "object" && selectedAnswer !== null && !Array.isArray(selectedAnswer) ? selectedAnswer : {},
|
|
2564
|
-
correctMatches: currentQuestion.correctMatches,
|
|
2565
|
-
showFeedback,
|
|
2566
|
-
onMatchChange: handleAnswerChange
|
|
2567
|
-
}
|
|
2568
|
-
),
|
|
2569
|
-
currentQuestion.type === "assessment" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: (() => {
|
|
2570
|
-
const scaleType = currentQuestion.scaleType || "likert";
|
|
2571
|
-
if (scaleType === "yes-no") {
|
|
2572
|
-
const options = ["Yes", "No"];
|
|
2573
|
-
return options.map((option, idx) => {
|
|
2574
|
-
const isSelected = selectedAnswer === option;
|
|
2575
|
-
let optionStyle = { ...defaultStyles.option };
|
|
2576
|
-
if (isSelected) {
|
|
2577
|
-
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
2885
|
+
}
|
|
2886
|
+
),
|
|
2887
|
+
(currentQuestion.type === "single" || currentQuestion.type === "true-false") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
2888
|
+
const isSelected = selectedAnswer === option;
|
|
2889
|
+
const isCorrectOption = currentQuestion.correctAnswer === option;
|
|
2890
|
+
let optionStyle = { ...defaultStyles.option };
|
|
2891
|
+
if (showFeedback) {
|
|
2892
|
+
if (isCorrectOption) {
|
|
2893
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
2894
|
+
} else if (isSelected && !isCorrectOption) {
|
|
2895
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
2578
2896
|
}
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
"
|
|
2591
|
-
|
|
2592
|
-
},
|
|
2593
|
-
idx
|
|
2594
|
-
);
|
|
2595
|
-
});
|
|
2596
|
-
}
|
|
2597
|
-
if (scaleType === "rating") {
|
|
2598
|
-
const min = currentQuestion.scaleMin || 1;
|
|
2599
|
-
const max = currentQuestion.scaleMax || 5;
|
|
2600
|
-
const ratings = Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
|
2601
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap", justifyContent: "center" }, children: ratings.map((rating) => {
|
|
2602
|
-
const isSelected = selectedAnswer === rating;
|
|
2603
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2604
|
-
"button",
|
|
2605
|
-
{
|
|
2606
|
-
onClick: () => !showFeedback && handleAnswerChange(rating),
|
|
2607
|
-
disabled: showFeedback,
|
|
2608
|
-
style: {
|
|
2609
|
-
width: "48px",
|
|
2610
|
-
height: "48px",
|
|
2611
|
-
borderRadius: "50%",
|
|
2612
|
-
border: isSelected ? "2px solid #6721b0" : "2px solid #e5e7eb",
|
|
2613
|
-
backgroundColor: isSelected ? "#f3e8ff" : "#ffffff",
|
|
2614
|
-
cursor: showFeedback ? "not-allowed" : "pointer",
|
|
2615
|
-
fontSize: "18px",
|
|
2616
|
-
fontWeight: "600",
|
|
2617
|
-
color: isSelected ? "#6721b0" : "#374151"
|
|
2618
|
-
},
|
|
2619
|
-
"data-testid": `assessment-rating-${rating}`,
|
|
2620
|
-
children: rating
|
|
2897
|
+
} else if (isSelected) {
|
|
2898
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
2899
|
+
}
|
|
2900
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2901
|
+
"div",
|
|
2902
|
+
{
|
|
2903
|
+
className: "quiz-option",
|
|
2904
|
+
style: {
|
|
2905
|
+
...optionStyle,
|
|
2906
|
+
cursor: showFeedback ? "default" : "pointer",
|
|
2907
|
+
display: "flex",
|
|
2908
|
+
alignItems: "center",
|
|
2909
|
+
gap: "8px"
|
|
2621
2910
|
},
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
const
|
|
2911
|
+
onClick: () => !showFeedback && handleAnswerChange(option),
|
|
2912
|
+
children: [
|
|
2913
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
|
|
2914
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: option })
|
|
2915
|
+
]
|
|
2916
|
+
},
|
|
2917
|
+
idx
|
|
2918
|
+
);
|
|
2919
|
+
}) }),
|
|
2920
|
+
currentQuestion.type === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
|
|
2921
|
+
const selected = Array.isArray(selectedAnswer) && selectedAnswer.includes(option);
|
|
2922
|
+
const correctAnswers = Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer : currentQuestion.correctAnswer ? [currentQuestion.correctAnswer] : [];
|
|
2923
|
+
const isCorrectOption = correctAnswers.includes(option);
|
|
2635
2924
|
let optionStyle = { ...defaultStyles.option };
|
|
2636
|
-
if (
|
|
2925
|
+
if (showFeedback) {
|
|
2926
|
+
if (isCorrectOption) {
|
|
2927
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
|
|
2928
|
+
} else if (selected && !isCorrectOption) {
|
|
2929
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
|
|
2930
|
+
}
|
|
2931
|
+
} else if (selected) {
|
|
2637
2932
|
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
2638
2933
|
}
|
|
2639
|
-
return /* @__PURE__ */ (0,
|
|
2934
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
2640
2935
|
"div",
|
|
2641
2936
|
{
|
|
2937
|
+
className: "quiz-option",
|
|
2642
2938
|
style: {
|
|
2643
2939
|
...optionStyle,
|
|
2644
2940
|
cursor: showFeedback ? "default" : "pointer",
|
|
@@ -2646,356 +2942,504 @@ function QuizPlayer({
|
|
|
2646
2942
|
alignItems: "center",
|
|
2647
2943
|
gap: "8px"
|
|
2648
2944
|
},
|
|
2649
|
-
onClick: () =>
|
|
2650
|
-
|
|
2651
|
-
|
|
2945
|
+
onClick: () => {
|
|
2946
|
+
if (showFeedback) return;
|
|
2947
|
+
const current = Array.isArray(selectedAnswer) ? selectedAnswer : [];
|
|
2948
|
+
if (selected) {
|
|
2949
|
+
handleAnswerChange(current.filter((o) => o !== option));
|
|
2950
|
+
} else {
|
|
2951
|
+
handleAnswerChange([...current, option]);
|
|
2952
|
+
}
|
|
2953
|
+
},
|
|
2954
|
+
children: [
|
|
2955
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
|
|
2956
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: option })
|
|
2957
|
+
]
|
|
2652
2958
|
},
|
|
2653
2959
|
idx
|
|
2654
2960
|
);
|
|
2655
|
-
})
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
...defaultStyles.feedback,
|
|
2659
|
-
...currentQuestion.type === "assessment" ? defaultStyles.feedbackNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
|
|
2660
|
-
}, children: [
|
|
2661
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
|
|
2662
|
-
...defaultStyles.feedbackTitle,
|
|
2663
|
-
...currentQuestion.type === "assessment" ? defaultStyles.feedbackTitleNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
|
|
2664
|
-
}, children: currentQuestion.type === "assessment" ? "\u2713 Response recorded" : currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
|
|
2665
|
-
currentQuestion.explanation && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
|
|
2666
|
-
] })
|
|
2667
|
-
] }),
|
|
2668
|
-
showSkipModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
|
|
2669
|
-
position: "fixed",
|
|
2670
|
-
top: 0,
|
|
2671
|
-
left: 0,
|
|
2672
|
-
right: 0,
|
|
2673
|
-
bottom: 0,
|
|
2674
|
-
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
2675
|
-
display: "flex",
|
|
2676
|
-
alignItems: "center",
|
|
2677
|
-
justifyContent: "center",
|
|
2678
|
-
zIndex: 1e3
|
|
2679
|
-
}, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
|
|
2680
|
-
backgroundColor: "#ffffff",
|
|
2681
|
-
borderRadius: "12px",
|
|
2682
|
-
padding: "24px",
|
|
2683
|
-
maxWidth: "400px",
|
|
2684
|
-
width: "90%",
|
|
2685
|
-
boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
|
|
2686
|
-
}, children: [
|
|
2687
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Skip Question" }),
|
|
2688
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { margin: "0 0 16px 0", fontSize: "14px", color: "#6b7280" }, children: "Help us improve by telling us why you're skipping this question." }),
|
|
2689
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px", marginBottom: "16px" }, children: [
|
|
2690
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2691
|
-
"button",
|
|
2961
|
+
}) }),
|
|
2962
|
+
(currentQuestion.type === "free" || currentQuestion.type === "essay") && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2963
|
+
"textarea",
|
|
2692
2964
|
{
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
border: selectedSkipReason === "question_issue" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
|
|
2699
|
-
backgroundColor: selectedSkipReason === "question_issue" ? "#f5f3ff" : "#f9fafb",
|
|
2700
|
-
cursor: isSkipping ? "not-allowed" : "pointer",
|
|
2701
|
-
fontSize: "14px",
|
|
2702
|
-
fontWeight: "500",
|
|
2703
|
-
color: "#374151",
|
|
2704
|
-
textAlign: "left",
|
|
2705
|
-
opacity: isSkipping ? 0.6 : 1
|
|
2706
|
-
},
|
|
2707
|
-
"data-testid": "button-skip-reason-issue",
|
|
2708
|
-
children: "Question has an issue"
|
|
2965
|
+
style: { ...defaultStyles.input, minHeight: currentQuestion.type === "essay" ? "150px" : "60px" },
|
|
2966
|
+
value: selectedAnswer || "",
|
|
2967
|
+
onChange: (e) => handleAnswerChange(e.target.value),
|
|
2968
|
+
placeholder: "Type your answer here...",
|
|
2969
|
+
disabled: showFeedback
|
|
2709
2970
|
}
|
|
2710
2971
|
),
|
|
2711
|
-
/* @__PURE__ */ (0,
|
|
2712
|
-
"
|
|
2972
|
+
currentQuestion.type === "fill" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.options, children: currentQuestion.blanks?.map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2973
|
+
"input",
|
|
2713
2974
|
{
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
backgroundColor: selectedSkipReason === "dont_know" ? "#f5f3ff" : "#f9fafb",
|
|
2721
|
-
cursor: isSkipping ? "not-allowed" : "pointer",
|
|
2722
|
-
fontSize: "14px",
|
|
2723
|
-
fontWeight: "500",
|
|
2724
|
-
color: "#374151",
|
|
2725
|
-
textAlign: "left",
|
|
2726
|
-
opacity: isSkipping ? 0.6 : 1
|
|
2975
|
+
style: defaultStyles.input,
|
|
2976
|
+
value: (Array.isArray(selectedAnswer) ? selectedAnswer[idx] : "") || "",
|
|
2977
|
+
onChange: (e) => {
|
|
2978
|
+
const current = Array.isArray(selectedAnswer) ? [...selectedAnswer] : [];
|
|
2979
|
+
current[idx] = e.target.value;
|
|
2980
|
+
handleAnswerChange(current);
|
|
2727
2981
|
},
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
}
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2736
|
-
"textarea",
|
|
2982
|
+
placeholder: `Blank ${idx + 1}`,
|
|
2983
|
+
disabled: showFeedback
|
|
2984
|
+
},
|
|
2985
|
+
idx
|
|
2986
|
+
)) }),
|
|
2987
|
+
currentQuestion.type === "sorting" && currentQuestion.items && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2988
|
+
SortingDragDrop,
|
|
2737
2989
|
{
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
width: "100%",
|
|
2744
|
-
minHeight: "80px",
|
|
2745
|
-
padding: "10px 12px",
|
|
2746
|
-
borderRadius: "8px",
|
|
2747
|
-
border: "1px solid #e5e7eb",
|
|
2748
|
-
fontSize: "14px",
|
|
2749
|
-
resize: "vertical",
|
|
2750
|
-
fontFamily: "inherit",
|
|
2751
|
-
boxSizing: "border-box"
|
|
2752
|
-
},
|
|
2753
|
-
"data-testid": "input-skip-comment"
|
|
2990
|
+
items: currentQuestion.items,
|
|
2991
|
+
currentOrder: Array.isArray(selectedAnswer) ? selectedAnswer : currentQuestion.items.map((_, i) => i),
|
|
2992
|
+
correctOrder: currentQuestion.correctOrder,
|
|
2993
|
+
showFeedback,
|
|
2994
|
+
onOrderChange: handleAnswerChange
|
|
2754
2995
|
}
|
|
2755
2996
|
),
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
"/200"
|
|
2759
|
-
] })
|
|
2760
|
-
] }),
|
|
2761
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
2762
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2763
|
-
"button",
|
|
2997
|
+
currentQuestion.type === "matrix" && currentQuestion.leftItems && currentQuestion.rightItems && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2998
|
+
MatchingDragDrop,
|
|
2764
2999
|
{
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
flex: 1,
|
|
2772
|
-
padding: "10px 16px",
|
|
2773
|
-
borderRadius: "8px",
|
|
2774
|
-
border: "1px solid #e5e7eb",
|
|
2775
|
-
backgroundColor: "#ffffff",
|
|
2776
|
-
cursor: "pointer",
|
|
2777
|
-
fontSize: "14px",
|
|
2778
|
-
fontWeight: "500",
|
|
2779
|
-
color: "#6b7280"
|
|
2780
|
-
},
|
|
2781
|
-
"data-testid": "button-skip-cancel",
|
|
2782
|
-
children: "Cancel"
|
|
3000
|
+
leftItems: currentQuestion.leftItems,
|
|
3001
|
+
rightItems: currentQuestion.rightItems,
|
|
3002
|
+
currentMatches: typeof selectedAnswer === "object" && selectedAnswer !== null && !Array.isArray(selectedAnswer) ? selectedAnswer : {},
|
|
3003
|
+
correctMatches: currentQuestion.correctMatches,
|
|
3004
|
+
showFeedback,
|
|
3005
|
+
onMatchChange: handleAnswerChange
|
|
2783
3006
|
}
|
|
2784
3007
|
),
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2786
|
-
"
|
|
2787
|
-
{
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
3008
|
+
currentQuestion.type === "assessment" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.options, children: (() => {
|
|
3009
|
+
const scaleType = currentQuestion.scaleType || "likert";
|
|
3010
|
+
if (scaleType === "yes-no") {
|
|
3011
|
+
const options = ["Yes", "No"];
|
|
3012
|
+
return options.map((option, idx) => {
|
|
3013
|
+
const isSelected = selectedAnswer === option;
|
|
3014
|
+
let optionStyle = { ...defaultStyles.option };
|
|
3015
|
+
if (isSelected) {
|
|
3016
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
3017
|
+
}
|
|
3018
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3019
|
+
"div",
|
|
3020
|
+
{
|
|
3021
|
+
className: "quiz-option",
|
|
3022
|
+
style: {
|
|
3023
|
+
...optionStyle,
|
|
3024
|
+
cursor: showFeedback ? "default" : "pointer",
|
|
3025
|
+
display: "flex",
|
|
3026
|
+
alignItems: "center",
|
|
3027
|
+
gap: "8px"
|
|
3028
|
+
},
|
|
3029
|
+
onClick: () => !showFeedback && handleAnswerChange(option),
|
|
3030
|
+
"data-testid": `assessment-option-${option.toLowerCase()}`,
|
|
3031
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: option })
|
|
3032
|
+
},
|
|
3033
|
+
idx
|
|
3034
|
+
);
|
|
3035
|
+
});
|
|
2804
3036
|
}
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
placeholder: "Describe the issue with this question...",
|
|
2836
|
-
disabled: isReporting,
|
|
2837
|
-
style: {
|
|
2838
|
-
width: "100%",
|
|
2839
|
-
minHeight: "120px",
|
|
2840
|
-
padding: "10px 12px",
|
|
2841
|
-
borderRadius: "8px",
|
|
2842
|
-
border: "1px solid #e5e7eb",
|
|
2843
|
-
fontSize: "14px",
|
|
2844
|
-
resize: "vertical",
|
|
2845
|
-
fontFamily: "inherit",
|
|
2846
|
-
boxSizing: "border-box"
|
|
2847
|
-
},
|
|
2848
|
-
"data-testid": "input-report-comment"
|
|
3037
|
+
if (scaleType === "rating") {
|
|
3038
|
+
const min = currentQuestion.scaleMin || 1;
|
|
3039
|
+
const max = currentQuestion.scaleMax || 5;
|
|
3040
|
+
const ratings = Array.from({ length: max - min + 1 }, (_, i) => min + i);
|
|
3041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { display: "flex", gap: "8px", flexWrap: "wrap", justifyContent: "center" }, children: ratings.map((rating) => {
|
|
3042
|
+
const isSelected = selectedAnswer === rating;
|
|
3043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3044
|
+
"button",
|
|
3045
|
+
{
|
|
3046
|
+
className: "quiz-option",
|
|
3047
|
+
onClick: () => !showFeedback && handleAnswerChange(rating),
|
|
3048
|
+
disabled: showFeedback,
|
|
3049
|
+
style: {
|
|
3050
|
+
width: "48px",
|
|
3051
|
+
height: "48px",
|
|
3052
|
+
borderRadius: "50%",
|
|
3053
|
+
border: isSelected ? "2px solid #6721b0" : "2px solid #e5e7eb",
|
|
3054
|
+
backgroundColor: isSelected ? "#f3e8ff" : "#ffffff",
|
|
3055
|
+
cursor: showFeedback ? "not-allowed" : "pointer",
|
|
3056
|
+
fontSize: "18px",
|
|
3057
|
+
fontWeight: "600",
|
|
3058
|
+
color: isSelected ? "#6721b0" : "#374151",
|
|
3059
|
+
outline: "none"
|
|
3060
|
+
},
|
|
3061
|
+
"data-testid": `assessment-rating-${rating}`,
|
|
3062
|
+
children: rating
|
|
3063
|
+
},
|
|
3064
|
+
rating
|
|
3065
|
+
);
|
|
3066
|
+
}) });
|
|
2849
3067
|
}
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
3068
|
+
const likertOptions = [
|
|
3069
|
+
"Strongly Disagree",
|
|
3070
|
+
"Disagree",
|
|
3071
|
+
"Neutral",
|
|
3072
|
+
"Agree",
|
|
3073
|
+
"Strongly Agree"
|
|
3074
|
+
];
|
|
3075
|
+
return likertOptions.map((option, idx) => {
|
|
3076
|
+
const isSelected = selectedAnswer === option;
|
|
3077
|
+
let optionStyle = { ...defaultStyles.option };
|
|
3078
|
+
if (isSelected) {
|
|
3079
|
+
optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
|
|
3080
|
+
}
|
|
3081
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3082
|
+
"div",
|
|
3083
|
+
{
|
|
3084
|
+
className: "quiz-option",
|
|
3085
|
+
style: {
|
|
3086
|
+
...optionStyle,
|
|
3087
|
+
cursor: showFeedback ? "default" : "pointer",
|
|
3088
|
+
display: "flex",
|
|
3089
|
+
alignItems: "center",
|
|
3090
|
+
gap: "8px"
|
|
3091
|
+
},
|
|
3092
|
+
onClick: () => !showFeedback && handleAnswerChange(option),
|
|
3093
|
+
"data-testid": `assessment-likert-${idx}`,
|
|
3094
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { style: { flex: 1 }, children: option })
|
|
3095
|
+
},
|
|
3096
|
+
idx
|
|
3097
|
+
);
|
|
3098
|
+
});
|
|
3099
|
+
})() }),
|
|
3100
|
+
showFeedback && currentAnswerDetail && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
|
|
3101
|
+
...defaultStyles.feedback,
|
|
3102
|
+
...currentQuestion.type === "assessment" ? defaultStyles.feedbackNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
|
|
3103
|
+
}, children: [
|
|
3104
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
3105
|
+
...defaultStyles.feedbackTitle,
|
|
3106
|
+
...currentQuestion.type === "assessment" ? defaultStyles.feedbackTitleNeutral : currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
|
|
3107
|
+
}, children: currentQuestion.type === "assessment" ? "\u2713 Response recorded" : currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
|
|
3108
|
+
currentQuestion.explanation && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
|
|
2854
3109
|
] })
|
|
2855
3110
|
] }),
|
|
2856
|
-
/* @__PURE__ */ (0,
|
|
2857
|
-
|
|
3111
|
+
showSkipModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
3112
|
+
position: "fixed",
|
|
3113
|
+
top: 0,
|
|
3114
|
+
left: 0,
|
|
3115
|
+
right: 0,
|
|
3116
|
+
bottom: 0,
|
|
3117
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
3118
|
+
display: "flex",
|
|
3119
|
+
alignItems: "center",
|
|
3120
|
+
justifyContent: "center",
|
|
3121
|
+
zIndex: 1e3
|
|
3122
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
|
|
3123
|
+
backgroundColor: "#ffffff",
|
|
3124
|
+
borderRadius: "12px",
|
|
3125
|
+
padding: "24px",
|
|
3126
|
+
maxWidth: "400px",
|
|
3127
|
+
width: "90%",
|
|
3128
|
+
boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
|
|
3129
|
+
}, children: [
|
|
3130
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Skip Question" }),
|
|
3131
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { margin: "0 0 16px 0", fontSize: "14px", color: "#6b7280" }, children: "Help us improve by telling us why you're skipping this question." }),
|
|
3132
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px", marginBottom: "16px" }, children: [
|
|
3133
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3134
|
+
"button",
|
|
3135
|
+
{
|
|
3136
|
+
onClick: () => setSelectedSkipReason("question_issue"),
|
|
3137
|
+
disabled: isSkipping,
|
|
3138
|
+
style: {
|
|
3139
|
+
padding: "12px 16px",
|
|
3140
|
+
borderRadius: "8px",
|
|
3141
|
+
border: selectedSkipReason === "question_issue" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
|
|
3142
|
+
backgroundColor: selectedSkipReason === "question_issue" ? "#f5f3ff" : "#f9fafb",
|
|
3143
|
+
cursor: isSkipping ? "not-allowed" : "pointer",
|
|
3144
|
+
fontSize: "14px",
|
|
3145
|
+
fontWeight: "500",
|
|
3146
|
+
color: "#374151",
|
|
3147
|
+
textAlign: "left",
|
|
3148
|
+
opacity: isSkipping ? 0.6 : 1
|
|
3149
|
+
},
|
|
3150
|
+
"data-testid": "button-skip-reason-issue",
|
|
3151
|
+
children: "Question has an issue"
|
|
3152
|
+
}
|
|
3153
|
+
),
|
|
3154
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3155
|
+
"button",
|
|
3156
|
+
{
|
|
3157
|
+
onClick: () => setSelectedSkipReason("dont_know"),
|
|
3158
|
+
disabled: isSkipping,
|
|
3159
|
+
style: {
|
|
3160
|
+
padding: "12px 16px",
|
|
3161
|
+
borderRadius: "8px",
|
|
3162
|
+
border: selectedSkipReason === "dont_know" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
|
|
3163
|
+
backgroundColor: selectedSkipReason === "dont_know" ? "#f5f3ff" : "#f9fafb",
|
|
3164
|
+
cursor: isSkipping ? "not-allowed" : "pointer",
|
|
3165
|
+
fontSize: "14px",
|
|
3166
|
+
fontWeight: "500",
|
|
3167
|
+
color: "#374151",
|
|
3168
|
+
textAlign: "left",
|
|
3169
|
+
opacity: isSkipping ? 0.6 : 1
|
|
3170
|
+
},
|
|
3171
|
+
"data-testid": "button-skip-reason-dont-know",
|
|
3172
|
+
children: "I don't know the answer"
|
|
3173
|
+
}
|
|
3174
|
+
)
|
|
3175
|
+
] }),
|
|
3176
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginBottom: "16px" }, children: [
|
|
3177
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { style: { display: "block", fontSize: "13px", fontWeight: "500", color: "#374151", marginBottom: "6px" }, children: "Additional details (optional)" }),
|
|
3178
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3179
|
+
"textarea",
|
|
3180
|
+
{
|
|
3181
|
+
value: skipComment,
|
|
3182
|
+
onChange: (e) => setSkipComment(e.target.value.slice(0, 200)),
|
|
3183
|
+
placeholder: "Tell us more about the issue...",
|
|
3184
|
+
disabled: isSkipping,
|
|
3185
|
+
style: {
|
|
3186
|
+
width: "100%",
|
|
3187
|
+
minHeight: "80px",
|
|
3188
|
+
padding: "10px 12px",
|
|
3189
|
+
borderRadius: "8px",
|
|
3190
|
+
border: "1px solid #e5e7eb",
|
|
3191
|
+
fontSize: "14px",
|
|
3192
|
+
resize: "vertical",
|
|
3193
|
+
fontFamily: "inherit",
|
|
3194
|
+
boxSizing: "border-box"
|
|
3195
|
+
},
|
|
3196
|
+
"data-testid": "input-skip-comment"
|
|
3197
|
+
}
|
|
3198
|
+
),
|
|
3199
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
|
|
3200
|
+
skipComment.length,
|
|
3201
|
+
"/200"
|
|
3202
|
+
] })
|
|
3203
|
+
] }),
|
|
3204
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
3205
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3206
|
+
"button",
|
|
3207
|
+
{
|
|
3208
|
+
onClick: () => {
|
|
3209
|
+
setShowSkipModal(false);
|
|
3210
|
+
setSkipComment("");
|
|
3211
|
+
setSelectedSkipReason(null);
|
|
3212
|
+
},
|
|
3213
|
+
style: {
|
|
3214
|
+
flex: 1,
|
|
3215
|
+
padding: "10px 16px",
|
|
3216
|
+
borderRadius: "8px",
|
|
3217
|
+
border: "1px solid #e5e7eb",
|
|
3218
|
+
backgroundColor: "#ffffff",
|
|
3219
|
+
cursor: "pointer",
|
|
3220
|
+
fontSize: "14px",
|
|
3221
|
+
fontWeight: "500",
|
|
3222
|
+
color: "#6b7280"
|
|
3223
|
+
},
|
|
3224
|
+
"data-testid": "button-skip-cancel",
|
|
3225
|
+
children: "Cancel"
|
|
3226
|
+
}
|
|
3227
|
+
),
|
|
3228
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3229
|
+
"button",
|
|
3230
|
+
{
|
|
3231
|
+
onClick: () => selectedSkipReason && handleSkipQuestion(selectedSkipReason, skipComment),
|
|
3232
|
+
disabled: isSkipping || !selectedSkipReason,
|
|
3233
|
+
style: {
|
|
3234
|
+
flex: 1,
|
|
3235
|
+
padding: "10px 16px",
|
|
3236
|
+
borderRadius: "8px",
|
|
3237
|
+
border: "none",
|
|
3238
|
+
backgroundColor: selectedSkipReason ? "#8b5cf6" : "#d1d5db",
|
|
3239
|
+
cursor: isSkipping || !selectedSkipReason ? "not-allowed" : "pointer",
|
|
3240
|
+
fontSize: "14px",
|
|
3241
|
+
fontWeight: "500",
|
|
3242
|
+
color: "#ffffff",
|
|
3243
|
+
opacity: isSkipping ? 0.6 : 1
|
|
3244
|
+
},
|
|
3245
|
+
"data-testid": "button-skip-submit",
|
|
3246
|
+
children: isSkipping ? "Skipping..." : "Skip Question"
|
|
3247
|
+
}
|
|
3248
|
+
)
|
|
3249
|
+
] })
|
|
3250
|
+
] }) }),
|
|
3251
|
+
showReportModal && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: {
|
|
3252
|
+
position: "fixed",
|
|
3253
|
+
top: 0,
|
|
3254
|
+
left: 0,
|
|
3255
|
+
right: 0,
|
|
3256
|
+
bottom: 0,
|
|
3257
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
3258
|
+
display: "flex",
|
|
3259
|
+
alignItems: "center",
|
|
3260
|
+
justifyContent: "center",
|
|
3261
|
+
zIndex: 1e3
|
|
3262
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: {
|
|
3263
|
+
backgroundColor: "#ffffff",
|
|
3264
|
+
borderRadius: "12px",
|
|
3265
|
+
padding: "24px",
|
|
3266
|
+
maxWidth: "400px",
|
|
3267
|
+
width: "90%",
|
|
3268
|
+
boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
|
|
3269
|
+
}, children: [
|
|
3270
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Report Question" }),
|
|
3271
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { margin: "0 0 16px 0", fontSize: "14px", color: "#6b7280" }, children: "What's wrong with this question?" }),
|
|
3272
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { marginBottom: "16px" }, children: [
|
|
3273
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3274
|
+
"textarea",
|
|
3275
|
+
{
|
|
3276
|
+
value: reportComment,
|
|
3277
|
+
onChange: (e) => setReportComment(e.target.value.slice(0, 300)),
|
|
3278
|
+
placeholder: "Describe the issue with this question...",
|
|
3279
|
+
disabled: isReporting,
|
|
3280
|
+
style: {
|
|
3281
|
+
width: "100%",
|
|
3282
|
+
minHeight: "120px",
|
|
3283
|
+
padding: "10px 12px",
|
|
3284
|
+
borderRadius: "8px",
|
|
3285
|
+
border: "1px solid #e5e7eb",
|
|
3286
|
+
fontSize: "14px",
|
|
3287
|
+
resize: "vertical",
|
|
3288
|
+
fontFamily: "inherit",
|
|
3289
|
+
boxSizing: "border-box"
|
|
3290
|
+
},
|
|
3291
|
+
"data-testid": "input-report-comment"
|
|
3292
|
+
}
|
|
3293
|
+
),
|
|
3294
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
|
|
3295
|
+
reportComment.length,
|
|
3296
|
+
"/300"
|
|
3297
|
+
] })
|
|
3298
|
+
] }),
|
|
3299
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
3300
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3301
|
+
"button",
|
|
3302
|
+
{
|
|
3303
|
+
onClick: () => {
|
|
3304
|
+
setShowReportModal(false);
|
|
3305
|
+
setReportComment("");
|
|
3306
|
+
},
|
|
3307
|
+
style: {
|
|
3308
|
+
flex: 1,
|
|
3309
|
+
padding: "10px 16px",
|
|
3310
|
+
borderRadius: "8px",
|
|
3311
|
+
border: "1px solid #e5e7eb",
|
|
3312
|
+
backgroundColor: "#ffffff",
|
|
3313
|
+
cursor: "pointer",
|
|
3314
|
+
fontSize: "14px",
|
|
3315
|
+
fontWeight: "500",
|
|
3316
|
+
color: "#6b7280"
|
|
3317
|
+
},
|
|
3318
|
+
"data-testid": "button-report-cancel",
|
|
3319
|
+
children: "Cancel"
|
|
3320
|
+
}
|
|
3321
|
+
),
|
|
3322
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3323
|
+
"button",
|
|
3324
|
+
{
|
|
3325
|
+
onClick: () => handleReportQuestion(reportComment),
|
|
3326
|
+
disabled: isReporting || !reportComment.trim(),
|
|
3327
|
+
style: {
|
|
3328
|
+
flex: 1,
|
|
3329
|
+
padding: "10px 16px",
|
|
3330
|
+
borderRadius: "8px",
|
|
3331
|
+
border: "none",
|
|
3332
|
+
backgroundColor: reportComment.trim() ? "#ef4444" : "#d1d5db",
|
|
3333
|
+
cursor: isReporting || !reportComment.trim() ? "not-allowed" : "pointer",
|
|
3334
|
+
fontSize: "14px",
|
|
3335
|
+
fontWeight: "500",
|
|
3336
|
+
color: "#ffffff",
|
|
3337
|
+
opacity: isReporting ? 0.6 : 1
|
|
3338
|
+
},
|
|
3339
|
+
"data-testid": "button-report-submit",
|
|
3340
|
+
children: isReporting ? "Reporting..." : "Report"
|
|
3341
|
+
}
|
|
3342
|
+
)
|
|
3343
|
+
] })
|
|
3344
|
+
] }) }),
|
|
3345
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles.buttonsColumn, children: [
|
|
3346
|
+
showFeedback && isLastQuestion && canAddMore && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2858
3347
|
"button",
|
|
2859
3348
|
{
|
|
2860
|
-
onClick: () => {
|
|
2861
|
-
setShowReportModal(false);
|
|
2862
|
-
setReportComment("");
|
|
2863
|
-
},
|
|
2864
3349
|
style: {
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
borderRadius: "8px",
|
|
2868
|
-
border: "1px solid #e5e7eb",
|
|
2869
|
-
backgroundColor: "#ffffff",
|
|
2870
|
-
cursor: "pointer",
|
|
2871
|
-
fontSize: "14px",
|
|
2872
|
-
fontWeight: "500",
|
|
2873
|
-
color: "#6b7280"
|
|
3350
|
+
...defaultStyles.buttonAddMore,
|
|
3351
|
+
...isGeneratingExtra ? defaultStyles.buttonAddMoreDisabled : {}
|
|
2874
3352
|
},
|
|
2875
|
-
|
|
2876
|
-
|
|
3353
|
+
onClick: handleAddMoreQuestions,
|
|
3354
|
+
disabled: isGeneratingExtra,
|
|
3355
|
+
"data-testid": "button-add-more-questions",
|
|
3356
|
+
children: isGeneratingExtra ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
3357
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Spinner, { size: 16, color: "#9ca3af" }),
|
|
3358
|
+
"Generating Questions..."
|
|
3359
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
3360
|
+
"+ Add ",
|
|
3361
|
+
questionsToAdd,
|
|
3362
|
+
" More Question",
|
|
3363
|
+
questionsToAdd !== 1 ? "s" : ""
|
|
3364
|
+
] })
|
|
2877
3365
|
}
|
|
2878
3366
|
),
|
|
2879
|
-
/* @__PURE__ */ (0,
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { ...defaultStyles.buttons, justifyContent: "flex-end" }, children: showFeedback ? (
|
|
3368
|
+
// After viewing feedback
|
|
3369
|
+
isLastQuestion ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3370
|
+
"button",
|
|
3371
|
+
{
|
|
3372
|
+
style: {
|
|
3373
|
+
...defaultStyles.button,
|
|
3374
|
+
...isSubmitting || isGeneratingExtra ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
3375
|
+
},
|
|
3376
|
+
onClick: handleSubmit,
|
|
3377
|
+
disabled: isSubmitting || isGeneratingExtra,
|
|
3378
|
+
"data-testid": "button-submit-quiz",
|
|
3379
|
+
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Submit Quiz"
|
|
3380
|
+
}
|
|
3381
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3382
|
+
"button",
|
|
3383
|
+
{
|
|
3384
|
+
style: {
|
|
3385
|
+
...defaultStyles.button,
|
|
3386
|
+
...defaultStyles.buttonPrimary
|
|
3387
|
+
},
|
|
3388
|
+
onClick: handleContinue,
|
|
3389
|
+
"data-testid": "button-continue",
|
|
3390
|
+
children: "Continue"
|
|
3391
|
+
}
|
|
3392
|
+
)
|
|
3393
|
+
) : (
|
|
3394
|
+
// Before checking answer
|
|
3395
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3396
|
+
"button",
|
|
3397
|
+
{
|
|
3398
|
+
style: {
|
|
3399
|
+
...defaultStyles.button,
|
|
3400
|
+
...isNavigating || selectedAnswer === void 0 ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
3401
|
+
},
|
|
3402
|
+
onClick: handleCheckAnswer,
|
|
3403
|
+
disabled: isNavigating || selectedAnswer === void 0,
|
|
3404
|
+
"data-testid": "button-check-answer",
|
|
3405
|
+
children: isNavigating ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Check Answer"
|
|
3406
|
+
}
|
|
3407
|
+
)
|
|
3408
|
+
) })
|
|
2900
3409
|
] })
|
|
2901
|
-
] })
|
|
2902
|
-
/* @__PURE__ */ (0,
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
style: {
|
|
2930
|
-
...defaultStyles.button,
|
|
2931
|
-
...isSubmitting || isGeneratingExtra ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
2932
|
-
},
|
|
2933
|
-
onClick: handleSubmit,
|
|
2934
|
-
disabled: isSubmitting || isGeneratingExtra,
|
|
2935
|
-
"data-testid": "button-submit-quiz",
|
|
2936
|
-
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Submit Quiz"
|
|
2937
|
-
}
|
|
2938
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2939
|
-
"button",
|
|
2940
|
-
{
|
|
2941
|
-
style: {
|
|
2942
|
-
...defaultStyles.button,
|
|
2943
|
-
...defaultStyles.buttonPrimary
|
|
2944
|
-
},
|
|
2945
|
-
onClick: handleContinue,
|
|
2946
|
-
"data-testid": "button-continue",
|
|
2947
|
-
children: "Continue"
|
|
2948
|
-
}
|
|
2949
|
-
)
|
|
2950
|
-
) : (
|
|
2951
|
-
// Before checking answer
|
|
2952
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2953
|
-
"button",
|
|
2954
|
-
{
|
|
2955
|
-
style: {
|
|
2956
|
-
...defaultStyles.button,
|
|
2957
|
-
...isNavigating || selectedAnswer === void 0 ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
|
|
2958
|
-
},
|
|
2959
|
-
onClick: handleCheckAnswer,
|
|
2960
|
-
disabled: isNavigating || selectedAnswer === void 0,
|
|
2961
|
-
"data-testid": "button-check-answer",
|
|
2962
|
-
children: isNavigating ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Check Answer"
|
|
2963
|
-
}
|
|
2964
|
-
)
|
|
2965
|
-
) })
|
|
2966
|
-
] })
|
|
2967
|
-
] }),
|
|
2968
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.chatPanel, children: apiClient.current && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
2969
|
-
QuestionChatPanel,
|
|
2970
|
-
{
|
|
2971
|
-
apiClient: apiClient.current,
|
|
2972
|
-
question: {
|
|
2973
|
-
id: currentQuestion.id,
|
|
2974
|
-
question: currentQuestion.question,
|
|
2975
|
-
type: currentQuestion.type,
|
|
2976
|
-
options: currentQuestion.options,
|
|
2977
|
-
correctAnswer: currentQuestion.correctAnswer,
|
|
2978
|
-
explanation: currentQuestion.explanation
|
|
2979
|
-
},
|
|
2980
|
-
quizId: quiz.id,
|
|
2981
|
-
childId,
|
|
2982
|
-
parentId,
|
|
2983
|
-
lessonId,
|
|
2984
|
-
courseId,
|
|
2985
|
-
answerResult: showFeedback && currentAnswerDetail ? {
|
|
2986
|
-
wasIncorrect: currentQuestion.type !== "assessment" && !currentAnswerDetail.isCorrect,
|
|
2987
|
-
selectedAnswer: typeof selectedAnswer === "string" ? selectedAnswer : Array.isArray(selectedAnswer) ? selectedAnswer.join(", ") : void 0,
|
|
2988
|
-
correctAnswer: typeof currentQuestion.correctAnswer === "string" ? currentQuestion.correctAnswer : Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer.join(", ") : void 0,
|
|
2989
|
-
explanation: currentQuestion.explanation
|
|
2990
|
-
} : void 0
|
|
2991
|
-
}
|
|
2992
|
-
) })
|
|
2993
|
-
] }) });
|
|
3410
|
+
] }),
|
|
3411
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles.chatPanel, children: apiClient.current && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
3412
|
+
QuestionChatPanel,
|
|
3413
|
+
{
|
|
3414
|
+
apiClient: apiClient.current,
|
|
3415
|
+
question: {
|
|
3416
|
+
id: currentQuestion.id,
|
|
3417
|
+
question: currentQuestion.question,
|
|
3418
|
+
type: currentQuestion.type,
|
|
3419
|
+
options: currentQuestion.options,
|
|
3420
|
+
correctAnswer: currentQuestion.correctAnswer,
|
|
3421
|
+
explanation: currentQuestion.explanation
|
|
3422
|
+
},
|
|
3423
|
+
quizId: quiz.id,
|
|
3424
|
+
childId,
|
|
3425
|
+
parentId,
|
|
3426
|
+
lessonId,
|
|
3427
|
+
courseId,
|
|
3428
|
+
answerResult: showFeedback && currentAnswerDetail ? {
|
|
3429
|
+
wasIncorrect: currentQuestion.type !== "assessment" && !currentAnswerDetail.isCorrect,
|
|
3430
|
+
selectedAnswer: typeof selectedAnswer === "string" ? selectedAnswer : Array.isArray(selectedAnswer) ? selectedAnswer.join(", ") : void 0,
|
|
3431
|
+
correctAnswer: typeof currentQuestion.correctAnswer === "string" ? currentQuestion.correctAnswer : Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer.join(", ") : void 0,
|
|
3432
|
+
explanation: currentQuestion.explanation
|
|
3433
|
+
} : void 0
|
|
3434
|
+
}
|
|
3435
|
+
) })
|
|
3436
|
+
] })
|
|
3437
|
+
] });
|
|
2994
3438
|
}
|
|
2995
3439
|
|
|
2996
3440
|
// src/AttemptViewer.tsx
|
|
2997
3441
|
var import_react4 = require("react");
|
|
2998
|
-
var
|
|
3442
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2999
3443
|
var defaultStyles2 = {
|
|
3000
3444
|
container: {
|
|
3001
3445
|
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
@@ -3138,7 +3582,12 @@ var defaultStyles2 = {
|
|
|
3138
3582
|
marginTop: "12px",
|
|
3139
3583
|
display: "flex",
|
|
3140
3584
|
flexDirection: "column",
|
|
3141
|
-
gap: "8px"
|
|
3585
|
+
gap: "8px",
|
|
3586
|
+
backgroundColor: "#ffffff",
|
|
3587
|
+
padding: "16px",
|
|
3588
|
+
borderRadius: "8px",
|
|
3589
|
+
border: "1px solid #e5e7eb",
|
|
3590
|
+
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.05)"
|
|
3142
3591
|
},
|
|
3143
3592
|
chatMessage: {
|
|
3144
3593
|
padding: "8px 12px",
|
|
@@ -3248,23 +3697,39 @@ function AttemptViewer({
|
|
|
3248
3697
|
}) {
|
|
3249
3698
|
const [attempt, setAttempt] = (0, import_react4.useState)(null);
|
|
3250
3699
|
const [loading, setLoading] = (0, import_react4.useState)(true);
|
|
3251
|
-
const [
|
|
3700
|
+
const [errorCode, setErrorCode] = (0, import_react4.useState)(null);
|
|
3252
3701
|
const [chatHistories, setChatHistories] = (0, import_react4.useState)({});
|
|
3253
3702
|
const [expandedChats, setExpandedChats] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
3703
|
+
const [fetchedAttemptId, setFetchedAttemptId] = (0, import_react4.useState)(null);
|
|
3704
|
+
const onErrorRef = (0, import_react4.useRef)(onError);
|
|
3705
|
+
onErrorRef.current = onError;
|
|
3254
3706
|
(0, import_react4.useEffect)(() => {
|
|
3707
|
+
if (fetchedAttemptId === attemptId) return;
|
|
3255
3708
|
const apiClient = new QuizApiClient({
|
|
3256
3709
|
baseUrl: apiBaseUrl,
|
|
3257
3710
|
authToken
|
|
3258
3711
|
});
|
|
3259
3712
|
async function fetchAttempt() {
|
|
3260
3713
|
setLoading(true);
|
|
3261
|
-
|
|
3714
|
+
setErrorCode(null);
|
|
3262
3715
|
try {
|
|
3263
3716
|
const response = await fetch(`${apiBaseUrl}/api/external/quiz-attempts/${attemptId}`, {
|
|
3264
3717
|
headers: authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
3265
3718
|
});
|
|
3266
3719
|
if (!response.ok) {
|
|
3267
|
-
|
|
3720
|
+
const code = getErrorFromHttpStatus(response.status, "attempt");
|
|
3721
|
+
setErrorCode(code);
|
|
3722
|
+
apiClient.logError({
|
|
3723
|
+
errorCode: code,
|
|
3724
|
+
context: "attempt",
|
|
3725
|
+
resourceId: attemptId,
|
|
3726
|
+
component: "AttemptViewer",
|
|
3727
|
+
message: `HTTP ${response.status}: ${response.statusText}`
|
|
3728
|
+
});
|
|
3729
|
+
onErrorRef.current?.(new Error(`Failed to fetch attempt: ${response.statusText}`));
|
|
3730
|
+
setLoading(false);
|
|
3731
|
+
setFetchedAttemptId(attemptId);
|
|
3732
|
+
return;
|
|
3268
3733
|
}
|
|
3269
3734
|
const data = await response.json();
|
|
3270
3735
|
setAttempt(data);
|
|
@@ -3278,14 +3743,23 @@ function AttemptViewer({
|
|
|
3278
3743
|
}
|
|
3279
3744
|
} catch (err) {
|
|
3280
3745
|
const errorMessage = err instanceof Error ? err.message : "Failed to load attempt";
|
|
3281
|
-
|
|
3282
|
-
|
|
3746
|
+
const code = getErrorFromMessage(errorMessage, "attempt");
|
|
3747
|
+
setErrorCode(code);
|
|
3748
|
+
apiClient.logError({
|
|
3749
|
+
errorCode: code,
|
|
3750
|
+
context: "attempt",
|
|
3751
|
+
resourceId: attemptId,
|
|
3752
|
+
component: "AttemptViewer",
|
|
3753
|
+
message: errorMessage
|
|
3754
|
+
});
|
|
3755
|
+
onErrorRef.current?.(err instanceof Error ? err : new Error(errorMessage));
|
|
3283
3756
|
} finally {
|
|
3284
3757
|
setLoading(false);
|
|
3758
|
+
setFetchedAttemptId(attemptId);
|
|
3285
3759
|
}
|
|
3286
3760
|
}
|
|
3287
3761
|
fetchAttempt();
|
|
3288
|
-
}, [attemptId, apiBaseUrl, authToken,
|
|
3762
|
+
}, [attemptId, apiBaseUrl, authToken, showConversation, fetchedAttemptId]);
|
|
3289
3763
|
const toggleChatExpanded = (questionId) => {
|
|
3290
3764
|
setExpandedChats((prev) => {
|
|
3291
3765
|
const newSet = new Set(prev);
|
|
@@ -3299,53 +3773,49 @@ function AttemptViewer({
|
|
|
3299
3773
|
};
|
|
3300
3774
|
const handleRetry = () => {
|
|
3301
3775
|
setLoading(true);
|
|
3302
|
-
|
|
3776
|
+
setErrorCode(null);
|
|
3303
3777
|
window.location.reload();
|
|
3304
3778
|
};
|
|
3305
3779
|
if (loading) {
|
|
3306
|
-
return /* @__PURE__ */ (0,
|
|
3307
|
-
/* @__PURE__ */ (0,
|
|
3308
|
-
/* @__PURE__ */ (0,
|
|
3309
|
-
/* @__PURE__ */ (0,
|
|
3310
|
-
/* @__PURE__ */ (0,
|
|
3780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.container, className, children: [
|
|
3781
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: spinnerKeyframes }),
|
|
3782
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.loading, children: [
|
|
3783
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.spinner }),
|
|
3784
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { style: { marginTop: "16px", color: "#6b7280" }, children: "Loading attempt..." })
|
|
3311
3785
|
] })
|
|
3312
3786
|
] });
|
|
3313
3787
|
}
|
|
3314
|
-
if (
|
|
3315
|
-
return /* @__PURE__ */ (0,
|
|
3316
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { fontSize: "18px", fontWeight: "500" }, children: "Failed to load attempt" }),
|
|
3317
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { style: { marginTop: "8px", color: "#6b7280" }, children: error }),
|
|
3318
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { style: defaultStyles2.retryButton, onClick: handleRetry, children: "Try Again" })
|
|
3319
|
-
] }) });
|
|
3788
|
+
if (errorCode || !attempt) {
|
|
3789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.container, className, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MaintenanceScreen, { errorCode: errorCode || "ATTEMPT_NOT_FOUND" }) });
|
|
3320
3790
|
}
|
|
3321
3791
|
const scorePercentage = attempt.score ?? 0;
|
|
3322
3792
|
const correctCount = attempt.correctAnswers ?? 0;
|
|
3323
3793
|
const totalQuestions = attempt.totalQuestions;
|
|
3324
3794
|
const timeSpent = attempt.timeSpentSeconds ?? 0;
|
|
3325
|
-
return /* @__PURE__ */ (0,
|
|
3326
|
-
/* @__PURE__ */ (0,
|
|
3327
|
-
/* @__PURE__ */ (0,
|
|
3328
|
-
/* @__PURE__ */ (0,
|
|
3329
|
-
/* @__PURE__ */ (0,
|
|
3795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.container, className, children: [
|
|
3796
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("style", { children: spinnerKeyframes }),
|
|
3797
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.header, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryGrid, children: [
|
|
3798
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryValue, children: [
|
|
3330
3800
|
scorePercentage,
|
|
3331
3801
|
"%"
|
|
3332
3802
|
] }),
|
|
3333
|
-
/* @__PURE__ */ (0,
|
|
3803
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Score" })
|
|
3334
3804
|
] }),
|
|
3335
|
-
/* @__PURE__ */ (0,
|
|
3336
|
-
/* @__PURE__ */ (0,
|
|
3805
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
3806
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryValue, children: [
|
|
3337
3807
|
correctCount,
|
|
3338
3808
|
"/",
|
|
3339
3809
|
totalQuestions
|
|
3340
3810
|
] }),
|
|
3341
|
-
/* @__PURE__ */ (0,
|
|
3811
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Correct" })
|
|
3342
3812
|
] }),
|
|
3343
|
-
/* @__PURE__ */ (0,
|
|
3344
|
-
/* @__PURE__ */ (0,
|
|
3345
|
-
/* @__PURE__ */ (0,
|
|
3813
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.summaryCard, children: [
|
|
3814
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.summaryValue, children: formatTime(timeSpent) }),
|
|
3815
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.summaryLabel, children: "Time" })
|
|
3346
3816
|
] })
|
|
3347
3817
|
] }) }),
|
|
3348
|
-
/* @__PURE__ */ (0,
|
|
3818
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.questionsList, children: attempt.answers.map((answer, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3349
3819
|
"div",
|
|
3350
3820
|
{
|
|
3351
3821
|
style: {
|
|
@@ -3353,12 +3823,12 @@ function AttemptViewer({
|
|
|
3353
3823
|
...answer.isCorrect ? defaultStyles2.questionCardCorrect : defaultStyles2.questionCardIncorrect
|
|
3354
3824
|
},
|
|
3355
3825
|
children: [
|
|
3356
|
-
/* @__PURE__ */ (0,
|
|
3357
|
-
/* @__PURE__ */ (0,
|
|
3826
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.questionHeader, children: [
|
|
3827
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: defaultStyles2.questionNumber, children: [
|
|
3358
3828
|
"Question ",
|
|
3359
3829
|
index + 1
|
|
3360
3830
|
] }),
|
|
3361
|
-
/* @__PURE__ */ (0,
|
|
3831
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3362
3832
|
"span",
|
|
3363
3833
|
{
|
|
3364
3834
|
style: {
|
|
@@ -3369,35 +3839,35 @@ function AttemptViewer({
|
|
|
3369
3839
|
}
|
|
3370
3840
|
)
|
|
3371
3841
|
] }),
|
|
3372
|
-
/* @__PURE__ */ (0,
|
|
3373
|
-
/* @__PURE__ */ (0,
|
|
3374
|
-
/* @__PURE__ */ (0,
|
|
3375
|
-
/* @__PURE__ */ (0,
|
|
3842
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.questionText, children: answer.questionText }),
|
|
3843
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.answerSection, children: [
|
|
3844
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: defaultStyles2.answerLabel, children: "Your answer:" }),
|
|
3845
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: defaultStyles2.studentAnswer, children: formatAnswer(answer.selectedAnswer, answer.questionType, answer.items, answer.leftItems) })
|
|
3376
3846
|
] }),
|
|
3377
|
-
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ (0,
|
|
3378
|
-
/* @__PURE__ */ (0,
|
|
3379
|
-
/* @__PURE__ */ (0,
|
|
3847
|
+
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.answerSection, children: [
|
|
3848
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: defaultStyles2.answerLabel, children: "Correct answer:" }),
|
|
3849
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("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) })
|
|
3380
3850
|
] }),
|
|
3381
|
-
/* @__PURE__ */ (0,
|
|
3851
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.points, children: [
|
|
3382
3852
|
answer.pointsEarned,
|
|
3383
3853
|
" / ",
|
|
3384
3854
|
answer.points,
|
|
3385
3855
|
" points"
|
|
3386
3856
|
] }),
|
|
3387
|
-
showExplanations && answer.explanation && /* @__PURE__ */ (0,
|
|
3388
|
-
/* @__PURE__ */ (0,
|
|
3857
|
+
showExplanations && answer.explanation && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.explanation, children: [
|
|
3858
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: "Explanation:" }),
|
|
3389
3859
|
" ",
|
|
3390
3860
|
answer.explanation
|
|
3391
3861
|
] }),
|
|
3392
|
-
showConversation && chatHistories[answer.questionId] && chatHistories[answer.questionId].messages.length > 0 && /* @__PURE__ */ (0,
|
|
3393
|
-
/* @__PURE__ */ (0,
|
|
3862
|
+
showConversation && chatHistories[answer.questionId] && chatHistories[answer.questionId].messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: defaultStyles2.chatHistorySection, children: [
|
|
3863
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
3394
3864
|
"button",
|
|
3395
3865
|
{
|
|
3396
3866
|
style: defaultStyles2.chatToggleButton,
|
|
3397
3867
|
onClick: () => toggleChatExpanded(answer.questionId),
|
|
3398
3868
|
"data-testid": `button-toggle-chat-${answer.questionId}`,
|
|
3399
3869
|
children: [
|
|
3400
|
-
/* @__PURE__ */ (0,
|
|
3870
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) }),
|
|
3401
3871
|
expandedChats.has(answer.questionId) ? "Hide" : "View",
|
|
3402
3872
|
" Chat History (",
|
|
3403
3873
|
chatHistories[answer.questionId].messages.length,
|
|
@@ -3405,7 +3875,7 @@ function AttemptViewer({
|
|
|
3405
3875
|
]
|
|
3406
3876
|
}
|
|
3407
3877
|
),
|
|
3408
|
-
expandedChats.has(answer.questionId) && /* @__PURE__ */ (0,
|
|
3878
|
+
expandedChats.has(answer.questionId) && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: defaultStyles2.chatMessages, children: chatHistories[answer.questionId].messages.map((msg, msgIndex) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
3409
3879
|
"div",
|
|
3410
3880
|
{
|
|
3411
3881
|
style: {
|
|
@@ -3423,15 +3893,621 @@ function AttemptViewer({
|
|
|
3423
3893
|
)) })
|
|
3424
3894
|
] });
|
|
3425
3895
|
}
|
|
3896
|
+
|
|
3897
|
+
// src/ErrorTypesPanel.tsx
|
|
3898
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
3899
|
+
var panelStyles2 = {
|
|
3900
|
+
container: {
|
|
3901
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
3902
|
+
padding: "24px",
|
|
3903
|
+
backgroundColor: "#ffffff",
|
|
3904
|
+
borderRadius: "12px",
|
|
3905
|
+
maxWidth: "800px"
|
|
3906
|
+
},
|
|
3907
|
+
header: {
|
|
3908
|
+
marginBottom: "24px"
|
|
3909
|
+
},
|
|
3910
|
+
title: {
|
|
3911
|
+
fontSize: "20px",
|
|
3912
|
+
fontWeight: "600",
|
|
3913
|
+
color: "#111827",
|
|
3914
|
+
marginBottom: "8px"
|
|
3915
|
+
},
|
|
3916
|
+
subtitle: {
|
|
3917
|
+
fontSize: "14px",
|
|
3918
|
+
color: "#6b7280"
|
|
3919
|
+
},
|
|
3920
|
+
section: {
|
|
3921
|
+
marginBottom: "24px"
|
|
3922
|
+
},
|
|
3923
|
+
sectionTitle: {
|
|
3924
|
+
fontSize: "14px",
|
|
3925
|
+
fontWeight: "600",
|
|
3926
|
+
color: "#374151",
|
|
3927
|
+
marginBottom: "12px",
|
|
3928
|
+
textTransform: "uppercase",
|
|
3929
|
+
letterSpacing: "0.05em"
|
|
3930
|
+
},
|
|
3931
|
+
errorList: {
|
|
3932
|
+
display: "flex",
|
|
3933
|
+
flexDirection: "column",
|
|
3934
|
+
gap: "12px"
|
|
3935
|
+
},
|
|
3936
|
+
errorCard: {
|
|
3937
|
+
padding: "16px",
|
|
3938
|
+
backgroundColor: "#f9fafb",
|
|
3939
|
+
borderRadius: "8px",
|
|
3940
|
+
border: "1px solid #e5e7eb"
|
|
3941
|
+
},
|
|
3942
|
+
errorCardBlocking: {
|
|
3943
|
+
borderLeft: "4px solid #ef4444"
|
|
3944
|
+
},
|
|
3945
|
+
errorCardNonBlocking: {
|
|
3946
|
+
borderLeft: "4px solid #f59e0b"
|
|
3947
|
+
},
|
|
3948
|
+
errorHeader: {
|
|
3949
|
+
display: "flex",
|
|
3950
|
+
justifyContent: "space-between",
|
|
3951
|
+
alignItems: "flex-start",
|
|
3952
|
+
marginBottom: "8px"
|
|
3953
|
+
},
|
|
3954
|
+
errorCode: {
|
|
3955
|
+
fontSize: "13px",
|
|
3956
|
+
fontWeight: "600",
|
|
3957
|
+
color: "#1f2937",
|
|
3958
|
+
fontFamily: "monospace",
|
|
3959
|
+
backgroundColor: "#e5e7eb",
|
|
3960
|
+
padding: "2px 8px",
|
|
3961
|
+
borderRadius: "4px"
|
|
3962
|
+
},
|
|
3963
|
+
errorBadge: {
|
|
3964
|
+
fontSize: "11px",
|
|
3965
|
+
fontWeight: "500",
|
|
3966
|
+
padding: "2px 8px",
|
|
3967
|
+
borderRadius: "12px"
|
|
3968
|
+
},
|
|
3969
|
+
blockingBadge: {
|
|
3970
|
+
backgroundColor: "#fee2e2",
|
|
3971
|
+
color: "#dc2626"
|
|
3972
|
+
},
|
|
3973
|
+
nonBlockingBadge: {
|
|
3974
|
+
backgroundColor: "#fef3c7",
|
|
3975
|
+
color: "#d97706"
|
|
3976
|
+
},
|
|
3977
|
+
userMessage: {
|
|
3978
|
+
fontSize: "15px",
|
|
3979
|
+
fontWeight: "500",
|
|
3980
|
+
color: "#111827",
|
|
3981
|
+
marginBottom: "4px"
|
|
3982
|
+
},
|
|
3983
|
+
subMessage: {
|
|
3984
|
+
fontSize: "13px",
|
|
3985
|
+
color: "#6b7280",
|
|
3986
|
+
marginBottom: "8px"
|
|
3987
|
+
},
|
|
3988
|
+
causeLabel: {
|
|
3989
|
+
fontSize: "11px",
|
|
3990
|
+
fontWeight: "600",
|
|
3991
|
+
color: "#9ca3af",
|
|
3992
|
+
textTransform: "uppercase",
|
|
3993
|
+
marginBottom: "4px"
|
|
3994
|
+
},
|
|
3995
|
+
causeText: {
|
|
3996
|
+
fontSize: "13px",
|
|
3997
|
+
color: "#4b5563",
|
|
3998
|
+
fontStyle: "italic"
|
|
3999
|
+
}
|
|
4000
|
+
};
|
|
4001
|
+
function ErrorTypesPanel({ className }) {
|
|
4002
|
+
const blockingErrors = Object.values(ERROR_DEFINITIONS).filter((e) => e.isBlocking);
|
|
4003
|
+
const nonBlockingErrors = Object.values(ERROR_DEFINITIONS).filter((e) => !e.isBlocking);
|
|
4004
|
+
const renderErrorCard = (error) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
4005
|
+
"div",
|
|
4006
|
+
{
|
|
4007
|
+
style: {
|
|
4008
|
+
...panelStyles2.errorCard,
|
|
4009
|
+
...error.isBlocking ? panelStyles2.errorCardBlocking : panelStyles2.errorCardNonBlocking
|
|
4010
|
+
},
|
|
4011
|
+
"data-testid": `error-card-${error.code}`,
|
|
4012
|
+
children: [
|
|
4013
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: panelStyles2.errorHeader, children: [
|
|
4014
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { style: panelStyles2.errorCode, children: error.code }),
|
|
4015
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
4016
|
+
"span",
|
|
4017
|
+
{
|
|
4018
|
+
style: {
|
|
4019
|
+
...panelStyles2.errorBadge,
|
|
4020
|
+
...error.isBlocking ? panelStyles2.blockingBadge : panelStyles2.nonBlockingBadge
|
|
4021
|
+
},
|
|
4022
|
+
children: error.isBlocking ? "Blocking" : "Non-Blocking"
|
|
4023
|
+
}
|
|
4024
|
+
)
|
|
4025
|
+
] }),
|
|
4026
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.userMessage, children: error.userMessage }),
|
|
4027
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.subMessage, children: error.subMessage }),
|
|
4028
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.causeLabel, children: "Why this happens:" }),
|
|
4029
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.causeText, children: error.cause })
|
|
4030
|
+
]
|
|
4031
|
+
},
|
|
4032
|
+
error.code
|
|
4033
|
+
);
|
|
4034
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: panelStyles2.container, className, "data-testid": "error-types-panel", children: [
|
|
4035
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: panelStyles2.header, children: [
|
|
4036
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { style: panelStyles2.title, children: "Error Types Reference" }),
|
|
4037
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: panelStyles2.subtitle, children: "List of all error types that can occur in the quiz components, with user-facing messages and technical causes." })
|
|
4038
|
+
] }),
|
|
4039
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: panelStyles2.section, children: [
|
|
4040
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h3", { style: panelStyles2.sectionTitle, children: [
|
|
4041
|
+
"Blocking Errors (",
|
|
4042
|
+
blockingErrors.length,
|
|
4043
|
+
")"
|
|
4044
|
+
] }),
|
|
4045
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { ...panelStyles2.subtitle, marginBottom: "12px" }, children: "These errors prevent the quiz from loading or continuing. Users see a full-screen error message." }),
|
|
4046
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.errorList, children: blockingErrors.map(renderErrorCard) })
|
|
4047
|
+
] }),
|
|
4048
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: panelStyles2.section, children: [
|
|
4049
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h3", { style: panelStyles2.sectionTitle, children: [
|
|
4050
|
+
"Non-Blocking Errors (",
|
|
4051
|
+
nonBlockingErrors.length,
|
|
4052
|
+
")"
|
|
4053
|
+
] }),
|
|
4054
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { ...panelStyles2.subtitle, marginBottom: "12px" }, children: "These errors affect specific features but allow the quiz to continue. Users may see a toast notification." }),
|
|
4055
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: panelStyles2.errorList, children: nonBlockingErrors.map(renderErrorCard) })
|
|
4056
|
+
] })
|
|
4057
|
+
] });
|
|
4058
|
+
}
|
|
4059
|
+
|
|
4060
|
+
// src/ErrorLogsPanel.tsx
|
|
4061
|
+
var import_react5 = require("react");
|
|
4062
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
4063
|
+
var panelStyles3 = {
|
|
4064
|
+
container: {
|
|
4065
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
4066
|
+
padding: "24px",
|
|
4067
|
+
backgroundColor: "#ffffff",
|
|
4068
|
+
borderRadius: "12px",
|
|
4069
|
+
maxWidth: "1000px"
|
|
4070
|
+
},
|
|
4071
|
+
header: {
|
|
4072
|
+
marginBottom: "24px"
|
|
4073
|
+
},
|
|
4074
|
+
title: {
|
|
4075
|
+
fontSize: "20px",
|
|
4076
|
+
fontWeight: "600",
|
|
4077
|
+
color: "#111827",
|
|
4078
|
+
marginBottom: "8px"
|
|
4079
|
+
},
|
|
4080
|
+
subtitle: {
|
|
4081
|
+
fontSize: "14px",
|
|
4082
|
+
color: "#6b7280"
|
|
4083
|
+
},
|
|
4084
|
+
tabs: {
|
|
4085
|
+
display: "flex",
|
|
4086
|
+
gap: "8px",
|
|
4087
|
+
marginBottom: "16px",
|
|
4088
|
+
borderBottom: "1px solid #e5e7eb",
|
|
4089
|
+
paddingBottom: "12px"
|
|
4090
|
+
},
|
|
4091
|
+
tab: {
|
|
4092
|
+
padding: "8px 16px",
|
|
4093
|
+
fontSize: "14px",
|
|
4094
|
+
fontWeight: "500",
|
|
4095
|
+
borderRadius: "6px",
|
|
4096
|
+
cursor: "pointer",
|
|
4097
|
+
border: "none",
|
|
4098
|
+
backgroundColor: "transparent",
|
|
4099
|
+
color: "#6b7280"
|
|
4100
|
+
},
|
|
4101
|
+
tabActive: {
|
|
4102
|
+
backgroundColor: "#6721b0",
|
|
4103
|
+
color: "#ffffff"
|
|
4104
|
+
},
|
|
4105
|
+
stats: {
|
|
4106
|
+
display: "flex",
|
|
4107
|
+
gap: "16px",
|
|
4108
|
+
marginBottom: "20px"
|
|
4109
|
+
},
|
|
4110
|
+
statCard: {
|
|
4111
|
+
padding: "12px 16px",
|
|
4112
|
+
backgroundColor: "#f9fafb",
|
|
4113
|
+
borderRadius: "8px",
|
|
4114
|
+
flex: 1
|
|
4115
|
+
},
|
|
4116
|
+
statValue: {
|
|
4117
|
+
fontSize: "24px",
|
|
4118
|
+
fontWeight: "700",
|
|
4119
|
+
color: "#111827"
|
|
4120
|
+
},
|
|
4121
|
+
statLabel: {
|
|
4122
|
+
fontSize: "12px",
|
|
4123
|
+
color: "#6b7280",
|
|
4124
|
+
textTransform: "uppercase",
|
|
4125
|
+
letterSpacing: "0.05em"
|
|
4126
|
+
},
|
|
4127
|
+
errorList: {
|
|
4128
|
+
display: "flex",
|
|
4129
|
+
flexDirection: "column",
|
|
4130
|
+
gap: "12px"
|
|
4131
|
+
},
|
|
4132
|
+
errorCard: {
|
|
4133
|
+
padding: "16px",
|
|
4134
|
+
backgroundColor: "#f9fafb",
|
|
4135
|
+
borderRadius: "8px",
|
|
4136
|
+
border: "1px solid #e5e7eb"
|
|
4137
|
+
},
|
|
4138
|
+
errorCardRecent: {
|
|
4139
|
+
borderLeft: "4px solid #ef4444",
|
|
4140
|
+
backgroundColor: "#fef2f2"
|
|
4141
|
+
},
|
|
4142
|
+
errorCardOld: {
|
|
4143
|
+
borderLeft: "4px solid #9ca3af",
|
|
4144
|
+
opacity: 0.7
|
|
4145
|
+
},
|
|
4146
|
+
errorHeader: {
|
|
4147
|
+
display: "flex",
|
|
4148
|
+
justifyContent: "space-between",
|
|
4149
|
+
alignItems: "flex-start",
|
|
4150
|
+
marginBottom: "8px"
|
|
4151
|
+
},
|
|
4152
|
+
errorLeft: {
|
|
4153
|
+
flex: 1
|
|
4154
|
+
},
|
|
4155
|
+
errorCode: {
|
|
4156
|
+
fontSize: "13px",
|
|
4157
|
+
fontWeight: "600",
|
|
4158
|
+
color: "#1f2937",
|
|
4159
|
+
fontFamily: "monospace",
|
|
4160
|
+
backgroundColor: "#e5e7eb",
|
|
4161
|
+
padding: "2px 8px",
|
|
4162
|
+
borderRadius: "4px",
|
|
4163
|
+
display: "inline-block"
|
|
4164
|
+
},
|
|
4165
|
+
countBadge: {
|
|
4166
|
+
fontSize: "14px",
|
|
4167
|
+
fontWeight: "700",
|
|
4168
|
+
padding: "4px 12px",
|
|
4169
|
+
borderRadius: "16px",
|
|
4170
|
+
backgroundColor: "#ef4444",
|
|
4171
|
+
color: "#ffffff"
|
|
4172
|
+
},
|
|
4173
|
+
countBadgeLow: {
|
|
4174
|
+
backgroundColor: "#f59e0b"
|
|
4175
|
+
},
|
|
4176
|
+
contextBadge: {
|
|
4177
|
+
fontSize: "11px",
|
|
4178
|
+
fontWeight: "500",
|
|
4179
|
+
padding: "2px 8px",
|
|
4180
|
+
borderRadius: "4px",
|
|
4181
|
+
marginLeft: "8px",
|
|
4182
|
+
backgroundColor: "#dbeafe",
|
|
4183
|
+
color: "#1d4ed8"
|
|
4184
|
+
},
|
|
4185
|
+
userMessage: {
|
|
4186
|
+
fontSize: "15px",
|
|
4187
|
+
fontWeight: "500",
|
|
4188
|
+
color: "#111827",
|
|
4189
|
+
marginTop: "8px",
|
|
4190
|
+
marginBottom: "4px"
|
|
4191
|
+
},
|
|
4192
|
+
resourceId: {
|
|
4193
|
+
fontSize: "12px",
|
|
4194
|
+
color: "#6b7280",
|
|
4195
|
+
fontFamily: "monospace",
|
|
4196
|
+
marginTop: "4px"
|
|
4197
|
+
},
|
|
4198
|
+
resourceLink: {
|
|
4199
|
+
color: "#6721b0",
|
|
4200
|
+
textDecoration: "underline",
|
|
4201
|
+
cursor: "pointer"
|
|
4202
|
+
},
|
|
4203
|
+
timestamps: {
|
|
4204
|
+
display: "flex",
|
|
4205
|
+
gap: "16px",
|
|
4206
|
+
marginTop: "8px",
|
|
4207
|
+
fontSize: "12px",
|
|
4208
|
+
color: "#9ca3af"
|
|
4209
|
+
},
|
|
4210
|
+
dismissButton: {
|
|
4211
|
+
padding: "6px 12px",
|
|
4212
|
+
fontSize: "12px",
|
|
4213
|
+
fontWeight: "500",
|
|
4214
|
+
borderRadius: "4px",
|
|
4215
|
+
cursor: "pointer",
|
|
4216
|
+
border: "1px solid #e5e7eb",
|
|
4217
|
+
backgroundColor: "#ffffff",
|
|
4218
|
+
color: "#6b7280",
|
|
4219
|
+
marginTop: "8px"
|
|
4220
|
+
},
|
|
4221
|
+
dismissButtonHover: {
|
|
4222
|
+
backgroundColor: "#f3f4f6"
|
|
4223
|
+
},
|
|
4224
|
+
emptyState: {
|
|
4225
|
+
textAlign: "center",
|
|
4226
|
+
padding: "40px",
|
|
4227
|
+
color: "#9ca3af",
|
|
4228
|
+
fontSize: "14px"
|
|
4229
|
+
},
|
|
4230
|
+
loading: {
|
|
4231
|
+
textAlign: "center",
|
|
4232
|
+
padding: "40px",
|
|
4233
|
+
color: "#6b7280",
|
|
4234
|
+
fontSize: "14px"
|
|
4235
|
+
},
|
|
4236
|
+
pagination: {
|
|
4237
|
+
display: "flex",
|
|
4238
|
+
justifyContent: "center",
|
|
4239
|
+
gap: "8px",
|
|
4240
|
+
marginTop: "20px"
|
|
4241
|
+
},
|
|
4242
|
+
pageButton: {
|
|
4243
|
+
padding: "8px 12px",
|
|
4244
|
+
fontSize: "14px",
|
|
4245
|
+
borderRadius: "4px",
|
|
4246
|
+
cursor: "pointer",
|
|
4247
|
+
border: "1px solid #e5e7eb",
|
|
4248
|
+
backgroundColor: "#ffffff",
|
|
4249
|
+
color: "#374151"
|
|
4250
|
+
},
|
|
4251
|
+
pageButtonDisabled: {
|
|
4252
|
+
opacity: 0.5,
|
|
4253
|
+
cursor: "not-allowed"
|
|
4254
|
+
}
|
|
4255
|
+
};
|
|
4256
|
+
function formatRelativeTime(dateStr) {
|
|
4257
|
+
const date = new Date(dateStr);
|
|
4258
|
+
const now = /* @__PURE__ */ new Date();
|
|
4259
|
+
const diffMs = now.getTime() - date.getTime();
|
|
4260
|
+
const diffMins = Math.floor(diffMs / 6e4);
|
|
4261
|
+
const diffHours = Math.floor(diffMs / 36e5);
|
|
4262
|
+
const diffDays = Math.floor(diffMs / 864e5);
|
|
4263
|
+
if (diffMins < 1) return "Just now";
|
|
4264
|
+
if (diffMins < 60) return `${diffMins}m ago`;
|
|
4265
|
+
if (diffHours < 24) return `${diffHours}h ago`;
|
|
4266
|
+
if (diffDays < 7) return `${diffDays}d ago`;
|
|
4267
|
+
return date.toLocaleDateString();
|
|
4268
|
+
}
|
|
4269
|
+
function isRecent(dateStr) {
|
|
4270
|
+
const date = new Date(dateStr);
|
|
4271
|
+
const now = /* @__PURE__ */ new Date();
|
|
4272
|
+
const diffMs = now.getTime() - date.getTime();
|
|
4273
|
+
const diffHours = diffMs / 36e5;
|
|
4274
|
+
return diffHours < 24;
|
|
4275
|
+
}
|
|
4276
|
+
function ErrorLogsPanel({ apiBaseUrl, authToken, onResourceClick }) {
|
|
4277
|
+
const [logs, setLogs] = (0, import_react5.useState)([]);
|
|
4278
|
+
const [loading, setLoading] = (0, import_react5.useState)(true);
|
|
4279
|
+
const [showDismissed, setShowDismissed] = (0, import_react5.useState)(false);
|
|
4280
|
+
const [page, setPage] = (0, import_react5.useState)(1);
|
|
4281
|
+
const [totalPages, setTotalPages] = (0, import_react5.useState)(1);
|
|
4282
|
+
const [total, setTotal] = (0, import_react5.useState)(0);
|
|
4283
|
+
(0, import_react5.useEffect)(() => {
|
|
4284
|
+
fetchLogs();
|
|
4285
|
+
}, [showDismissed, page]);
|
|
4286
|
+
async function fetchLogs() {
|
|
4287
|
+
setLoading(true);
|
|
4288
|
+
try {
|
|
4289
|
+
const params = new URLSearchParams();
|
|
4290
|
+
params.set("dismissed", showDismissed ? "true" : "false");
|
|
4291
|
+
params.set("page", page.toString());
|
|
4292
|
+
params.set("limit", "20");
|
|
4293
|
+
const response = await fetch(`${apiBaseUrl}/api/admin/error-logs?${params}`, {
|
|
4294
|
+
headers: authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
4295
|
+
});
|
|
4296
|
+
if (response.ok) {
|
|
4297
|
+
const data = await response.json();
|
|
4298
|
+
setLogs(data.items || []);
|
|
4299
|
+
setTotalPages(data.totalPages || 1);
|
|
4300
|
+
setTotal(data.total || 0);
|
|
4301
|
+
}
|
|
4302
|
+
} catch (err) {
|
|
4303
|
+
console.error("Failed to fetch error logs:", err);
|
|
4304
|
+
} finally {
|
|
4305
|
+
setLoading(false);
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
async function handleDismiss(id) {
|
|
4309
|
+
try {
|
|
4310
|
+
const response = await fetch(`${apiBaseUrl}/api/admin/error-logs/${id}/dismiss`, {
|
|
4311
|
+
method: "PATCH",
|
|
4312
|
+
headers: authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
4313
|
+
});
|
|
4314
|
+
if (response.ok) {
|
|
4315
|
+
fetchLogs();
|
|
4316
|
+
}
|
|
4317
|
+
} catch (err) {
|
|
4318
|
+
console.error("Failed to dismiss error:", err);
|
|
4319
|
+
}
|
|
4320
|
+
}
|
|
4321
|
+
async function handleUndismiss(id) {
|
|
4322
|
+
try {
|
|
4323
|
+
const response = await fetch(`${apiBaseUrl}/api/admin/error-logs/${id}/undismiss`, {
|
|
4324
|
+
method: "PATCH",
|
|
4325
|
+
headers: authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
4326
|
+
});
|
|
4327
|
+
if (response.ok) {
|
|
4328
|
+
fetchLogs();
|
|
4329
|
+
}
|
|
4330
|
+
} catch (err) {
|
|
4331
|
+
console.error("Failed to undismiss error:", err);
|
|
4332
|
+
}
|
|
4333
|
+
}
|
|
4334
|
+
function getErrorDefinition(code) {
|
|
4335
|
+
return ERROR_DEFINITIONS[code];
|
|
4336
|
+
}
|
|
4337
|
+
const totalErrors = logs.reduce((sum, log) => sum + log.count, 0);
|
|
4338
|
+
const recentCount = logs.filter((log) => isRecent(log.lastSeenAt)).length;
|
|
4339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.container, "data-testid": "error-logs-panel", children: [
|
|
4340
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.header, children: [
|
|
4341
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h2", { style: panelStyles3.title, children: "Error Tracking" }),
|
|
4342
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { style: panelStyles3.subtitle, children: "Aggregated errors from QuizPlayer and AttemptViewer components, sorted by occurrence count" })
|
|
4343
|
+
] }),
|
|
4344
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.tabs, children: [
|
|
4345
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4346
|
+
"button",
|
|
4347
|
+
{
|
|
4348
|
+
style: {
|
|
4349
|
+
...panelStyles3.tab,
|
|
4350
|
+
...showDismissed ? {} : panelStyles3.tabActive
|
|
4351
|
+
},
|
|
4352
|
+
onClick: () => {
|
|
4353
|
+
setShowDismissed(false);
|
|
4354
|
+
setPage(1);
|
|
4355
|
+
},
|
|
4356
|
+
"data-testid": "tab-active-errors",
|
|
4357
|
+
children: "Active Errors"
|
|
4358
|
+
}
|
|
4359
|
+
),
|
|
4360
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4361
|
+
"button",
|
|
4362
|
+
{
|
|
4363
|
+
style: {
|
|
4364
|
+
...panelStyles3.tab,
|
|
4365
|
+
...showDismissed ? panelStyles3.tabActive : {}
|
|
4366
|
+
},
|
|
4367
|
+
onClick: () => {
|
|
4368
|
+
setShowDismissed(true);
|
|
4369
|
+
setPage(1);
|
|
4370
|
+
},
|
|
4371
|
+
"data-testid": "tab-dismissed-errors",
|
|
4372
|
+
children: "Dismissed"
|
|
4373
|
+
}
|
|
4374
|
+
)
|
|
4375
|
+
] }),
|
|
4376
|
+
!showDismissed && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.stats, children: [
|
|
4377
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.statCard, children: [
|
|
4378
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.statValue, children: total }),
|
|
4379
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.statLabel, children: "Unique Errors" })
|
|
4380
|
+
] }),
|
|
4381
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.statCard, children: [
|
|
4382
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.statValue, children: totalErrors }),
|
|
4383
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.statLabel, children: "Total Occurrences" })
|
|
4384
|
+
] }),
|
|
4385
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.statCard, children: [
|
|
4386
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { ...panelStyles3.statValue, color: recentCount > 0 ? "#ef4444" : "#22c55e" }, children: recentCount }),
|
|
4387
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.statLabel, children: "Last 24h" })
|
|
4388
|
+
] })
|
|
4389
|
+
] }),
|
|
4390
|
+
loading ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.loading, children: "Loading..." }) : logs.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.emptyState, children: showDismissed ? "No dismissed errors" : "No active errors" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.errorList, children: logs.map((log) => {
|
|
4391
|
+
const def = getErrorDefinition(log.errorCode);
|
|
4392
|
+
const recent = isRecent(log.lastSeenAt);
|
|
4393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
4394
|
+
"div",
|
|
4395
|
+
{
|
|
4396
|
+
style: {
|
|
4397
|
+
...panelStyles3.errorCard,
|
|
4398
|
+
...recent ? panelStyles3.errorCardRecent : panelStyles3.errorCardOld
|
|
4399
|
+
},
|
|
4400
|
+
"data-testid": `error-log-${log.id}`,
|
|
4401
|
+
children: [
|
|
4402
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.errorHeader, children: [
|
|
4403
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.errorLeft, children: [
|
|
4404
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: panelStyles3.errorCode, children: log.errorCode }),
|
|
4405
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: panelStyles3.contextBadge, children: log.context }),
|
|
4406
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { ...panelStyles3.contextBadge, backgroundColor: "#f3e8ff", color: "#7c3aed" }, children: log.component })
|
|
4407
|
+
] }),
|
|
4408
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
4409
|
+
"span",
|
|
4410
|
+
{
|
|
4411
|
+
style: {
|
|
4412
|
+
...panelStyles3.countBadge,
|
|
4413
|
+
...log.count < 10 ? panelStyles3.countBadgeLow : {}
|
|
4414
|
+
},
|
|
4415
|
+
children: [
|
|
4416
|
+
log.count,
|
|
4417
|
+
"x"
|
|
4418
|
+
]
|
|
4419
|
+
}
|
|
4420
|
+
)
|
|
4421
|
+
] }),
|
|
4422
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: panelStyles3.userMessage, children: def?.userMessage || log.lastMessage || "Unknown error" }),
|
|
4423
|
+
log.resourceId && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.resourceId, children: [
|
|
4424
|
+
"Resource:",
|
|
4425
|
+
" ",
|
|
4426
|
+
onResourceClick ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4427
|
+
"span",
|
|
4428
|
+
{
|
|
4429
|
+
style: panelStyles3.resourceLink,
|
|
4430
|
+
onClick: () => onResourceClick(log.resourceId, log.context),
|
|
4431
|
+
"data-testid": `link-resource-${log.id}`,
|
|
4432
|
+
children: log.resourceId
|
|
4433
|
+
}
|
|
4434
|
+
) : log.resourceId
|
|
4435
|
+
] }),
|
|
4436
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.timestamps, children: [
|
|
4437
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
4438
|
+
"First: ",
|
|
4439
|
+
formatRelativeTime(log.firstSeenAt)
|
|
4440
|
+
] }),
|
|
4441
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { children: [
|
|
4442
|
+
"Last: ",
|
|
4443
|
+
formatRelativeTime(log.lastSeenAt)
|
|
4444
|
+
] })
|
|
4445
|
+
] }),
|
|
4446
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4447
|
+
"button",
|
|
4448
|
+
{
|
|
4449
|
+
style: panelStyles3.dismissButton,
|
|
4450
|
+
onClick: () => showDismissed ? handleUndismiss(log.id) : handleDismiss(log.id),
|
|
4451
|
+
"data-testid": `button-dismiss-${log.id}`,
|
|
4452
|
+
children: showDismissed ? "Restore" : "Dismiss"
|
|
4453
|
+
}
|
|
4454
|
+
)
|
|
4455
|
+
]
|
|
4456
|
+
},
|
|
4457
|
+
log.id
|
|
4458
|
+
);
|
|
4459
|
+
}) }),
|
|
4460
|
+
totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: panelStyles3.pagination, children: [
|
|
4461
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4462
|
+
"button",
|
|
4463
|
+
{
|
|
4464
|
+
style: {
|
|
4465
|
+
...panelStyles3.pageButton,
|
|
4466
|
+
...page <= 1 ? panelStyles3.pageButtonDisabled : {}
|
|
4467
|
+
},
|
|
4468
|
+
onClick: () => setPage((p) => Math.max(1, p - 1)),
|
|
4469
|
+
disabled: page <= 1,
|
|
4470
|
+
"data-testid": "button-prev-page",
|
|
4471
|
+
children: "Previous"
|
|
4472
|
+
}
|
|
4473
|
+
),
|
|
4474
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { padding: "8px 12px", color: "#6b7280" }, children: [
|
|
4475
|
+
"Page ",
|
|
4476
|
+
page,
|
|
4477
|
+
" of ",
|
|
4478
|
+
totalPages
|
|
4479
|
+
] }),
|
|
4480
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
4481
|
+
"button",
|
|
4482
|
+
{
|
|
4483
|
+
style: {
|
|
4484
|
+
...panelStyles3.pageButton,
|
|
4485
|
+
...page >= totalPages ? panelStyles3.pageButtonDisabled : {}
|
|
4486
|
+
},
|
|
4487
|
+
onClick: () => setPage((p) => Math.min(totalPages, p + 1)),
|
|
4488
|
+
disabled: page >= totalPages,
|
|
4489
|
+
"data-testid": "button-next-page",
|
|
4490
|
+
children: "Next"
|
|
4491
|
+
}
|
|
4492
|
+
)
|
|
4493
|
+
] })
|
|
4494
|
+
] });
|
|
4495
|
+
}
|
|
3426
4496
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3427
4497
|
0 && (module.exports = {
|
|
3428
4498
|
AttemptViewer,
|
|
4499
|
+
ERROR_DEFINITIONS,
|
|
4500
|
+
ErrorLogsPanel,
|
|
4501
|
+
ErrorTypesPanel,
|
|
4502
|
+
MaintenanceScreen,
|
|
3429
4503
|
QuizApiClient,
|
|
3430
4504
|
QuizPlayer,
|
|
3431
4505
|
TextToSpeech,
|
|
3432
4506
|
calculateScore,
|
|
3433
4507
|
checkAnswer,
|
|
3434
4508
|
createAnswerDetail,
|
|
3435
|
-
formatTime
|
|
4509
|
+
formatTime,
|
|
4510
|
+
getErrorFromHttpStatus,
|
|
4511
|
+
getErrorFromMessage
|
|
3436
4512
|
});
|
|
3437
4513
|
//# sourceMappingURL=index.js.map
|