fix(ui): refactor results page for exam results logic

This commit is contained in:
shafin-r
2025-08-31 23:27:32 +06:00
parent 7df2708db7
commit 5507602031
9 changed files with 127 additions and 444 deletions

View File

@ -1,122 +1,82 @@
"use client";
import { useRouter } from "next/navigation";
import { useExam } from "@/context/ExamContext";
import { useEffect, useState } from "react";
import React from "react";
import { ArrowLeft } from "lucide-react";
import SlidingGallery from "@/components/SlidingGallery";
import { useExamStore } from "@/stores/examStore";
import QuestionItem from "@/components/QuestionItem";
import SlidingGallery from "@/components/SlidingGallery";
import { getResultViews } from "@/lib/gallery-views";
import { Question } from "@/types/exam";
export default function ResultsPage() {
const router = useRouter();
const {
clearExam,
isExamCompleted,
getApiResponse,
currentAttempt,
isHydrated,
} = useExam();
const { result, clearResult } = useExamStore();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
// Wait for hydration first
if (!isHydrated) return;
// Check if exam is completed, redirect if not
if (!isExamCompleted() || !currentAttempt) {
router.push("/unit");
return;
}
// If we have exam results, we're ready to render
if (currentAttempt?.answers) {
setIsLoading(false);
}
}, [isExamCompleted, currentAttempt, isHydrated, router]);
const handleBackToHome = () => {
clearExam();
router.push("/unit");
};
// Show loading screen while initializing or if no exam results
if (isLoading || !currentAttempt) {
if (!result) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<div className="mt-60 flex flex-col items-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mb-4"></div>
<p className="text-xl font-medium text-center">Loading...</p>
</div>
</div>
<div className="min-h-screen flex items-center justify-center">
<p className="text-lg font-medium">No results to display.</p>
</div>
);
}
const apiResponse = getApiResponse();
// const timeTaken =
// currentAttempt.endTime && currentAttempt.startTime
// ? Math.round(
// (currentAttempt.endTime.getTime() -
// currentAttempt.startTime.getTime()) /
// 1000 /
// 60
// )
// : 0;
const views = getResultViews(currentAttempt);
// Get score-based message
const getScoreMessage = () => {
if (!currentAttempt.score || currentAttempt.score < 30)
return "Try harder!";
if (currentAttempt.score < 70) return "Getting Better";
return "You did great!";
const handleBackToHome = () => {
clearResult();
router.push("/categories");
};
const views = getResultViews(result);
return (
<div className="min-h-screen bg-white">
<button className="p-10" onClick={handleBackToHome}>
<button className="px-10 pt-10" onClick={handleBackToHome}>
<ArrowLeft size={30} color="black" />
</button>
<div className="bg-white rounded-lg shadow-lg px-10 pb-20">
<h1 className="text-2xl font-bold text-[#113768] mb-4 text-center">
{getScoreMessage()}
<h1 className="text-2xl font-bold text-[#113768] text-center">
You did great!
</h1>
{/* Score Display */}
<SlidingGallery className="my-8" views={views} height="170px" />
<SlidingGallery views={views} height={"26vh"} />
{apiResponse?.questions && (
<div className="mb-8">
<h3 className="text-2xl font-bold text-[#113768] mb-4">
Solutions
</h3>
<div className="flex flex-col gap-7">
{apiResponse.questions.map((question: Question) => (
<QuestionItem
key={question.id}
question={question}
selectedAnswer={
currentAttempt.answers[parseInt(question.id) - 1]
}
mode="result"
/>
))}
{/* Render questions with correctness */}
{result.user_questions.map((q, idx) => {
const userAnswer = result.user_answers[idx];
const correctAnswer = result.correct_answers[idx];
return (
<div key={q.question_id} className={`rounded-3xl mb-6`}>
<QuestionItem
question={q}
index={idx}
selectedAnswer={userAnswer}
onSelect={() => {}} // disabled in results
/>
{/* Answer feedback */}
<div className="mt-2 text-sm">
{userAnswer === null ? (
<span className="text-yellow-600 font-medium">
Skipped Correct: {String.fromCharCode(65 + correctAnswer)}
</span>
) : userAnswer === correctAnswer ? (
<span className="text-green-600 font-medium">Correct</span>
) : (
<span className="text-red-600 font-medium">
Your Answer: {String.fromCharCode(65 + userAnswer)} |
Correct Answer: {String.fromCharCode(65 + correctAnswer)}
</span>
)}
</div>
</div>
</div>
)}
);
})}
</div>
<button
onClick={handleBackToHome}
className="fixed bottom-0 w-full bg-blue-900 text-white h-[74px] font-bold text-lg disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
className="fixed bottom-0 w-full bg-blue-900 text-white h-[74px] font-bold text-lg hover:bg-blue-800 transition-colors"
>
Finish
</button>