generated from muhtadeetaron/nextjs-template
fix(nav): fix exam flow navigation
chore(zustand): refactor auth code for zustand store
This commit is contained in:
@ -10,7 +10,6 @@ import { useTimerStore } from "@/stores/timerStore";
|
||||
|
||||
export default function ExamPage() {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
const test_id = searchParams.get("test_id") || "";
|
||||
const type = searchParams.get("type") || "";
|
||||
@ -23,55 +22,46 @@ export default function ExamPage() {
|
||||
|
||||
// Start exam + timer automatically
|
||||
useEffect(() => {
|
||||
if (type && test_id) {
|
||||
startExam(type, test_id).then((fetchedTest) => {
|
||||
if (fetchedTest?.metadata.time_limit_minutes) {
|
||||
setStatus("in-progress"); // ✅ make sure exam status is set here
|
||||
resetTimer(fetchedTest.metadata.time_limit_minutes * 60, () => {
|
||||
// Timer ended → auto-submit
|
||||
setStatus("finished");
|
||||
stopTimer();
|
||||
submitExam(type);
|
||||
router.replace(`/exam/results`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!type || !test_id) return;
|
||||
|
||||
const initExam = async () => {
|
||||
const fetchedTest = await startExam(type, test_id);
|
||||
|
||||
if (!fetchedTest) return;
|
||||
|
||||
setStatus("in-progress");
|
||||
|
||||
const timeLimit = fetchedTest.metadata.time_limit_minutes;
|
||||
if (timeLimit) {
|
||||
resetTimer(timeLimit * 60, async () => {
|
||||
// Auto-submit when timer ends
|
||||
stopTimer();
|
||||
setStatus("finished");
|
||||
await submitExam(type);
|
||||
router.replace("/exam/results");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
initExam();
|
||||
}, [
|
||||
type,
|
||||
test_id,
|
||||
startExam,
|
||||
resetTimer,
|
||||
stopTimer,
|
||||
submitExam,
|
||||
router,
|
||||
setStatus,
|
||||
stopTimer,
|
||||
]);
|
||||
|
||||
// useEffect(() => {
|
||||
// const handlePopState = (event: PopStateEvent) => {
|
||||
// if (status === "in-progress") {
|
||||
// const confirmExit = window.confirm(
|
||||
// "Are you sure you want to quit the exam?"
|
||||
// );
|
||||
|
||||
// if (confirmExit) {
|
||||
// setStatus("finished");
|
||||
// stopTimer();
|
||||
// cancelExam();
|
||||
// router.replace(`/categories/${type}s`);
|
||||
// } else {
|
||||
// // User canceled → push them back to current page
|
||||
// router.replace(pathname, { scroll: false });
|
||||
// }
|
||||
// } else {
|
||||
// router.replace(`/categories/${type}s`);
|
||||
// }
|
||||
// };
|
||||
|
||||
// window.addEventListener("popstate", handlePopState);
|
||||
// return () => window.removeEventListener("popstate", handlePopState);
|
||||
// }, [status, router, pathname, type, setStatus, stopTimer, cancelExam]);
|
||||
if (isSubmitting) {
|
||||
return (
|
||||
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
|
||||
<p className="text-lg font-medium text-gray-900">Submitting exam...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!test) {
|
||||
return (
|
||||
@ -85,12 +75,18 @@ export default function ExamPage() {
|
||||
}
|
||||
|
||||
const handleSubmitExam = async (type: string) => {
|
||||
setIsSubmitting(true);
|
||||
stopTimer();
|
||||
|
||||
try {
|
||||
setStatus("finished"); // ✅ mark exam finished
|
||||
stopTimer();
|
||||
setIsSubmitting(true);
|
||||
await submitExam(type);
|
||||
router.replace(`/exam/results`); // ✅ replace to prevent back nav
|
||||
const result = await submitExam(type); // throws if fails
|
||||
|
||||
if (!result) throw new Error("Submission failed");
|
||||
|
||||
router.replace("/exam/results"); // navigate
|
||||
} catch (err) {
|
||||
console.error("Submit exam failed:", err);
|
||||
alert("Failed to submit exam. Please try again.");
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
@ -137,6 +133,3 @@ export default function ExamPage() {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function cancelExam() {
|
||||
throw new Error("Function not implemented.");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user