import { useCallback, useEffect, useState } from "react"; import { toast } from "react-toastify"; import { admin } from "../api/client"; import type { AdminUser, AuditLog, Agent, GlobalSettings } from "../api/types"; import { useAuth } from "../context/AuthContext"; import { Button, Card, PageHeader, Spinner, Toggle } from "../components/ui"; import { relativeTime } from "../utils"; type Tab = "users" | "agents" | "settings" | "audit"; export function AdminPage() { const [tab, setTab] = useState("users"); const tabs: { id: Tab; label: string }[] = [ { id: "users", label: "Users" }, { id: "agents", label: "Agents" }, { id: "settings", label: "Global settings" }, { id: "audit", label: "Audit logs" }, ]; return (
{tabs.map((t) => ( ))}
{tab === "users" && } {tab === "agents" && } {tab === "settings" && } {tab === "audit" && }
); } function UsersTab() { const { user: me } = useAuth(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const load = useCallback(async () => { try { setUsers(await admin.users()); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); const setRole = async (u: AdminUser, role: "ADMIN" | "USER") => { try { await admin.updateUser(u.id, { role }); toast.success("Role updated"); load(); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; const toggleDisabled = async (u: AdminUser) => { try { await admin.updateUser(u.id, { disabled: !u.disabled }); load(); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; const remove = async (u: AdminUser) => { if (!confirm(`Delete user "${u.username}" and all their data?`)) return; try { await admin.deleteUser(u.id); toast.success("User deleted"); load(); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; if (loading) return ; return (
{users.map((u) => (
{u.display_name} @{u.username} {u.role === "ADMIN" && ( ADMIN )} {u.disabled && ( DISABLED )}

{u.agent_count} agents · {u.request_count} requests · joined {relativeTime(u.created_at)}

{u.id !== me?.id && (
)}
))}
); } function AgentsTab() { const [agents, setAgents] = useState<(Agent & { owner: { id: number; username: string } })[]>([]); const [loading, setLoading] = useState(true); const load = useCallback(async () => { try { setAgents(await admin.agents()); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); const toggle = async (a: Agent) => { try { await admin.setAgentDisabled(a.id, !a.disabled); load(); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; const remove = async (a: Agent) => { if (!confirm(`Delete agent "${a.name}"?`)) return; try { await admin.deleteAgent(a.id); toast.success("Agent deleted"); load(); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; if (loading) return ; return (
{agents.map((a) => (
{a.name} by @{a.owner.username} {a.disabled && ( DISABLED )}
{a.description &&

{a.description}

}
))}
); } function SettingsTab() { const [settings, setSettings] = useState(null); useEffect(() => { admin.settings().then(setSettings).catch(() => {}); }, []); const update = async (patch: Partial) => { try { const res = await admin.updateSettings(patch); setSettings(res); toast.success("Settings updated"); } catch (e) { toast.error(e instanceof Error ? e.message : "Failed"); } }; if (!settings) return ; return (

Enable registration

Allow new humans to create accounts.

update({ registration_enabled: v })} />

Enable requests

Allow agents to submit new change requests platform-wide.

update({ requests_enabled: v })} />
); } function AuditTab() { const [logs, setLogs] = useState([]); const [page, setPage] = useState(1); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); admin .auditLogs(page) .then((d) => { setLogs(d.logs); setTotal(d.total); }) .finally(() => setLoading(false)); }, [page]); const totalPages = Math.max(1, Math.ceil(total / 30)); if (loading) return ; return (
{logs.map((l) => ( {l.action} {l.actor ? `@${l.actor.username}` : "system"} {l.target_type && ` → ${l.target_type}:${l.target_id}`} {l.detail && ` · ${l.detail}`} {relativeTime(l.created_at)} ))}
{totalPages > 1 && (
Page {page} of {totalPages}
)}
); } function Loader() { return (
); }