From 56482bf66ae4e119a246345d0e6a95762bbfdf51 Mon Sep 17 00:00:00 2001 From: Forge Date: Wed, 25 Mar 2026 08:41:51 +0800 Subject: [PATCH] feat: Settings Users page with toggle active --- app/(app)/settings/users/page.tsx | 155 ++++++++++++++++-------------- 1 file changed, 82 insertions(+), 73 deletions(-) diff --git a/app/(app)/settings/users/page.tsx b/app/(app)/settings/users/page.tsx index 3cfe70e..64dc36f 100644 --- a/app/(app)/settings/users/page.tsx +++ b/app/(app)/settings/users/page.tsx @@ -1,105 +1,114 @@ 'use client'; -import { useQuery } from '@tanstack/react-query'; -import { Card, CardContent } from '@/components/ui/card'; -import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { Skeleton } from '@/components/ui/skeleton'; -import { - Table, TableBody, TableCell, TableHead, TableHeader, TableRow, -} from '@/components/ui/table'; -import { UserPlus, Shield, User } from 'lucide-react'; +import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { api } from '@/lib/api'; -import { format } from 'date-fns'; +import { Card, CardContent } from '@/components/ui/card'; +import { Skeleton } from '@/components/ui/skeleton'; +import { Badge } from '@/components/ui/badge'; +import { UserPlus } from 'lucide-react'; -interface UserItem { +interface User { id: string; firstName: string; lastName: string; email: string; isActive: boolean; - createdAt: string; - roleAssignments?: { role: string }[]; + roles: Array<{ role: string }>; } -const ROLE_COLORS: Record = { +const roleColors: Record = { ADMIN: 'bg-purple-100 text-purple-700', STAFF: 'bg-blue-100 text-blue-700', TECHNICIAN: 'bg-orange-100 text-orange-700', - COLLECTOR: 'bg-cyan-100 text-cyan-700', + COLLECTOR: 'bg-green-100 text-green-700', }; export default function UsersSettingsPage() { - const { data, isLoading } = useQuery({ + const qc = useQueryClient(); + + const { data: users, isLoading } = useQuery({ queryKey: ['users'], - queryFn: async () => (await api.get('/api/v1/users')).data, + queryFn: async () => { + const res = await api.get('/api/v1/users'); + return res.data; + }, }); - const users: UserItem[] = Array.isArray(data) ? data : (data?.data ?? []); + const toggleActive = useMutation({ + mutationFn: async ({ id, isActive }: { id: string; isActive: boolean }) => { + await api.patch(`/api/v1/users/${id}`, { isActive: !isActive }); + }, + onSuccess: () => qc.invalidateQueries({ queryKey: ['users'] }), + }); return (
-
+
-

User Management

-

Staff accounts and role assignments

+

Users

+

Manage staff access and roles

- +
- + - - - - Name - Email - Roles - Status - Joined - - - - {isLoading ? ( - Array.from({ length: 5 }).map((_, i) => ( - {Array.from({ length: 5 }).map((_, j) => ( - - ))} - )) - ) : users.length === 0 ? ( - No users found - ) : ( - users.map((u) => { - const roles = u.roleAssignments?.map(r => r.role) ?? []; - return ( - - {u.firstName} {u.lastName} - {u.email} - -
- {roles.length === 0 ? No role : - roles.map(r => ( - {r} - ))} -
-
- - - {u.isActive ? 'Active' : 'Inactive'} - - - - {format(new Date(u.createdAt), 'MMM d, yyyy')} - -
- ); - }) - )} -
-
+ + + + + + + + + + + + {isLoading + ? Array.from({ length: 4 }).map((_, i) => ( + + {[...Array(5)].map((_, j) => ( + + ))} + + )) + : users?.map((u) => { + const role = u.roles?.[0]?.role ?? 'STAFF'; + return ( + + + + + + + + ); + })} + +
NameEmailRoleStatus
+ {u.firstName} {u.lastName} + {u.email} + + {role} + + + + {u.isActive ? 'Active' : 'Inactive'} + + + +