LMS-BGN/src/app/exam-summary/page.tsx

242 lines
8.7 KiB
TypeScript

'use client';
import { useEffect, useState } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
import { CheckCircle, XCircle, Clock, Award, BarChart3, Home, FileText } from 'lucide-react';
import { cn } from '@/utils/cn';
interface ExamResult {
examId: string;
examTitle: string;
totalQuestions: number;
correctAnswers: number;
score: number;
timeSpent: string;
completedAt: string;
answers: Array<{
questionId: string;
question: string;
userAnswer: any;
correctAnswer: any;
isCorrect: boolean;
type: string;
}>;
}
export default function ExamSummaryPage() {
const router = useRouter();
const searchParams = useSearchParams();
const [examResult, setExamResult] = useState<ExamResult | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Simulate loading exam results
// In real app, this would fetch from API or localStorage
const mockResult: ExamResult = {
examId: 'exam-1',
examTitle: 'Ujian Keamanan Pangan MBG',
totalQuestions: 10,
correctAnswers: 8,
score: 80,
timeSpent: '25 menit 30 detik',
completedAt: new Date().toLocaleString('id-ID'),
answers: [
{
questionId: '1',
question: 'Suhu ideal untuk menyimpan daging segar adalah...',
userAnswer: 'Di bawah 4°C',
correctAnswer: 'Di bawah 4°C',
isCorrect: true,
type: 'multiple_choice'
},
{
questionId: '2',
question: 'Langkah pertama dalam sistem HACCP adalah...',
userAnswer: 'Analisis bahaya',
correctAnswer: 'Analisis bahaya',
isCorrect: true,
type: 'multiple_choice'
},
// Add more mock answers as needed
]
};
setTimeout(() => {
setExamResult(mockResult);
setLoading(false);
}, 1000);
}, []);
const getScoreColor = (score: number) => {
if (score >= 80) return 'text-green-600';
if (score >= 60) return 'text-yellow-600';
return 'text-red-600';
};
const getScoreBgColor = (score: number) => {
if (score >= 80) return 'bg-green-100 border-green-200';
if (score >= 60) return 'bg-yellow-100 border-yellow-200';
return 'bg-red-100 border-red-200';
};
if (loading) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto mb-4"></div>
<p className="text-gray-600">Memproses hasil ujian...</p>
</div>
</div>
);
}
if (!examResult) {
return (
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<XCircle className="w-16 h-16 text-red-500 mx-auto mb-4" />
<h2 className="text-xl font-semibold text-gray-900 mb-2">Hasil ujian tidak ditemukan</h2>
<button
onClick={() => router.push('/exams')}
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Kembali ke Daftar Ujian
</button>
</div>
</div>
);
}
return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
{/* Header */}
<div className="text-center mb-8">
<div className="flex justify-center mb-4">
{examResult.score >= 80 ? (
<CheckCircle className="w-16 h-16 text-green-500" />
) : examResult.score >= 60 ? (
<Award className="w-16 h-16 text-yellow-500" />
) : (
<XCircle className="w-16 h-16 text-red-500" />
)}
</div>
<h1 className="text-3xl font-bold text-gray-900 mb-2">
{examResult.score >= 80 ? 'Selamat!' : examResult.score >= 60 ? 'Cukup Baik!' : 'Perlu Perbaikan'}
</h1>
<p className="text-gray-600">Anda telah menyelesaikan ujian</p>
</div>
{/* Score Summary */}
<div className={cn(
"bg-white rounded-xl shadow-lg p-6 mb-8 border-2",
getScoreBgColor(examResult.score)
)}>
<div className="text-center">
<h2 className="text-2xl font-bold text-gray-900 mb-4">{examResult.examTitle}</h2>
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
<div className="text-center">
<div className={cn("text-4xl font-bold mb-2", getScoreColor(examResult.score))}>
{examResult.score}%
</div>
<p className="text-gray-600">Skor Akhir</p>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-gray-900 mb-2">
{examResult.correctAnswers}/{examResult.totalQuestions}
</div>
<p className="text-gray-600">Jawaban Benar</p>
</div>
<div className="text-center">
<div className="text-2xl font-bold text-gray-900 mb-2 flex items-center justify-center gap-2">
<Clock className="w-6 h-6" />
{examResult.timeSpent}
</div>
<p className="text-gray-600">Waktu Pengerjaan</p>
</div>
<div className="text-center">
<div className="text-lg font-semibold text-gray-900 mb-2">
{examResult.completedAt}
</div>
<p className="text-gray-600">Selesai Pada</p>
</div>
</div>
</div>
</div>
{/* Detailed Results */}
<div className="bg-white rounded-xl shadow-lg p-6 mb-8">
<h3 className="text-xl font-bold text-gray-900 mb-6 flex items-center gap-2">
<BarChart3 className="w-6 h-6" />
Detail Jawaban
</h3>
<div className="space-y-4">
{examResult.answers.map((answer, index) => (
<div
key={answer.questionId}
className={cn(
"p-4 rounded-lg border-2",
answer.isCorrect
? "bg-green-50 border-green-200"
: "bg-red-50 border-red-200"
)}
>
<div className="flex items-start gap-3">
<div className="flex-shrink-0">
{answer.isCorrect ? (
<CheckCircle className="w-6 h-6 text-green-600" />
) : (
<XCircle className="w-6 h-6 text-red-600" />
)}
</div>
<div className="flex-1">
<h4 className="font-semibold text-gray-900 mb-2">
Soal {index + 1}: {answer.question}
</h4>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<p className="text-sm text-gray-600 mb-1">Jawaban Anda:</p>
<p className={cn(
"font-medium",
answer.isCorrect ? "text-green-700" : "text-red-700"
)}>
{typeof answer.userAnswer === 'string' ? answer.userAnswer : 'Tidak dijawab'}
</p>
</div>
{!answer.isCorrect && (
<div>
<p className="text-sm text-gray-600 mb-1">Jawaban Benar:</p>
<p className="font-medium text-green-700">
{typeof answer.correctAnswer === 'string' ? answer.correctAnswer : 'N/A'}
</p>
</div>
)}
</div>
</div>
</div>
</div>
))}
</div>
</div>
{/* Action Buttons */}
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<button
onClick={() => router.push('/exams')}
className="flex items-center justify-center gap-2 px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
<FileText className="w-5 h-5" />
Lihat Ujian Lain
</button>
<button
onClick={() => router.push('/')}
className="flex items-center justify-center gap-2 px-6 py-3 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors font-medium"
>
<Home className="w-5 h-5" />
Kembali ke Dashboard
</button>
</div>
</div>
</div>
);
}