"use client" import { useState, useTransition } from "react" import { useRouter } from "next/navigation" import { toast } from "sonner" import { useTranslations } from "next-intl" import { BookOpen, CheckCircle2, XCircle } from "lucide-react" import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/shared/components/ui/alert-dialog" import { Badge } from "@/shared/components/ui/badge" import { Button } from "@/shared/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/shared/components/ui/card" import { EmptyState } from "@/shared/components/ui/empty-state" import { COURSE_SELECTION_STATUS_BADGE_VARIANTS, COURSE_SELECTION_STATUS_LABEL_KEYS, ELECTIVE_STATUS_BADGE_VARIANTS, ELECTIVE_STATUS_LABEL_KEYS, SELECTION_MODE_LABEL_KEYS, } from "../constants" import type { CourseSelectionWithDetails, ElectiveCourseWithDetails, } from "../types" import { selectCourseAction, dropCourseAction } from "../actions" export function StudentSelectionView({ availableCourses, mySelections, }: { availableCourses: ElectiveCourseWithDetails[] mySelections: CourseSelectionWithDetails[] }) { const router = useRouter() const t = useTranslations("elective") const [pendingId, setPendingId] = useState(null) const [isPending, startTransition] = useTransition() const activeSelections = mySelections.filter((s) => ["selected", "enrolled", "waitlist"].includes(s.status) ) const selectedCourseIds = new Set( activeSelections.map((s) => s.courseId) ) const handleSelect = (courseId: string) => { setPendingId(courseId) startTransition(async () => { const formData = new FormData() formData.set("courseId", courseId) const res = await selectCourseAction(null, formData) if (res.success) { toast.success(res.message || t("student.selectSuccess")) router.refresh() } else { toast.error(res.message ?? t("errors.unexpected")) } setPendingId(null) }) } const handleDrop = (courseId: string) => { setPendingId(courseId) startTransition(async () => { const formData = new FormData() formData.set("courseId", courseId) const res = await dropCourseAction(null, formData) if (res.success) { toast.success(res.message || t("student.dropSuccess")) router.refresh() } else { toast.error(res.message ?? t("errors.unexpected")) } setPendingId(null) }) } return (

{t("student.mySelections")}

{activeSelections.length}
{activeSelections.length === 0 ? ( ) : (
{activeSelections.map((sel) => ( {sel.courseName ?? t("errors.notFound")} {t(COURSE_SELECTION_STATUS_LABEL_KEYS[sel.status])} {sel.courseCapacity !== null && sel.courseEnrolledCount !== null ? (

{t("fields.enrolled")}: {sel.courseEnrolledCount}/{sel.courseCapacity}

) : null} {sel.lotteryRank ? (

#{sel.lotteryRank}

) : null} {t("student.confirmDrop")} {t("student.confirmDrop")} {t("actions.cancel")} handleDrop(sel.courseId)} > {t("actions.drop")}
))}
)}

{t("student.availableCourses")}

{availableCourses.length}
{availableCourses.length === 0 ? ( ) : (
{availableCourses.map((course) => { const isFull = course.enrolledCount >= course.capacity const alreadySelected = selectedCourseIds.has(course.id) const isPendingThis = isPending && pendingId === course.id return ( {course.name} {t(ELECTIVE_STATUS_LABEL_KEYS[course.status])}
{course.subjectName ? ( {course.subjectName} ) : null} {t("fields.credit")}: {course.credit} · {t(SELECTION_MODE_LABEL_KEYS[course.selectionMode])}
{course.description ? (

{course.description}

) : null}
{t("fields.teacher")}:{" "} {course.teacherName ?? "—"}
{t("fields.capacity")}:{" "} {course.enrolledCount}/{course.capacity} {isFull ? ` (${t("student.capacityFull")})` : ""}
{course.schedule ? (

{t("fields.schedule")}: {course.schedule}

) : null}
{alreadySelected ? ( ) : ( )}
) })}
)}
) }