import { useState } from "react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible"; import { Label } from "@/components/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Plus, ChevronRight, CalendarCheck, CheckCircle2, Loader2 } from "lucide-react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { institutionalExamService } from "@/services/institutional-exam.service"; import { useCourses, useBatches } from "@/hooks/queries"; import { useToast } from "@/hooks/use-toast"; import type { InstitutionalExamSession, InstitutionalExam } from "@/types/institutional-exam"; const stateBadgeVariant: Record = { draft: "outline", schedule: "secondary", held: "default", cancel: "destructive", done: "default", }; export default function InstitutionalExamSessions() { const { toast } = useToast(); const qc = useQueryClient(); const [showCreate, setShowCreate] = useState(false); const [expandedId, setExpandedId] = useState(null); const { data: sessionsData, isLoading } = useQuery({ queryKey: ["inst-exam-sessions", "list"], queryFn: () => institutionalExamService.listSessions(), }); const sessions = sessionsData?.items ?? []; const { data: expandedSession } = useQuery({ queryKey: ["inst-exam-sessions", expandedId], queryFn: () => institutionalExamService.getSession(expandedId!), enabled: !!expandedId, }); const { data: examTypesData } = useQuery({ queryKey: ["exam-types", "list"], queryFn: () => institutionalExamService.listExamTypes(), }); const examTypes = examTypesData?.items ?? []; const { data: coursesData } = useCourses(); const courses = coursesData?.items ?? []; const { data: batchesData } = useBatches(); const batches = batchesData?.items ?? []; const [form, setForm] = useState({ name: "", course_id: 0, batch_id: 0, start_date: "", end_date: "", exam_type_id: 0, evaluation_type: "normal" as "normal" | "grade", }); const createMutation = useMutation({ mutationFn: () => institutionalExamService.createSession(form as Parameters[0]), onSuccess: () => { qc.invalidateQueries({ queryKey: ["inst-exam-sessions"] }); toast({ title: "Exam session created" }); setShowCreate(false); setForm({ name: "", course_id: 0, batch_id: 0, start_date: "", end_date: "", exam_type_id: 0, evaluation_type: "normal" }); }, onError: () => toast({ title: "Error", description: "Failed to create session", variant: "destructive" }), }); const scheduleMutation = useMutation({ mutationFn: (id: number) => institutionalExamService.scheduleSession(id), onSuccess: () => { qc.invalidateQueries({ queryKey: ["inst-exam-sessions"] }); toast({ title: "Session scheduled" }); }, onError: () => toast({ title: "Error", description: "Failed to schedule", variant: "destructive" }), }); const doneMutation = useMutation({ mutationFn: (id: number) => institutionalExamService.markSessionDone(id), onSuccess: () => { qc.invalidateQueries({ queryKey: ["inst-exam-sessions"] }); toast({ title: "Session marked as done" }); }, onError: () => toast({ title: "Error", description: "Failed to update", variant: "destructive" }), }); if (isLoading) return
; return (

Exam Sessions

Manage institutional exam sessions and their exams.

Create Exam Session
setForm({ ...form, name: e.target.value })} />
setForm({ ...form, start_date: e.target.value })} />
setForm({ ...form, end_date: e.target.value })} />
Name Course / Batch Dates Type Exams State Actions {sessions.map((session: InstitutionalExamSession) => ( setExpandedId(open ? session.id : null)}> <> {session.name}
{session.course_name} / {session.batch_name}
{session.start_date} — {session.end_date} {session.exam_type_name} {session.exam_count} {session.state}
{session.state === "draft" && ( )} {session.state === "schedule" && ( )}
{expandedSession && expandedId === session.id ? (

Exams in Session

{(expandedSession as InstitutionalExamSession & { exams?: InstitutionalExam[] }).exams?.length ? (
{((expandedSession as InstitutionalExamSession & { exams?: InstitutionalExam[] }).exams ?? []).map((exam: InstitutionalExam) => (
{exam.name} {exam.subject_name}
{exam.total_marks} marks {exam.state}
))}
) : (

No exams in this session yet.

)}
) : (
)}
))} {sessions.length === 0 && ( No exam sessions found. )}
); }