'use client'; import { useState, useEffect, useCallback } from 'react'; import { type ColumnDef } from '@tanstack/react-table'; import { Pencil, Trash2, Plus, Lock } from 'lucide-react'; import { DataTable } from '@/components/shared/data-table'; import { PageHeader } from '@/components/shared/page-header'; import { ConfirmationDialog } from '@/components/shared/confirmation-dialog'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { apiFetch } from '@/lib/api/client'; import { RoleForm } from './role-form'; interface Role { id: string; name: string; description: string | null; isSystem: boolean; isGlobal: boolean; permissions: Record>; createdAt: string; } export function RoleList() { const [roles, setRoles] = useState([]); const [loading, setLoading] = useState(true); const [formOpen, setFormOpen] = useState(false); const [editingRole, setEditingRole] = useState(null); const [deletingId, setDeletingId] = useState(null); const fetchRoles = useCallback(async () => { setLoading(true); try { const res = await apiFetch<{ data: Role[] }>('/api/v1/admin/roles'); setRoles(res.data); } finally { setLoading(false); } }, []); useEffect(() => { void fetchRoles(); }, [fetchRoles]); function handleNewRole() { setEditingRole(null); setFormOpen(true); } function handleEditRole(role: Role) { setEditingRole(role); setFormOpen(true); } async function handleDeleteRole(id: string) { setDeletingId(id); try { await apiFetch(`/api/v1/admin/roles/${id}`, { method: 'DELETE' }); await fetchRoles(); } finally { setDeletingId(null); } } function countPermissions(perms: Record>): string { let granted = 0; let total = 0; for (const group of Object.values(perms)) { for (const val of Object.values(group)) { total++; if (val) granted++; } } return `${granted}/${total}`; } const columns: ColumnDef[] = [ { accessorKey: 'name', header: 'Name', cell: ({ row }) => (
{row.original.name} {row.original.isSystem && ( System )}
), }, { accessorKey: 'description', header: 'Description', cell: ({ row }) => ( {row.original.description ?? '—'} ), }, { id: 'permissions', header: 'Permissions', cell: ({ row }) => ( {countPermissions(row.original.permissions)} ), }, { id: 'actions', header: '', cell: ({ row }) => (
{!row.original.isSystem && ( Delete } title="Delete Role" description={`Delete "${row.original.name}"? Users assigned to this role must be reassigned first.`} confirmLabel="Delete" onConfirm={() => handleDeleteRole(row.original.id)} loading={deletingId === row.original.id} /> )}
), enableSorting: false, size: 80, }, ]; return (
New Role } /> row.id} emptyState={

No roles defined.

} />
); }