// Painel SUPERADMIN — visível só pra usuários role=SUPERADMIN. // Gerencia tipos de perícia (bancária, veicular, tributária, cartão RMC, etc.) // e versiona prompts/templates/fórmulas. function AdminPanel() { const [types, setTypes] = useState([]); const [loading, setLoading] = useState(true); const [err, setErr] = useState(null); const [selectedTypeId, setSelectedTypeId] = useState(null); const [showNewType, setShowNewType] = useState(false); const reloadTypes = async () => { setLoading(true); setErr(null); try { const res = await window.apiFetch('/admin/pericia-types'); if (!res.ok) throw new Error(`HTTP ${res.status}`); setTypes(await res.json()); } catch (e) { setErr(`Não foi possível carregar tipos de perícia: ${e.message}`); } finally { setLoading(false); } }; useEffect(() => { reloadTypes(); }, []); return (

Painel administrativo

Gerencie tipos de perícia e versione prompts, planilhas e fórmulas da metodologia.

{err && (
{err}
)} {selectedTypeId ? ( { setSelectedTypeId(null); reloadTypes(); }} /> ) : ( )} setShowNewType(false)} onCreated={() => { setShowNewType(false); reloadTypes(); }} />
); } // ─── Lista de tipos ─────────────────────────────────────────────────────────── function PericiaTypesList({ types, loading, onOpen }) { if (loading) { return (
Carregando tipos de perícia…
); } if (!types.length) { return (
Nenhum tipo de perícia cadastrado.
Clique em "Nova perícia" pra criar o primeiro (ex.: bancária, tributária, cartão RMC).
); } return ( <> {/* Mobile: cards stackados */}
{types.map((t) => ( ))}
{/* Desktop: tabela completa */}
{types.map((t) => ( onOpen(t.id)} className="border-b border-ink-100 last:border-0 hover:bg-ink-50 cursor-pointer transition-colors" > ))}
Code Label Versão ativa Status Criada em
{t.code} {t.label} {t.active_version_label ? {t.active_version_label} : (nenhuma ativa)} {t.status} {fmtDate.format(new Date(t.created_at))}
); } // ─── Modal: criar tipo de perícia ───────────────────────────────────────────── function NewPericiaTypeModal({ open, onClose, onCreated }) { const [code, setCode] = useState(''); const [label, setLabel] = useState(''); const [description, setDescription] = useState(''); const [submitting, setSubmitting] = useState(false); const [err, setErr] = useState(null); useEffect(() => { if (open) { setCode(''); setLabel(''); setDescription(''); setErr(null); } }, [open]); const submit = async (e) => { e.preventDefault(); if (!code.match(/^[a-z][a-z0-9_]*$/)) { setErr('Code precisa começar com letra minúscula e usar só letras, números e _'); return; } if (!label.trim()) { setErr('Informe um label.'); return; } setSubmitting(true); setErr(null); try { const res = await window.apiFetch('/admin/pericia-types', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code: code.trim(), label: label.trim(), description: description.trim() || null }), }); if (!res.ok) { const body = await res.json().catch(() => ({})); throw new Error(body.detail || `HTTP ${res.status}`); } onCreated(); } catch (e2) { setErr(e2.message); } finally { setSubmitting(false); } }; return (
setCode(e.target.value.toLowerCase())} placeholder="ex.: cartao_rmc" className="font-mono" autoFocus /> setLabel(e.target.value)} placeholder="ex.: Revisional de Cartão RMC (Reserva de Margem Consignável)" />