@schoolio/player 1.4.1 → 1.4.3

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.js CHANGED
@@ -113,6 +113,12 @@ var QuizApiClient = class {
113
113
  `/api/external/question-chat/${questionId}/${childId}`
114
114
  );
115
115
  }
116
+ async getChatsByAttempt(attemptId) {
117
+ return this.request(
118
+ "GET",
119
+ `/api/external/quiz-attempts/${attemptId}/chats`
120
+ );
121
+ }
116
122
  async getTextToSpeech(text, voice = "nova") {
117
123
  const headers = {
118
124
  "Content-Type": "application/json"
@@ -695,7 +701,8 @@ function QuestionChatPanel({
695
701
  childId,
696
702
  parentId,
697
703
  lessonId,
698
- courseId
704
+ courseId,
705
+ answerResult
699
706
  }) {
700
707
  const [messages, setMessages] = (0, import_react2.useState)([]);
701
708
  const [inputValue, setInputValue] = (0, import_react2.useState)("");
@@ -705,6 +712,7 @@ function QuestionChatPanel({
705
712
  const [isListening, setIsListening] = (0, import_react2.useState)(false);
706
713
  const [speakingIndex, setSpeakingIndex] = (0, import_react2.useState)(null);
707
714
  const [audioReadyMap, setAudioReadyMap] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
715
+ const [hasOfferedHelp, setHasOfferedHelp] = (0, import_react2.useState)(false);
708
716
  const messagesContainerRef = (0, import_react2.useRef)(null);
709
717
  const messagesEndRef = (0, import_react2.useRef)(null);
710
718
  const recognitionRef = (0, import_react2.useRef)(null);
@@ -824,6 +832,7 @@ function QuestionChatPanel({
824
832
  setMessages([]);
825
833
  setChatId(null);
826
834
  setInputValue("");
835
+ setHasOfferedHelp(false);
827
836
  const loadHistory = async () => {
828
837
  try {
829
838
  const history = await apiClient.getChatHistory(question.id, childId);
@@ -838,6 +847,20 @@ function QuestionChatPanel({
838
847
  };
839
848
  loadHistory();
840
849
  }, [question.id, childId, apiClient, preCacheAudio]);
850
+ (0, import_react2.useEffect)(() => {
851
+ if (answerResult?.wasIncorrect && !hasOfferedHelp) {
852
+ setHasOfferedHelp(true);
853
+ const selectedAnswerText = answerResult.selectedAnswer || "that answer";
854
+ const helpMessage = `Looks like you chose "${selectedAnswerText}" which was incorrect. Would you like me to help explain the correct answer?`;
855
+ const assistantMessage = {
856
+ role: "assistant",
857
+ content: helpMessage,
858
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
859
+ };
860
+ setMessages((prev) => [...prev, assistantMessage]);
861
+ preCacheAudio(helpMessage);
862
+ }
863
+ }, [answerResult, hasOfferedHelp, preCacheAudio]);
841
864
  const initializeChat = async () => {
842
865
  if (chatId) return chatId;
843
866
  try {
@@ -1030,15 +1053,30 @@ var defaultStyles = {
1030
1053
  container: {
1031
1054
  fontFamily: "system-ui, -apple-system, sans-serif",
1032
1055
  width: "100%",
1056
+ height: "100%",
1057
+ maxHeight: "calc(100vh - 40px)",
1033
1058
  padding: "20px",
1034
1059
  backgroundColor: "#ffffff",
1035
1060
  borderRadius: "12px",
1036
- boxSizing: "border-box"
1061
+ boxSizing: "border-box",
1062
+ display: "flex",
1063
+ flexDirection: "column",
1064
+ overflow: "hidden"
1037
1065
  },
1038
1066
  header: {
1039
1067
  marginBottom: "20px",
1040
1068
  borderBottom: "1px solid #e5e7eb",
1041
- paddingBottom: "16px"
1069
+ paddingBottom: "16px",
1070
+ display: "flex",
1071
+ flexDirection: "column"
1072
+ },
1073
+ headerTop: {
1074
+ display: "flex",
1075
+ justifyContent: "space-between",
1076
+ alignItems: "flex-start"
1077
+ },
1078
+ headerLeft: {
1079
+ flex: 1
1042
1080
  },
1043
1081
  title: {
1044
1082
  fontSize: "24px",
@@ -1077,6 +1115,7 @@ var defaultStyles = {
1077
1115
  gap: "8px"
1078
1116
  },
1079
1117
  option: {
1118
+ width: "100%",
1080
1119
  padding: "12px 16px",
1081
1120
  border: "2px solid #e5e7eb",
1082
1121
  borderRadius: "8px",
@@ -1086,7 +1125,8 @@ var defaultStyles = {
1086
1125
  boxShadow: "none",
1087
1126
  backgroundColor: "#ffffff",
1088
1127
  WebkitTapHighlightColor: "transparent",
1089
- userSelect: "none"
1128
+ userSelect: "none",
1129
+ boxSizing: "border-box"
1090
1130
  },
1091
1131
  optionSelected: {
1092
1132
  borderColor: "#6721b0",
@@ -1165,16 +1205,25 @@ var defaultStyles = {
1165
1205
  },
1166
1206
  mainLayout: {
1167
1207
  display: "flex",
1168
- gap: "24px"
1208
+ gap: "24px",
1209
+ flex: 1,
1210
+ minHeight: 0,
1211
+ alignItems: "stretch",
1212
+ overflow: "hidden"
1169
1213
  },
1170
1214
  quizContent: {
1171
1215
  flex: 1,
1172
- minWidth: 0
1216
+ minWidth: 0,
1217
+ minHeight: 0,
1218
+ overflow: "auto"
1173
1219
  },
1174
1220
  chatPanel: {
1175
1221
  width: "320px",
1176
1222
  flexShrink: 0,
1177
- height: "460px"
1223
+ display: "flex",
1224
+ flexDirection: "column",
1225
+ minHeight: 0,
1226
+ overflow: "hidden"
1178
1227
  },
1179
1228
  timer: {
1180
1229
  fontSize: "14px",
@@ -1382,6 +1431,16 @@ function QuizPlayer({
1382
1431
  const apiClient = (0, import_react3.useRef)(null);
1383
1432
  const timerRef = (0, import_react3.useRef)(null);
1384
1433
  const startTimeRef = (0, import_react3.useRef)(0);
1434
+ const onCompleteRef = (0, import_react3.useRef)(onComplete);
1435
+ const onErrorRef = (0, import_react3.useRef)(onError);
1436
+ const onProgressRef = (0, import_react3.useRef)(onProgress);
1437
+ const onGenerateMoreQuestionsRef = (0, import_react3.useRef)(onGenerateMoreQuestions);
1438
+ (0, import_react3.useEffect)(() => {
1439
+ onCompleteRef.current = onComplete;
1440
+ onErrorRef.current = onError;
1441
+ onProgressRef.current = onProgress;
1442
+ onGenerateMoreQuestionsRef.current = onGenerateMoreQuestions;
1443
+ });
1385
1444
  (0, import_react3.useEffect)(() => {
1386
1445
  apiClient.current = new QuizApiClient({ baseUrl: apiBaseUrl, authToken });
1387
1446
  }, [apiBaseUrl, authToken]);
@@ -1428,11 +1487,11 @@ function QuizPlayer({
1428
1487
  const message = err instanceof Error ? err.message : "Failed to load quiz";
1429
1488
  setError(message);
1430
1489
  setIsLoading(false);
1431
- onError?.(err instanceof Error ? err : new Error(message));
1490
+ onErrorRef.current?.(err instanceof Error ? err : new Error(message));
1432
1491
  }
1433
1492
  }
1434
1493
  initialize();
1435
- }, [quizId, lessonId, assignLessonId, courseId, childId, parentId, forceNewAttempt, onError]);
1494
+ }, [quizId, lessonId, assignLessonId, courseId, childId, parentId, forceNewAttempt]);
1436
1495
  (0, import_react3.useEffect)(() => {
1437
1496
  if (timerStarted && !isCompleted && !error) {
1438
1497
  startTimeRef.current = Date.now();
@@ -1458,14 +1517,14 @@ function QuizPlayer({
1458
1517
  const totalQuestions = allQuestions.length;
1459
1518
  const maxQuestions = 50;
1460
1519
  (0, import_react3.useEffect)(() => {
1461
- if (quiz && onProgress) {
1462
- onProgress({
1520
+ if (quiz && onProgressRef.current) {
1521
+ onProgressRef.current({
1463
1522
  currentQuestion: currentQuestionIndex + 1,
1464
1523
  totalQuestions,
1465
1524
  answeredQuestions: answers.size
1466
1525
  });
1467
1526
  }
1468
- }, [currentQuestionIndex, answers.size, quiz, onProgress, totalQuestions]);
1527
+ }, [currentQuestionIndex, answers.size, quiz, totalQuestions]);
1469
1528
  const currentQuestion = allQuestions[currentQuestionIndex];
1470
1529
  const handleAnswerChange = (0, import_react3.useCallback)((value) => {
1471
1530
  if (!currentQuestion) return;
@@ -1510,7 +1569,7 @@ function QuizPlayer({
1510
1569
  if (totalQuestions >= maxQuestions) return;
1511
1570
  setIsGeneratingExtra(true);
1512
1571
  try {
1513
- const result2 = await onGenerateMoreQuestions(attempt.id, totalQuestions);
1572
+ const result2 = await onGenerateMoreQuestionsRef.current(attempt.id, totalQuestions);
1514
1573
  if (result2.extraQuestions && result2.extraQuestions.length > 0) {
1515
1574
  const slotsAvailable = maxQuestions - totalQuestions;
1516
1575
  const questionsToAppend = result2.extraQuestions.slice(0, slotsAvailable);
@@ -1523,11 +1582,11 @@ function QuizPlayer({
1523
1582
  }
1524
1583
  } catch (err) {
1525
1584
  console.error("Failed to generate extra questions:", err);
1526
- onError?.(err instanceof Error ? err : new Error("Failed to generate extra questions"));
1585
+ onErrorRef.current?.(err instanceof Error ? err : new Error("Failed to generate extra questions"));
1527
1586
  } finally {
1528
1587
  setIsGeneratingExtra(false);
1529
1588
  }
1530
- }, [attempt, onGenerateMoreQuestions, isGeneratingExtra, totalQuestions, maxQuestions, onError]);
1589
+ }, [attempt, isGeneratingExtra, totalQuestions, maxQuestions]);
1531
1590
  const handleSubmit = (0, import_react3.useCallback)(async () => {
1532
1591
  if (!quiz || !attempt || !apiClient.current) return;
1533
1592
  setIsSubmitting(true);
@@ -1566,15 +1625,15 @@ function QuizPlayer({
1566
1625
  if (timerRef.current) {
1567
1626
  clearInterval(timerRef.current);
1568
1627
  }
1569
- onComplete?.(quizResult);
1628
+ onCompleteRef.current?.(quizResult);
1570
1629
  } catch (err) {
1571
1630
  const message = err instanceof Error ? err.message : "Failed to submit quiz";
1572
1631
  setError(message);
1573
- onError?.(err instanceof Error ? err : new Error(message));
1632
+ onErrorRef.current?.(err instanceof Error ? err : new Error(message));
1574
1633
  } finally {
1575
1634
  setIsSubmitting(false);
1576
1635
  }
1577
- }, [quiz, attempt, currentQuestion, answers, answersDetail, onComplete, onError, totalQuestions, timerStarted, elapsedSeconds]);
1636
+ }, [quiz, attempt, currentQuestion, answers, answersDetail, totalQuestions, timerStarted, elapsedSeconds]);
1578
1637
  const isExtraQuestion = currentQuestion && extraQuestions.some((q) => q.id === currentQuestion.id);
1579
1638
  const handleSkipQuestion = (0, import_react3.useCallback)(async (reason, comment) => {
1580
1639
  if (!currentQuestion || !apiClient.current || !attempt) return;
@@ -1610,7 +1669,7 @@ function QuizPlayer({
1610
1669
  timeSpentSeconds: elapsedSeconds
1611
1670
  };
1612
1671
  setResult(quizResult);
1613
- onComplete?.(quizResult);
1672
+ onCompleteRef.current?.(quizResult);
1614
1673
  } else if (currentQuestionIndex >= newTotalQuestions) {
1615
1674
  setCurrentQuestionIndex(newTotalQuestions - 1);
1616
1675
  }
@@ -1622,7 +1681,7 @@ function QuizPlayer({
1622
1681
  } finally {
1623
1682
  setIsSkipping(false);
1624
1683
  }
1625
- }, [currentQuestion, apiClient, attempt, quiz, childId, parentId, lessonId, courseId, assignLessonId, skippedQuestionIds, extraQuestions, currentQuestionIndex, elapsedSeconds, onComplete]);
1684
+ }, [currentQuestion, apiClient, attempt, quiz, childId, parentId, lessonId, courseId, assignLessonId, skippedQuestionIds, extraQuestions, currentQuestionIndex, elapsedSeconds]);
1626
1685
  const handleReportQuestion = (0, import_react3.useCallback)(async (comment) => {
1627
1686
  if (!currentQuestion || !apiClient.current || !attempt || !comment.trim()) return;
1628
1687
  setIsReporting(true);
@@ -1992,533 +2051,537 @@ function QuizPlayer({
1992
2051
  const remainingSlots = maxQuestions - totalQuestions;
1993
2052
  const questionsToAdd = Math.min(5, remainingSlots);
1994
2053
  const canAddMore = onGenerateMoreQuestions && remainingSlots > 0;
1995
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className, style: defaultStyles.container, children: [
1996
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.header, children: [
1997
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.title, children: quiz.title }),
1998
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.progress, children: [
1999
- "Question ",
2000
- currentQuestionIndex + 1,
2001
- " of ",
2002
- totalQuestions
2054
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className, style: defaultStyles.container, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.mainLayout, children: [
2055
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.quizContent, children: [
2056
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.header, children: [
2057
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.title, children: quiz.title }),
2058
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.progress, children: [
2059
+ "Question ",
2060
+ currentQuestionIndex + 1,
2061
+ " of ",
2062
+ totalQuestions
2063
+ ] }),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.progressBar, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...defaultStyles.progressFill, width: `${progressPercent}%` } }) })
2003
2065
  ] }),
2004
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.progressBar, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...defaultStyles.progressFill, width: `${progressPercent}%` } }) })
2005
- ] }),
2006
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.mainLayout, children: [
2007
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.quizContent, children: [
2008
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...defaultStyles.question, position: "relative", paddingBottom: "40px" }, children: [
2009
- /* @__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" }) }),
2010
- isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2011
- "button",
2066
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...defaultStyles.question, position: "relative", paddingBottom: "40px" }, children: [
2067
+ /* @__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" }) }),
2068
+ isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2069
+ "button",
2070
+ {
2071
+ onClick: () => setShowSkipModal(true),
2072
+ title: "Skip question",
2073
+ style: {
2074
+ position: "absolute",
2075
+ bottom: "8px",
2076
+ left: "0",
2077
+ background: "transparent",
2078
+ border: "none",
2079
+ cursor: "pointer",
2080
+ padding: "6px 10px",
2081
+ borderRadius: "6px",
2082
+ color: "#9ca3af",
2083
+ display: "flex",
2084
+ alignItems: "center",
2085
+ justifyContent: "center",
2086
+ gap: "4px",
2087
+ fontSize: "12px",
2088
+ opacity: 0.6,
2089
+ transition: "opacity 0.2s, color 0.2s"
2090
+ },
2091
+ onMouseEnter: (e) => {
2092
+ e.currentTarget.style.opacity = "1";
2093
+ e.currentTarget.style.color = "#6b7280";
2094
+ },
2095
+ onMouseLeave: (e) => {
2096
+ e.currentTarget.style.opacity = "0.6";
2097
+ e.currentTarget.style.color = "#9ca3af";
2098
+ },
2099
+ "data-testid": "button-skip-question",
2100
+ children: [
2101
+ /* @__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: [
2102
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "5 4 15 12 5 20 5 4" }),
2103
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "19", y1: "5", x2: "19", y2: "19" })
2104
+ ] }),
2105
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Skip" })
2106
+ ]
2107
+ }
2108
+ ),
2109
+ !isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2110
+ "button",
2111
+ {
2112
+ onClick: () => setShowReportModal(true),
2113
+ title: "Report an issue with this question",
2114
+ style: {
2115
+ position: "absolute",
2116
+ bottom: "8px",
2117
+ left: "0",
2118
+ background: "transparent",
2119
+ border: "none",
2120
+ cursor: "pointer",
2121
+ padding: "6px 10px",
2122
+ borderRadius: "6px",
2123
+ color: "#9ca3af",
2124
+ display: "flex",
2125
+ alignItems: "center",
2126
+ justifyContent: "center",
2127
+ gap: "4px",
2128
+ fontSize: "12px",
2129
+ opacity: 0.6,
2130
+ transition: "opacity 0.2s, color 0.2s"
2131
+ },
2132
+ onMouseEnter: (e) => {
2133
+ e.currentTarget.style.opacity = "1";
2134
+ e.currentTarget.style.color = "#ef4444";
2135
+ },
2136
+ onMouseLeave: (e) => {
2137
+ e.currentTarget.style.opacity = "0.6";
2138
+ e.currentTarget.style.color = "#9ca3af";
2139
+ },
2140
+ "data-testid": "button-report-question",
2141
+ children: [
2142
+ /* @__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: [
2143
+ /* @__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" }),
2144
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "4", y1: "22", x2: "4", y2: "15" })
2145
+ ] }),
2146
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Report" })
2147
+ ]
2148
+ }
2149
+ ),
2150
+ (currentQuestion.type === "single" || currentQuestion.type === "true-false") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
2151
+ const isSelected = selectedAnswer === option;
2152
+ const isCorrectOption = currentQuestion.correctAnswer === option;
2153
+ let optionStyle = { ...defaultStyles.option };
2154
+ if (showFeedback) {
2155
+ if (isCorrectOption) {
2156
+ optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
2157
+ } else if (isSelected && !isCorrectOption) {
2158
+ optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
2159
+ }
2160
+ } else if (isSelected) {
2161
+ optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2162
+ }
2163
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2164
+ "div",
2012
2165
  {
2013
- onClick: () => setShowSkipModal(true),
2014
- title: "Skip question",
2015
2166
  style: {
2016
- position: "absolute",
2017
- bottom: "8px",
2018
- left: "0",
2019
- background: "transparent",
2020
- border: "none",
2021
- cursor: "pointer",
2022
- padding: "6px 10px",
2023
- borderRadius: "6px",
2024
- color: "#9ca3af",
2167
+ ...optionStyle,
2168
+ cursor: showFeedback ? "default" : "pointer",
2025
2169
  display: "flex",
2026
2170
  alignItems: "center",
2027
- justifyContent: "center",
2028
- gap: "4px",
2029
- fontSize: "12px",
2030
- opacity: 0.6,
2031
- transition: "opacity 0.2s, color 0.2s"
2032
- },
2033
- onMouseEnter: (e) => {
2034
- e.currentTarget.style.opacity = "1";
2035
- e.currentTarget.style.color = "#6b7280";
2171
+ gap: "8px"
2036
2172
  },
2037
- onMouseLeave: (e) => {
2038
- e.currentTarget.style.opacity = "0.6";
2039
- e.currentTarget.style.color = "#9ca3af";
2040
- },
2041
- "data-testid": "button-skip-question",
2173
+ onClick: () => !showFeedback && handleAnswerChange(option),
2042
2174
  children: [
2043
- /* @__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: [
2044
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polygon", { points: "5 4 15 12 5 20 5 4" }),
2045
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "19", y1: "5", x2: "19", y2: "19" })
2046
- ] }),
2047
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Skip" })
2175
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
2176
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 }, children: option })
2048
2177
  ]
2178
+ },
2179
+ idx
2180
+ );
2181
+ }) }),
2182
+ currentQuestion.type === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
2183
+ const selected = Array.isArray(selectedAnswer) && selectedAnswer.includes(option);
2184
+ const correctAnswers = Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer : currentQuestion.correctAnswer ? [currentQuestion.correctAnswer] : [];
2185
+ const isCorrectOption = correctAnswers.includes(option);
2186
+ let optionStyle = { ...defaultStyles.option };
2187
+ if (showFeedback) {
2188
+ if (isCorrectOption) {
2189
+ optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
2190
+ } else if (selected && !isCorrectOption) {
2191
+ optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
2049
2192
  }
2050
- ),
2051
- !isExtraQuestion && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2052
- "button",
2193
+ } else if (selected) {
2194
+ optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2195
+ }
2196
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2197
+ "div",
2053
2198
  {
2054
- onClick: () => setShowReportModal(true),
2055
- title: "Report an issue with this question",
2056
2199
  style: {
2057
- position: "absolute",
2058
- bottom: "8px",
2059
- left: "0",
2060
- background: "transparent",
2061
- border: "none",
2062
- cursor: "pointer",
2063
- padding: "6px 10px",
2064
- borderRadius: "6px",
2065
- color: "#9ca3af",
2200
+ ...optionStyle,
2201
+ cursor: showFeedback ? "default" : "pointer",
2066
2202
  display: "flex",
2067
2203
  alignItems: "center",
2068
- justifyContent: "center",
2069
- gap: "4px",
2070
- fontSize: "12px",
2071
- opacity: 0.6,
2072
- transition: "opacity 0.2s, color 0.2s"
2204
+ gap: "8px"
2073
2205
  },
2074
- onMouseEnter: (e) => {
2075
- e.currentTarget.style.opacity = "1";
2076
- e.currentTarget.style.color = "#ef4444";
2077
- },
2078
- onMouseLeave: (e) => {
2079
- e.currentTarget.style.opacity = "0.6";
2080
- e.currentTarget.style.color = "#9ca3af";
2206
+ onClick: () => {
2207
+ if (showFeedback) return;
2208
+ const current = Array.isArray(selectedAnswer) ? selectedAnswer : [];
2209
+ if (selected) {
2210
+ handleAnswerChange(current.filter((o) => o !== option));
2211
+ } else {
2212
+ handleAnswerChange([...current, option]);
2213
+ }
2081
2214
  },
2082
- "data-testid": "button-report-question",
2083
2215
  children: [
2084
- /* @__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: [
2085
- /* @__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" }),
2086
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("line", { x1: "4", y1: "22", x2: "4", y2: "15" })
2087
- ] }),
2088
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Report" })
2216
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
2217
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 }, children: option })
2089
2218
  ]
2219
+ },
2220
+ idx
2221
+ );
2222
+ }) }),
2223
+ (currentQuestion.type === "free" || currentQuestion.type === "essay") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2224
+ "textarea",
2225
+ {
2226
+ style: { ...defaultStyles.input, minHeight: currentQuestion.type === "essay" ? "150px" : "60px" },
2227
+ value: selectedAnswer || "",
2228
+ onChange: (e) => handleAnswerChange(e.target.value),
2229
+ placeholder: "Type your answer here...",
2230
+ disabled: showFeedback
2231
+ }
2232
+ ),
2233
+ currentQuestion.type === "fill" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.blanks?.map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2234
+ "input",
2235
+ {
2236
+ style: defaultStyles.input,
2237
+ value: (Array.isArray(selectedAnswer) ? selectedAnswer[idx] : "") || "",
2238
+ onChange: (e) => {
2239
+ const current = Array.isArray(selectedAnswer) ? [...selectedAnswer] : [];
2240
+ current[idx] = e.target.value;
2241
+ handleAnswerChange(current);
2242
+ },
2243
+ placeholder: `Blank ${idx + 1}`,
2244
+ disabled: showFeedback
2245
+ },
2246
+ idx
2247
+ )) }),
2248
+ showFeedback && currentAnswerDetail && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2249
+ ...defaultStyles.feedback,
2250
+ ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
2251
+ }, children: [
2252
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2253
+ ...defaultStyles.feedbackTitle,
2254
+ ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
2255
+ }, children: currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
2256
+ currentQuestion.explanation && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
2257
+ ] })
2258
+ ] }),
2259
+ showSkipModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2260
+ position: "fixed",
2261
+ top: 0,
2262
+ left: 0,
2263
+ right: 0,
2264
+ bottom: 0,
2265
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2266
+ display: "flex",
2267
+ alignItems: "center",
2268
+ justifyContent: "center",
2269
+ zIndex: 1e3
2270
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2271
+ backgroundColor: "#ffffff",
2272
+ borderRadius: "12px",
2273
+ padding: "24px",
2274
+ maxWidth: "400px",
2275
+ width: "90%",
2276
+ boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
2277
+ }, children: [
2278
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Skip Question" }),
2279
+ /* @__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." }),
2280
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px", marginBottom: "16px" }, children: [
2281
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2282
+ "button",
2283
+ {
2284
+ onClick: () => setSelectedSkipReason("question_issue"),
2285
+ disabled: isSkipping,
2286
+ style: {
2287
+ padding: "12px 16px",
2288
+ borderRadius: "8px",
2289
+ border: selectedSkipReason === "question_issue" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
2290
+ backgroundColor: selectedSkipReason === "question_issue" ? "#f5f3ff" : "#f9fafb",
2291
+ cursor: isSkipping ? "not-allowed" : "pointer",
2292
+ fontSize: "14px",
2293
+ fontWeight: "500",
2294
+ color: "#374151",
2295
+ textAlign: "left",
2296
+ opacity: isSkipping ? 0.6 : 1
2297
+ },
2298
+ "data-testid": "button-skip-reason-issue",
2299
+ children: "Question has an issue"
2090
2300
  }
2091
2301
  ),
2092
- (currentQuestion.type === "single" || currentQuestion.type === "true-false") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
2093
- const isSelected = selectedAnswer === option;
2094
- const isCorrectOption = currentQuestion.correctAnswer === option;
2095
- let optionStyle = { ...defaultStyles.option };
2096
- if (showFeedback) {
2097
- if (isCorrectOption) {
2098
- optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
2099
- } else if (isSelected && !isCorrectOption) {
2100
- optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
2101
- }
2102
- } else if (isSelected) {
2103
- optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2104
- }
2105
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2106
- "div",
2107
- {
2108
- style: {
2109
- ...optionStyle,
2110
- cursor: showFeedback ? "default" : "pointer",
2111
- display: "flex",
2112
- alignItems: "center",
2113
- gap: "8px"
2114
- },
2115
- onClick: () => !showFeedback && handleAnswerChange(option),
2116
- children: [
2117
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
2118
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 }, children: option })
2119
- ]
2302
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2303
+ "button",
2304
+ {
2305
+ onClick: () => setSelectedSkipReason("dont_know"),
2306
+ disabled: isSkipping,
2307
+ style: {
2308
+ padding: "12px 16px",
2309
+ borderRadius: "8px",
2310
+ border: selectedSkipReason === "dont_know" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
2311
+ backgroundColor: selectedSkipReason === "dont_know" ? "#f5f3ff" : "#f9fafb",
2312
+ cursor: isSkipping ? "not-allowed" : "pointer",
2313
+ fontSize: "14px",
2314
+ fontWeight: "500",
2315
+ color: "#374151",
2316
+ textAlign: "left",
2317
+ opacity: isSkipping ? 0.6 : 1
2120
2318
  },
2121
- idx
2122
- );
2123
- }) }),
2124
- currentQuestion.type === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.options?.map((option, idx) => {
2125
- const selected = Array.isArray(selectedAnswer) && selectedAnswer.includes(option);
2126
- const correctAnswers = Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer : currentQuestion.correctAnswer ? [currentQuestion.correctAnswer] : [];
2127
- const isCorrectOption = correctAnswers.includes(option);
2128
- let optionStyle = { ...defaultStyles.option };
2129
- if (showFeedback) {
2130
- if (isCorrectOption) {
2131
- optionStyle = { ...optionStyle, ...defaultStyles.optionCorrect };
2132
- } else if (selected && !isCorrectOption) {
2133
- optionStyle = { ...optionStyle, ...defaultStyles.optionIncorrect };
2134
- }
2135
- } else if (selected) {
2136
- optionStyle = { ...optionStyle, ...defaultStyles.optionSelected };
2319
+ "data-testid": "button-skip-reason-dont-know",
2320
+ children: "I don't know the answer"
2137
2321
  }
2138
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2139
- "div",
2140
- {
2141
- style: {
2142
- ...optionStyle,
2143
- cursor: showFeedback ? "default" : "pointer",
2144
- display: "flex",
2145
- alignItems: "center",
2146
- gap: "8px"
2147
- },
2148
- onClick: () => {
2149
- if (showFeedback) return;
2150
- const current = Array.isArray(selectedAnswer) ? selectedAnswer : [];
2151
- if (selected) {
2152
- handleAnswerChange(current.filter((o) => o !== option));
2153
- } else {
2154
- handleAnswerChange([...current, option]);
2155
- }
2156
- },
2157
- children: [
2158
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TextToSpeech, { text: option, size: "sm" }) }),
2159
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 }, children: option })
2160
- ]
2161
- },
2162
- idx
2163
- );
2164
- }) }),
2165
- (currentQuestion.type === "free" || currentQuestion.type === "essay") && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2322
+ )
2323
+ ] }),
2324
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "16px" }, children: [
2325
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: { display: "block", fontSize: "13px", fontWeight: "500", color: "#374151", marginBottom: "6px" }, children: "Additional details (optional)" }),
2326
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2166
2327
  "textarea",
2167
2328
  {
2168
- style: { ...defaultStyles.input, minHeight: currentQuestion.type === "essay" ? "150px" : "60px" },
2169
- value: selectedAnswer || "",
2170
- onChange: (e) => handleAnswerChange(e.target.value),
2171
- placeholder: "Type your answer here...",
2172
- disabled: showFeedback
2329
+ value: skipComment,
2330
+ onChange: (e) => setSkipComment(e.target.value.slice(0, 200)),
2331
+ placeholder: "Tell us more about the issue...",
2332
+ disabled: isSkipping,
2333
+ style: {
2334
+ width: "100%",
2335
+ minHeight: "80px",
2336
+ padding: "10px 12px",
2337
+ borderRadius: "8px",
2338
+ border: "1px solid #e5e7eb",
2339
+ fontSize: "14px",
2340
+ resize: "vertical",
2341
+ fontFamily: "inherit",
2342
+ boxSizing: "border-box"
2343
+ },
2344
+ "data-testid": "input-skip-comment"
2173
2345
  }
2174
2346
  ),
2175
- currentQuestion.type === "fill" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.options, children: currentQuestion.blanks?.map((_, idx) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2176
- "input",
2347
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
2348
+ skipComment.length,
2349
+ "/200"
2350
+ ] })
2351
+ ] }),
2352
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
2353
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2354
+ "button",
2177
2355
  {
2178
- style: defaultStyles.input,
2179
- value: (Array.isArray(selectedAnswer) ? selectedAnswer[idx] : "") || "",
2180
- onChange: (e) => {
2181
- const current = Array.isArray(selectedAnswer) ? [...selectedAnswer] : [];
2182
- current[idx] = e.target.value;
2183
- handleAnswerChange(current);
2356
+ onClick: () => {
2357
+ setShowSkipModal(false);
2358
+ setSkipComment("");
2359
+ setSelectedSkipReason(null);
2184
2360
  },
2185
- placeholder: `Blank ${idx + 1}`,
2186
- disabled: showFeedback
2187
- },
2188
- idx
2189
- )) }),
2190
- showFeedback && currentAnswerDetail && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2191
- ...defaultStyles.feedback,
2192
- ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackCorrect : defaultStyles.feedbackIncorrect
2193
- }, children: [
2194
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2195
- ...defaultStyles.feedbackTitle,
2196
- ...currentAnswerDetail.isCorrect ? defaultStyles.feedbackTitleCorrect : defaultStyles.feedbackTitleIncorrect
2197
- }, children: currentAnswerDetail.isCorrect ? "\u2713 Correct!" : "\u2717 Incorrect" }),
2198
- currentQuestion.explanation && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.feedbackExplanation, children: currentQuestion.explanation })
2361
+ style: {
2362
+ flex: 1,
2363
+ padding: "10px 16px",
2364
+ borderRadius: "8px",
2365
+ border: "1px solid #e5e7eb",
2366
+ backgroundColor: "#ffffff",
2367
+ cursor: "pointer",
2368
+ fontSize: "14px",
2369
+ fontWeight: "500",
2370
+ color: "#6b7280"
2371
+ },
2372
+ "data-testid": "button-skip-cancel",
2373
+ children: "Cancel"
2374
+ }
2375
+ ),
2376
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2377
+ "button",
2378
+ {
2379
+ onClick: () => selectedSkipReason && handleSkipQuestion(selectedSkipReason, skipComment),
2380
+ disabled: isSkipping || !selectedSkipReason,
2381
+ style: {
2382
+ flex: 1,
2383
+ padding: "10px 16px",
2384
+ borderRadius: "8px",
2385
+ border: "none",
2386
+ backgroundColor: selectedSkipReason ? "#8b5cf6" : "#d1d5db",
2387
+ cursor: isSkipping || !selectedSkipReason ? "not-allowed" : "pointer",
2388
+ fontSize: "14px",
2389
+ fontWeight: "500",
2390
+ color: "#ffffff",
2391
+ opacity: isSkipping ? 0.6 : 1
2392
+ },
2393
+ "data-testid": "button-skip-submit",
2394
+ children: isSkipping ? "Skipping..." : "Skip Question"
2395
+ }
2396
+ )
2397
+ ] })
2398
+ ] }) }),
2399
+ showReportModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2400
+ position: "fixed",
2401
+ top: 0,
2402
+ left: 0,
2403
+ right: 0,
2404
+ bottom: 0,
2405
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
2406
+ display: "flex",
2407
+ alignItems: "center",
2408
+ justifyContent: "center",
2409
+ zIndex: 1e3
2410
+ }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2411
+ backgroundColor: "#ffffff",
2412
+ borderRadius: "12px",
2413
+ padding: "24px",
2414
+ maxWidth: "400px",
2415
+ width: "90%",
2416
+ boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
2417
+ }, children: [
2418
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Report Question" }),
2419
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { margin: "0 0 16px 0", fontSize: "14px", color: "#6b7280" }, children: "What's wrong with this question?" }),
2420
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "16px" }, children: [
2421
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2422
+ "textarea",
2423
+ {
2424
+ value: reportComment,
2425
+ onChange: (e) => setReportComment(e.target.value.slice(0, 300)),
2426
+ placeholder: "Describe the issue with this question...",
2427
+ disabled: isReporting,
2428
+ style: {
2429
+ width: "100%",
2430
+ minHeight: "120px",
2431
+ padding: "10px 12px",
2432
+ borderRadius: "8px",
2433
+ border: "1px solid #e5e7eb",
2434
+ fontSize: "14px",
2435
+ resize: "vertical",
2436
+ fontFamily: "inherit",
2437
+ boxSizing: "border-box"
2438
+ },
2439
+ "data-testid": "input-report-comment"
2440
+ }
2441
+ ),
2442
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
2443
+ reportComment.length,
2444
+ "/300"
2199
2445
  ] })
2200
2446
  ] }),
2201
- showSkipModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2202
- position: "fixed",
2203
- top: 0,
2204
- left: 0,
2205
- right: 0,
2206
- bottom: 0,
2207
- backgroundColor: "rgba(0, 0, 0, 0.5)",
2208
- display: "flex",
2209
- alignItems: "center",
2210
- justifyContent: "center",
2211
- zIndex: 1e3
2212
- }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2213
- backgroundColor: "#ffffff",
2214
- borderRadius: "12px",
2215
- padding: "24px",
2216
- maxWidth: "400px",
2217
- width: "90%",
2218
- boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
2219
- }, children: [
2220
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Skip Question" }),
2221
- /* @__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." }),
2222
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "8px", marginBottom: "16px" }, children: [
2223
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2224
- "button",
2225
- {
2226
- onClick: () => setSelectedSkipReason("question_issue"),
2227
- disabled: isSkipping,
2228
- style: {
2229
- padding: "12px 16px",
2230
- borderRadius: "8px",
2231
- border: selectedSkipReason === "question_issue" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
2232
- backgroundColor: selectedSkipReason === "question_issue" ? "#f5f3ff" : "#f9fafb",
2233
- cursor: isSkipping ? "not-allowed" : "pointer",
2234
- fontSize: "14px",
2235
- fontWeight: "500",
2236
- color: "#374151",
2237
- textAlign: "left",
2238
- opacity: isSkipping ? 0.6 : 1
2239
- },
2240
- "data-testid": "button-skip-reason-issue",
2241
- children: "Question has an issue"
2242
- }
2243
- ),
2244
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2245
- "button",
2246
- {
2247
- onClick: () => setSelectedSkipReason("dont_know"),
2248
- disabled: isSkipping,
2249
- style: {
2250
- padding: "12px 16px",
2251
- borderRadius: "8px",
2252
- border: selectedSkipReason === "dont_know" ? "2px solid #8b5cf6" : "1px solid #e5e7eb",
2253
- backgroundColor: selectedSkipReason === "dont_know" ? "#f5f3ff" : "#f9fafb",
2254
- cursor: isSkipping ? "not-allowed" : "pointer",
2255
- fontSize: "14px",
2256
- fontWeight: "500",
2257
- color: "#374151",
2258
- textAlign: "left",
2259
- opacity: isSkipping ? 0.6 : 1
2260
- },
2261
- "data-testid": "button-skip-reason-dont-know",
2262
- children: "I don't know the answer"
2263
- }
2264
- )
2265
- ] }),
2266
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "16px" }, children: [
2267
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { style: { display: "block", fontSize: "13px", fontWeight: "500", color: "#374151", marginBottom: "6px" }, children: "Additional details (optional)" }),
2268
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2269
- "textarea",
2270
- {
2271
- value: skipComment,
2272
- onChange: (e) => setSkipComment(e.target.value.slice(0, 200)),
2273
- placeholder: "Tell us more about the issue...",
2274
- disabled: isSkipping,
2275
- style: {
2276
- width: "100%",
2277
- minHeight: "80px",
2278
- padding: "10px 12px",
2279
- borderRadius: "8px",
2280
- border: "1px solid #e5e7eb",
2281
- fontSize: "14px",
2282
- resize: "vertical",
2283
- fontFamily: "inherit",
2284
- boxSizing: "border-box"
2285
- },
2286
- "data-testid": "input-skip-comment"
2287
- }
2288
- ),
2289
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
2290
- skipComment.length,
2291
- "/200"
2292
- ] })
2293
- ] }),
2294
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
2295
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2296
- "button",
2297
- {
2298
- onClick: () => {
2299
- setShowSkipModal(false);
2300
- setSkipComment("");
2301
- setSelectedSkipReason(null);
2302
- },
2303
- style: {
2304
- flex: 1,
2305
- padding: "10px 16px",
2306
- borderRadius: "8px",
2307
- border: "1px solid #e5e7eb",
2308
- backgroundColor: "#ffffff",
2309
- cursor: "pointer",
2310
- fontSize: "14px",
2311
- fontWeight: "500",
2312
- color: "#6b7280"
2313
- },
2314
- "data-testid": "button-skip-cancel",
2315
- children: "Cancel"
2316
- }
2317
- ),
2318
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2319
- "button",
2320
- {
2321
- onClick: () => selectedSkipReason && handleSkipQuestion(selectedSkipReason, skipComment),
2322
- disabled: isSkipping || !selectedSkipReason,
2323
- style: {
2324
- flex: 1,
2325
- padding: "10px 16px",
2326
- borderRadius: "8px",
2327
- border: "none",
2328
- backgroundColor: selectedSkipReason ? "#8b5cf6" : "#d1d5db",
2329
- cursor: isSkipping || !selectedSkipReason ? "not-allowed" : "pointer",
2330
- fontSize: "14px",
2331
- fontWeight: "500",
2332
- color: "#ffffff",
2333
- opacity: isSkipping ? 0.6 : 1
2334
- },
2335
- "data-testid": "button-skip-submit",
2336
- children: isSkipping ? "Skipping..." : "Skip Question"
2337
- }
2338
- )
2339
- ] })
2340
- ] }) }),
2341
- showReportModal && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: {
2342
- position: "fixed",
2343
- top: 0,
2344
- left: 0,
2345
- right: 0,
2346
- bottom: 0,
2347
- backgroundColor: "rgba(0, 0, 0, 0.5)",
2348
- display: "flex",
2349
- alignItems: "center",
2350
- justifyContent: "center",
2351
- zIndex: 1e3
2352
- }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: {
2353
- backgroundColor: "#ffffff",
2354
- borderRadius: "12px",
2355
- padding: "24px",
2356
- maxWidth: "400px",
2357
- width: "90%",
2358
- boxShadow: "0 20px 40px rgba(0, 0, 0, 0.2)"
2359
- }, children: [
2360
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { style: { margin: "0 0 8px 0", fontSize: "18px", fontWeight: "600", color: "#1f2937" }, children: "Report Question" }),
2361
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: { margin: "0 0 16px 0", fontSize: "14px", color: "#6b7280" }, children: "What's wrong with this question?" }),
2362
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { marginBottom: "16px" }, children: [
2363
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2364
- "textarea",
2365
- {
2366
- value: reportComment,
2367
- onChange: (e) => setReportComment(e.target.value.slice(0, 300)),
2368
- placeholder: "Describe the issue with this question...",
2369
- disabled: isReporting,
2370
- style: {
2371
- width: "100%",
2372
- minHeight: "120px",
2373
- padding: "10px 12px",
2374
- borderRadius: "8px",
2375
- border: "1px solid #e5e7eb",
2376
- fontSize: "14px",
2377
- resize: "vertical",
2378
- fontFamily: "inherit",
2379
- boxSizing: "border-box"
2380
- },
2381
- "data-testid": "input-report-comment"
2382
- }
2383
- ),
2384
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { fontSize: "12px", color: "#9ca3af", marginTop: "4px", textAlign: "right" }, children: [
2385
- reportComment.length,
2386
- "/300"
2387
- ] })
2388
- ] }),
2389
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
2390
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2391
- "button",
2392
- {
2393
- onClick: () => {
2394
- setShowReportModal(false);
2395
- setReportComment("");
2396
- },
2397
- style: {
2398
- flex: 1,
2399
- padding: "10px 16px",
2400
- borderRadius: "8px",
2401
- border: "1px solid #e5e7eb",
2402
- backgroundColor: "#ffffff",
2403
- cursor: "pointer",
2404
- fontSize: "14px",
2405
- fontWeight: "500",
2406
- color: "#6b7280"
2407
- },
2408
- "data-testid": "button-report-cancel",
2409
- children: "Cancel"
2410
- }
2411
- ),
2412
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2413
- "button",
2414
- {
2415
- onClick: () => handleReportQuestion(reportComment),
2416
- disabled: isReporting || !reportComment.trim(),
2417
- style: {
2418
- flex: 1,
2419
- padding: "10px 16px",
2420
- borderRadius: "8px",
2421
- border: "none",
2422
- backgroundColor: reportComment.trim() ? "#ef4444" : "#d1d5db",
2423
- cursor: isReporting || !reportComment.trim() ? "not-allowed" : "pointer",
2424
- fontSize: "14px",
2425
- fontWeight: "500",
2426
- color: "#ffffff",
2427
- opacity: isReporting ? 0.6 : 1
2428
- },
2429
- "data-testid": "button-report-submit",
2430
- children: isReporting ? "Reporting..." : "Report"
2431
- }
2432
- )
2433
- ] })
2434
- ] }) }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.buttonsColumn, children: [
2436
- showFeedback && isLastQuestion && canAddMore && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2447
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: "10px" }, children: [
2448
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2437
2449
  "button",
2438
2450
  {
2451
+ onClick: () => {
2452
+ setShowReportModal(false);
2453
+ setReportComment("");
2454
+ },
2439
2455
  style: {
2440
- ...defaultStyles.buttonAddMore,
2441
- ...isGeneratingExtra ? defaultStyles.buttonAddMoreDisabled : {}
2456
+ flex: 1,
2457
+ padding: "10px 16px",
2458
+ borderRadius: "8px",
2459
+ border: "1px solid #e5e7eb",
2460
+ backgroundColor: "#ffffff",
2461
+ cursor: "pointer",
2462
+ fontSize: "14px",
2463
+ fontWeight: "500",
2464
+ color: "#6b7280"
2442
2465
  },
2443
- onClick: handleAddMoreQuestions,
2444
- disabled: isGeneratingExtra,
2445
- "data-testid": "button-add-more-questions",
2446
- children: isGeneratingExtra ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2447
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }),
2448
- "Generating Questions..."
2449
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2450
- "+ Add ",
2451
- questionsToAdd,
2452
- " More Question",
2453
- questionsToAdd !== 1 ? "s" : ""
2454
- ] })
2466
+ "data-testid": "button-report-cancel",
2467
+ children: "Cancel"
2455
2468
  }
2456
2469
  ),
2457
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...defaultStyles.buttons, justifyContent: "flex-end" }, children: showFeedback ? (
2458
- // After viewing feedback
2459
- isLastQuestion ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2460
- "button",
2461
- {
2462
- style: {
2463
- ...defaultStyles.button,
2464
- ...isSubmitting || isGeneratingExtra ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
2465
- },
2466
- onClick: handleSubmit,
2467
- disabled: isSubmitting || isGeneratingExtra,
2468
- "data-testid": "button-submit-quiz",
2469
- children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Submit Quiz"
2470
- }
2471
- ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2472
- "button",
2473
- {
2474
- style: {
2475
- ...defaultStyles.button,
2476
- ...defaultStyles.buttonPrimary
2477
- },
2478
- onClick: handleContinue,
2479
- "data-testid": "button-continue",
2480
- children: "Continue"
2481
- }
2482
- )
2483
- ) : (
2484
- // Before checking answer
2485
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2486
- "button",
2487
- {
2488
- style: {
2489
- ...defaultStyles.button,
2490
- ...isNavigating || selectedAnswer === void 0 ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
2491
- },
2492
- onClick: handleCheckAnswer,
2493
- disabled: isNavigating || selectedAnswer === void 0,
2494
- "data-testid": "button-check-answer",
2495
- children: isNavigating ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Check Answer"
2496
- }
2497
- )
2498
- ) })
2470
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2471
+ "button",
2472
+ {
2473
+ onClick: () => handleReportQuestion(reportComment),
2474
+ disabled: isReporting || !reportComment.trim(),
2475
+ style: {
2476
+ flex: 1,
2477
+ padding: "10px 16px",
2478
+ borderRadius: "8px",
2479
+ border: "none",
2480
+ backgroundColor: reportComment.trim() ? "#ef4444" : "#d1d5db",
2481
+ cursor: isReporting || !reportComment.trim() ? "not-allowed" : "pointer",
2482
+ fontSize: "14px",
2483
+ fontWeight: "500",
2484
+ color: "#ffffff",
2485
+ opacity: isReporting ? 0.6 : 1
2486
+ },
2487
+ "data-testid": "button-report-submit",
2488
+ children: isReporting ? "Reporting..." : "Report"
2489
+ }
2490
+ )
2499
2491
  ] })
2500
- ] }),
2501
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.chatPanel, children: apiClient.current && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2502
- QuestionChatPanel,
2503
- {
2504
- apiClient: apiClient.current,
2505
- question: {
2506
- id: currentQuestion.id,
2507
- question: currentQuestion.question,
2508
- type: currentQuestion.type,
2509
- options: currentQuestion.options,
2510
- correctAnswer: currentQuestion.correctAnswer,
2511
- explanation: currentQuestion.explanation
2512
- },
2513
- quizId: quiz.id,
2514
- childId,
2515
- parentId,
2516
- lessonId,
2517
- courseId
2518
- }
2519
- ) })
2520
- ] })
2521
- ] });
2492
+ ] }) }),
2493
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: defaultStyles.buttonsColumn, children: [
2494
+ showFeedback && isLastQuestion && canAddMore && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2495
+ "button",
2496
+ {
2497
+ style: {
2498
+ ...defaultStyles.buttonAddMore,
2499
+ ...isGeneratingExtra ? defaultStyles.buttonAddMoreDisabled : {}
2500
+ },
2501
+ onClick: handleAddMoreQuestions,
2502
+ disabled: isGeneratingExtra,
2503
+ "data-testid": "button-add-more-questions",
2504
+ children: isGeneratingExtra ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2505
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }),
2506
+ "Generating Questions..."
2507
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2508
+ "+ Add ",
2509
+ questionsToAdd,
2510
+ " More Question",
2511
+ questionsToAdd !== 1 ? "s" : ""
2512
+ ] })
2513
+ }
2514
+ ),
2515
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { ...defaultStyles.buttons, justifyContent: "flex-end" }, children: showFeedback ? (
2516
+ // After viewing feedback
2517
+ isLastQuestion ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2518
+ "button",
2519
+ {
2520
+ style: {
2521
+ ...defaultStyles.button,
2522
+ ...isSubmitting || isGeneratingExtra ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
2523
+ },
2524
+ onClick: handleSubmit,
2525
+ disabled: isSubmitting || isGeneratingExtra,
2526
+ "data-testid": "button-submit-quiz",
2527
+ children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Submit Quiz"
2528
+ }
2529
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2530
+ "button",
2531
+ {
2532
+ style: {
2533
+ ...defaultStyles.button,
2534
+ ...defaultStyles.buttonPrimary
2535
+ },
2536
+ onClick: handleContinue,
2537
+ "data-testid": "button-continue",
2538
+ children: "Continue"
2539
+ }
2540
+ )
2541
+ ) : (
2542
+ // Before checking answer
2543
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2544
+ "button",
2545
+ {
2546
+ style: {
2547
+ ...defaultStyles.button,
2548
+ ...isNavigating || selectedAnswer === void 0 ? defaultStyles.buttonDisabled : defaultStyles.buttonPrimary
2549
+ },
2550
+ onClick: handleCheckAnswer,
2551
+ disabled: isNavigating || selectedAnswer === void 0,
2552
+ "data-testid": "button-check-answer",
2553
+ children: isNavigating ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Spinner, { size: 16, color: "#9ca3af" }) : "Check Answer"
2554
+ }
2555
+ )
2556
+ ) })
2557
+ ] })
2558
+ ] }),
2559
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: defaultStyles.chatPanel, children: apiClient.current && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2560
+ QuestionChatPanel,
2561
+ {
2562
+ apiClient: apiClient.current,
2563
+ question: {
2564
+ id: currentQuestion.id,
2565
+ question: currentQuestion.question,
2566
+ type: currentQuestion.type,
2567
+ options: currentQuestion.options,
2568
+ correctAnswer: currentQuestion.correctAnswer,
2569
+ explanation: currentQuestion.explanation
2570
+ },
2571
+ quizId: quiz.id,
2572
+ childId,
2573
+ parentId,
2574
+ lessonId,
2575
+ courseId,
2576
+ answerResult: showFeedback && currentAnswerDetail ? {
2577
+ wasIncorrect: !currentAnswerDetail.isCorrect,
2578
+ selectedAnswer: typeof selectedAnswer === "string" ? selectedAnswer : Array.isArray(selectedAnswer) ? selectedAnswer.join(", ") : void 0,
2579
+ correctAnswer: typeof currentQuestion.correctAnswer === "string" ? currentQuestion.correctAnswer : Array.isArray(currentQuestion.correctAnswer) ? currentQuestion.correctAnswer.join(", ") : void 0,
2580
+ explanation: currentQuestion.explanation
2581
+ } : void 0
2582
+ }
2583
+ ) })
2584
+ ] }) });
2522
2585
  }
2523
2586
 
2524
2587
  // src/AttemptViewer.tsx
@@ -2644,6 +2707,46 @@ var defaultStyles2 = {
2644
2707
  fontSize: "14px",
2645
2708
  color: "#581c87"
2646
2709
  },
2710
+ chatHistorySection: {
2711
+ marginTop: "12px",
2712
+ borderTop: "1px solid #e5e7eb",
2713
+ paddingTop: "12px"
2714
+ },
2715
+ chatToggleButton: {
2716
+ display: "flex",
2717
+ alignItems: "center",
2718
+ gap: "6px",
2719
+ padding: "6px 12px",
2720
+ backgroundColor: "#f3f4f6",
2721
+ border: "none",
2722
+ borderRadius: "6px",
2723
+ fontSize: "13px",
2724
+ color: "#6b7280",
2725
+ cursor: "pointer",
2726
+ fontWeight: "500"
2727
+ },
2728
+ chatMessages: {
2729
+ marginTop: "12px",
2730
+ display: "flex",
2731
+ flexDirection: "column",
2732
+ gap: "8px"
2733
+ },
2734
+ chatMessage: {
2735
+ padding: "8px 12px",
2736
+ borderRadius: "8px",
2737
+ fontSize: "13px",
2738
+ maxWidth: "85%"
2739
+ },
2740
+ chatMessageUser: {
2741
+ backgroundColor: "#6721b0",
2742
+ color: "#ffffff",
2743
+ alignSelf: "flex-end"
2744
+ },
2745
+ chatMessageAssistant: {
2746
+ backgroundColor: "#f3f4f6",
2747
+ color: "#111827",
2748
+ alignSelf: "flex-start"
2749
+ },
2647
2750
  loading: {
2648
2751
  textAlign: "center",
2649
2752
  padding: "40px 20px"
@@ -2701,11 +2804,14 @@ function AttemptViewer({
2701
2804
  onError,
2702
2805
  className,
2703
2806
  showExplanations = true,
2807
+ showConversation = false,
2704
2808
  title
2705
2809
  }) {
2706
2810
  const [attempt, setAttempt] = (0, import_react4.useState)(null);
2707
2811
  const [loading, setLoading] = (0, import_react4.useState)(true);
2708
2812
  const [error, setError] = (0, import_react4.useState)(null);
2813
+ const [chatHistories, setChatHistories] = (0, import_react4.useState)({});
2814
+ const [expandedChats, setExpandedChats] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
2709
2815
  (0, import_react4.useEffect)(() => {
2710
2816
  const apiClient = new QuizApiClient({
2711
2817
  baseUrl: apiBaseUrl,
@@ -2723,6 +2829,14 @@ function AttemptViewer({
2723
2829
  }
2724
2830
  const data = await response.json();
2725
2831
  setAttempt(data);
2832
+ if (showConversation) {
2833
+ try {
2834
+ const chats = await apiClient.getChatsByAttempt(attemptId);
2835
+ setChatHistories(chats);
2836
+ } catch (chatErr) {
2837
+ console.error("Failed to load chat histories:", chatErr);
2838
+ }
2839
+ }
2726
2840
  } catch (err) {
2727
2841
  const errorMessage = err instanceof Error ? err.message : "Failed to load attempt";
2728
2842
  setError(errorMessage);
@@ -2732,7 +2846,18 @@ function AttemptViewer({
2732
2846
  }
2733
2847
  }
2734
2848
  fetchAttempt();
2735
- }, [attemptId, apiBaseUrl, authToken, onError]);
2849
+ }, [attemptId, apiBaseUrl, authToken, onError, showConversation]);
2850
+ const toggleChatExpanded = (questionId) => {
2851
+ setExpandedChats((prev) => {
2852
+ const newSet = new Set(prev);
2853
+ if (newSet.has(questionId)) {
2854
+ newSet.delete(questionId);
2855
+ } else {
2856
+ newSet.add(questionId);
2857
+ }
2858
+ return newSet;
2859
+ });
2860
+ };
2736
2861
  const handleRetry = () => {
2737
2862
  setLoading(true);
2738
2863
  setError(null);
@@ -2824,6 +2949,34 @@ function AttemptViewer({
2824
2949
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: "Explanation:" }),
2825
2950
  " ",
2826
2951
  answer.explanation
2952
+ ] }),
2953
+ showConversation && chatHistories[answer.questionId] && chatHistories[answer.questionId].messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: defaultStyles2.chatHistorySection, children: [
2954
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2955
+ "button",
2956
+ {
2957
+ style: defaultStyles2.chatToggleButton,
2958
+ onClick: () => toggleChatExpanded(answer.questionId),
2959
+ "data-testid": `button-toggle-chat-${answer.questionId}`,
2960
+ children: [
2961
+ /* @__PURE__ */ (0, import_jsx_runtime4.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_runtime4.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" }) }),
2962
+ expandedChats.has(answer.questionId) ? "Hide" : "View",
2963
+ " Chat History (",
2964
+ chatHistories[answer.questionId].messages.length,
2965
+ " messages)"
2966
+ ]
2967
+ }
2968
+ ),
2969
+ expandedChats.has(answer.questionId) && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: defaultStyles2.chatMessages, children: chatHistories[answer.questionId].messages.map((msg, msgIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2970
+ "div",
2971
+ {
2972
+ style: {
2973
+ ...defaultStyles2.chatMessage,
2974
+ ...msg.role === "user" ? defaultStyles2.chatMessageUser : defaultStyles2.chatMessageAssistant
2975
+ },
2976
+ children: msg.content
2977
+ },
2978
+ msgIndex
2979
+ )) })
2827
2980
  ] })
2828
2981
  ]
2829
2982
  },