selectOption(id)}>
+
x.option === id)
@@ -166,6 +151,52 @@ export function MatchSentencesSolutions({allowRepetition, options, prompt, sente
))}
+
+
+
+ {sentences.map(({sentence, id, color}) => (
+
+
+ {id}. {sentence}{" "}
+
+
+
+ ))}
+
+
+ {options.map(({sentence, id}) => (
+
+
x.option === id)
+ ? {
+ border: `2px solid ${getSentenceColor(userSolutions.find((x) => x.option === id)!.question)}`,
+ }
+ : {}
+ }
+ className={clsx("border-2 border-green-500 bg-transparent w-4 h-4 rounded-full", id)}
+ />
+
+ {id}. {sentence}{" "}
+
+
+ ))}
+
+ {sentences.map(({id, solution}, index) => (
+
+ x.id === id)!.color}
+ borderWidth={5}
+ />
+
+ ))}
+
);
}
diff --git a/src/components/Exercises/MultipleChoice.tsx b/src/components/Exercises/MultipleChoice.tsx
index 2c3c6e44..0b106c7a 100644
--- a/src/components/Exercises/MultipleChoice.tsx
+++ b/src/components/Exercises/MultipleChoice.tsx
@@ -1,7 +1,7 @@
/* eslint-disable @next/next/no-img-element */
import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles";
import {MultipleChoiceExercise, MultipleChoiceQuestion} from "@/interfaces/exam";
-import {mdiArrowLeft, mdiArrowRight} from "@mdi/js";
+import {mdiArrowLeft, mdiArrowRight, mdiCheck, mdiClose} from "@mdi/js";
import Icon from "@mdi/react";
import clsx from "clsx";
import {useState} from "react";
@@ -9,13 +9,47 @@ import {CommonProps} from ".";
function Question({
variant,
- id,
prompt,
solution,
options,
userSolution,
onSelectOption,
-}: MultipleChoiceQuestion & {userSolution: string | undefined; onSelectOption: (option: string) => void}) {
+ showSolution = false,
+}: MultipleChoiceQuestion & {userSolution: string | undefined; onSelectOption?: (option: string) => void; showSolution?: boolean}) {
+ const optionColor = (option: string) => {
+ if (!showSolution) {
+ return userSolution === option ? "border-blue-400" : "";
+ }
+
+ if (option === solution) {
+ return "border-green-500 text-green-500";
+ }
+
+ return userSolution === option ? "border-red-500 text-red-500" : "";
+ };
+
+ const optionBadge = (option: string) => {
+ if (option === userSolution) {
+ if (solution === option) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+ }
+ };
+
return (
{prompt}
@@ -24,11 +58,12 @@ function Question({
options.map((option) => (
onSelectOption(option.id)}
+ onClick={() => (onSelectOption ? onSelectOption(option.id) : null)}
className={clsx(
- "flex flex-col items-center border-2 p-4 rounded-xl gap-4 cursor-pointer bg-white",
- userSolution === option.id && "border-blue-400",
+ "flex flex-col items-center border-2 p-4 rounded-xl gap-4 cursor-pointer bg-white relative",
+ optionColor(option.id),
)}>
+ {showSolution && optionBadge(option.id)}
{option.id}
@@ -37,11 +72,8 @@ function Question({
options.map((option) => (
onSelectOption(option.id)}
- className={clsx(
- "flex border-2 p-4 rounded-xl gap-2 cursor-pointer bg-white",
- userSolution === option.id && "border-blue-400",
- )}>
+ onClick={() => (onSelectOption ? onSelectOption(option.id) : null)}
+ className={clsx("flex border-2 p-4 rounded-xl gap-2 cursor-pointer bg-white", optionColor(option.id))}>
{option.id}.
{option.text}
@@ -105,3 +137,52 @@ export default function MultipleChoice({prompt, questions, onNext, onBack}: Mult
>
);
}
+
+export function MultipleChoiceSolutions({prompt, questions, userSolutions, onNext, onBack}: MultipleChoiceExercise & CommonProps) {
+ const [questionIndex, setQuestionIndex] = useState(0);
+
+ const next = () => {
+ if (questionIndex === questions.length - 1) {
+ onNext();
+ } else {
+ setQuestionIndex((prev) => prev + 1);
+ }
+ };
+
+ const back = () => {
+ if (questionIndex === 0) {
+ onBack();
+ } else {
+ setQuestionIndex((prev) => prev - 1);
+ }
+ };
+
+ return (
+ <>
+
+ {prompt}
+ {questionIndex < questions.length && (
+ questions[questionIndex].id === x.question)?.option}
+ showSolution
+ />
+ )}
+
+
+
+
+
+
+ Back
+
+
+ Next
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/exams/Listening.tsx b/src/exams/Listening.tsx
index 915a9fea..9d9e43da 100644
--- a/src/exams/Listening.tsx
+++ b/src/exams/Listening.tsx
@@ -57,7 +57,11 @@ export default function Listening({exam, onFinish}: Props) {
{exam.audio.repeatableTimes > 0 && (
<>{exam.audio.repeatableTimes <= timesListened &&
You are no longer allowed to listen to the audio again. }>
)}
-
AUDIO WILL GO HERE
+
setTimesListened((prev) => prev + 1)} onPause={() => alert("PAUSE")}>
+
+
+ Your browser does not support the audio element
+
>
);
diff --git a/src/interfaces/exam.ts b/src/interfaces/exam.ts
index d3500d49..ac436690 100644
--- a/src/interfaces/exam.ts
+++ b/src/interfaces/exam.ts
@@ -65,6 +65,7 @@ export interface WriteBlanksExercise {
export interface MatchSentencesExercise {
type: "matchSentences";
prompt: string;
+ userSolutions: {question: string; option: string}[];
sentences: {
id: string;
sentence: string;
@@ -82,6 +83,7 @@ export interface MultipleChoiceExercise {
type: "multipleChoice";
prompt: string; // *EXAMPLE: "Select the appropriate option."
questions: MultipleChoiceQuestion[];
+ userSolutions: {question: string; option: string}[];
}
export interface MultipleChoiceQuestion {