import React, { useEffect, useState, useCallback } from 'react' import { Plus, Search, RefreshCw, UserX, UserCheck, Trash2 } from 'lucide-react' import { api } from '../api/client' interface Reseller { id: number; username: string; email: string; company: string | null; status: string; _count?: { accounts: number } } export default function Resellers() { const [items, setItems] = useState([]) const [search, setSearch] = useState('') const [loading, setLoading] = useState(false) const [showModal, setShowModal] = useState(false) const [saving, setSaving] = useState(false) const [error, setError] = useState('') const [form, setForm] = useState({ username: '', password: '', email: '', company: '', maxAccounts: 10, diskLimitMb: 51200, bandwidthLimitMb: 512000 }) const fetch = useCallback(async () => { setLoading(true) try { const params = search ? `?search=${encodeURIComponent(search)}` : '' const r = await api.get(`/nixserver/resellers${params}`) setItems(r.data.data.items ?? r.data.data) } finally { setLoading(false) } }, [search]) useEffect(() => { fetch() }, [fetch]) const save = async (e: React.FormEvent) => { e.preventDefault(); setSaving(true); setError('') try { await api.post('/nixserver/resellers', form); setShowModal(false); fetch() } catch (err: unknown) { setError((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } finally { setSaving(false) } } const act = async (id: number, action: 'suspend' | 'unsuspend' | 'delete') => { if (action === 'delete' && !confirm('Delete this reseller?')) return try { if (action === 'suspend') await api.post(`/nixserver/resellers/${id}/suspend`) else if (action === 'unsuspend') await api.post(`/nixserver/resellers/${id}/unsuspend`) else await api.delete(`/nixserver/resellers/${id}`) fetch() } catch (err: unknown) { alert((err as { response?: { data?: { error?: string } } })?.response?.data?.error ?? 'Failed') } } return (

Resellers

{items.length} resellers

setSearch(e.target.value)} placeholder="Search resellers..." className="w-full bg-[#1a1d27] border border-[#2a2d3e] text-white text-sm rounded-lg pl-9 pr-3 py-2 focus:outline-none focus:border-indigo-500" />
{['Username', 'Email', 'Company', 'Accounts', 'Status', ''].map(h => )} {items.map(r => ( ))} {!loading && items.length === 0 && }
{h}
{r.username} {r.email} {r.company ?? '—'} {r._count?.accounts ?? 0} {r.status}
{r.status === 'active' ? : }
No resellers
{showModal && (

New Reseller

{error &&
{error}
} {[['Username', 'username', 'text'], ['Password', 'password', 'password'], ['Email', 'email', 'email'], ['Company', 'company', 'text']].map(([label, key, type]) => (
setForm(f => ({ ...f, [key]: e.target.value }))} className="w-full bg-[#0f1117] border border-[#2a2d3e] text-white text-sm rounded px-3 py-2 focus:outline-none focus:border-indigo-500" />
))}
)}
) }