136 lines
5.1 KiB
TypeScript
136 lines
5.1 KiB
TypeScript
import {infoButtonStyle} from "@/constants/buttonStyles";
|
|
import {Module} from "@/interfaces";
|
|
import {User} from "@/interfaces/user";
|
|
import useExamStore from "@/stores/examStore";
|
|
import {getExam, getExamById} from "@/utils/exams";
|
|
import {MODULE_ARRAY} from "@/utils/moduleUtils";
|
|
import {writingMarking} from "@/utils/score";
|
|
import {Menu} from "@headlessui/react";
|
|
import axios from "axios";
|
|
import clsx from "clsx";
|
|
import {capitalize} from "lodash";
|
|
import {useRouter} from "next/router";
|
|
import {useEffect, useState} from "react";
|
|
import {BsBook, BsChevronDown, BsHeadphones, BsMegaphone, BsPen, BsQuestionSquare} from "react-icons/bs";
|
|
import {toast} from "react-toastify";
|
|
import Button from "./Low/Button";
|
|
import ModuleLevelSelector from "./Medium/ModuleLevelSelector";
|
|
|
|
interface Props {
|
|
user: User;
|
|
onFinish: () => void;
|
|
}
|
|
|
|
export default function Diagnostic({onFinish}: Props) {
|
|
const [focus, setFocus] = useState<"academic" | "general">();
|
|
const [levels, setLevels] = useState({reading: -1, listening: -1, writing: -1, speaking: -1, level: 0});
|
|
const [desiredLevels, setDesiredLevels] = useState({reading: 9, listening: 9, writing: 9, speaking: 9, level: 9});
|
|
|
|
const router = useRouter();
|
|
|
|
const setExams = useExamStore((state) => state.setExams);
|
|
const setSelectedModules = useExamStore((state) => state.setSelectedModules);
|
|
|
|
const isNextDisabled = () => {
|
|
if (!focus) return true;
|
|
return Object.values(levels).includes(-1);
|
|
};
|
|
|
|
const selectExam = () => {
|
|
const examPromises = MODULE_ARRAY.map((module) => getExam(module, true, "partial"));
|
|
|
|
Promise.all(examPromises).then((exams) => {
|
|
if (exams.every((x) => !!x)) {
|
|
setExams(exams.map((x) => x!));
|
|
setSelectedModules(exams.map((x) => x!.module));
|
|
router.push("/exam");
|
|
}
|
|
});
|
|
};
|
|
|
|
const updateUser = (callback: () => void) => {
|
|
axios
|
|
.patch("/api/users/update", {
|
|
focus,
|
|
levels: Object.values(levels).includes(-1) ? {reading: 0, listening: 0, writing: 0, speaking: 0, level: 0} : levels,
|
|
desiredLevels,
|
|
isFirstLogin: false,
|
|
})
|
|
.then(callback)
|
|
.catch(() => {
|
|
toast.error("Something went wrong, please try again later!", {toastId: "user-update-error"});
|
|
});
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col items-center justify-center gap-12 w-full">
|
|
<div className="flex flex-col items-center justify-center gap-8 w-full">
|
|
<h2 className="font-semibold text-xl">What is your current focus?</h2>
|
|
<div className="flex flex-col gap-16 w-full">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-y-4 gap-x-16">
|
|
<button
|
|
onClick={() => setFocus("academic")}
|
|
className={clsx(
|
|
"w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white",
|
|
"hover:bg-mti-purple-light hover:text-white",
|
|
focus === "academic" && "!bg-mti-purple-light !text-white",
|
|
"transition duration-300 ease-in-out",
|
|
)}>
|
|
Academic
|
|
</button>
|
|
<button
|
|
onClick={() => setFocus("general")}
|
|
className={clsx(
|
|
"w-full border border-mti-gray-platinum rounded-full px-6 py-4 flex justify-center items-center gap-12 bg-white",
|
|
"hover:bg-mti-purple-light hover:text-white",
|
|
focus === "general" && "!bg-mti-purple-light !text-white",
|
|
"transition duration-300 ease-in-out",
|
|
)}>
|
|
General
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex flex-col items-center justify-center gap-8 w-full">
|
|
<h2 className="font-semibold text-xl">What is your current IELTS level?</h2>
|
|
<ModuleLevelSelector levels={levels} setLevels={setLevels} />
|
|
</div>
|
|
|
|
<div className="flex flex-col items-center justify-center gap-8 w-full mb-44">
|
|
<h2 className="font-semibold text-xl">What is your desired IELTS level?</h2>
|
|
<ModuleLevelSelector levels={desiredLevels} setLevels={setDesiredLevels} />
|
|
</div>
|
|
|
|
<div className="md:self-end flex -md:flex-col justify-between w-full gap-8 absolute bottom-8 left-0 px-4 md:px-8">
|
|
<div className="w-full tooltip" data-tip="Your screen size is too small to perform a diagnostic test">
|
|
<Button
|
|
color="purple"
|
|
variant="outline"
|
|
className="group flex items-center justify-center gap-6 relative md:max-w-[400px] w-full md:hidden"
|
|
disabled>
|
|
<BsQuestionSquare className="text-mti-purple-light transition duration-300 ease-in-out" size={20} />
|
|
<span>Perform diagnostic test instead</span>
|
|
</Button>
|
|
</div>
|
|
<Button
|
|
onClick={() => updateUser(selectExam)}
|
|
color="purple"
|
|
variant="outline"
|
|
className="group flex items-center justify-center gap-6 relative md:max-w-[400px] w-full -md:hidden"
|
|
disabled={!focus}>
|
|
<BsQuestionSquare
|
|
className="text-mti-purple-light group-hover:text-white transition duration-300 ease-in-out"
|
|
size={20}
|
|
onClick={() => updateUser(selectExam)}
|
|
/>
|
|
<span onClick={() => updateUser(selectExam)}>Perform diagnostic test instead</span>
|
|
</Button>
|
|
<Button color="purple" className="md:max-w-[400px] w-full" onClick={() => updateUser(onFinish)} disabled={isNextDisabled()}>
|
|
Next Step
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|