From 06dbf1e5f69def5566c1daa8542d0c9238701deb Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Mon, 10 Apr 2023 11:40:44 +0100 Subject: [PATCH] Added a solution version for the MultipleChoice Exercise --- src/components/Exercises/FillBlanks.tsx | 2 +- src/components/Exercises/MatchSentences.tsx | 69 +++++++++---- src/components/Exercises/MultipleChoice.tsx | 103 +++++++++++++++++--- src/exams/Listening.tsx | 6 +- src/interfaces/exam.ts | 2 + 5 files changed, 150 insertions(+), 32 deletions(-) diff --git a/src/components/Exercises/FillBlanks.tsx b/src/components/Exercises/FillBlanks.tsx index 42ede5d1..239537f6 100644 --- a/src/components/Exercises/FillBlanks.tsx +++ b/src/components/Exercises/FillBlanks.tsx @@ -166,7 +166,7 @@ export function FillBlanksSolutions({ return ( <> - + ); } diff --git a/src/components/Exercises/MatchSentences.tsx b/src/components/Exercises/MatchSentences.tsx index 2f46234f..5503a39d 100644 --- a/src/components/Exercises/MatchSentences.tsx +++ b/src/components/Exercises/MatchSentences.tsx @@ -98,16 +98,7 @@ export default function MatchSentences({allowRepetition, options, prompt, senten ); } -export function MatchSentencesSolutions({allowRepetition, options, prompt, sentences}: MatchSentencesExercise) { - const [selectedQuestion, setSelectedQuestion] = useState(); - const [userSolutions, setUserSolutions] = useState<{question: string; option: string}[]>([]); - - const selectOption = (option: string) => { - if (!selectedQuestion) return; - setUserSolutions((prev) => [...prev.filter((x) => x.question !== selectedQuestion), {question: selectedQuestion, option}]); - setSelectedQuestion(undefined); - }; - +export function MatchSentencesSolutions({allowRepetition, options, prompt, sentences, userSolutions}: MatchSentencesExercise) { const getSentenceColor = (id: string) => { return sentences.find((x) => x.id === id)?.color || ""; }; @@ -118,15 +109,12 @@ export function MatchSentencesSolutions({allowRepetition, options, prompt, sente
{sentences.map(({sentence, id, color}) => ( -
setSelectedQuestion((prev) => (prev === id ? undefined : id))}> +
{id}. {sentence}{" "}
@@ -134,10 +122,7 @@ export function MatchSentencesSolutions({allowRepetition, options, prompt, sente
{options.map(({sentence, id}) => ( -
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 {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 + /> + )} +
+
+ + +
+ + ); +} 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 +
); 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 {