/** * User Management Page * * Manage organization users, roles, and invitations */ 'use client'; import { useState, useEffect } from 'react'; import { useRouter } from 'next/navigation'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { listUsers, updateUser, deleteUser } from '@/lib/api'; import { createInvitation } from '@/lib/api/invitations'; import { useAuth } from '@/lib/context/auth-context'; export default function UsersManagementPage() { const router = useRouter(); const queryClient = useQueryClient(); const { user: currentUser } = useAuth(); const [showInviteModal, setShowInviteModal] = useState(false); const [inviteForm, setInviteForm] = useState({ email: '', firstName: '', lastName: '', role: 'USER' as 'MANAGER' | 'USER' | 'VIEWER', }); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); const { data: users, isLoading } = useQuery({ queryKey: ['users'], queryFn: () => listUsers(), }); const inviteMutation = useMutation({ mutationFn: (data: typeof inviteForm) => { return createInvitation({ email: data.email, firstName: data.firstName, lastName: data.lastName, role: data.role, }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); setSuccess('Invitation sent successfully! The user will receive an email with a registration link.'); setShowInviteModal(false); setInviteForm({ email: '', firstName: '', lastName: '', role: 'USER', }); setTimeout(() => setSuccess(''), 5000); }, onError: (err: any) => { setError(err.response?.data?.message || 'Failed to send invitation'); setTimeout(() => setError(''), 5000); }, }); const changeRoleMutation = useMutation({ mutationFn: ({ id, role }: { id: string; role: 'ADMIN' | 'MANAGER' | 'USER' | 'VIEWER' }) => { return updateUser(id, { role }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); setSuccess('Role updated successfully'); setTimeout(() => setSuccess(''), 3000); }, onError: (err: any) => { setError(err.response?.data?.message || 'Failed to update role'); setTimeout(() => setError(''), 5000); }, }); const toggleActiveMutation = useMutation({ mutationFn: ({ id, isActive }: { id: string; isActive: boolean }) => { return updateUser(id, { isActive: !isActive }); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); setSuccess('User status updated successfully'); setTimeout(() => setSuccess(''), 3000); }, onError: (err: any) => { setError(err.response?.data?.message || 'Failed to update user status'); setTimeout(() => setError(''), 5000); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => deleteUser(id), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); setSuccess('User deleted successfully'); setTimeout(() => setSuccess(''), 3000); }, onError: (err: any) => { setError(err.response?.data?.message || 'Failed to delete user'); setTimeout(() => setError(''), 5000); }, }); // Restrict access to ADMIN and MANAGER only useEffect(() => { if (currentUser && currentUser.role !== 'ADMIN' && currentUser.role !== 'MANAGER') { router.push('/dashboard'); } }, [currentUser, router]); // Don't render until we've checked permissions if (!currentUser || (currentUser.role !== 'ADMIN' && currentUser.role !== 'MANAGER')) { return (
Manage team members and their permissions
| User | Role | Status | Last Login | Actions | |
|---|---|---|---|---|---|
|
{user.firstName[0]}
{user.lastName[0]}
{user.firstName} {user.lastName}
{user.email}
|
{user.email}
|
{new Date(user.createdAt).toLocaleDateString()} |
Get started by inviting a team member