import { useState, useEffect, useCallback } from 'react' import { Plus, Pencil, UserX, Shield, User as UserIcon } from 'lucide-react' import { admin, type AdminUser } from '../../services/api' export function UserManagement() { const [users, setUsers] = useState([]) const [loading, setLoading] = useState(true) const [showCreate, setShowCreate] = useState(false) const [editingUser, setEditingUser] = useState(null) const [error, setError] = useState(null) const fetchUsers = useCallback(async () => { try { const data = await admin.listUsers() setUsers(data.users) } catch { setError('Failed to load users.') } finally { setLoading(false) } }, []) useEffect(() => { fetchUsers() }, [fetchUsers]) if (loading) { return
Loading users…
} return (

Users

{error && (
{error}
)} {users.map((u) => ( ))}
Username Role Photos Status Actions
{u.role === 'admin' ? ( ) : ( )} {u.username}
{u.role} {u.photo_count.toLocaleString()} {u.is_active ? 'Active' : 'Inactive'}
{u.is_active && ( )}
{showCreate && ( setShowCreate(false)} onCreated={() => { setShowCreate(false) fetchUsers() }} /> )} {editingUser && ( setEditingUser(null)} onSaved={() => { setEditingUser(null) fetchUsers() }} /> )}
) } // ── Create User Modal ────────────────────────────────────────────────── function CreateUserModal({ onClose, onCreated, }: { onClose: () => void onCreated: () => void }) { const [username, setUsername] = useState('') const [password, setPassword] = useState('') const [role, setRole] = useState<'user' | 'admin'>('user') const [error, setError] = useState(null) const [loading, setLoading] = useState(false) const handleSubmit = async () => { setError(null) setLoading(true) try { await admin.createUser({ username: username.trim(), password, role }) onCreated() } catch (err: any) { setError(err.response?.data?.detail ?? 'Failed to create user.') } finally { setLoading(false) } } return ( {error && (
{error}
)}
setUsername(e.target.value)} className="w-full rounded border border-border bg-bg px-2 py-1 text-xs text-text outline-none focus:border-accent" autoFocus /> setPassword(e.target.value)} className="w-full rounded border border-border bg-bg px-2 py-1 text-xs text-text outline-none focus:border-accent" />
) } // ── Edit User Modal ──────────────────────────────────────────────────── function EditUserModal({ user, onClose, onSaved, }: { user: AdminUser onClose: () => void onSaved: () => void }) { const [role, setRole] = useState(user.role) const [newPassword, setNewPassword] = useState('') const [error, setError] = useState(null) const [loading, setLoading] = useState(false) const handleSubmit = async () => { setError(null) setLoading(true) try { const data: { role?: string; new_password?: string } = {} if (role !== user.role) data.role = role if (newPassword) data.new_password = newPassword if (Object.keys(data).length > 0) { await admin.updateUser(user.id, data) } onSaved() } catch (err: any) { setError(err.response?.data?.detail ?? 'Failed to update user.') } finally { setLoading(false) } } return ( {error && (
{error}
)}
setNewPassword(e.target.value)} className="w-full rounded border border-border bg-bg px-2 py-1 text-xs text-text outline-none focus:border-accent" placeholder="Unchanged" />
) } // ── Shared helpers ───────────────────────────────────────────────────── function ModalOverlay({ onClose: _onClose, title, children, }: { onClose: () => void title: string children: React.ReactNode }) { return (
e.stopPropagation()}>

{title}

{children}
) } function Field({ label, children }: { label: string; children: React.ReactNode }) { return (
{children}
) }