import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles"; import {WriteBlanksExercise} from "@/interfaces/exam"; import {mdiArrowLeft, mdiArrowRight} from "@mdi/js"; import Icon from "@mdi/react"; import clsx from "clsx"; import {useEffect, useState} from "react"; import reactStringReplace from "react-string-replace"; import {CommonProps} from "."; import {toast} from "react-toastify"; function Blank({ id, maxWords, showSolutions = false, setUserSolution, }: { id: string; solutions?: string[]; userSolution?: string; maxWords: number; showSolutions?: boolean; setUserSolution?: (solution: string) => void; }) { const [userInput, setUserInput] = useState(""); useEffect(() => { const words = userInput.split(" ").filter((x) => x !== ""); if (words.length >= maxWords) { toast.warning(`You have reached your word limit of ${maxWords} words!`, {toastId: "word-limit"}); setUserInput(words.join(" ").trim()); } }, [maxWords, userInput]); return ( setUserInput(e.target.value)} value={userInput} contentEditable={showSolutions} /> ); } export default function WriteBlanks({id, prompt, maxWords, solutions, text, onNext, onBack}: WriteBlanksExercise & CommonProps) { const [userSolutions, setUserSolutions] = useState<{id: string; solution: string}[]>([]); const calculateScore = () => { const total = text.match(/({{\d+}})/g)?.length || 0; const correct = userSolutions.filter( (x) => solutions .find((y) => x.id === y.id) ?.solution.map((y) => y.toLowerCase()) .includes(x.solution.toLowerCase()) || false, ).length; return {total, correct}; }; const renderLines = (line: string) => { return ( {reactStringReplace(line, /({{\d+}})/g, (match) => { const id = match.replaceAll(/[\{\}]/g, ""); const userSolution = userSolutions.find((x) => x.id === id); const setUserSolution = (solution: string) => { setUserSolutions((prev) => [...prev.filter((x) => x.id !== id), {id, solution}]); }; return ; })} ); }; return ( <>
{prompt} {text.split("\n").map((line) => ( <> {renderLines(line)}
))}
); }