From efb153a33d27d3f8362a542fbe193c5cca3f01b1 Mon Sep 17 00:00:00 2001 From: Carlos-Mesquita Date: Tue, 26 Nov 2024 15:46:20 +0000 Subject: [PATCH] More navigation bugs and fixed broken modal during transition --- src/components/QuestionsModal.tsx | 75 ++++++++++++++++++---- src/exams/Finish.tsx | 8 +-- src/exams/Level/index.tsx | 12 ++-- src/exams/Navigation/useExamNavigation.tsx | 9 ++- src/stores/exam/reducers/index.ts | 2 +- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/src/components/QuestionsModal.tsx b/src/components/QuestionsModal.tsx index 04daac67..108739a8 100644 --- a/src/components/QuestionsModal.tsx +++ b/src/components/QuestionsModal.tsx @@ -1,5 +1,5 @@ import { Dialog, Transition } from "@headlessui/react"; -import { Fragment, useEffect, useState } from "react"; +import { Fragment, useCallback, useEffect, useState } from "react"; import Button from "./Low/Button"; interface Props { @@ -11,21 +11,55 @@ interface Props { export default function QuestionsModal({ isOpen, onClose, type = "module", unanswered = false }: Props) { const [isClosing, setIsClosing] = useState(false); + const [mounted, setMounted] = useState(false); - const blockMultipleClicksClose = (x: boolean) => { - if (!isClosing) { - setIsClosing(true); - onClose(x); + useEffect(() => { + if (isOpen) { + setMounted(true); } + }, [isOpen]); - setTimeout(() => { + useEffect(() => { + if (!isOpen && mounted) { + const timer = setTimeout(() => { + setMounted(false); + setIsClosing(false); + }, 300); + return () => clearTimeout(timer); + } + }, [isOpen, mounted]); + + const blockMultipleClicksClose = useCallback((value: boolean) => { + if (isClosing) return; + + setIsClosing(true); + onClose(value); + + const timer = setTimeout(() => { setIsClosing(false); - }, 400); - } + }, 300); + + return () => clearTimeout(timer); + }, [isClosing, onClose]); + + if (!mounted && !isOpen) return null; return ( - - onClose(false)} className="relative z-50"> + setIsClosing(false)} + beforeLeave={() => setIsClosing(true)} + afterLeave={() => { + setIsClosing(false); + setMounted(false); + }} + > + blockMultipleClicksClose(false)} + className="relative z-50" + static + > + leaveTo="opacity-0" + >
@@ -44,7 +79,8 @@ export default function QuestionsModal({ isOpen, onClose, type = "module", unans enterTo="opacity-100 scale-100" leave="ease-in duration-200" leaveFrom="opacity-100 scale-100" - leaveTo="opacity-0 scale-95"> + leaveTo="opacity-0 scale-95" + >
{type === "module" && ( @@ -57,10 +93,21 @@ export default function QuestionsModal({ isOpen, onClose, type = "module", unans Are you sure you want to continue without completing those questions?
- -
diff --git a/src/exams/Finish.tsx b/src/exams/Finish.tsx index ff67ee33..fddfe4e8 100644 --- a/src/exams/Finish.tsx +++ b/src/exams/Finish.tsx @@ -61,8 +61,8 @@ export default function Finish({ user, practiceScores, scores, modules, informat const aiUsage = Math.round(ai_usage(solutions) * 100); - //const entity = useMemo(() => assignment?.entity || user.entities[0]?.id || "", [assignment?.entity, user.entities]) - //const { gradingSystem } = useGradingSystem(entity); + const entity = useMemo(() => assignment?.entity || user.entities[0]?.id || "", [assignment?.entity, user.entities]) + const { gradingSystem } = useGradingSystem(entity); const router = useRouter() @@ -104,7 +104,7 @@ export default function Finish({ user, practiceScores, scores, modules, informat const showLevel = (level: number) => { if (selectedModule === "level") { - const label = getGradingLabel(level, []); + const label = getGradingLabel(level, gradingSystem?.steps || []); return (
{label} @@ -180,7 +180,7 @@ export default function Finish({ user, practiceScores, scores, modules, informat Writing
- {aiUsage >= 50 && user.type !== "student" && ( + {aiUsage >= 50 && selectedModule === "writing" && user.type !== "student" && (
> = ({ exam, showSolutions = false, pr const [showQuestionsModal, setShowQuestionsModal] = useState(false); const [continueAnyways, setContinueAnyways] = useState(false); const [textRender, setTextRender] = useState(false); - const [changedPrompt, setChangedPrompt] = useState(false); const [questionModalKwargs, setQuestionModalKwargs] = useState<{ @@ -98,9 +97,9 @@ const Level: React.FC> = ({ exam, showSolutions = false, pr { exam, module: "level", showBlankModal: showQuestionsModal, setShowBlankModal: setShowQuestionsModal, showSolutions, - preview, disableBetweenParts: true, modalKwargs - }); - + preview, disableBetweenParts: true, modalBetweenParts: true ,modalKwargs + } + ); const registerSolution = useCallback((updateSolution: () => UserSolution) => { userSolutionRef.current = updateSolution; @@ -299,7 +298,6 @@ const Level: React.FC> = ({ exam, showSolutions = false, pr currentExercise!.questions[questionIndex + i].prompt = updatedPrompt; } }) - setChangedPrompt(true); } } // eslint-disable-next-line react-hooks/exhaustive-deps @@ -366,14 +364,14 @@ const Level: React.FC> = ({ exam, showSolutions = false, pr onNext={() => { setShowPartDivider(false); setIsFirstTimeRender(false); setBgColor("bg-white"); setSeenParts(prev => new Set(prev).add(partIndex)); }} /> : ( <> - 1 && + />} { - if(startNow && partIndex !== 0) { + if(startNow && !showPartDivider && partIndex !== 0) { setStartNow(false); } - } , [partIndex, startNow]) + } , [partIndex, startNow, showPartDivider]) useEffect(() => { if (!showSolutions && hasDivider(exam, isPartExam ? partIndex : exerciseIndex) && !seenParts.has(partIndex)) { @@ -161,8 +161,7 @@ const useExamNavigation: UseExamNavigation = ({ return; } - console.log(modalBetweenParts); - if (modalBetweenParts && !answeredEveryQuestion(exam as PartExam, userSolutions) && !keepGoing && setShowBlankModal && !showSolutions && !preview) { + if (modalBetweenParts && !seenParts.has(partIndex + 1) && !answeredEveryQuestion(exam as PartExam, userSolutions) && !keepGoing && setShowBlankModal && !showSolutions && !preview) { if (modalKwargs) modalKwargs(); setShowBlankModal(true); return; @@ -197,7 +196,7 @@ const useExamNavigation: UseExamNavigation = ({ const previousPartExam = () => { - if (partIndex === 0 && exerciseIndex === 0 && !startNow) { + if (!showPartDivider && partIndex === 0 && exerciseIndex === 0 && questionIndex === 0 && !startNow) { setStartNow(true); return; } diff --git a/src/stores/exam/reducers/index.ts b/src/stores/exam/reducers/index.ts index 656d9c57..d56212df 100644 --- a/src/stores/exam/reducers/index.ts +++ b/src/stores/exam/reducers/index.ts @@ -146,7 +146,7 @@ export const rootReducer = ( questionIndex: 0, exerciseIndex: 0, partIndex: 0, - exam: state.exams[moduleIndex + 1], + exam: state.exams[moduleIndex], moduleIndex: moduleIndex } } else {