- Solved the bug on Diagnostic where the exams weren't loading;

- Removed the Layout appearance and made it so the abandon popup appears on click and not on enter
This commit is contained in:
Tiago Ribeiro
2023-08-22 23:13:26 +01:00
parent 78c5b7027e
commit 14a719b8b5
7 changed files with 80 additions and 98 deletions

View File

@@ -3,60 +3,53 @@ import {Fragment} from "react";
import Button from "./Low/Button"; import Button from "./Low/Button";
interface Props { interface Props {
isOpen: boolean; isOpen: boolean;
abandonPopupTitle: string; abandonPopupTitle: string;
abandonPopupDescription: string; abandonPopupDescription: string;
abandonConfirmButtonText: string; abandonConfirmButtonText: string;
onAbandon: Function; onAbandon: () => void;
onCancel: Function; onCancel: () => void;
} }
export default function AbandonPopup({ export default function AbandonPopup({isOpen, abandonPopupTitle, abandonPopupDescription, abandonConfirmButtonText, onAbandon, onCancel}: Props) {
isOpen, return (
abandonPopupTitle, <Transition show={isOpen} as={Fragment}>
abandonPopupDescription, <Dialog onClose={onCancel} className="relative z-50">
abandonConfirmButtonText, <Transition.Child
onAbandon, as={Fragment}
onCancel, enter="ease-out duration-300"
}: Props) { enterFrom="opacity-0"
return ( enterTo="opacity-100"
<Transition show={isOpen} as={Fragment}> leave="ease-in duration-200"
<Dialog onClose={onCancel} className="relative z-50"> leaveFrom="opacity-100"
<Transition.Child leaveTo="opacity-0">
as={Fragment} <div className="fixed inset-0 bg-black/30" />
enter="ease-out duration-300" </Transition.Child>
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 <Transition.Child
as={Fragment} as={Fragment}
enter="ease-out duration-300" enter="ease-out duration-300"
enterFrom="opacity-0 scale-95" enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100" enterTo="opacity-100 scale-100"
leave="ease-in duration-200" leave="ease-in duration-200"
leaveFrom="opacity-100 scale-100" leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"> leaveTo="opacity-0 scale-95">
<div className="fixed inset-0 flex items-center justify-center p-4"> <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.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">{abandonPopupTitle}</Dialog.Title> <Dialog.Title className="font-bold text-xl">{abandonPopupTitle}</Dialog.Title>
<span>{abandonPopupDescription}</span> <span>{abandonPopupDescription}</span>
<div className="w-full flex justify-between mt-8"> <div className="w-full flex justify-between mt-8">
<Button color="purple" onClick={onCancel} variant="outline" className="max-w-[200px] self-end w-full"> <Button color="purple" onClick={onCancel} variant="outline" className="max-w-[200px] self-end w-full">
Cancel Cancel
</Button> </Button>
<Button color="purple" onClick={onAbandon} className="max-w-[200px] self-end w-full"> <Button color="purple" onClick={onAbandon} className="max-w-[200px] self-end w-full">
{abandonConfirmButtonText} {abandonConfirmButtonText}
</Button> </Button>
</div> </div>
</Dialog.Panel> </Dialog.Panel>
</div> </div>
</Transition.Child> </Transition.Child>
</Dialog> </Dialog>
</Transition> </Transition>
); );
} }

View File

@@ -10,7 +10,7 @@ import axios from "axios";
import clsx from "clsx"; import clsx from "clsx";
import {capitalize} from "lodash"; import {capitalize} from "lodash";
import {useRouter} from "next/router"; import {useRouter} from "next/router";
import {useState} from "react"; import {useEffect, useState} from "react";
import {BsBook, BsChevronDown, BsHeadphones, BsMegaphone, BsPen, BsQuestionSquare} from "react-icons/bs"; import {BsBook, BsChevronDown, BsHeadphones, BsMegaphone, BsPen, BsQuestionSquare} from "react-icons/bs";
import {toast} from "react-toastify"; import {toast} from "react-toastify";
import Button from "./Low/Button"; import Button from "./Low/Button";
@@ -23,7 +23,7 @@ interface Props {
const DIAGNOSTIC_EXAMS = [ const DIAGNOSTIC_EXAMS = [
["reading", "CurQtQoxWmHaJHeN0JW2"], ["reading", "CurQtQoxWmHaJHeN0JW2"],
["listening", "Y6cMao8kUcVnPQOo6teV"], ["listening", "Y6cMao8kUcVnPQOo6teV"],
["writing", "hbueuDaEZXV37EW7I12A"], ["writing", "B1J90R4Lmdn2dwjdHEwj"],
["speaking", "QVFm4pdcziJQZN2iUTDo"], ["speaking", "QVFm4pdcziJQZN2iUTDo"],
]; ];
@@ -49,7 +49,7 @@ export default function Diagnostic({onFinish}: Props) {
if (exams.every((x) => !!x)) { if (exams.every((x) => !!x)) {
setExams(exams.map((x) => x!)); setExams(exams.map((x) => x!));
setSelectedModules(exams.map((x) => x!.module)); setSelectedModules(exams.map((x) => x!.module));
router.push("/exam"); router.push("/exercises");
} }
}); });
}; };
@@ -58,7 +58,7 @@ export default function Diagnostic({onFinish}: Props) {
axios axios
.patch("/api/users/update", { .patch("/api/users/update", {
focus, focus,
levels: Object.values(levels).includes(-1) ? {reading: -1, listening: -1, writing: -1, speaking: -1} : levels, levels: Object.values(levels).includes(-1) ? {reading: 0, listening: 0, writing: 0, speaking: 0} : levels,
desiredLevels, desiredLevels,
isFirstLogin: false, isFirstLogin: false,
}) })

View File

@@ -1,13 +1,9 @@
import {useEffect, useState} from "react"; import {useEffect, useState} from "react";
interface Props { interface Props {
onFocusLayerMouseEnter: Function, onFocusLayerMouseEnter?: () => void;
} }
export default function FocusLayer({ export default function FocusLayer({onFocusLayerMouseEnter}: Props) {
onFocusLayerMouseEnter, return <div className="absolute top-0 left-0 bottom-0 right-0" onMouseDown={onFocusLayerMouseEnter} />;
}: Props) {
return (
<div className="bg-gray-700 bg-opacity-30 absolute top-0 left-0 bottom-0 right-0" onMouseEnter={onFocusLayerMouseEnter}/>
);
} }

View File

@@ -9,18 +9,18 @@ interface Props {
children: React.ReactNode; children: React.ReactNode;
className?: string; className?: string;
navDisabled?: boolean; navDisabled?: boolean;
focusMode?: boolean focusMode?: boolean;
onFocusLayerMouseEnter?: Function; onFocusLayerMouseEnter?: () => void;
} }
export default function Layout({user, children, className, navDisabled = false, focusMode = false, onFocusLayerMouseEnter }: Props) { export default function Layout({user, children, className, navDisabled = false, focusMode = false, onFocusLayerMouseEnter}: Props) {
const router = useRouter(); const router = useRouter();
return ( return (
<main className="w-full min-h-full h-screen flex flex-col bg-mti-gray-smoke"> <main className="w-full min-h-full h-screen flex flex-col bg-mti-gray-smoke">
<Navbar user={user} navDisabled={navDisabled} focusMode={focusMode} onFocusLayerMouseEnter={onFocusLayerMouseEnter} /> <Navbar user={user} navDisabled={navDisabled} focusMode={focusMode} onFocusLayerMouseEnter={onFocusLayerMouseEnter} />
<div className="h-full w-full flex gap-2"> <div className="h-full w-full flex gap-2">
<Sidebar path={router.pathname} navDisabled={navDisabled} focusMode={focusMode} onFocusLayerMouseEnter={onFocusLayerMouseEnter}/> <Sidebar path={router.pathname} navDisabled={navDisabled} focusMode={focusMode} onFocusLayerMouseEnter={onFocusLayerMouseEnter} />
<div <div
className={clsx( className={clsx(
"w-5/6 min-h-full h-fit mr-8 bg-white shadow-md rounded-2xl p-12 pb-8 flex flex-col gap-12 relative overflow-hidden mt-2", "w-5/6 min-h-full h-fit mr-8 bg-white shadow-md rounded-2xl p-12 pb-8 flex flex-col gap-12 relative overflow-hidden mt-2",

View File

@@ -1,15 +1,14 @@
import {User} from "@/interfaces/user"; import {User} from "@/interfaces/user";
import Link from "next/link"; import Link from "next/link";
import {Avatar} from "primereact/avatar"; import {Avatar} from "primereact/avatar";
import FocusLayer from '@/components/FocusLayer'; import FocusLayer from "@/components/FocusLayer";
import { preventNavigation } from "@/utils/navigation.disabled"; import {preventNavigation} from "@/utils/navigation.disabled";
interface Props { interface Props {
user: User; user: User;
navDisabled?: boolean; navDisabled?: boolean;
focusMode?: boolean; focusMode?: boolean;
onFocusLayerMouseEnter?: Function; onFocusLayerMouseEnter?: () => void;
} }
/* eslint-disable @next/next/no-img-element */ /* eslint-disable @next/next/no-img-element */
@@ -26,7 +25,7 @@ export default function Navbar({user, navDisabled = false, focusMode = false, on
<span className="text-right">{user.name}</span> <span className="text-right">{user.name}</span>
</Link> </Link>
</div> </div>
{focusMode && <FocusLayer onFocusLayerMouseEnter={onFocusLayerMouseEnter}/>} {focusMode && <FocusLayer onFocusLayerMouseEnter={onFocusLayerMouseEnter} />}
</header> </header>
); );
} }

View File

@@ -321,25 +321,22 @@ export default function Page() {
user={user} user={user}
className="justify-between" className="justify-between"
focusMode={selectedModules.length !== 0} focusMode={selectedModules.length !== 0}
onFocusLayerMouseEnter={() => setShowAbandonPopup(true)} onFocusLayerMouseEnter={() => setShowAbandonPopup(true)}>
> <>
<>
{renderScreen()} {renderScreen()}
<AbandonPopup <AbandonPopup
isOpen={showAbandonPopup} isOpen={showAbandonPopup}
abandonPopupTitle="Leave Exam" abandonPopupTitle="Leave Exercise"
abandonPopupDescription="Are you sure you want to leave the exam? You will lose all your progress." abandonPopupDescription="Are you sure you want to leave the exercise? You will lose all your progress."
abandonConfirmButtonText="Confirm" abandonConfirmButtonText="Confirm"
onAbandon={() => { onAbandon={() => {
console.log('TODO: Handle Abandon');
setExam(undefined); setExam(undefined);
setSelectedModules([]); setSelectedModules([]);
setShowAbandonPopup(false) setShowAbandonPopup(false);
return true;
}} }}
onCancel={() => setShowAbandonPopup(false)} onCancel={() => setShowAbandonPopup(false)}
/> />
</> </>
</Layout> </Layout>
)} )}
</> </>

View File

@@ -323,25 +323,22 @@ export default function Page() {
user={user} user={user}
className="justify-between" className="justify-between"
focusMode={selectedModules.length !== 0} focusMode={selectedModules.length !== 0}
onFocusLayerMouseEnter={() => setShowAbandonPopup(true)} onFocusLayerMouseEnter={() => setShowAbandonPopup(true)}>
>
<> <>
{renderScreen()} {renderScreen()}
<AbandonPopup <AbandonPopup
isOpen={showAbandonPopup} isOpen={showAbandonPopup}
abandonPopupTitle="Leave Exercise"
abandonPopupTitle="Leave Exercise" abandonPopupDescription="Are you sure you want to leave the exercise? You will lose all your progress."
abandonPopupDescription="Are you sure you want to leave the exercise? You will lose all your progress." abandonConfirmButtonText="Confirm"
abandonConfirmButtonText="Confirm" onAbandon={() => {
onAbandon={() => { setExam(undefined);
setExam(undefined); setSelectedModules([]);
setSelectedModules([]); setShowAbandonPopup(false);
setShowAbandonPopup(false) }}
return true; onCancel={() => setShowAbandonPopup(false)}
}} />
onCancel={() => setShowAbandonPopup(false)} </>
/>
</>
</Layout> </Layout>
)} )}
</> </>