import { WriteBlanksExercise } from "@/interfaces/exam"; import clsx from "clsx"; import { useCallback, useEffect, useState } from "react"; import reactStringReplace from "react-string-replace"; import { CommonProps } from "../types"; import Blank from "./Blank"; import PracticeBadge from "../../Low/PracticeBadge"; const WriteBlanks: React.FC = ({ id, prompt, type, maxWords, solutions, userSolutions, isPractice = false, text, registerSolution, headerButtons, footerButtons, }) => { const [answers, setAnswers] = useState<{ id: string; solution: string }[]>(userSolutions); const calculateScore = useCallback(() => { const total = text.match(/({{\d+}})/g)?.length || 0; const correct = answers.filter( (x) => solutions .find((y) => x.id.toString() === y.id.toString()) ?.solution.map((y) => y.toLowerCase().trim()) .includes(x.solution.toLowerCase().trim()) || false, ).length; const missing = total - answers.filter((x) => solutions.find((y) => x.id === y.id)).length; return { total, correct, missing }; }, [answers, solutions, text]); useEffect(() => { registerSolution(() => ({ exercise: id, solutions: answers, score: calculateScore(), type, isPractice })); // eslint-disable-next-line react-hooks/exhaustive-deps }, [id, answers, type, isPractice, calculateScore]); const renderLines = (line: string) => { return ( {reactStringReplace(line, /({{\d+}})/g, (match) => { const id = match.replaceAll(/[\{\}]/g, ""); const userSolution = answers.find((x) => x.id === id); const setUserSolution = (solution: string) => { setAnswers((prev) => [...prev.filter((x) => x.id !== id), { id, solution }]); }; return ; })} ); }; return (
{headerButtons}
{prompt.split("\\n").map((line, index) => ( {line}
))}
{isPractice && } {text.split("\\n").map((line, index) => (

{renderLines(line)}

))}
{footerButtons}
); } export default WriteBlanks;