// Painel Administrativo Ezza CRM // Acesso: /?admin=1 — a chave é validada NO SERVIDOR (nunca exposta no JS) // Gerencia clientes, usuários e configurações const { useState: useAdmState, useEffect: useAdmEffect } = React; function AdminPanel() { const [authed, setAuthed] = useAdmState(false); const [keyInput, setKeyInput] = useAdmState(''); const [adminKey, setAdminKey] = useAdmState(''); // chave validada, mantida só em memória const [tab, setTab] = useAdmState('clientes'); const [clientes, setClientes] = useAdmState([]); const [loading, setLoading] = useAdmState(false); const [msg, setMsg] = useAdmState(''); // Form novo cliente const [novoNome, setNovoNome] = useAdmState(''); const [novoSlug, setNovoSlug] = useAdmState(''); const [novoCor, setNovoCor] = useAdmState('#6C63FF'); const [novoWaPhoneId, setNovoWaPhoneId] = useAdmState(''); const [novoWaToken, setNovoWaToken] = useAdmState(''); // Form novo usuário const [uNome, setUNome] = useAdmState(''); const [uEmail, setUEmail] = useAdmState(''); const [uSenha, setUSenha] = useAdmState(''); const [uSlug, setUSlug] = useAdmState(''); const [uPapel, setUPapel] = useAdmState('admin'); const toast = (t) => { setMsg(t); setTimeout(() => setMsg(''), 3500); }; const carregar = async (key) => { setLoading(true); try { const r = await fetch('/api/admin/clientes-lista', { headers: { 'x-admin-key': key || adminKey } }); const d = await r.json(); if (d.ok) setClientes(d.clientes); } catch (e) {} setLoading(false); }; useAdmEffect(() => { if (authed) carregar(); }, [authed]); // Login: valida a chave NO SERVIDOR (tenta listar clientes com ela) const entrarAdmin = async (e) => { e.preventDefault(); if (!keyInput.trim()) return; setLoading(true); try { const r = await fetch('/api/admin/clientes-lista', { headers: { 'x-admin-key': keyInput.trim() } }); if (r.ok) { setAdminKey(keyInput.trim()); setAuthed(true); } else { toast('❌ Chave incorreta'); } } catch (err) { toast('❌ Erro de conexão'); } setLoading(false); }; const criarCliente = async (e) => { e.preventDefault(); setLoading(true); try { const r = await fetch('/api/admin/clientes', { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-admin-key': adminKey }, body: JSON.stringify({ nome: novoNome, slug: novoSlug, corPrimaria: novoCor, whatsappPhoneId: novoWaPhoneId || null, whatsappToken: novoWaToken || null, }), }); const d = await r.json(); if (d.ok) { toast(`✅ Cliente "${novoNome}" criado!`); setNovoNome(''); setNovoSlug(''); setNovoWaPhoneId(''); setNovoWaToken(''); carregar(); } else { toast(`❌ ${d.error}`); } } catch (e) { toast('❌ Erro de conexão'); } setLoading(false); }; const criarUsuario = async (e) => { e.preventDefault(); setLoading(true); try { const r = await fetch('/auth/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ nome: uNome, email: uEmail, senha: uSenha, clienteSlug: uSlug, papel: uPapel }), }); const d = await r.json(); if (d.ok) { toast(`✅ Usuário "${uNome}" criado para ${uSlug}!`); setUNome(''); setUEmail(''); setUSenha(''); setUSlug(''); } else { toast(`❌ ${d.error}`); } } catch (e) { toast('❌ Erro de conexão'); } setLoading(false); }; const atualizarWa = async (clienteId, token, phoneId) => { const r = await fetch('/api/admin/clientes/whatsapp', { method: 'PUT', headers: { 'Content-Type': 'application/json', 'x-admin-key': adminKey }, body: JSON.stringify({ clienteId, whatsappToken: token, whatsappPhoneId: phoneId }), }); const d = await r.json(); toast(d.ok ? '✅ WhatsApp atualizado!' : `❌ ${d.error}`); if (d.ok) carregar(); }; if (!authed) { return (
Ezza Admin
Painel interno
setKeyInput(e.target.value)} style={{ width: '100%', marginBottom: 16, fontSize: 14 }} autoFocus />
{msg &&
{msg}
}
); } return (
{/* Header */}
Ezza Admin
{['clientes', 'usuarios', 'whatsapp'].map(t => ( ))}
{clientes.length} cliente{clientes.length !== 1 ? 's' : ''} cadastrado{clientes.length !== 1 ? 's' : ''}
{msg && (
{msg}
)}
{/* ── ABA CLIENTES ── */} {tab === 'clientes' && <>
Novo cliente
setNovoNome(e.target.value)} placeholder="Bio Pro Mais" required />
ezzacrm.com.br/ setNovoSlug(e.target.value.toLowerCase().replace(/[^a-z0-9-]/g, ''))} placeholder="biopromais" required style={{ paddingLeft: 120 }} />
setNovoCor(e.target.value)} style={{ width: 40, height: 36, borderRadius: 8, border: '1px solid oklch(0.88 0.01 255)', cursor: 'pointer', padding: 2 }} /> setNovoCor(e.target.value)} style={{ flex: 1 }} />
setNovoWaPhoneId(e.target.value)} placeholder="1112814668..." />
setNovoWaToken(e.target.value)} placeholder="EAAiuAS..." />
Clientes cadastrados
{loading &&
Carregando…
} {clientes.map(c => (
{c.nome[0]}
{c.nome}
{c.slug}.ezzacrm.com.br
{c.whatsapp_phone_id ? WhatsApp ✓ : Sem WhatsApp} ID {c.id}
))} {!loading && clientes.length === 0 &&
Nenhum cliente cadastrado ainda.
}
} {/* ── ABA USUÁRIOS ── */} {tab === 'usuarios' && <>
Novo usuário
setUNome(e.target.value)} placeholder="João Silva" required />
setUEmail(e.target.value)} placeholder="joao@empresa.com.br" required />
setUSenha(e.target.value)} placeholder="mínimo 6 caracteres" required minLength={6} />
Clientes disponíveis
{clientes.map(c => (
{c.nome} slug: {c.slug}
))}
} {/* ── ABA WHATSAPP ── */} {tab === 'whatsapp' && (
{clientes.map(c => ( ))} {clientes.length === 0 &&

Nenhum cliente cadastrado.

}
)}
); } function ClienteWaCard({ cliente, onSave, toast }) { const [token, setToken] = useAdmState(cliente.whatsapp_token || ''); const [phoneId, setPhoneId] = useAdmState(cliente.whatsapp_phone_id || ''); const [saving, setSaving] = useAdmState(false); const save = async () => { setSaving(true); await onSave(cliente.id, token, phoneId); setSaving(false); }; return (
{cliente.nome[0]}
{cliente.nome}
{cliente.slug}
{cliente.whatsapp_phone_id ? ✓ Configurado : ⚠ Sem WhatsApp}
setPhoneId(e.target.value)} placeholder="1112814668574225" />
setToken(e.target.value)} placeholder="EAAiuAS..." type="password" />
); } window.AdminPanel = AdminPanel;