130 lines
5.4 KiB
TypeScript
130 lines
5.4 KiB
TypeScript
import { Head, Link } from '@inertiajs/react';
|
|
import { XCircle } from 'lucide-react';
|
|
import { DataTable } from '@/components/data-table';
|
|
import { PageHeader } from '@/components/page-header';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Card, CardContent } from '@/components/ui/card';
|
|
import { formatRupiah } from '@/lib/currency';
|
|
import { create } from '@/routes/student/course-registrations';
|
|
import type { AcademicTerm } from '@/types/academic-term';
|
|
import type { RegistrationStatus } from '@/types/course-registration';
|
|
import type { SubmissionSummary } from './columns';
|
|
import { submissionColumns } from './columns';
|
|
|
|
type PaymentStatus = {
|
|
has_invoice: boolean;
|
|
is_paid: boolean;
|
|
amount_due: number | null;
|
|
paid_total: number | null;
|
|
};
|
|
|
|
type ActiveSubmission = {
|
|
status: RegistrationStatus;
|
|
rejection_reason: string | null;
|
|
};
|
|
|
|
type Props = {
|
|
academicTerm: AcademicTerm | null;
|
|
payment: PaymentStatus | null;
|
|
canSubmit: boolean;
|
|
activeSubmission: ActiveSubmission | null;
|
|
submissions: SubmissionSummary[];
|
|
};
|
|
|
|
export default function CourseRegistrationIndex({
|
|
academicTerm,
|
|
payment,
|
|
canSubmit,
|
|
activeSubmission,
|
|
submissions,
|
|
}: Props) {
|
|
return (
|
|
<>
|
|
<Head title="KRS" />
|
|
|
|
<div className="flex h-full flex-1 flex-col gap-6 overflow-x-auto p-4 md:p-6">
|
|
<PageHeader
|
|
title="Kartu Rencana Studi"
|
|
description={
|
|
academicTerm && (
|
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
Periode aktif: {academicTerm.name} (
|
|
{academicTerm.semester === 'odd'
|
|
? 'Ganjil'
|
|
: 'Genap'}
|
|
)
|
|
</p>
|
|
)
|
|
}
|
|
/>
|
|
|
|
{!academicTerm && (
|
|
<Card>
|
|
<CardContent className="pt-6 text-sm text-muted-foreground">
|
|
Belum ada periode akademik yang aktif. Silakan
|
|
hubungi admin.
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{academicTerm && payment && !payment.is_paid && (
|
|
<Card className="border-destructive/50">
|
|
<CardContent className="pt-6 text-sm">
|
|
<p className="font-medium text-destructive">
|
|
Anda belum bisa mengisi KRS periode ini.
|
|
</p>
|
|
<p className="mt-1 text-muted-foreground">
|
|
{payment.has_invoice
|
|
? `Tagihan periode ini belum lunas (terbayar ${formatRupiah(payment.paid_total ?? 0)} dari ${formatRupiah(payment.amount_due ?? 0)}).`
|
|
: 'Tagihan untuk periode ini belum diterbitkan. Silakan hubungi staf keuangan.'}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{academicTerm && payment?.is_paid && canSubmit && (
|
|
<Card
|
|
className={
|
|
activeSubmission?.status === 'rejected'
|
|
? 'border-destructive/50'
|
|
: undefined
|
|
}
|
|
>
|
|
<CardContent className="flex flex-col gap-3 pt-6 sm:flex-row sm:items-center sm:justify-between">
|
|
<div>
|
|
{activeSubmission?.status === 'rejected' ? (
|
|
<>
|
|
<p className="flex items-center gap-2 text-sm font-medium text-destructive">
|
|
<XCircle className="h-4 w-4" />
|
|
KRS Anda untuk periode ini ditolak
|
|
</p>
|
|
<p className="mt-1 text-sm text-muted-foreground">
|
|
{activeSubmission.rejection_reason ??
|
|
'Tidak ada alasan yang diberikan.'}{' '}
|
|
Silakan perbaiki dan ajukan kembali.
|
|
</p>
|
|
</>
|
|
) : (
|
|
<p className="text-sm text-muted-foreground">
|
|
Anda belum mengisi KRS untuk periode
|
|
aktif ini.
|
|
</p>
|
|
)}
|
|
</div>
|
|
<Button asChild>
|
|
<Link href={create.url()}>
|
|
{activeSubmission?.status === 'rejected'
|
|
? 'Ajukan Ulang KRS'
|
|
: 'Isi KRS'}
|
|
</Link>
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
<DataTable columns={submissionColumns} data={submissions} />
|
|
</div>
|
|
</>
|
|
);
|
|
}
|