import { useState, SyntheticEvent } from 'react'; import { LoadingState, TextInput } from '../components'; import { Button } from '../components/Button'; import { Table, type Column } from '../components/Table'; import { useGetUsers, useUpdateUser } from '../generated/anthoLumeAPIV1'; import type { User } from '../generated/model'; import { AddIcon, DeleteIcon } from '../icons'; import { useMutationWithToast } from '../hooks/useMutationWithToast'; import { useToasts } from '../components/ToastContext'; import { formatDate } from '../utils/formatters'; import { dataForStatus } from '../utils/apiResponses'; interface AddUserFormProps { onCreate: (_username: string, _password: string, _isAdmin: boolean) => void; } function AddUserForm({ onCreate }: AddUserFormProps) { const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [isAdmin, setIsAdmin] = useState(false); const handleSubmit = (e: SyntheticEvent) => { e.preventDefault(); onCreate(username, password, isAdmin); }; return (
setUsername(e.target.value)} placeholder="Username" className="p-2" /> setPassword(e.target.value)} placeholder="Password" className="p-2" />
setIsAdmin(e.target.checked)} />
); } interface ResetPasswordDialogProps { userId: string; onClose: () => void; onSave: (_userId: string, _password: string) => void; } function ResetPasswordDialog({ userId, onClose, onSave }: ResetPasswordDialogProps) { const [password, setPassword] = useState(''); return (
e.stopPropagation()} onSubmit={e => { e.preventDefault(); if (!password) return; onSave(userId, password); onClose(); }} >

Reset password for {userId}

setPassword(e.target.value)} placeholder="New password" autoFocus />
); } const permissionButtonClass = (active: boolean) => `rounded-md px-2 py-1 ${ active ? 'cursor-default bg-content text-content-inverse' : 'cursor-pointer bg-surface-strong text-content' }`; export default function AdminUsersPage() { const { data: usersData, isLoading, refetch } = useGetUsers({}); const updateUser = useUpdateUser(); const toastMutationOptions = useMutationWithToast(); const { showError } = useToasts(); const [showAddForm, setShowAddForm] = useState(false); const [resetUserId, setResetUserId] = useState(null); const users = dataForStatus(usersData, 200)?.users ?? []; const handleCreateUser = (username: string, password: string, isAdmin: boolean) => { if (!username || !password) { showError('Please enter username and password'); return; } updateUser.mutate( { data: { operation: 'CREATE', user: username, password, is_admin: isAdmin, }, }, toastMutationOptions({ success: 'User created successfully', error: 'Failed to create user', onSuccess: () => { setShowAddForm(false); refetch(); }, }) ); }; const handleDeleteUser = (userId: string) => { updateUser.mutate( { data: { operation: 'DELETE', user: userId }, }, toastMutationOptions({ success: 'User deleted successfully', error: 'Failed to delete user', onSuccess: refetch, }) ); }; const handleUpdatePassword = (userId: string, password: string) => { if (!password) return; updateUser.mutate( { data: { operation: 'UPDATE', user: userId, password }, }, toastMutationOptions({ success: 'Password updated successfully', error: 'Failed to update password', onSuccess: refetch, }) ); }; const handleToggleAdmin = (userId: string, isAdmin: boolean) => { updateUser.mutate( { data: { operation: 'UPDATE', user: userId, is_admin: isAdmin }, }, toastMutationOptions({ success: `User permissions updated to ${isAdmin ? 'admin' : 'user'}`, error: 'Failed to update admin status', onSuccess: refetch, }) ); }; const userColumns: Column[] = [ { id: 'actions', className: 'w-12', header: ( ), render: user => ( ), }, { id: 'user', header: 'User', render: user => user.id }, { id: 'password', header: 'Password', render: user => ( ), }, { id: 'permissions', header: 'Permissions', className: 'text-center', render: user => (
), }, { id: 'created', header: 'Created', className: 'w-48', render: user => formatDate(user.created_at), }, ]; if (isLoading) { return ; } return (
{showAddForm && } {resetUserId && ( setResetUserId(null)} onSave={handleUpdatePassword} /> )} ); }