import QuestionAnswerResult from '@/components/exam/question-answer-result'; import QuestionStatusBadge from '@/components/exam/question-status-badge'; import QuestionStatusIcon from '@/components/exam/question-status-icon'; import QuestionTypeBadge from '@/components/exam/question-type-badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Link, router } from '@inertiajs/react'; import { ArrowLeft, Clock } from 'lucide-react'; import { useState } from 'react'; import { Renderer } from 'richtor'; import 'richtor/styles'; interface AttemptAnswerWithQuestion extends ExamAttemptAnswer { exam_question: ExamQuestion; } const ExamAttemptReview = ({ attempt }: { attempt: ExamAttempt }) => { const [manualGrades, setManualGrades] = useState>({}); const [submitting, setSubmitting] = useState(false); const answers = attempt.attempt_answers ?? []; const safeQuestion = (answer: AttemptAnswerWithQuestion) => answer.exam_question ?? ({} as ExamQuestion); const handleManualGradeChange = (questionId: number, value: string) => { const numValue = parseFloat(value) || 0; setManualGrades((prev) => ({ ...prev, [questionId]: numValue, })); }; const handleSubmitGrades = () => { setSubmitting(true); router.post( route('exam-attempts.grade', attempt.id), { manual_grades: manualGrades, }, { preserveScroll: true, onSuccess: () => { setSubmitting(false); setManualGrades({}); }, onError: () => { setSubmitting(false); }, }, ); }; const needsManualGrading = answers.some((answer) => { const question = safeQuestion(answer); return question.question_type === 'listening' || question.question_type === 'short_answer'; }); if (!attempt) { return (

Attempt data unavailable

Please return to the exam list and try again.

); } return (
{/* Question-wise Analysis */}
Detailed Analysis {/*
Attempt {attempt.attempt_number} Result
*/}
{answers.map((answer, index) => { const question = safeQuestion(answer); const questionId = question.id as number; return (
{/* Question Header */}
Question {index + 1} {question.question_type && }

{question.title}

{answer.marks_obtained || 0}/{question.marks || 0}

marks

{/* Question Content */}
{question.description && } {/* Render Question with Answer */}
{/* Manual Grading Section for listening and short_answer */} {(question.question_type === 'listening' || question.question_type === 'short_answer') && (
) => handleManualGradeChange(questionId, e.target.value)} className="mt-1 w-full" /> {answer.is_correct === null && (

This question requires manual grading

)}
)}
); })}
{/* Submit Grades Button */} {needsManualGrading && (
)}
); }; export default ExamAttemptReview;