import {errorButtonStyle, infoButtonStyle} from "@/constants/buttonStyles"; import {MatchSentenceExerciseOption, MatchSentenceExerciseSentence, MatchSentencesExercise} from "@/interfaces/exam"; import {mdiArrowLeft, mdiArrowRight} from "@mdi/js"; import Icon from "@mdi/react"; import clsx from "clsx"; import {Fragment, useEffect, useState} from "react"; import LineTo from "react-lineto"; import {CommonProps} from "."; import Button from "../Low/Button"; import Xarrow from "react-xarrows"; import useExamStore from "@/stores/examStore"; import {DndContext, DragEndEvent, useDraggable, useDroppable} from "@dnd-kit/core"; function DroppableQuestionArea({question, answer}: {question: MatchSentenceExerciseSentence; answer?: string}) { const {isOver, setNodeRef} = useDroppable({id: `droppable_sentence_${question.id}`}); return (
{question.sentence}
{answer && `Paragraph ${answer}`}
); } function DraggableOptionArea({option}: {option: MatchSentenceExerciseOption}) { const {attributes, listeners, setNodeRef, transform} = useDraggable({ id: `draggable_option_${option.id}`, }); const style = transform ? { transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`, zIndex: 99, } : undefined; return (
); } export default function MatchSentences({id, options, type, prompt, sentences, userSolutions, onNext, onBack}: MatchSentencesExercise & CommonProps) { const [answers, setAnswers] = useState<{question: string; option: string}[]>(userSolutions); const hasExamEnded = useExamStore((state) => state.hasExamEnded); const handleDragEnd = (event: DragEndEvent) => { if (event.over && event.over.id.toString().startsWith("droppable")) { const optionID = event.active.id.toString().replace("draggable_option_", ""); const sentenceID = event.over.id.toString().replace("droppable_sentence_", ""); setAnswers((prev) => [...prev.filter((x) => x.question.toString() !== sentenceID), {question: sentenceID, option: optionID}]); } }; const calculateScore = () => { const total = sentences.length; const correct = answers.filter( (x) => sentences.find((y) => y.id.toString() === x.question.toString())?.solution === x.option || false, ).length; const missing = total - answers.filter((x) => sentences.find((y) => y.id.toString() === x.question.toString())).length; return {total, correct, missing}; }; useEffect(() => { if (hasExamEnded) onNext({exercise: id, solutions: answers, score: calculateScore(), type}); // eslint-disable-next-line react-hooks/exhaustive-deps }, [hasExamEnded]); return ( <>
{prompt.split("\\n").map((line, index) => ( {line}
))}
{sentences.map((question) => ( x.question.toString() === question.id.toString())?.option} /> ))}
Drag one of these paragraphs into the slots above:
{options.map((option) => ( ))}
); }