144 lines
3.6 KiB
TypeScript
144 lines
3.6 KiB
TypeScript
'use client';
|
|
|
|
import { useCallback, useState } from 'react';
|
|
import { Plus, ShieldCheck } from 'lucide-react';
|
|
|
|
import { PageHeader } from '@/components/page-header';
|
|
import { PoweredBy } from '@/components/powered-by';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useAppStore } from '@/store/app.store';
|
|
import type { Role } from '@/types';
|
|
|
|
import { useRoleColumns } from './components/RoleColumns';
|
|
import { RoleFilters } from './components/RoleFilters';
|
|
import { RoleSheet } from './components/RoleSheet';
|
|
import { RoleTable } from './components/RoleTable';
|
|
import { useRoleFilters } from './hooks/useRoleFilters';
|
|
import { useRoleForm } from './hooks/useRoleForm';
|
|
import {
|
|
usePermissionsTreeQuery,
|
|
useRolesQuery,
|
|
useRoleStatusMutation,
|
|
} from './hooks/useRoleQueries';
|
|
|
|
export default function RolesPage() {
|
|
const organizationId = useAppStore((state) => state.user?.organization_id ?? null);
|
|
const [isSheetOpen, setIsSheetOpen] = useState(false);
|
|
const {
|
|
skip,
|
|
setSkip,
|
|
limit,
|
|
searchTerm,
|
|
debouncedSearchTerm,
|
|
setSearchTerm,
|
|
statusFilter,
|
|
setStatusFilter,
|
|
} = useRoleFilters();
|
|
|
|
const rolesQuery = useRolesQuery({
|
|
skip,
|
|
limit,
|
|
searchTerm: debouncedSearchTerm,
|
|
statusFilter,
|
|
});
|
|
const permissionsQuery = usePermissionsTreeQuery();
|
|
const roleForm = useRoleForm({
|
|
organizationId,
|
|
permissionTree: permissionsQuery.permissionTree,
|
|
onSaved: () => setIsSheetOpen(false),
|
|
});
|
|
const {
|
|
openCreate: prepareCreateRole,
|
|
openEdit: prepareEditRole,
|
|
register,
|
|
onSubmit,
|
|
roleId,
|
|
permissionIds,
|
|
setPermissionIds,
|
|
isSaving,
|
|
} = roleForm;
|
|
const statusMutation = useRoleStatusMutation();
|
|
const { mutate: updateRoleStatus, isPending: isStatusPending } = statusMutation;
|
|
|
|
const openCreate = useCallback(() => {
|
|
prepareCreateRole();
|
|
setIsSheetOpen(true);
|
|
}, [prepareCreateRole]);
|
|
|
|
const openEdit = useCallback(
|
|
(role: Role) => {
|
|
prepareEditRole(role);
|
|
setIsSheetOpen(true);
|
|
},
|
|
[prepareEditRole],
|
|
);
|
|
|
|
const toggleStatus = useCallback(
|
|
(role: Role) => {
|
|
updateRoleStatus(role);
|
|
},
|
|
[updateRoleStatus],
|
|
);
|
|
|
|
const columns = useRoleColumns({
|
|
onEdit: openEdit,
|
|
onToggleStatus: toggleStatus,
|
|
isStatusPending,
|
|
});
|
|
|
|
const total = rolesQuery.data?.total ?? 0;
|
|
const roles = rolesQuery.data?.items ?? [];
|
|
const toolbar = (
|
|
<RoleFilters
|
|
searchTerm={searchTerm}
|
|
statusFilter={statusFilter}
|
|
onSearchChange={setSearchTerm}
|
|
onStatusChange={setStatusFilter}
|
|
/>
|
|
);
|
|
|
|
return (
|
|
<>
|
|
<main className="relative z-10 space-y-5">
|
|
<PageHeader
|
|
title="Role Management"
|
|
description="Manage roles and permission access"
|
|
icon={ShieldCheck}
|
|
actions={
|
|
<Button onClick={openCreate}>
|
|
<Plus className="mr-2 size-4" />
|
|
Add Role
|
|
</Button>
|
|
}
|
|
/>
|
|
|
|
<RoleTable
|
|
columns={columns}
|
|
roles={roles}
|
|
isLoading={rolesQuery.isLoading}
|
|
toolbar={toolbar}
|
|
skip={skip}
|
|
limit={limit}
|
|
total={total}
|
|
onPageChange={setSkip}
|
|
/>
|
|
|
|
<PoweredBy />
|
|
</main>
|
|
|
|
<RoleSheet
|
|
open={isSheetOpen}
|
|
onOpenChange={setIsSheetOpen}
|
|
roleId={roleId}
|
|
register={register}
|
|
onSubmit={onSubmit}
|
|
permissionTree={permissionsQuery.permissionTree}
|
|
permissionIds={permissionIds}
|
|
onPermissionIdsChange={setPermissionIds}
|
|
isPermissionsLoading={permissionsQuery.isLoading}
|
|
isSaving={isSaving}
|
|
/>
|
|
</>
|
|
);
|
|
}
|