From 893b49c7014765c3f6d395a1f2857ceef8c5787f Mon Sep 17 00:00:00 2001 From: "santasri.pachhal" Date: Tue, 16 Jun 2026 11:16:28 +0530 Subject: [PATCH] refactor(admin): refactor admin roles and users management --- .../roles/components/RoleColumns.tsx | 82 +++ .../roles/components/RoleFilters.tsx | 47 ++ .../(modules)/roles/components/RoleSheet.tsx | 125 ++++ .../(modules)/roles/components/RoleTable.tsx | 47 ++ .../(modules)/roles/hooks/useRoleFilters.ts | 44 ++ src/app/(modules)/roles/hooks/useRoleForm.ts | 120 ++++ .../(modules)/roles/hooks/useRoleQueries.ts | 77 +++ src/app/(modules)/roles/page.tsx | 547 +++--------------- src/app/(modules)/roles/queries/roleKeys.ts | 9 + .../users/components/UserColumns.tsx | 109 ++++ .../users/components/UserFilters.tsx | 47 ++ .../(modules)/users/components/UserSheet.tsx | 142 +++++ .../(modules)/users/components/UserStats.tsx | 28 + .../(modules)/users/components/UserTable.tsx | 47 ++ .../(modules)/users/hooks/useUserFilters.ts | 36 ++ src/app/(modules)/users/hooks/useUserForm.ts | 99 ++++ .../(modules)/users/hooks/useUserMutations.ts | 55 ++ .../(modules)/users/hooks/useUserQueries.ts | 64 ++ src/app/(modules)/users/page.tsx | 465 ++++----------- src/app/(modules)/users/queries/userKeys.ts | 10 + src/components/data-table/TableHeader.tsx | 4 +- src/components/data-table/index.tsx | 2 +- src/components/permission-tree.tsx | 56 ++ src/components/ui/tree.tsx | 161 ++++++ src/hooks/useDebounce.ts | 17 + 25 files changed, 1615 insertions(+), 825 deletions(-) create mode 100644 src/app/(modules)/roles/components/RoleColumns.tsx create mode 100644 src/app/(modules)/roles/components/RoleFilters.tsx create mode 100644 src/app/(modules)/roles/components/RoleSheet.tsx create mode 100644 src/app/(modules)/roles/components/RoleTable.tsx create mode 100644 src/app/(modules)/roles/hooks/useRoleFilters.ts create mode 100644 src/app/(modules)/roles/hooks/useRoleForm.ts create mode 100644 src/app/(modules)/roles/hooks/useRoleQueries.ts create mode 100644 src/app/(modules)/roles/queries/roleKeys.ts create mode 100644 src/app/(modules)/users/components/UserColumns.tsx create mode 100644 src/app/(modules)/users/components/UserFilters.tsx create mode 100644 src/app/(modules)/users/components/UserSheet.tsx create mode 100644 src/app/(modules)/users/components/UserStats.tsx create mode 100644 src/app/(modules)/users/components/UserTable.tsx create mode 100644 src/app/(modules)/users/hooks/useUserFilters.ts create mode 100644 src/app/(modules)/users/hooks/useUserForm.ts create mode 100644 src/app/(modules)/users/hooks/useUserMutations.ts create mode 100644 src/app/(modules)/users/hooks/useUserQueries.ts create mode 100644 src/app/(modules)/users/queries/userKeys.ts create mode 100644 src/components/permission-tree.tsx create mode 100644 src/components/ui/tree.tsx create mode 100644 src/hooks/useDebounce.ts diff --git a/src/app/(modules)/roles/components/RoleColumns.tsx b/src/app/(modules)/roles/components/RoleColumns.tsx new file mode 100644 index 0000000..63b2be2 --- /dev/null +++ b/src/app/(modules)/roles/components/RoleColumns.tsx @@ -0,0 +1,82 @@ +'use client'; + +import { useMemo } from 'react'; +import type { ColumnDef } from '@tanstack/react-table'; +import { Edit, RotateCcw } from 'lucide-react'; + +import { Badge } from '@/components/ui/badge'; +import { Button } from '@/components/ui/button'; +import type { Role } from '@/types'; + +interface UseRoleColumnsParams { + onEdit: (role: Role) => void; + onToggleStatus: (role: Role) => void; + isStatusPending: boolean; +} + +export function useRoleColumns({ + onEdit, + onToggleStatus, + isStatusPending, +}: UseRoleColumnsParams): ColumnDef[] { + return useMemo( + () => [ + { + accessorKey: 'name', + header: 'Name', + cell: ({ row }) => {row.original.name}, + }, + { + accessorKey: 'display_name', + header: 'Display Name', + }, + { + accessorKey: 'description', + header: 'Description', + cell: ({ row }) => ( + + {row.original.description || '-'} + + ), + }, + { + accessorKey: 'user_count', + header: 'Users', + cell: ({ row }) => row.original.user_count ?? 0, + }, + { + accessorKey: 'effective_status', + header: 'Status', + cell: ({ row }) => ( + + {row.original.effective_status ? 'Active' : 'Inactive'} + + ), + }, + { + id: 'actions', + header: () =>
Actions
, + cell: ({ row }) => { + const role = row.original; + return ( +
+ + +
+ ); + }, + }, + ], + [isStatusPending, onEdit, onToggleStatus], + ); +} diff --git a/src/app/(modules)/roles/components/RoleFilters.tsx b/src/app/(modules)/roles/components/RoleFilters.tsx new file mode 100644 index 0000000..d6406b7 --- /dev/null +++ b/src/app/(modules)/roles/components/RoleFilters.tsx @@ -0,0 +1,47 @@ +'use client'; + +import { Input } from '@/components/ui/input'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; + +import type { StatusFilter } from '../hooks/useRoleFilters'; + +interface RoleFiltersProps { + searchTerm: string; + statusFilter: StatusFilter; + onSearchChange: (value: string) => void; + onStatusChange: (value: StatusFilter) => void; +} + +export function RoleFilters({ + searchTerm, + statusFilter, + onSearchChange, + onStatusChange, +}: RoleFiltersProps) { + return ( +
+ onSearchChange(event.target.value)} + placeholder="Search roles" + className="md:max-w-sm" + /> + +
+ ); +} diff --git a/src/app/(modules)/roles/components/RoleSheet.tsx b/src/app/(modules)/roles/components/RoleSheet.tsx new file mode 100644 index 0000000..eba2ceb --- /dev/null +++ b/src/app/(modules)/roles/components/RoleSheet.tsx @@ -0,0 +1,125 @@ +'use client'; + +import type { ComponentProps } from 'react'; +import type { UseFormRegister } from 'react-hook-form'; +import { Loader2 } from 'lucide-react'; + +import { PermissionTree } from '@/components/permission-tree'; +import { Button } from '@/components/ui/button'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { + Sheet, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, +} from '@/components/ui/sheet'; +import type { PermissionTreeItem } from '@/types'; + +import type { RoleFormValues } from '../hooks/useRoleForm'; + +interface RoleSheetProps { + open: boolean; + onOpenChange: (open: boolean) => void; + roleId?: number; + register: UseFormRegister; + onSubmit: ComponentProps<'form'>['onSubmit']; + permissionTree: PermissionTreeItem[]; + permissionIds: number[]; + onPermissionIdsChange: (ids: number[]) => void; + isPermissionsLoading: boolean; + isSaving: boolean; +} + +export function RoleSheet({ + open, + onOpenChange, + roleId, + register, + onSubmit, + permissionTree, + permissionIds, + onPermissionIdsChange, + isPermissionsLoading, + isSaving, +}: RoleSheetProps) { + return ( + + + + {roleId ? 'Edit Role' : 'Create Role'} + + Assign the role details and permission access for this organization. + + +
+
+
+ + +
+
+ + +
+
+ +
+ +