'use client'; import { useEffect, useState } from 'react'; import { apiFetch } from '@/lib/api'; import { Input } from '@/components/input'; import { Button } from '@/components/ui/button'; import { ShieldCheck, Trash2 } from 'lucide-react'; interface AdminUser { id: string; email: string; name: string | null; isAdmin: boolean; emailVerified: boolean; lastLoginAt: string | null; createdAt: string; org: { orgId: string; orgName: string; orgSlug: string; plan: string; role: string } | null; serverCount: number; } export default function AdminUsersPage() { const [users, setUsers] = useState(null); const [search, setSearch] = useState(''); async function reload() { const r = await apiFetch<{ users: AdminUser[] }>( `/v1/admin/users${search ? `?search=${encodeURIComponent(search)}` : ''}`, ); setUsers(r.users); } useEffect(() => { reload(); }, [search]); async function toggleAdmin(u: AdminUser) { if (!confirm(`${u.isAdmin ? 'Revoke' : 'Grant'} admin for ${u.email}?`)) return; await apiFetch(`/v1/admin/users/${u.id}`, { method: 'PATCH', body: JSON.stringify({ isAdmin: !u.isAdmin }), }); reload(); } async function remove(u: AdminUser) { if (!confirm(`Delete user ${u.email}? This cascades to their org and servers.`)) return; try { await apiFetch(`/v1/admin/users/${u.id}`, { method: 'DELETE' }); reload(); } catch (e) { const detail = (e as { detail?: { error?: string } }).detail; alert(`Failed: ${detail?.error ?? (e as Error).message}`); } } return (

Users

{users?.length ?? 0} total. Click admin toggle to elevate or revoke privileges.

setSearch(e.target.value)} placeholder="Search by email or name…" className="w-80" />
{users === null && (

Loading…

)} {users && users.length === 0 && (

No matches.

)} {users && users.length > 0 && ( {users.map((u) => ( ))}
Email Org Plan Servers Last login Joined Actions
{u.isAdmin && ( admin )} {u.email}
{u.name && (
{u.name}
)}
{u.org?.orgName ?? '—'} {u.org?.plan ?? '—'} {u.serverCount} {u.lastLoginAt ? new Date(u.lastLoginAt).toLocaleString() : '—'} {new Date(u.createdAt).toLocaleDateString()}
)}
); }