260 lines
13 KiB
TypeScript

import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { EmptyState } from '@/components/ui/empty-state';
import { Input } from '@/components/ui/input';
import { Pagination } from '@/components/ui/pagination';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import AppLayout from '@/layouts/app-layout';
import { type BreadcrumbItem } from '@/types';
import { Head, Link, usePage } from '@inertiajs/react';
import { PencilIcon, PlusIcon, Trash2Icon } from 'lucide-react';
import { useEffect, useState } from 'react';
import { Toaster, toast } from 'sonner';
interface Registration {
id: string;
registration_number: string;
patient_name: string;
employee_name: string;
service_room_name: string;
registration_type: string;
patient_type: string;
registration_datetime: string;
discharge_datetime: string | null;
status: string;
payment_status: string;
is_active: boolean;
created_at: string;
}
interface PageProps {
registrations: {
data: Registration[];
links: Array<{
url: string | null;
label: string;
active: boolean;
}>;
};
status?: string;
}
const breadcrumbs: BreadcrumbItem[] = [
{ title: 'Dashboard', href: '/dashboard' },
{ title: 'Registrasi', href: '/registrations' },
];
export default function RegistrationIndex() {
const { registrations, status } = usePage<PageProps>().props;
const [searchTerm, setSearchTerm] = useState('');
const [filteredRegistrations, setFilteredRegistrations] = useState<Registration[]>(registrations.data);
useEffect(() => {
if (status) {
toast.success(status);
}
}, [status]);
useEffect(() => {
const results = registrations.data.filter((registration) =>
Object.values(registration).some((value) => value && value.toString().toLowerCase().includes(searchTerm.toLowerCase())),
);
setFilteredRegistrations(results);
}, [searchTerm, registrations.data]);
const getStatusBadgeVariant = (status: string) => {
switch (status) {
case 'completed':
return 'default';
case 'cancelled':
return 'destructive';
case 'in_progress':
return 'warning';
default:
return 'outline';
}
};
const getPaymentStatusBadgeVariant = (status: string) => {
switch (status) {
case 'paid':
return 'default';
case 'unpaid':
return 'destructive';
case 'partial':
return 'warning';
case 'insurance_cover':
return 'success';
default:
return 'outline';
}
};
const getRegistrationTypeBadgeVariant = (type: string) => {
switch (type) {
case 'Rawat Inap':
return 'purple';
case 'UGD':
return 'red';
default:
return 'blue';
}
};
return (
<AppLayout breadcrumbs={breadcrumbs}>
<Head title="Manajemen Registrasi Pasien" />
<Toaster position="top-right" richColors />
<div className="flex h-full flex-1 flex-col gap-4 rounded-xl p-4">
<div className="flex items-center justify-between">
<div>
<h1 className="text-2xl font-bold">Data Registrasi Pasien</h1>
</div>
<Button asChild>
<Link href={route('registrations.create')}>
<PlusIcon className="mr-2 h-4 w-4" />
Tambah Registrasi
</Link>
</Button>
</div>
<div className="w-full md:w-1/3">
<Input type="text" placeholder="Cari registrasi..." value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} />
</div>
<div>
{filteredRegistrations.length === 0 ? (
<EmptyState
title={searchTerm ? 'Registrasi tidak ditemukan' : 'Belum ada registrasi'}
description={
searchTerm ? 'Tidak ada registrasi yang sesuai dengan pencarian Anda' : 'Mulai dengan menambahkan registrasi baru'
}
action={
<Button asChild>
<Link href={route('registrations.create')}>
<PlusIcon className="mr-2 h-4 w-4" />
Tambah Registrasi
</Link>
</Button>
}
/>
) : (
<>
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>No. Registrasi</TableHead>
<TableHead>Nama Pasien</TableHead>
<TableHead>Petugas</TableHead>
<TableHead>Ruangan</TableHead>
<TableHead>Jenis</TableHead>
<TableHead>Tanggal Masuk</TableHead>
<TableHead>Status</TableHead>
<TableHead>Pembayaran</TableHead>
<TableHead>Aksi</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{filteredRegistrations.map((registration) => (
<TableRow key={registration.id}>
<TableCell className="font-medium">{registration.registration_number}</TableCell>
<TableCell>{registration.patient_name}</TableCell>
<TableCell>{registration.employee_name}</TableCell>
<TableCell>{registration.service_room_name}</TableCell>
<TableCell>
<Badge variant={getRegistrationTypeBadgeVariant(registration.registration_type)}>
{registration.registration_type}
</Badge>
</TableCell>
<TableCell>
{new Date(registration.registration_datetime).toLocaleDateString('id-ID', {
day: '2-digit',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
})}
</TableCell>
<TableCell>
<Badge variant={getStatusBadgeVariant(registration.status)}>
{registration.status.replace('_', ' ')}
</Badge>
</TableCell>
<TableCell>
<Badge variant={getPaymentStatusBadgeVariant(registration.payment_status)}>
{registration.payment_status.replace('_', ' ')}
</Badge>
</TableCell>
<TableCell className="flex justify-start gap-2">
<Button variant="ghost" size="icon" asChild className="hover:bg-neutral-100">
<Link href={route('registrations.edit', registration.id)}>
<PencilIcon className="h-4 w-4" />
</Link>
</Button>
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="ghost"
size="icon"
className="text-red-600 hover:bg-red-50 hover:text-red-700"
disabled={registration.status === 'completed'}
>
<Trash2Icon className="h-4 w-4" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Apakah Anda yakin?</AlertDialogTitle>
<AlertDialogDescription>
Data registrasi akan dihapus permanen. Tindakan ini tidak dapat dibatalkan.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Batal</AlertDialogCancel>
<AlertDialogAction asChild>
<Link
href={route('registrations.destroy', registration.id)}
method="delete"
as="button"
preserveScroll
>
Hapus
</Link>
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
{registrations.links.length > 3 && (
<div className="mt-4">
<Pagination links={registrations.links} />
</div>
)}
</>
)}
</div>
</div>
</AppLayout>
);
}