import { DashboardLayout } from '@/frontend/components/DashboardLayout' import { StatsCard } from '@/frontend/components/StatsCard' import { ActionIcon, Avatar, Badge, Button, Card, Container, Divider, Group, List, Modal, Pagination, Paper, PasswordInput, Select, SimpleGrid, Stack, Table, Tabs, Text, TextInput, ThemeIcon, Title, } from '@mantine/core' import { useDisclosure } from '@mantine/hooks' import { notifications } from '@mantine/notifications' import { createFileRoute } from '@tanstack/react-router' import { useEffect, useState } from 'react' import { TbAccessPoint, TbCircleCheck, TbCircleX, TbPencil, TbPlus, TbSearch, TbShieldCheck, TbTrash, TbUserCheck } from 'react-icons/tb' import useSWR from 'swr' import { API_URLS } from '../config/api' import { useSession } from '../hooks/useAuth' export const Route = createFileRoute('/users')({ component: UsersPage, }) const fetcher = (url: string) => fetch(url).then((res) => res.json()) const getRoleColor = (role: string) => { const r = (role || '').toLowerCase() if (r.includes('super')) return 'red' if (r.includes('admin')) return 'brand-blue' if (r.includes('developer')) return 'violet' return 'gray' } const roles = [ { name: 'DEVELOPER', color: 'red', permissions: ['Full Access', 'Error Feedback', 'Error Management', 'App Version Management', 'User Management'] }, { name: 'ADMIN', color: 'orange', permissions: ['View All Apps', 'View Logs', 'Report Errors'] }, ] function UsersPage() { const [search, setSearch] = useState('') const [debouncedSearch, setDebouncedSearch] = useState('') const [page, setPage] = useState(1) const { data: session } = useSession() const isDeveloper = session?.user?.role === 'DEVELOPER' useEffect(() => { const timer = setTimeout(() => setDebouncedSearch(search), 300) return () => clearTimeout(timer) }, [search]) const { data: stats, mutate: mutateStats } = useSWR(API_URLS.getOperatorStats(), fetcher) const { data: response, isLoading, mutate: mutateOperators } = useSWR( API_URLS.getOperators(page, debouncedSearch), fetcher ) const operators = response?.data || [] // ── Create User Modal ── const [createOpened, { open: openCreate, close: closeCreate }] = useDisclosure(false) const [isCreating, setIsCreating] = useState(false) const [createForm, setCreateForm] = useState({ name: '', email: '', password: '', role: 'USER', }) const handleCreateUser = async () => { if (!createForm.name || !createForm.email || !createForm.password) { notifications.show({ title: 'Validation Error', message: 'Please fill in all required fields.', color: 'red' }) return } setIsCreating(true) try { const res = await fetch(API_URLS.createOperator(), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(createForm), }) if (res.ok) { notifications.show({ title: 'Success', message: 'User has been created.', color: 'teal', icon: }) mutateOperators() mutateStats() closeCreate() setCreateForm({ name: '', email: '', password: '', role: 'USER' }) } else { const err = await res.json() throw new Error(err.error || 'Failed to create user') } } catch (e: any) { notifications.show({ title: 'Error', message: e.message || 'Something went wrong.', color: 'red', icon: }) } finally { setIsCreating(false) } } // ── Edit User Modal ── const [editOpened, { open: openEdit, close: closeEdit }] = useDisclosure(false) const [isEditing, setIsEditing] = useState(false) const [editingUserId, setEditingUserId] = useState(null) const [editForm, setEditForm] = useState({ name: '', email: '', role: '', }) const handleOpenEdit = (user: any) => { setEditingUserId(user.id) setEditForm({ name: user.name, email: user.email, role: user.role }) openEdit() } const handleEditUser = async () => { if (!editingUserId || !editForm.name || !editForm.email) return setIsEditing(true) try { const res = await fetch(API_URLS.editOperator(editingUserId), { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(editForm), }) if (res.ok) { notifications.show({ title: 'Success', message: 'User has been updated.', color: 'teal', icon: }) mutateOperators() closeEdit() } else { throw new Error('Failed to update user') } } catch (e) { notifications.show({ title: 'Error', message: 'Something went wrong.', color: 'red', icon: }) } finally { setIsEditing(false) } } // ── Delete User ── const [deleteOpened, { open: openDelete, close: closeDelete }] = useDisclosure(false) const [isDeleting, setIsDeleting] = useState(false) const [deletingUser, setDeletingUser] = useState(null) const handleOpenDelete = (user: any) => { setDeletingUser(user) openDelete() } const handleDeleteUser = async () => { if (!deletingUser) return setIsDeleting(true) try { const res = await fetch(API_URLS.deleteOperator(deletingUser.id), { method: 'DELETE', }) if (res.ok) { notifications.show({ title: 'Success', message: 'User has been deleted.', color: 'teal', icon: }) mutateOperators() mutateStats() closeDelete() } else { const err = await res.json() throw new Error(err.error || 'Failed to delete user') } } catch (e: any) { notifications.show({ title: 'Error', message: e.message || 'Something went wrong.', color: 'red', icon: }) } finally { setIsDeleting(false) } } return ( Users Manage system users, security roles, and application access control. }>User Management }>Role Management } radius="md" w={350} variant="filled" value={search} onChange={(e) => { setSearch(e.currentTarget.value) setPage(1) }} /> {isDeveloper && ( )} Name & Contact Role Joined Date Actions {isLoading ? ( Loading user data... ) : operators.length === 0 ? ( No users found. ) : ( operators.map((user: any) => ( {user.name.charAt(0)} {user.name} {user.email} {user.role} {new Date(user.createdAt).toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' })} handleOpenEdit(user)}> handleOpenDelete(user)}> )) )}
{response?.totalPages > 1 && ( )}
{roles.map((role) => ( {role.name.replace('_', ' ')} Core role for secure app management. Key Permissions } > {role.permissions.map((p) => ( {p} ))} ))}
{/* Create User Modal */} Add New User} radius="xl" overlayProps={{ backgroundOpacity: 0.55, blur: 3 }} > setCreateForm({ ...createForm, name: e.target.value })} /> setCreateForm({ ...createForm, email: e.target.value })} /> setCreateForm({ ...createForm, password: e.target.value })} /> setEditForm({ ...editForm, role: val || 'USER' })} /> {/* Delete Confirmation Modal */} Delete User} radius="xl" size="sm" overlayProps={{ backgroundOpacity: 0.55, blur: 3 }} > Are you sure you want to delete {deletingUser?.name}? This action cannot be undone.
) }