"use client"; import { useState, useTransition } from "react"; import { useRouter } from "next/navigation"; import { useTableControls } from "@/components/ui/use-table-controls"; import { TableControls, SortableTh } from "@/components/ui/table-controls"; import { AddUserButton, EditUserButton } from "./user-form"; import { RowActionsMenu, RowActionsItem, RowActionsDestructiveItem, RowActionsSeparator } from "@/components/ui/row-actions-menu"; import { DeleteConfirmDialog } from "@/components/ui/delete-confirm-dialog"; import { deleteUser, toggleUserActive } from "./actions"; import { grantSuperUser } from "../superuser-requests/actions"; import { ShieldCheck } from "lucide-react"; export type UserRow = { id: string; employeeId: string; name: string; email: string; role: string; isActive: boolean; createdAt: string; // serialised as ISO string from server }; const ROLE_LABELS: Record = { TECHNICAL: "Technical", MANNING: "Manning", ACCOUNTS: "Accounts", MANAGER: "Manager", SUPERUSER: "SuperUser", AUDITOR: "Auditor", ADMIN: "Admin", }; const CHIPS = ["Manning", "Technical", "Accounts", "Manager", "Superuser", "Auditor", "Admin", "Active", "Inactive"]; function UserActionsMenu({ user }: { user: UserRow }) { const router = useRouter(); const [editOpen, setEditOpen] = useState(false); const [deleteOpen, setDeleteOpen] = useState(false); const [isPending, startTransition] = useTransition(); const [grantPending, startGrantTransition] = useTransition(); function handleToggle() { startTransition(async () => { await toggleUserActive(user.id); router.refresh(); }); } function handleGrantSuperUser() { startGrantTransition(async () => { await grantSuperUser(user.id); router.refresh(); }); } return ( <> setEditOpen(true)}>Edit {user.isActive ? "Deactivate" : "Activate"} {user.role !== "SUPERUSER" && user.role !== "ADMIN" && ( Grant SuperUser )} setDeleteOpen(true)}>Delete deleteUser(user.id)} /> ); } export function UsersTable({ users }: { users: UserRow[] }) { const { search, setSearch, sortKey, sortDir, toggleSort, activeFilters, toggleFilter, filtered } = useTableControls({ rows: users, defaultSortKey: "employeeId", searchText: (u) => [u.employeeId, u.name, u.email, ROLE_LABELS[u.role] ?? u.role, u.isActive ? "active" : "inactive"].join(" "), chipMatch: (u, chip) => { const chipLower = chip.toLowerCase(); if (chipLower === "active") return u.isActive; if (chipLower === "inactive") return !u.isActive; return (ROLE_LABELS[u.role] ?? u.role).toLowerCase() === chipLower; }, sortValue: (u, key) => { if (key === "role") return ROLE_LABELS[u.role] ?? u.role; if (key === "isActive") return u.isActive ? "Active" : "Inactive"; const v = u[key as keyof UserRow]; return typeof v === "string" || typeof v === "number" || typeof v === "boolean" ? v : String(v); }, }); return (

User Management

toggleSort(k as keyof UserRow)}>Employee ID toggleSort(k as keyof UserRow)}>Name toggleSort(k as keyof UserRow)}>Email toggleSort(k as keyof UserRow)}>Role toggleSort(k as keyof UserRow)}>Status {filtered.length === 0 && ( )} {filtered.map((user) => ( ))}
Created
No users match your search.
{user.employeeId} {user.name} {user.email} {ROLE_LABELS[user.role] ?? user.role} {user.isActive ? "Active" : "Inactive"} {new Intl.DateTimeFormat("en-US", { year: "numeric", month: "short", day: "numeric" }).format(new Date(user.createdAt))}
); }