ENCOA-107, ENCOA-115 Fixed completion percentage, brought back the line numbers, 'Level Exam' was replaced by 'Placement Test', Next/Back instructions with quotes, 'Submit' on last level question

This commit is contained in:
Carlos Mesquita
2024-08-27 17:08:33 +01:00
parent c464375414
commit 845bccbe2a
7 changed files with 128 additions and 120 deletions

View File

@@ -8,7 +8,7 @@ import { Exercise, FillBlanksMCOption, LevelExam, MultipleChoiceExercise, Multip
import useExamStore from "@/stores/examStore";
import { countExercises } from "@/utils/moduleUtils";
import clsx from "clsx";
import { use, useEffect, useState } from "react";
import { use, useEffect, useMemo, useState } from "react";
import TextComponent from "./TextComponent";
import PartDivider from "./PartDivider";
import Timer from "@/components/Medium/Timer";
@@ -56,6 +56,7 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
const [showQuestionsModal, setShowQuestionsModal] = useState(false);
const [continueAnyways, setContinueAnyways] = useState(false);
const [textRender, setTextRender] = useState(false);
const [changedPrompt, setChangedPrompt] = useState(false);
const [seenParts, setSeenParts] = useState<number[]>(showSolutions ? exam.parts.map((_, index) => index) : [0]);
@@ -66,8 +67,6 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
onClose: function (x: boolean | undefined) { if (x) { setShowQuestionsModal(false); nextExercise(); } else { setShowQuestionsModal(false) } }
});
const [currentExercise, setCurrentExercise] = useState<Exercise>(exam.parts[0].exercises[0]);
const [showPartDivider, setShowPartDivider] = useState<boolean>(typeof exam.parts[0].intro === "string" && !showSolutions);
@@ -120,37 +119,6 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
}, [partIndex, exerciseIndex, questionIndex]);
useEffect(() => {
const regex = /.*?['"](.*?)['"] in line (\d+)\?$/;
if (
exerciseIndex !== -1 && currentExercise &&
currentExercise.type === "multipleChoice" &&
currentExercise.questions[questionIndex] &&
currentExercise.questions[questionIndex].prompt &&
exam.parts[partIndex].context
) {
const match = currentExercise.questions[questionIndex].prompt.match(regex);
if (match) {
const word = match[1];
const originalLineNumber = match[2];
if (word !== contextWord) {
setContextWord(word);
}
const updatedPrompt = currentExercise.questions[questionIndex].prompt.replace(
`in line ${originalLineNumber}`,
`in line ${contextWordLine || originalLineNumber}`
);
currentExercise.questions[questionIndex].prompt = updatedPrompt;
} else {
setContextWord(undefined);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentExercise, questionIndex]);
const nextExercise = (solution?: UserSolution) => {
scrollToTop();
@@ -341,6 +309,38 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
});
}
useEffect(() => {
const regex = /.*?['"](.*?)['"] in line (\d+)\?$/;
if (
exerciseIndex !== -1 && currentExercise &&
currentExercise.type === "multipleChoice" &&
currentExercise.questions[questionIndex] &&
currentExercise.questions[questionIndex].prompt &&
exam.parts[partIndex].context
) {
const match = currentExercise.questions[questionIndex].prompt.match(regex);
if (match) {
const word = match[1];
const originalLineNumber = match[2];
if (word !== contextWord) {
setContextWord(word);
}
const updatedPrompt = currentExercise.questions[questionIndex].prompt.replace(
`in line ${originalLineNumber}`,
`in line ${contextWordLine || originalLineNumber}`
);
currentExercise.questions[questionIndex].prompt = updatedPrompt;
setChangedPrompt(true);
} else {
setContextWord(undefined);
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentExercise, questionIndex, contextWordLine]);
useEffect(() => {
if (continueAnyways) {
setContinueAnyways(false);
@@ -375,6 +375,24 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
}
const memoizedRender = useMemo(() => {
setChangedPrompt(false);
return (
<>
{textRender ?
renderText() :
<>
{exam.parts[partIndex].context && renderText()}
{(showSolutions || editing) ?
renderSolution(currentExercise, nextExercise, previousExercise)
:
renderExercise(currentExercise, exam.id, nextExercise, previousExercise)
}
</>
}
</>)
}, [textRender, currentExercise, changedPrompt]);
return (
<>
<div className={clsx("flex flex-col h-full w-full gap-8 items-center", showPartDivider && "justify-center")}>
@@ -429,18 +447,7 @@ export default function Level({ exam, showSolutions = false, onFinish, editing =
"mb-20 w-full",
!!exam.parts[partIndex].context && !textRender && "grid grid-cols-2 gap-4",
)}>
{textRender ?
renderText() :
<>
{exam.parts[partIndex].context && renderText()}
{(showSolutions || editing) ?
renderSolution(currentExercise, nextExercise, previousExercise)
:
renderExercise(currentExercise, exam.id, nextExercise, previousExercise)
}
</>
}
{memoizedRender}
</div>
{/*exerciseIndex === -1 && partIndex > 0 && (
<div className="self-end flex justify-between w-full gap-8 absolute bottom-8 left-0 px-8">