@schoolio/player 1.1.1 → 1.2.1
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/README.md +90 -1
- package/dist/index.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +302 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +302 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# @schoolio/player
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React components for loading quizzes and displaying attempt results from Quiz Engine.
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
- **QuizPlayer** - Interactive quiz-taking component
|
|
8
|
+
- **AttemptViewer** - Displays quiz attempt results with detailed breakdown
|
|
4
9
|
|
|
5
10
|
## Installation
|
|
6
11
|
|
|
@@ -138,6 +143,90 @@ await client.updateAttempt(attempt.id, {
|
|
|
138
143
|
});
|
|
139
144
|
```
|
|
140
145
|
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## AttemptViewer
|
|
149
|
+
|
|
150
|
+
The `AttemptViewer` component displays quiz attempt results with a summary and detailed question-by-question breakdown.
|
|
151
|
+
|
|
152
|
+
### Usage
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import { AttemptViewer } from '@schoolio/player';
|
|
156
|
+
|
|
157
|
+
function MyResultsPage() {
|
|
158
|
+
return (
|
|
159
|
+
<AttemptViewer
|
|
160
|
+
attemptId={123}
|
|
161
|
+
apiBaseUrl="https://your-quiz-engine-url.com"
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Props
|
|
168
|
+
|
|
169
|
+
| Prop | Type | Required | Description |
|
|
170
|
+
|------|------|----------|-------------|
|
|
171
|
+
| `attemptId` | `number` | Yes | The ID of the quiz attempt to display |
|
|
172
|
+
| `apiBaseUrl` | `string` | Yes | Base URL of your Quiz Engine API |
|
|
173
|
+
| `title` | `string` | No | Optional title (reserved for future use) |
|
|
174
|
+
|
|
175
|
+
### API Endpoint Required
|
|
176
|
+
|
|
177
|
+
The component expects this endpoint:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
GET {apiBaseUrl}/api/quiz-attempts/{attemptId}/results
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Response format:**
|
|
184
|
+
|
|
185
|
+
```json
|
|
186
|
+
{
|
|
187
|
+
"attempt": {
|
|
188
|
+
"id": 123,
|
|
189
|
+
"quizId": 1,
|
|
190
|
+
"score": 80,
|
|
191
|
+
"totalQuestions": 10,
|
|
192
|
+
"correctAnswers": 8,
|
|
193
|
+
"timeTaken": 300,
|
|
194
|
+
"completedAt": "2025-01-02T10:00:00Z",
|
|
195
|
+
"answers": { "1": "selected_answer", "2": "another_answer" }
|
|
196
|
+
},
|
|
197
|
+
"questions": [
|
|
198
|
+
{
|
|
199
|
+
"id": 1,
|
|
200
|
+
"questionText": "What is 2+2?",
|
|
201
|
+
"questionType": "multiple_choice",
|
|
202
|
+
"options": ["3", "4", "5"],
|
|
203
|
+
"correctAnswer": "4",
|
|
204
|
+
"explanation": "Basic addition"
|
|
205
|
+
}
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Styling
|
|
211
|
+
|
|
212
|
+
The component uses 100% width to fill its parent container. Wrap it in a sized container to control dimensions:
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
<div style={{ maxWidth: '800px', margin: '0 auto' }}>
|
|
216
|
+
<AttemptViewer attemptId={123} apiBaseUrl="https://api.example.com" />
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Features
|
|
221
|
+
|
|
222
|
+
- **Summary cards** showing score, questions count, and time taken
|
|
223
|
+
- **Detailed breakdown** of each question with correct/incorrect indicators
|
|
224
|
+
- **Explanations** displayed for each question when available
|
|
225
|
+
- **Purple theme** (#6721b0) matching the QuizPlayer design
|
|
226
|
+
- **Responsive layout** that adapts to container width
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
141
230
|
## License
|
|
142
231
|
|
|
143
232
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -94,9 +94,20 @@ interface QuizPlayerStyles {
|
|
|
94
94
|
buttonClassName?: string;
|
|
95
95
|
progressClassName?: string;
|
|
96
96
|
}
|
|
97
|
+
interface AttemptViewerProps {
|
|
98
|
+
attemptId: string;
|
|
99
|
+
apiBaseUrl: string;
|
|
100
|
+
authToken?: string;
|
|
101
|
+
onError?: (error: Error) => void;
|
|
102
|
+
className?: string;
|
|
103
|
+
showExplanations?: boolean;
|
|
104
|
+
title?: string;
|
|
105
|
+
}
|
|
97
106
|
|
|
98
107
|
declare function QuizPlayer({ quizId, lessonId, assignLessonId, courseId, childId, parentId, apiBaseUrl, authToken, onComplete, onError, onProgress, className, }: QuizPlayerProps): react_jsx_runtime.JSX.Element;
|
|
99
108
|
|
|
109
|
+
declare function AttemptViewer({ attemptId, apiBaseUrl, authToken, onError, className, showExplanations, title, }: AttemptViewerProps): react_jsx_runtime.JSX.Element;
|
|
110
|
+
|
|
100
111
|
interface ApiClientConfig {
|
|
101
112
|
baseUrl: string;
|
|
102
113
|
authToken?: string;
|
|
@@ -143,4 +154,4 @@ declare function calculateScore(answers: QuizAnswerDetail[]): {
|
|
|
143
154
|
};
|
|
144
155
|
declare function formatTime(seconds: number): string;
|
|
145
156
|
|
|
146
|
-
export { type ApiClientConfig, type AttemptStatus, type ExternalQuizAttempt, type QuestionType, type Quiz, type QuizAnswerDetail, QuizApiClient, QuizPlayer, type QuizPlayerProps, type QuizPlayerStyles, type QuizProgress, type QuizQuestion, type QuizResult, calculateScore, checkAnswer, createAnswerDetail, formatTime };
|
|
157
|
+
export { type ApiClientConfig, type AttemptStatus, AttemptViewer, type AttemptViewerProps, type ExternalQuizAttempt, type QuestionType, type Quiz, type QuizAnswerDetail, QuizApiClient, QuizPlayer, type QuizPlayerProps, type QuizPlayerStyles, type QuizProgress, type QuizQuestion, type QuizResult, calculateScore, checkAnswer, createAnswerDetail, formatTime };
|
package/dist/index.d.ts
CHANGED
|
@@ -94,9 +94,20 @@ interface QuizPlayerStyles {
|
|
|
94
94
|
buttonClassName?: string;
|
|
95
95
|
progressClassName?: string;
|
|
96
96
|
}
|
|
97
|
+
interface AttemptViewerProps {
|
|
98
|
+
attemptId: string;
|
|
99
|
+
apiBaseUrl: string;
|
|
100
|
+
authToken?: string;
|
|
101
|
+
onError?: (error: Error) => void;
|
|
102
|
+
className?: string;
|
|
103
|
+
showExplanations?: boolean;
|
|
104
|
+
title?: string;
|
|
105
|
+
}
|
|
97
106
|
|
|
98
107
|
declare function QuizPlayer({ quizId, lessonId, assignLessonId, courseId, childId, parentId, apiBaseUrl, authToken, onComplete, onError, onProgress, className, }: QuizPlayerProps): react_jsx_runtime.JSX.Element;
|
|
99
108
|
|
|
109
|
+
declare function AttemptViewer({ attemptId, apiBaseUrl, authToken, onError, className, showExplanations, title, }: AttemptViewerProps): react_jsx_runtime.JSX.Element;
|
|
110
|
+
|
|
100
111
|
interface ApiClientConfig {
|
|
101
112
|
baseUrl: string;
|
|
102
113
|
authToken?: string;
|
|
@@ -143,4 +154,4 @@ declare function calculateScore(answers: QuizAnswerDetail[]): {
|
|
|
143
154
|
};
|
|
144
155
|
declare function formatTime(seconds: number): string;
|
|
145
156
|
|
|
146
|
-
export { type ApiClientConfig, type AttemptStatus, type ExternalQuizAttempt, type QuestionType, type Quiz, type QuizAnswerDetail, QuizApiClient, QuizPlayer, type QuizPlayerProps, type QuizPlayerStyles, type QuizProgress, type QuizQuestion, type QuizResult, calculateScore, checkAnswer, createAnswerDetail, formatTime };
|
|
157
|
+
export { type ApiClientConfig, type AttemptStatus, AttemptViewer, type AttemptViewerProps, type ExternalQuizAttempt, type QuestionType, type Quiz, type QuizAnswerDetail, QuizApiClient, QuizPlayer, type QuizPlayerProps, type QuizPlayerStyles, type QuizProgress, type QuizQuestion, type QuizResult, calculateScore, checkAnswer, createAnswerDetail, formatTime };
|
package/dist/index.js
CHANGED
|
@@ -614,7 +614,309 @@ function QuizPlayer({
|
|
|
614
614
|
] })
|
|
615
615
|
] });
|
|
616
616
|
}
|
|
617
|
+
var defaultStyles2 = {
|
|
618
|
+
container: {
|
|
619
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
620
|
+
width: "100%",
|
|
621
|
+
padding: "20px",
|
|
622
|
+
backgroundColor: "#ffffff",
|
|
623
|
+
borderRadius: "12px",
|
|
624
|
+
boxSizing: "border-box"
|
|
625
|
+
},
|
|
626
|
+
header: {
|
|
627
|
+
marginBottom: "24px",
|
|
628
|
+
borderBottom: "1px solid #e5e7eb",
|
|
629
|
+
paddingBottom: "20px"
|
|
630
|
+
},
|
|
631
|
+
summaryGrid: {
|
|
632
|
+
display: "grid",
|
|
633
|
+
gridTemplateColumns: "repeat(auto-fit, minmax(120px, 1fr))",
|
|
634
|
+
gap: "16px"
|
|
635
|
+
},
|
|
636
|
+
summaryCard: {
|
|
637
|
+
padding: "12px",
|
|
638
|
+
backgroundColor: "#f9fafb",
|
|
639
|
+
borderRadius: "8px",
|
|
640
|
+
textAlign: "center"
|
|
641
|
+
},
|
|
642
|
+
summaryValue: {
|
|
643
|
+
fontSize: "20px",
|
|
644
|
+
fontWeight: "600",
|
|
645
|
+
color: "#6721b0",
|
|
646
|
+
marginBottom: "2px"
|
|
647
|
+
},
|
|
648
|
+
summaryLabel: {
|
|
649
|
+
fontSize: "10px",
|
|
650
|
+
color: "#6b7280",
|
|
651
|
+
textTransform: "uppercase",
|
|
652
|
+
letterSpacing: "0.05em"
|
|
653
|
+
},
|
|
654
|
+
questionsList: {
|
|
655
|
+
display: "flex",
|
|
656
|
+
flexDirection: "column",
|
|
657
|
+
gap: "16px"
|
|
658
|
+
},
|
|
659
|
+
questionCard: {
|
|
660
|
+
padding: "16px",
|
|
661
|
+
border: "2px solid #e5e7eb",
|
|
662
|
+
borderRadius: "8px"
|
|
663
|
+
},
|
|
664
|
+
questionCardCorrect: {
|
|
665
|
+
borderColor: "#22c55e",
|
|
666
|
+
backgroundColor: "#f0fdf4"
|
|
667
|
+
},
|
|
668
|
+
questionCardIncorrect: {
|
|
669
|
+
borderColor: "#ef4444",
|
|
670
|
+
backgroundColor: "#fef2f2"
|
|
671
|
+
},
|
|
672
|
+
questionHeader: {
|
|
673
|
+
display: "flex",
|
|
674
|
+
justifyContent: "space-between",
|
|
675
|
+
alignItems: "flex-start",
|
|
676
|
+
marginBottom: "12px"
|
|
677
|
+
},
|
|
678
|
+
questionNumber: {
|
|
679
|
+
fontSize: "12px",
|
|
680
|
+
color: "#6b7280",
|
|
681
|
+
fontWeight: "500"
|
|
682
|
+
},
|
|
683
|
+
questionBadge: {
|
|
684
|
+
padding: "4px 8px",
|
|
685
|
+
borderRadius: "4px",
|
|
686
|
+
fontSize: "12px",
|
|
687
|
+
fontWeight: "600"
|
|
688
|
+
},
|
|
689
|
+
badgeCorrect: {
|
|
690
|
+
backgroundColor: "#dcfce7",
|
|
691
|
+
color: "#166534"
|
|
692
|
+
},
|
|
693
|
+
badgeIncorrect: {
|
|
694
|
+
backgroundColor: "#fee2e2",
|
|
695
|
+
color: "#991b1b"
|
|
696
|
+
},
|
|
697
|
+
questionText: {
|
|
698
|
+
fontSize: "16px",
|
|
699
|
+
fontWeight: "500",
|
|
700
|
+
marginBottom: "12px",
|
|
701
|
+
color: "#111827"
|
|
702
|
+
},
|
|
703
|
+
answerSection: {
|
|
704
|
+
fontSize: "14px",
|
|
705
|
+
marginBottom: "8px"
|
|
706
|
+
},
|
|
707
|
+
answerLabel: {
|
|
708
|
+
fontWeight: "600",
|
|
709
|
+
color: "#6b7280",
|
|
710
|
+
marginRight: "8px"
|
|
711
|
+
},
|
|
712
|
+
studentAnswer: {
|
|
713
|
+
color: "#111827"
|
|
714
|
+
},
|
|
715
|
+
correctAnswer: {
|
|
716
|
+
color: "#166534"
|
|
717
|
+
},
|
|
718
|
+
points: {
|
|
719
|
+
fontSize: "13px",
|
|
720
|
+
color: "#6b7280",
|
|
721
|
+
marginTop: "8px"
|
|
722
|
+
},
|
|
723
|
+
explanation: {
|
|
724
|
+
marginTop: "12px",
|
|
725
|
+
padding: "12px",
|
|
726
|
+
backgroundColor: "#f3e8ff",
|
|
727
|
+
borderRadius: "6px",
|
|
728
|
+
fontSize: "14px",
|
|
729
|
+
color: "#581c87"
|
|
730
|
+
},
|
|
731
|
+
loading: {
|
|
732
|
+
textAlign: "center",
|
|
733
|
+
padding: "40px 20px"
|
|
734
|
+
},
|
|
735
|
+
spinner: {
|
|
736
|
+
display: "inline-block",
|
|
737
|
+
width: "32px",
|
|
738
|
+
height: "32px",
|
|
739
|
+
border: "3px solid #e5e7eb",
|
|
740
|
+
borderTopColor: "#6721b0",
|
|
741
|
+
borderRadius: "50%",
|
|
742
|
+
animation: "spin 1s linear infinite"
|
|
743
|
+
},
|
|
744
|
+
error: {
|
|
745
|
+
textAlign: "center",
|
|
746
|
+
padding: "40px 20px",
|
|
747
|
+
color: "#ef4444"
|
|
748
|
+
},
|
|
749
|
+
retryButton: {
|
|
750
|
+
marginTop: "16px",
|
|
751
|
+
padding: "12px 24px",
|
|
752
|
+
backgroundColor: "#6721b0",
|
|
753
|
+
color: "#ffffff",
|
|
754
|
+
border: "none",
|
|
755
|
+
borderRadius: "8px",
|
|
756
|
+
fontSize: "16px",
|
|
757
|
+
fontWeight: "500",
|
|
758
|
+
cursor: "pointer"
|
|
759
|
+
}
|
|
760
|
+
};
|
|
761
|
+
var spinnerKeyframes = `
|
|
762
|
+
@keyframes spin {
|
|
763
|
+
to { transform: rotate(360deg); }
|
|
764
|
+
}
|
|
765
|
+
`;
|
|
766
|
+
function formatAnswer(answer) {
|
|
767
|
+
if (answer === null || answer === void 0) {
|
|
768
|
+
return "No answer";
|
|
769
|
+
}
|
|
770
|
+
if (typeof answer === "string") {
|
|
771
|
+
return answer;
|
|
772
|
+
}
|
|
773
|
+
if (Array.isArray(answer)) {
|
|
774
|
+
return answer.join(", ");
|
|
775
|
+
}
|
|
776
|
+
if (typeof answer === "object") {
|
|
777
|
+
return Object.entries(answer).map(([k, v]) => `${k} \u2192 ${v}`).join(", ");
|
|
778
|
+
}
|
|
779
|
+
return String(answer);
|
|
780
|
+
}
|
|
781
|
+
function AttemptViewer({
|
|
782
|
+
attemptId,
|
|
783
|
+
apiBaseUrl,
|
|
784
|
+
authToken,
|
|
785
|
+
onError,
|
|
786
|
+
className,
|
|
787
|
+
showExplanations = true,
|
|
788
|
+
title
|
|
789
|
+
}) {
|
|
790
|
+
const [attempt, setAttempt] = react.useState(null);
|
|
791
|
+
const [loading, setLoading] = react.useState(true);
|
|
792
|
+
const [error, setError] = react.useState(null);
|
|
793
|
+
react.useEffect(() => {
|
|
794
|
+
new QuizApiClient({
|
|
795
|
+
baseUrl: apiBaseUrl,
|
|
796
|
+
authToken
|
|
797
|
+
});
|
|
798
|
+
async function fetchAttempt() {
|
|
799
|
+
setLoading(true);
|
|
800
|
+
setError(null);
|
|
801
|
+
try {
|
|
802
|
+
const response = await fetch(`${apiBaseUrl}/api/external/quiz-attempts/${attemptId}`, {
|
|
803
|
+
headers: authToken ? { Authorization: `Bearer ${authToken}` } : {}
|
|
804
|
+
});
|
|
805
|
+
if (!response.ok) {
|
|
806
|
+
throw new Error(`Failed to fetch attempt: ${response.statusText}`);
|
|
807
|
+
}
|
|
808
|
+
const data = await response.json();
|
|
809
|
+
setAttempt(data);
|
|
810
|
+
} catch (err) {
|
|
811
|
+
const errorMessage = err instanceof Error ? err.message : "Failed to load attempt";
|
|
812
|
+
setError(errorMessage);
|
|
813
|
+
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
814
|
+
} finally {
|
|
815
|
+
setLoading(false);
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
fetchAttempt();
|
|
819
|
+
}, [attemptId, apiBaseUrl, authToken, onError]);
|
|
820
|
+
const handleRetry = () => {
|
|
821
|
+
setLoading(true);
|
|
822
|
+
setError(null);
|
|
823
|
+
window.location.reload();
|
|
824
|
+
};
|
|
825
|
+
if (loading) {
|
|
826
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.container, className, children: [
|
|
827
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: spinnerKeyframes }),
|
|
828
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.loading, children: [
|
|
829
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.spinner }),
|
|
830
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: "16px", color: "#6b7280" }, children: "Loading attempt..." })
|
|
831
|
+
] })
|
|
832
|
+
] });
|
|
833
|
+
}
|
|
834
|
+
if (error || !attempt) {
|
|
835
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.container, className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.error, children: [
|
|
836
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "18px", fontWeight: "500" }, children: "Failed to load attempt" }),
|
|
837
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: "8px", color: "#6b7280" }, children: error }),
|
|
838
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { style: defaultStyles2.retryButton, onClick: handleRetry, children: "Try Again" })
|
|
839
|
+
] }) });
|
|
840
|
+
}
|
|
841
|
+
const scorePercentage = attempt.score ?? 0;
|
|
842
|
+
const correctCount = attempt.correctAnswers ?? 0;
|
|
843
|
+
const totalQuestions = attempt.totalQuestions;
|
|
844
|
+
const timeSpent = attempt.timeSpentSeconds ?? 0;
|
|
845
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.container, className, children: [
|
|
846
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: spinnerKeyframes }),
|
|
847
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.header, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryGrid, children: [
|
|
848
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryCard, children: [
|
|
849
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryValue, children: [
|
|
850
|
+
scorePercentage,
|
|
851
|
+
"%"
|
|
852
|
+
] }),
|
|
853
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.summaryLabel, children: "Score" })
|
|
854
|
+
] }),
|
|
855
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryCard, children: [
|
|
856
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryValue, children: [
|
|
857
|
+
correctCount,
|
|
858
|
+
"/",
|
|
859
|
+
totalQuestions
|
|
860
|
+
] }),
|
|
861
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.summaryLabel, children: "Correct" })
|
|
862
|
+
] }),
|
|
863
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.summaryCard, children: [
|
|
864
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.summaryValue, children: formatTime(timeSpent) }),
|
|
865
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.summaryLabel, children: "Time" })
|
|
866
|
+
] })
|
|
867
|
+
] }) }),
|
|
868
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.questionsList, children: attempt.answers.map((answer, index) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
869
|
+
"div",
|
|
870
|
+
{
|
|
871
|
+
style: {
|
|
872
|
+
...defaultStyles2.questionCard,
|
|
873
|
+
...answer.isCorrect ? defaultStyles2.questionCardCorrect : defaultStyles2.questionCardIncorrect
|
|
874
|
+
},
|
|
875
|
+
children: [
|
|
876
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.questionHeader, children: [
|
|
877
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { style: defaultStyles2.questionNumber, children: [
|
|
878
|
+
"Question ",
|
|
879
|
+
index + 1
|
|
880
|
+
] }),
|
|
881
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
882
|
+
"span",
|
|
883
|
+
{
|
|
884
|
+
style: {
|
|
885
|
+
...defaultStyles2.questionBadge,
|
|
886
|
+
...answer.isCorrect ? defaultStyles2.badgeCorrect : defaultStyles2.badgeIncorrect
|
|
887
|
+
},
|
|
888
|
+
children: answer.isCorrect ? "Correct" : "Incorrect"
|
|
889
|
+
}
|
|
890
|
+
)
|
|
891
|
+
] }),
|
|
892
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: defaultStyles2.questionText, children: answer.questionText }),
|
|
893
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.answerSection, children: [
|
|
894
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles2.answerLabel, children: "Your answer:" }),
|
|
895
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles2.studentAnswer, children: formatAnswer(answer.selectedAnswer) })
|
|
896
|
+
] }),
|
|
897
|
+
!answer.isCorrect && answer.correctAnswer && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.answerSection, children: [
|
|
898
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles2.answerLabel, children: "Correct answer:" }),
|
|
899
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: defaultStyles2.correctAnswer, children: formatAnswer(answer.correctAnswer) })
|
|
900
|
+
] }),
|
|
901
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.points, children: [
|
|
902
|
+
answer.pointsEarned,
|
|
903
|
+
" / ",
|
|
904
|
+
answer.points,
|
|
905
|
+
" points"
|
|
906
|
+
] }),
|
|
907
|
+
showExplanations && answer.explanation && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: defaultStyles2.explanation, children: [
|
|
908
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Explanation:" }),
|
|
909
|
+
" ",
|
|
910
|
+
answer.explanation
|
|
911
|
+
] })
|
|
912
|
+
]
|
|
913
|
+
},
|
|
914
|
+
answer.questionId
|
|
915
|
+
)) })
|
|
916
|
+
] });
|
|
917
|
+
}
|
|
617
918
|
|
|
919
|
+
exports.AttemptViewer = AttemptViewer;
|
|
618
920
|
exports.QuizApiClient = QuizApiClient;
|
|
619
921
|
exports.QuizPlayer = QuizPlayer;
|
|
620
922
|
exports.calculateScore = calculateScore;
|