Navigation rework, added prompt edit to components that were missing
This commit is contained in:
@@ -1,12 +1,13 @@
|
||||
//import "@/utils/wdyr";
|
||||
|
||||
import { FillBlanksExercise, FillBlanksMCOption } from "@/interfaces/exam";
|
||||
import useExamStore, { usePersistentExamStore } from "@/stores/examStore";
|
||||
import clsx from "clsx";
|
||||
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import reactStringReplace from "react-string-replace";
|
||||
import { CommonProps } from "..";
|
||||
import Button from "../../Low/Button";
|
||||
import { CommonProps } from "../types";
|
||||
import { v4 } from "uuid";
|
||||
import MCDropdown from "./MCDropdown";
|
||||
import useExamStore, { usePersistentExamStore } from "@/stores/exam";
|
||||
|
||||
const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
id,
|
||||
@@ -18,43 +19,29 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
words,
|
||||
userSolutions,
|
||||
variant,
|
||||
registerSolution,
|
||||
headerButtons,
|
||||
footerButtons,
|
||||
preview,
|
||||
onNext,
|
||||
onBack,
|
||||
disableProgressButtons = false
|
||||
}) => {
|
||||
|
||||
const examState = useExamStore((state) => state);
|
||||
const persistentExamState = usePersistentExamStore((state) => state);
|
||||
|
||||
const {
|
||||
hasExamEnded,
|
||||
exerciseIndex,
|
||||
partIndex,
|
||||
questionIndex,
|
||||
shuffles,
|
||||
exam,
|
||||
setCurrentSolution,
|
||||
} = !preview ? examState : persistentExamState;
|
||||
} = examState; !preview ? examState : persistentExamState;
|
||||
|
||||
const [answers, setAnswers] = useState<{ id: string; solution: string }[]>(userSolutions);
|
||||
const shuffleMaps = shuffles.find((x) => x.exerciseID == id)?.shuffles;
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (disableProgressButtons) onNext({ exercise: id, solutions: answers, score: calculateScore(), type, isPractice });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [answers, disableProgressButtons])
|
||||
|
||||
const excludeWordMCType = (x: any) => {
|
||||
return typeof x === "string" ? x : (x as { letter: string; word: string });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (hasExamEnded) onNext({ exercise: id, solutions: answers, score: calculateScore(), type });
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [hasExamEnded]);
|
||||
|
||||
let correctWords: any;
|
||||
if (exam && (exam.module === "level" || exam.module === "reading") && exam.parts[partIndex].exercises[exerciseIndex].type === "fillBlanks") {
|
||||
correctWords = (exam.parts[partIndex].exercises[exerciseIndex] as FillBlanksExercise).words;
|
||||
@@ -73,7 +60,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
};
|
||||
}, []);
|
||||
|
||||
const calculateScore = () => {
|
||||
const calculateScore = useCallback(() => {
|
||||
const total = text.match(/({{\d+}})/g)?.length || 0;
|
||||
const correct = answers!.filter((x) => {
|
||||
const solution = solutions.find((y) => x.id.toString() === y.id.toString())?.solution;
|
||||
@@ -100,7 +87,19 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
}).length;
|
||||
const missing = total - answers!.filter((x) => solutions.find((y) => x.id.toString() === y.id.toString())).length;
|
||||
return { total, correct, missing };
|
||||
};
|
||||
}, [answers, correctWords, solutions, text]);
|
||||
|
||||
useEffect(() => {
|
||||
registerSolution(() => ({
|
||||
exercise: id,
|
||||
solutions: answers,
|
||||
score: calculateScore(),
|
||||
type,
|
||||
shuffleMaps,
|
||||
isPractice
|
||||
}));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [id, answers, type, isPractice, shuffleMaps, calculateScore]);
|
||||
|
||||
const [openDropdownId, setOpenDropdownId] = useState<string | null>(null);
|
||||
|
||||
@@ -137,6 +136,7 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
key={`input-${id}`}
|
||||
className={styles}
|
||||
onChange={(e) => setAnswers((prev) => [...prev.filter((x) => x.id !== id), { id, solution: e.target.value }])}
|
||||
value={userSolution?.solution}
|
||||
@@ -151,10 +151,10 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
|
||||
const memoizedLines = useMemo(() => {
|
||||
return text.split("\\n").map((line, index) => (
|
||||
<p key={index} className={clsx(variant === "mc" && "whitespace-pre-wrap")}>
|
||||
<div key={index} className={clsx(variant === "mc" && "whitespace-pre-wrap")}>
|
||||
{renderLines(line)}
|
||||
<br />
|
||||
</p>
|
||||
</div>
|
||||
));
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [text, variant, renderLines]);
|
||||
@@ -163,40 +163,10 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
setAnswers((prev) => [...prev.filter((x) => x.id !== questionID), { id: questionID, solution: value }]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (variant === "mc") {
|
||||
setCurrentSolution({ exercise: id, solutions: answers, score: calculateScore(), type, shuffleMaps: shuffleMaps });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [answers]);
|
||||
|
||||
const progressButtons = () => (
|
||||
<div className="flex justify-between w-full gap-8">
|
||||
<Button
|
||||
color="purple"
|
||||
variant="outline"
|
||||
onClick={() => onBack({ exercise: id, solutions: answers, score: calculateScore(), type, shuffleMaps: shuffleMaps, isPractice })}
|
||||
className="max-w-[200px] w-full"
|
||||
disabled={exam && exam.module === "level" && partIndex === 0 && questionIndex === 0}>
|
||||
Previous Page
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
color="purple"
|
||||
onClick={() => {
|
||||
onNext({ exercise: id, solutions: answers, score: calculateScore(), type, shuffleMaps: shuffleMaps, isPractice });
|
||||
}}
|
||||
className="max-w-[200px] self-end w-full">
|
||||
Next Page
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
{!disableProgressButtons && progressButtons()}
|
||||
|
||||
<div className={clsx("flex flex-col gap-4 mt-4 h-full w-full", !disableProgressButtons && "mb-20")}>
|
||||
{headerButtons}
|
||||
<div className={clsx("flex flex-col gap-4 mt-4 h-full w-full", (!headerButtons && !footerButtons) && "mb-20")}>
|
||||
{variant !== "mc" && (
|
||||
<span className="text-sm w-full leading-6">
|
||||
{prompt.split("\\n").map((line, index) => (
|
||||
@@ -234,11 +204,12 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{footerButtons}
|
||||
</div>
|
||||
|
||||
{!disableProgressButtons && progressButtons()}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
//FillBlanks.whyDidYouRender = true
|
||||
|
||||
export default FillBlanks;
|
||||
|
||||
Reference in New Issue
Block a user