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. + + +
+
+
+ + +
+
+ + +
+
+ +
+ +