Exam generation rework, batch user tables, fastapi endpoint switch
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { FillBlanksExercise, FillBlanksMCOption } from "@/interfaces/exam";
|
||||
import useExamStore from "@/stores/examStore";
|
||||
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";
|
||||
@@ -17,16 +17,28 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
words,
|
||||
userSolutions,
|
||||
variant,
|
||||
preview,
|
||||
onNext,
|
||||
onBack,
|
||||
}) => {
|
||||
const { shuffles, exam, partIndex, questionIndex, exerciseIndex } = useExamStore((state) => state);
|
||||
|
||||
const examState = useExamStore((state) => state);
|
||||
const persistentExamState = usePersistentExamStore((state) => state);
|
||||
|
||||
const {
|
||||
hasExamEnded,
|
||||
exerciseIndex,
|
||||
partIndex,
|
||||
questionIndex,
|
||||
shuffles,
|
||||
exam,
|
||||
setCurrentSolution,
|
||||
} = !preview ? examState : persistentExamState;
|
||||
|
||||
const [answers, setAnswers] = useState<{ id: string; solution: string }[]>(userSolutions);
|
||||
const hasExamEnded = useExamStore((state) => state.hasExamEnded);
|
||||
const setCurrentSolution = useExamStore((state) => state.setCurrentSolution);
|
||||
const shuffleMaps = shuffles.find((x) => x.exerciseID == id)?.shuffles;
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
|
||||
const excludeWordMCType = (x: any) => {
|
||||
return typeof x === "string" ? x : (x as { letter: string; word: string });
|
||||
};
|
||||
@@ -88,30 +100,30 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
const renderLines = useCallback(
|
||||
(line: string) => {
|
||||
return (
|
||||
<div className="text-xl leading-5" key={v4()} ref={dropdownRef}>
|
||||
{reactStringReplace(line, /({{\d+}})/g, (match) => {
|
||||
<div className="text-xl leading-relaxed" key={v4()} ref={dropdownRef}>
|
||||
{reactStringReplace(line, /({{\d+}})/g, (match, i, original) => {
|
||||
const id = match.replaceAll(/[\{\}]/g, "");
|
||||
const userSolution = answers.find((x) => x.id === id);
|
||||
const styles = clsx(
|
||||
"rounded-full hover:text-white transition duration-300 ease-in-out my-1 px-5 py-2 text-center w-fit",
|
||||
"rounded-full hover:text-white transition duration-300 ease-in-out my-1 px-5 py-2 text-center w-fit inline-block",
|
||||
!userSolution && "text-center text-mti-purple-light bg-mti-purple-ultralight",
|
||||
userSolution && "text-center text-mti-purple-dark bg-mti-purple-ultralight",
|
||||
);
|
||||
|
||||
|
||||
const currentSelection = words.find((x) => {
|
||||
if (typeof x !== "string" && "id" in x) {
|
||||
return (x as FillBlanksMCOption).id.toString() == id.toString();
|
||||
}
|
||||
return false;
|
||||
}) as FillBlanksMCOption;
|
||||
|
||||
|
||||
return variant === "mc" ? (
|
||||
<MCDropdown
|
||||
id={id}
|
||||
options={currentSelection.options}
|
||||
onSelect={(value) => onSelection(id, value)}
|
||||
selectedValue={userSolution?.solution}
|
||||
className="inline-block py-2 px-1"
|
||||
className="inline-block py-2 px-1 align-middle"
|
||||
width={220}
|
||||
isOpen={openDropdownId === id}
|
||||
onToggle={()=> setOpenDropdownId(prevId => prevId === id ? null : id)}
|
||||
@@ -123,14 +135,13 @@ const FillBlanks: React.FC<FillBlanksExercise & CommonProps> = ({
|
||||
value={userSolution?.solution}
|
||||
/>
|
||||
);
|
||||
})
|
||||
}
|
||||
</div >
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
[variant, words, answers, openDropdownId],
|
||||
);
|
||||
|
||||
|
||||
const memoizedLines = useMemo(() => {
|
||||
return text.split("\\n").map((line, index) => (
|
||||
<p key={index} className={clsx(variant === "mc" && "whitespace-pre-wrap")}>
|
||||
|
||||
Reference in New Issue
Block a user