// Users management page (US-030) import { useState, useEffect, useCallback } from 'react' import apiClient from '@/api/client' import Button from '@/components/Button' import Input from '@/components/Input' import type { User } from '@/types' import { formatDateTime } from '@/utils/format' interface UserFormData { email: string name: string password: string } function UserModal({ user, onClose, onSave, }: { user: User | null onClose: () => void onSave: () => void }) { const [formData, setFormData] = useState({ email: user?.email || '', name: user?.name || '', password: '', }) const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() setIsLoading(true) setError(null) try { if (user) { // Update user - only send non-empty password const updateData: Partial = { name: formData.name, } if (formData.password) { updateData.password = formData.password } await apiClient.patch(`/users/${user.id}`, updateData) } else { // Create user await apiClient.post('/users', formData) } onSave() } catch (err) { setError(err instanceof Error ? err.message : 'Failed to save user') } finally { setIsLoading(false) } } return (

{user ? 'Edit User' : 'Create User'}

{error && (
{error}
)} setFormData({ ...formData, email: e.target.value })} placeholder="user@example.com" required disabled={!!user} autoFocus={!user} /> setFormData({ ...formData, name: e.target.value })} placeholder="Full name" autoFocus={!!user} /> setFormData({ ...formData, password: e.target.value })} placeholder={user ? 'Leave empty to keep current password' : 'Enter password'} required={!user} />
) } function DeleteConfirmModal({ user, onClose, onConfirm, }: { user: User onClose: () => void onConfirm: () => void }) { const [isLoading, setIsLoading] = useState(false) const [error, setError] = useState(null) const handleDelete = async () => { setIsLoading(true) setError(null) try { await apiClient.delete(`/users/${user.id}`) onConfirm() } catch (err) { setError(err instanceof Error ? err.message : 'Failed to delete user') setIsLoading(false) } } return (

Delete User

Are you sure you want to delete {user.name || user.email}? This action cannot be undone.

{error && (
{error}
)}
) } function Users() { const [users, setUsers] = useState([]) const [filteredUsers, setFilteredUsers] = useState([]) const [isLoading, setIsLoading] = useState(true) const [error, setError] = useState(null) const [searchQuery, setSearchQuery] = useState('') const [showCreateModal, setShowCreateModal] = useState(false) const [editingUser, setEditingUser] = useState(null) const [deletingUser, setDeletingUser] = useState(null) const fetchUsers = useCallback(async () => { setIsLoading(true) setError(null) try { // Always fetch all users - this is a system-level user management page const response = await apiClient.get<{ users?: User[] }>('/users') setUsers(response.users || []) } catch (err) { setError(err instanceof Error ? err.message : 'Failed to fetch users') } finally { setIsLoading(false) } }, []) useEffect(() => { fetchUsers() }, [fetchUsers]) useEffect(() => { const query = searchQuery.toLowerCase() setFilteredUsers( users.filter( (u) => u.email.toLowerCase().includes(query) || (u.name && u.name.toLowerCase().includes(query)) || u.id.toLowerCase().includes(query) ) ) }, [users, searchQuery]) const handleSave = () => { setShowCreateModal(false) setEditingUser(null) fetchUsers() } const handleDelete = () => { setDeletingUser(null) fetchUsers() } return (

Users

Manage all users in the system

{/* Search */}
setSearchQuery(e.target.value)} />
{/* Error state */} {error &&
{error}
} {/* Loading state */} {isLoading && (
)} {/* User list */} {!isLoading && !error && (
{filteredUsers.length === 0 ? (

{searchQuery ? 'No users match your search' : 'No users found'}

) : ( {filteredUsers.map((user) => ( ))}
User ID Created Updated Actions
{user.name?.[0]?.toUpperCase() || user.email[0].toUpperCase()}
{user.name || 'No name'}
{user.email}
{user.id.slice(0, 8)}...
{formatDateTime(user.created_at)}
{user.created_by_name && (
by {user.created_by_name}
)}
{formatDateTime(user.updated_at)}
{user.updated_by_name && (
by {user.updated_by_name}
)}
)}
)} {/* Modals */} {showCreateModal && ( setShowCreateModal(false)} onSave={handleSave} /> )} {editingUser && ( setEditingUser(null)} onSave={handleSave} /> )} {deletingUser && ( setDeletingUser(null)} onConfirm={handleDelete} /> )}
) } export default Users