import {renderExercise} from "@/components/Exercises"; import ModuleTitle from "@/components/Medium/ModuleTitle"; import {renderSolution} from "@/components/Solutions"; import {infoButtonStyle} from "@/constants/buttonStyles"; import {UserSolution, SpeakingExam, SpeakingExercise, InteractiveSpeakingExercise} from "@/interfaces/exam"; import useExamStore from "@/stores/examStore"; import {defaultUserSolutions} from "@/utils/exams"; import {countExercises} from "@/utils/moduleUtils"; import {convertCamelCaseToReadable} from "@/utils/string"; import {mdiArrowRight} from "@mdi/js"; import Icon from "@mdi/react"; import clsx from "clsx"; import {Fragment, useEffect, useState} from "react"; import {toast} from "react-toastify"; interface Props { exam: SpeakingExam; showSolutions?: boolean; onFinish: (userSolutions: UserSolution[]) => void; } export default function Speaking({exam, showSolutions = false, onFinish}: Props) { const [speakingPromptsDone, setSpeakingPromptsDone] = useState<{id: string; amount: number}[]>([]); const {userSolutions, setUserSolutions} = useExamStore((state) => state); const {questionIndex, setQuestionIndex} = useExamStore((state) => state); const {hasExamEnded, setHasExamEnded} = useExamStore((state) => state); const {exerciseIndex, setExerciseIndex} = useExamStore((state) => state); const scrollToTop = () => Array.from(document.getElementsByTagName("body")).forEach((body) => body.scrollTo(0, 0)); const nextExercise = (solution?: UserSolution) => { scrollToTop(); if (solution) { setUserSolutions([...userSolutions.filter((x) => x.exercise !== solution.exercise), {...solution, module: "speaking", exam: exam.id}]); } if (questionIndex > 0) { const exercise = getExercise(); setSpeakingPromptsDone((prev) => [...prev.filter((x) => x.id !== exercise.id), {id: exercise.id, amount: questionIndex}]); } setQuestionIndex(0); if (exerciseIndex + 1 < exam.exercises.length) { setExerciseIndex(exerciseIndex + 1); return; } if (exerciseIndex >= exam.exercises.length) return; setHasExamEnded(false); if (solution) { onFinish([...userSolutions.filter((x) => x.exercise !== solution.exercise), {...solution, module: "speaking", exam: exam.id}]); } else { onFinish(userSolutions); } }; const previousExercise = (solution?: UserSolution) => { scrollToTop(); if (solution) { setUserSolutions([...userSolutions.filter((x) => x.exercise !== solution.exercise), {...solution, module: "speaking", exam: exam.id}]); } if (exerciseIndex > 0) { setExerciseIndex(exerciseIndex - 1); } }; const getExercise = () => { const exercise = exam.exercises[exerciseIndex]; return { ...exercise, variant: exerciseIndex < 2 && exercise.type === "interactiveSpeaking" ? "initial" : undefined, userSolutions: userSolutions.find((x) => x.exercise === exercise.id)?.solutions || [], } as SpeakingExercise | InteractiveSpeakingExercise; }; return ( <>
acc + curr.amount, 0)} module="speaking" totalExercises={countExercises(exam.exercises)} disableTimer={showSolutions} /> {exerciseIndex > -1 && exerciseIndex < exam.exercises.length && !showSolutions && renderExercise(getExercise(), exam.id, nextExercise, previousExercise)} {exerciseIndex > -1 && exerciseIndex < exam.exercises.length && showSolutions && renderSolution(exam.exercises[exerciseIndex], nextExercise, previousExercise)}
); }