generated from muhtadeetaron/nextjs-template
fix(ui): fix results screen
This commit is contained in:
@ -7,6 +7,7 @@ import React, {
|
||||
useEffect,
|
||||
ReactNode,
|
||||
} from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import { Exam, ExamAnswer, ExamAttempt, ExamContextType } from "@/types/exam";
|
||||
import { getFromStorage, removeFromStorage, setToStorage } from "@/lib/utils";
|
||||
@ -21,6 +22,7 @@ const STORAGE_KEYS = {
|
||||
export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const router = useRouter();
|
||||
const [currentExam, setCurrentExamState] = useState<Exam | null>(null);
|
||||
const [currentAttempt, setCurrentAttemptState] = useState<ExamAttempt | null>(
|
||||
null
|
||||
@ -81,13 +83,14 @@ export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
const setCurrentExam = (exam: Exam) => {
|
||||
setCurrentExamState(exam);
|
||||
|
||||
setCurrentAttemptState(null);
|
||||
};
|
||||
|
||||
const startExam = () => {
|
||||
if (!currentExam) {
|
||||
throw new Error("No exam selected");
|
||||
console.warn("No exam selected, redirecting to /unit");
|
||||
router.push("/unit");
|
||||
return;
|
||||
}
|
||||
|
||||
const attempt: ExamAttempt = {
|
||||
@ -103,7 +106,9 @@ export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
const setAnswer = (questionId: string, answer: any) => {
|
||||
if (!currentAttempt) {
|
||||
throw new Error("No exam attempt started");
|
||||
console.warn("No exam attempt started, redirecting to /unit");
|
||||
router.push("/unit");
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentAttemptState((prev) => {
|
||||
@ -138,7 +143,9 @@ export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
|
||||
const setApiResponse = (response: any) => {
|
||||
if (!currentAttempt) {
|
||||
throw new Error("No exam attempt started");
|
||||
console.warn("No exam attempt started, redirecting to /unit");
|
||||
router.push("/unit");
|
||||
return;
|
||||
}
|
||||
|
||||
setCurrentAttemptState((prev) => {
|
||||
@ -150,9 +157,11 @@ export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
});
|
||||
};
|
||||
|
||||
const submitExam = (): ExamAttempt => {
|
||||
const submitExam = (): ExamAttempt | null => {
|
||||
if (!currentAttempt) {
|
||||
throw new Error("No exam attempt to submit");
|
||||
console.warn("No exam attempt to submit, redirecting to /unit");
|
||||
router.push("/unit");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Calculate score (simple example - you can customize this)
|
||||
@ -209,7 +218,7 @@ export const ExamProvider: React.FC<{ children: ReactNode }> = ({
|
||||
const isExamStarted = () => !!currentExam && !!currentAttempt;
|
||||
|
||||
const isExamCompleted = (): boolean => {
|
||||
if (!isHydrated) return false; // ⛔ wait for hydration
|
||||
if (!isHydrated) return false; // wait for hydration
|
||||
return currentAttempt !== null && currentAttempt.endTime !== undefined;
|
||||
};
|
||||
|
||||
@ -246,12 +255,18 @@ export const useExam = (): ExamContextType => {
|
||||
return context;
|
||||
};
|
||||
|
||||
// Hook for exam results (only when exam is completed)
|
||||
export const useExamResults = (): ExamAttempt => {
|
||||
const { currentAttempt, isExamCompleted } = useExam();
|
||||
// Hook for exam results (only when exam is completed) - now returns null instead of throwing
|
||||
export const useExamResults = (): ExamAttempt | null => {
|
||||
const { currentAttempt, isExamCompleted, isHydrated } = useExam();
|
||||
|
||||
// Wait for hydration before making decisions
|
||||
if (!isHydrated) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If no completed exam is found, return null (let component handle redirect)
|
||||
if (!isExamCompleted() || !currentAttempt) {
|
||||
throw new Error("No completed exam attempt found");
|
||||
return null;
|
||||
}
|
||||
|
||||
return currentAttempt;
|
||||
|
||||
Reference in New Issue
Block a user