Files
examjam-frontend/app/exam/results/page.tsx
2025-07-07 17:52:01 +06:00

142 lines
4.1 KiB
TypeScript

"use client";
import { useRouter } from "next/navigation";
import { useExam, useExamResults } from "@/context/ExamContext";
import { useEffect } from "react";
import React from "react";
interface Question {
solution: string;
id: number;
question: string;
options: Record<string, string>;
}
interface QuestionItemProps {
question: Question;
selectedAnswer: string | undefined;
}
const QuestionItem = React.memo<QuestionItemProps>(
({ question, selectedAnswer }) => (
<div className="border border-[#8abdff]/50 rounded-2xl p-4 flex flex-col gap-7">
<h3 className="text-xl font-medium">
{question.id}. {question.question}
</h3>
<div className="flex flex-col gap-4 items-start">
{Object.entries(question.options).map(([key, value]) => (
<button key={key} className="flex items-center gap-3">
<span
className={`flex items-center rounded-full border px-1.5 ${
selectedAnswer === key
? "text-white bg-[#113768] border-[#113768]"
: ""
}`}
>
{key.toUpperCase()}
</span>
<span className="option-description">{value}</span>
</button>
))}
</div>
<div className="flex flex-col gap-4">
<h3 className="text-xl font-bold text-black/40">Solution:</h3>
<p className="text-lg font-medium">{question.solution}</p>
</div>
</div>
)
);
export default function ResultsPage() {
const router = useRouter();
const { clearExam, isExamCompleted, getApiResponse } = useExam();
useEffect(() => {
// Redirect if no completed exam
if (!isExamCompleted()) {
router.push("/exam/select");
return;
}
}, [isExamCompleted, router]);
let examResults;
try {
examResults = useExamResults();
} catch (error) {
// Handle case where there's no completed exam
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<h1 className="text-2xl font-bold text-gray-900 mb-4">
No exam results found
</h1>
<button
onClick={() => router.push("/exam/select")}
className="bg-blue-900 text-white px-6 py-3 rounded-lg hover:bg-blue-800"
>
Take an Exam
</button>
</div>
</div>
);
}
// Get API response data
const apiResponse = getApiResponse();
const handleBackToHome = () => {
router.push("/unit");
clearExam();
};
const timeTaken =
examResults.endTime && examResults.startTime
? Math.round(
(examResults.endTime.getTime() - examResults.startTime.getTime()) /
1000 /
60
)
: 0;
return (
<div className="min-h-screen bg-white">
<div className="bg-white rounded-lg shadow-lg px-10 py-20">
<h1 className="text-2xl font-bold text-gray-900 mb-2 text-center">
Keep up the good work!
</h1>
{/* Score Display */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div className="bg-blue-50 rounded-lg p-6 text-center">
<div className="text-3xl font-bold text-blue-900 mb-2">
{examResults.score}%
</div>
<div className="text-sm text-gray-600">Final Score</div>
</div>
</div>
{apiResponse && (
<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) => (
<QuestionItem key={question.id} question={question} />
))}
</div>
</div>
)}
{/* Action Buttons */}
</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"
>
Finish
</button>
</div>
);
}