TIFNJK_E41222887/resources/js/pages/admin/departments/index.tsx

180 lines
9.7 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { Head, Link, usePage } from '@inertiajs/react';
import React from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { Input } from '@/components/ui/input';
import AppLayout from '@/layouts/app-layout';
import { Search } from 'lucide-react';
import { useState, useEffect } from 'react';
import { useDebounce } from 'use-debounce';
import { router } from '@inertiajs/react';
import * as XLSX from 'xlsx';
interface Department {
id: number;
name: string;
description: string;
employees_count: number;
}
interface PageProps {
departments: Department[];
filters: { search?: string };
[key: string]: unknown;
}
export default function Index({ departments, filters }: PageProps) {
const [search, setSearch] = useState(filters.search || '');
const [debouncedSearch] = useDebounce(search, 500);
useEffect(() => {
if (debouncedSearch !== filters.search) {
router.get(
'/admin/departments',
{ search: debouncedSearch },
{ preserveState: true, replace: true }
);
}
}, [debouncedSearch]);
const exportExcel = () => {
const rows = departments.map((d, i) => ({
No: i + 1,
'Nama Departemen': d.name,
Deskripsi: d.description || '-',
'Total Karyawan': d.employees_count,
}));
const ws = XLSX.utils.json_to_sheet(rows);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, 'Departemen');
XLSX.writeFile(wb, `Data_Departemen_${new Date().toISOString().slice(0, 10)}.xlsx`);
};
return (
<AppLayout>
<Head title="Manajemen Departemen" />
<div className="p-4 md:p-8 w-full space-y-4">
{/* Page Header */}
<div className="space-y-1">
<h2 className="text-2xl font-bold tracking-tight">Data Departemen</h2>
<p className="text-muted-foreground">Kelola struktur organisasi dan unit kerja.</p>
</div>
<Card>
<CardHeader className="flex flex-row items-center justify-between pb-4">
<CardTitle>Daftar Departemen</CardTitle>
<div className="flex gap-2">
<Button variant="outline" onClick={exportExcel}>Export Excel</Button>
<Button asChild>
<Link href="/admin/departments/create">+ Tambah Departemen</Link>
</Button>
</div>
</CardHeader>
<Separator />
<div className="p-4 w-full md:w-1/3">
<div className="relative">
<Search className="absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground" />
<Input
className="pl-8"
placeholder="Cari departemen..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
</div>
<CardContent className="pt-0">
<div className="relative w-full overflow-auto">
<table className="w-full text-sm text-left">
<thead className="text-muted-foreground bg-zinc-50/50">
<tr className="border-b">
<th className="h-12 px-4 font-medium">Nama Departemen</th>
<th className="h-12 px-4 font-medium">Deskripsi</th>
<th className="h-12 px-4 font-medium text-center">Total Karyawan</th>
<th className="h-12 px-4 font-medium text-right">Aksi</th>
</tr>
</thead>
<tbody>
{departments.length > 0 ? (
departments.map((dept) => (
<tr key={dept.id} className="border-b hover:bg-zinc-50">
<td className="p-4 font-bold text-gray-900">
{dept.name}
</td>
<td className="p-4 text-muted-foreground">
{dept.description || '-'}
</td>
<td className="p-4 text-center">
<span className={`inline-flex items-center justify-center px-2.5 py-0.5 rounded-full text-xs font-medium ${dept.employees_count > 0 ? 'bg-blue-100 text-blue-800' : 'bg-gray-100 text-gray-600'}`}>
{dept.employees_count}
</span>
</td>
<td className="p-4 text-right space-x-2">
<Button variant="ghost" size="sm" asChild>
<Link href={`/admin/departments/${dept.id}/edit`}>Edit</Link>
</Button>
{dept.employees_count > 0 ? (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<span tabIndex={0} className="cursor-not-allowed inline-block">
<Button
variant="ghost"
size="sm"
disabled
className="text-red-300 hover:text-red-300 hover:bg-transparent opacity-50"
>
Hapus
</Button>
</span>
</TooltipTrigger>
<TooltipContent className="bg-red-50 text-red-700 border-red-200">
<p className="font-semibold">Akses Ditolak</p>
<p className="text-xs">Masih ada {dept.employees_count} karyawan aktif di sini.</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
) : (
<Link
href={`/admin/departments/${dept.id}`}
method="delete"
as="button"
onClick={(e) => {
if (!confirm('Hapus departemen ini?')) e.preventDefault();
}}
className="inline-flex items-center justify-center rounded-md text-sm font-medium h-9 px-3 text-red-600 hover:bg-red-50 transition-colors"
>
Hapus
</Link>
)}
</td>
</tr>
))
) : (
<tr>
<td colSpan={4} className="p-8 text-center text-muted-foreground">
Belum ada data departemen.
</td>
</tr>
)}
</tbody>
</table>
</div>
</CardContent>
</Card>
</div>
</AppLayout>
);
}