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

133 lines
6.4 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { Head, Link, router, usePage } from '@inertiajs/react';
import React, { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Separator } from '@/components/ui/separator';
import AppLayout from '@/layouts/app-layout';
import { type BreadcrumbItem } from '@/types';
interface User {
id: number;
name: string;
email: string;
role: 'admin' | 'employee';
created_at: string;
}
interface PageProps {
users: User[];
[key: string]: unknown;
}
const breadcrumbs: BreadcrumbItem[] = [
{ title: 'Manajemen Pengguna', href: '/admin/users' },
];
export default function Index({ users }: PageProps) {
const { flash } = usePage<any>().props;
const [processingId, setProcessingId] = useState<number | null>(null);
const updateRole = (id: number, role: string) => {
setProcessingId(id);
router.patch(
`/admin/users/${id}`,
{ role },
{
preserveScroll: true,
onFinish: () => setProcessingId(null),
},
);
};
return (
<AppLayout breadcrumbs={breadcrumbs}>
<Head title="Manajemen Pengguna" />
<div className="p-4 md:p-8 w-full space-y-4">
{/* Flash Messages */}
{flash?.success && (
<div className="p-4 bg-green-50 text-green-700 border border-green-200 rounded-md text-sm">
{flash.success}
</div>
)}
{flash?.error && (
<div className="p-4 bg-red-50 text-red-700 border border-red-200 rounded-md text-sm">
{flash.error}
</div>
)}
{/* Header */}
<div className="flex items-center justify-between">
<div>
<h2 className="text-2xl font-bold tracking-tight">Manajemen Akses User</h2>
<p className="text-muted-foreground">Kelola akun dan hak akses pengguna sistem.</p>
</div>
<Button asChild>
<Link href="/admin/users/create">+ Tambah User Baru</Link>
</Button>
</div>
{/* Tabel */}
<Card>
<CardHeader className="pb-4">
<CardTitle>Daftar Pengguna</CardTitle>
</CardHeader>
<Separator />
<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</th>
<th className="h-12 px-4 font-medium">Email</th>
<th className="h-12 px-4 font-medium text-center">Role Saat Ini</th>
<th className="h-12 px-4 font-medium text-right">Ubah Role</th>
</tr>
</thead>
<tbody>
{users.length > 0 ? (
users.map((user) => (
<tr key={user.id} className="border-b hover:bg-zinc-50">
<td className="p-4 font-medium">{user.name}</td>
<td className="p-4 text-muted-foreground">{user.email}</td>
<td className="p-4 text-center">
<span className="bg-zinc-100 px-2.5 py-1 rounded-full text-[11px] font-semibold tracking-wide">
{user.role.toUpperCase()}
</span>
</td>
<td className="p-4 text-right">
<Select
defaultValue={user.role}
onValueChange={(val) => updateRole(user.id, val)}
disabled={processingId === user.id}
>
<SelectTrigger className="w-[130px] ml-auto">
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="admin">Admin</SelectItem>
<SelectItem value="employee">Employee</SelectItem>
</SelectContent>
</Select>
</td>
</tr>
))
) : (
<tr>
<td colSpan={4} className="p-8 text-center text-muted-foreground">
Belum ada data pengguna.
</td>
</tr>
)}
</tbody>
</table>
</div>
</CardContent>
</Card>
</div>
</AppLayout>
);
}