import { Form, Head, Link, router } from '@inertiajs/react'; import { format } from 'date-fns'; import { ArrowLeft, Check, Inbox, Send, X } from 'lucide-react'; import { useState } from 'react'; import { FormDialog } from '@/components/form-dialog'; import InputError from '@/components/input-error'; import { PageHeader } from '@/components/page-header'; import { SignaturePad } from '@/components/signature-pad'; import { Badge } from '@/components/ui/badge'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Checkbox } from '@/components/ui/checkbox'; import { Label } from '@/components/ui/label'; import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { Textarea } from '@/components/ui/textarea'; import { advisor_signature, approve, kaprodi_signature, reject, save, } from '@/routes/admin/manage/course-registrations'; import type { CourseRegistrationSubmission, CourseRegistrationSubmissionEntry, CourseRegistrationSubmissionLog, } from '@/types/course-registration'; import { RegistrationStatusLabels, semesterKey, } from '@/types/course-registration'; const RegistrationStatusVariants: Record< CourseRegistrationSubmission['status'], 'default' | 'secondary' | 'destructive' | 'outline' > = { submitted: 'outline', approved: 'default', rejected: 'destructive', }; function isSemesterOpenForStudent( semester: number | null, openSemesters: number[], studentCurrentSemester: number, ): boolean { return ( semester !== null && semester === studentCurrentSemester && openSemesters.includes(semester) ); } function InfoRow({ label, value }: { label: string; value: React.ReactNode }) { return (
{label} : {value}
); } function SignatureBox({ signatureUrl, alt, error, editable, }: { signatureUrl: string | null; alt: string; error?: string; editable: boolean; }) { if (!editable) { if (!signatureUrl) { return
; } return (
{alt}
); } return ; } function ReviewerSignatureField({ signatureUrl, alt, canSign, submitUrl, }: { signatureUrl: string | null; alt: string; canSign: boolean; submitUrl: string; }) { const [file, setFile] = useState(null); const [processing, setProcessing] = useState(false); if (signatureUrl) { return (
{alt}
); } if (!canSign) { return
; } function handleSave() { if (!file) { return; } setProcessing(true); router.patch( submitUrl, { signature: file }, { preserveScroll: true, onFinish: () => setProcessing(false), }, ); } return (
); } function LogBubble({ log, isResubmission, }: { log: CourseRegistrationSubmissionLog; isResubmission: boolean; }) { const actorName = log.actor?.profile?.full_name ?? 'Sistem'; const message = log.status === 'approved' ? `${actorName} menyetujui KRS ini.` : log.status === 'rejected' ? `${actorName} menolak KRS ini dengan alasan: "${log.reason}"` : isResubmission ? `${actorName} mengajukan ulang KRS.` : `${actorName} mengajukan KRS.`; const colorClasses = log.status === 'approved' ? 'border-primary/30 bg-primary/10' : log.status === 'rejected' ? 'border-destructive/30 bg-destructive/10' : 'border-border bg-muted'; return (

{message}

{format(new Date(log.created_at), 'd MMM yyyy, HH:mm')}

); } function RejectDialog({ open, onOpenChange, submissionId, }: { open: boolean; onOpenChange: (open: boolean) => void; submissionId: number; }) { return ( onOpenChange(false)} > {({ errors }) => (