'use client'; import { useEffect, useState, useCallback } from 'react'; import { AdminRoleGuard } from '@/components/admin-role-guard'; import { api } from '@/lib/api'; import { cn } from '@/lib/cn'; // ── Types ────────────────────────────────────────────────────────────────────── interface UserDto { id: string; name: string; email: string; role: string; banned: boolean; banReason: string | null; createdAt: string; updatedAt: string; } interface UserListDto { users: UserDto[]; total: number; } interface ServiceStatusDto { status: 'ok' | 'error'; latencyMs?: number; error?: string; } interface ProviderStatusDto { id: string; name: string; available: boolean; modelCount: number; } interface HealthStatusDto { status: 'ok' | 'degraded' | 'error'; database: ServiceStatusDto; cache: ServiceStatusDto; agentPool: { activeSessions: number }; providers: ProviderStatusDto[]; checkedAt: string; } // ── Admin Page ───────────────────────────────────────────────────────────────── export default function AdminPage(): React.ReactElement { return ( ); } function AdminContent(): React.ReactElement { const [activeTab, setActiveTab] = useState<'users' | 'health'>('users'); return (

Admin Panel

{(['users', 'health'] as const).map((tab) => ( ))}
{activeTab === 'users' ? : }
); } // ── Users Tab ────────────────────────────────────────────────────────────────── function UsersTab(): React.ReactElement { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showCreate, setShowCreate] = useState(false); const loadUsers = useCallback(async () => { setLoading(true); setError(null); try { const data = await api('/api/admin/users'); setUsers(data.users); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load users'); } finally { setLoading(false); } }, []); useEffect(() => { void loadUsers(); }, [loadUsers]); async function handleRoleToggle(user: UserDto): Promise { const newRole = user.role === 'admin' ? 'member' : 'admin'; try { await api(`/api/admin/users/${user.id}/role`, { method: 'PATCH', body: { role: newRole }, }); await loadUsers(); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to update role'); } } async function handleBanToggle(user: UserDto): Promise { const endpoint = user.banned ? 'unban' : 'ban'; try { await api(`/api/admin/users/${user.id}/${endpoint}`, { method: 'POST' }); await loadUsers(); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to update ban status'); } } async function handleDelete(user: UserDto): Promise { if (!confirm(`Delete user ${user.email}? This cannot be undone.`)) return; try { await api(`/api/admin/users/${user.id}`, { method: 'DELETE' }); await loadUsers(); } catch (err) { alert(err instanceof Error ? err.message : 'Failed to delete user'); } } if (loading) { return

Loading users...

; } if (error) { return (

{error}

); } return (

{users.length} user(s)

{showCreate && ( setShowCreate(false)} onCreated={() => { setShowCreate(false); void loadUsers(); }} /> )} {users.length === 0 ? (

No users found

) : (
{users.map((user) => ( ))}
Name / Email Role Status Created Actions
{user.name}
{user.email}
{user.role} {user.banned ? ( Banned ) : ( Active )} {new Date(user.createdAt).toLocaleDateString()}
)}
); } // ── Create User Form ────────────────────────────────────────────────────────── interface CreateUserFormProps { onCancel: () => void; onCreated: () => void; } function CreateUserForm({ onCancel, onCreated }: CreateUserFormProps): React.ReactElement { const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [role, setRole] = useState('member'); const [submitting, setSubmitting] = useState(false); const [error, setError] = useState(null); async function handleSubmit(e: React.FormEvent): Promise { e.preventDefault(); setSubmitting(true); setError(null); try { await api('/api/admin/users', { method: 'POST', body: { name, email, password, role }, }); onCreated(); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to create user'); } finally { setSubmitting(false); } } return (

Create New User

void handleSubmit(e)} className="space-y-3"> {error &&

{error}

}
setName(e.target.value)} className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500" />
setEmail(e.target.value)} className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500" />
setPassword(e.target.value)} className="w-full rounded-md border border-surface-border bg-surface-elevated px-3 py-1.5 text-sm text-text-primary focus:outline-none focus:ring-1 focus:ring-blue-500" />
); } // ── Health Tab ──────────────────────────────────────────────────────────────── function HealthTab(): React.ReactElement { const [health, setHealth] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const loadHealth = useCallback(async () => { setLoading(true); setError(null); try { const data = await api('/api/admin/health'); setHealth(data); } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load health'); } finally { setLoading(false); } }, []); useEffect(() => { void loadHealth(); }, [loadHealth]); if (loading) { return

Loading health status...

; } if (error) { return (

{error}

); } if (!health) return <>; return (
Last checked: {new Date(health.checkedAt).toLocaleTimeString()}
{/* Database */} {health.database.latencyMs !== undefined && (

Latency: {health.database.latencyMs}ms

)} {health.database.error &&

{health.database.error}

}
{/* Cache */} {health.cache.latencyMs !== undefined && (

Latency: {health.cache.latencyMs}ms

)} {health.cache.error &&

{health.cache.error}

}
{/* Agent Pool */}

Active sessions: {health.agentPool.activeSessions}

{/* Providers */} p.available) ? 'ok' : 'error'} > {health.providers.length === 0 ? (

No providers configured

) : (
    {health.providers.map((p) => (
  • {p.name} {p.available ? `${p.modelCount} models` : 'unavailable'}
  • ))}
)}
); } // ── Helper Components ───────────────────────────────────────────────────────── function StatusBadge({ status }: { status: 'ok' | 'degraded' | 'error' }): React.ReactElement { const map = { ok: 'bg-green-500/20 text-green-400', degraded: 'bg-yellow-500/20 text-yellow-400', error: 'bg-red-500/20 text-red-400', }; return ( {status} ); } interface HealthCardProps { title: string; status: 'ok' | 'error'; children?: React.ReactNode; } function HealthCard({ title, status, children }: HealthCardProps): React.ReactElement { return (

{title}

{children}
); }