Added a confirmation dialog for when the user leaves questions unanswered

This commit is contained in:
Tiago Ribeiro
2023-06-29 15:28:50 +01:00
parent 3fac92b54d
commit 3c4dba69db
3 changed files with 90 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
import {Dialog, Transition} from "@headlessui/react";
import {Fragment} from "react";
import Button from "./Low/Button";
interface Props {
isOpen: boolean;
onClose: (next?: boolean) => void;
}
export default function BlankQuestionsModal({isOpen, onClose}: Props) {
return (
<Transition show={isOpen} as={Fragment}>
<Dialog onClose={() => onClose(false)} className="relative z-50">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0">
<div className="fixed inset-0 bg-black/30" />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95">
<div className="fixed inset-0 flex items-center justify-center p-4">
<Dialog.Panel className="w-full max-w-2xl h-fit p-8 rounded-xl bg-white flex flex-col gap-4">
<Dialog.Title className="font-bold text-xl">Questions Unanswered</Dialog.Title>
<span>
Please note that you are finishing the current module and once you proceed to the next module, you will no longer be
able to change the answers in the current one, including your unanswered questions. <br />
<br />
Are you sure you want to continue without completing those questions?
</span>
<div className="w-full flex justify-between mt-8">
<Button color="green" onClick={() => onClose(false)} variant="outline" className="max-w-[200px] self-end w-full">
Go Back
</Button>
<Button color="green" onClick={() => onClose(true)} className="max-w-[200px] self-end w-full">
Continue
</Button>
</div>
</Dialog.Panel>
</div>
</Transition.Child>
</Dialog>
</Transition>
);
}

View File

@@ -9,6 +9,7 @@ import {renderSolution} from "@/components/Solutions";
import ModuleTitle from "@/components/Medium/ModuleTitle"; import ModuleTitle from "@/components/Medium/ModuleTitle";
import AudioPlayer from "@/components/Low/AudioPlayer"; import AudioPlayer from "@/components/Low/AudioPlayer";
import Button from "@/components/Low/Button"; import Button from "@/components/Low/Button";
import BlankQuestionsModal from "@/components/BlankQuestionsModal";
interface Props { interface Props {
exam: ListeningExam; exam: ListeningExam;
@@ -20,6 +21,16 @@ export default function Listening({exam, showSolutions = false, onFinish}: Props
const [exerciseIndex, setExerciseIndex] = useState(-1); const [exerciseIndex, setExerciseIndex] = useState(-1);
const [timesListened, setTimesListened] = useState(0); const [timesListened, setTimesListened] = useState(0);
const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]); const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]);
const [showBlankModal, setShowBlankModal] = useState(false);
const confirmFinishModule = (keepGoing?: boolean) => {
if (!keepGoing) {
setShowBlankModal(false);
return;
}
onFinish(userSolutions.map((x) => ({...x, module: "reading", exam: exam.id})));
};
const nextExercise = (solution?: UserSolution) => { const nextExercise = (solution?: UserSolution) => {
if (solution) { if (solution) {
@@ -31,6 +42,11 @@ export default function Listening({exam, showSolutions = false, onFinish}: Props
return; return;
} }
if (!userSolutions.map((x) => x.score.missing).every((x) => x === 0)) {
setShowBlankModal(true);
return;
}
if (solution) { if (solution) {
onFinish( onFinish(
[...userSolutions.filter((x) => x.exercise !== solution.exercise), solution].map((x) => ({...x, module: "listening", exam: exam.id})), [...userSolutions.filter((x) => x.exercise !== solution.exercise), solution].map((x) => ({...x, module: "listening", exam: exam.id})),
@@ -79,6 +95,7 @@ export default function Listening({exam, showSolutions = false, onFinish}: Props
return ( return (
<> <>
<BlankQuestionsModal isOpen={showBlankModal} onClose={confirmFinishModule} />
<div className="flex flex-col h-full w-full gap-8 justify-between"> <div className="flex flex-col h-full w-full gap-8 justify-between">
<ModuleTitle <ModuleTitle
exerciseIndex={exerciseIndex + 1} exerciseIndex={exerciseIndex + 1}

View File

@@ -15,6 +15,7 @@ import ProgressBar from "@/components/Low/ProgressBar";
import ModuleTitle from "@/components/Medium/ModuleTitle"; import ModuleTitle from "@/components/Medium/ModuleTitle";
import {Divider} from "primereact/divider"; import {Divider} from "primereact/divider";
import Button from "@/components/Low/Button"; import Button from "@/components/Low/Button";
import BlankQuestionsModal from "@/components/BlankQuestionsModal";
interface Props { interface Props {
exam: ReadingExam; exam: ReadingExam;
@@ -83,6 +84,16 @@ export default function Reading({exam, showSolutions = false, onFinish}: Props)
const [exerciseIndex, setExerciseIndex] = useState(-1); const [exerciseIndex, setExerciseIndex] = useState(-1);
const [showTextModal, setShowTextModal] = useState(false); const [showTextModal, setShowTextModal] = useState(false);
const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]); const [userSolutions, setUserSolutions] = useState<UserSolution[]>([]);
const [showBlankModal, setShowBlankModal] = useState(false);
const confirmFinishModule = (keepGoing?: boolean) => {
if (!keepGoing) {
setShowBlankModal(false);
return;
}
onFinish(userSolutions.map((x) => ({...x, module: "reading", exam: exam.id})));
};
const nextExercise = (solution?: UserSolution) => { const nextExercise = (solution?: UserSolution) => {
if (solution) { if (solution) {
@@ -94,6 +105,11 @@ export default function Reading({exam, showSolutions = false, onFinish}: Props)
return; return;
} }
if (!userSolutions.map((x) => x.score.missing).every((x) => x === 0)) {
setShowBlankModal(true);
return;
}
if (solution) { if (solution) {
onFinish( onFinish(
[...userSolutions.filter((x) => x.exercise !== solution.exercise), solution].map((x) => ({...x, module: "reading", exam: exam.id})), [...userSolutions.filter((x) => x.exercise !== solution.exercise), solution].map((x) => ({...x, module: "reading", exam: exam.id})),
@@ -142,6 +158,7 @@ export default function Reading({exam, showSolutions = false, onFinish}: Props)
return ( return (
<> <>
<div className="flex flex-col h-full w-full gap-8"> <div className="flex flex-col h-full w-full gap-8">
<BlankQuestionsModal isOpen={showBlankModal} onClose={confirmFinishModule} />
<TextModal {...exam.text} isOpen={showTextModal} onClose={() => setShowTextModal(false)} /> <TextModal {...exam.text} isOpen={showTextModal} onClose={() => setShowTextModal(false)} />
<ModuleTitle <ModuleTitle
minTimer={exam.minTimer} minTimer={exam.minTimer}