/* Painel Nanda — componentes reutilizáveis. window.App.UI */ (function () { const I = window.App.Icons; const CFG = window.NANDA_CONFIG || {}; const BR = CFG.brand || {}; const initials = (name) => (name || '?').split(/\s+/).filter(Boolean).slice(0, 2).map((s) => s[0]).join('').toUpperCase(); const hueFor = (s) => { let h = 0; for (const c of (s || '')) h = (h * 31 + c.charCodeAt(0)) % 360; return h; }; function Avatar({ name, size = 40, ring }) { const hu = hueFor(name); return (
{initials(name)}
); } function Badge({ children, tone = 'brand', soft = true, className = '' }) { const map = { brand: ['#5aa2ff', 'rgba(46,111,214,.16)', 'rgba(46,111,214,.35)'], ok: ['#57d8a3', 'rgba(38,162,105,.15)', 'rgba(38,162,105,.35)'], warn: ['#e6bd6a', 'rgba(216,161,58,.15)', 'rgba(216,161,58,.35)'], bad: ['#e08a8a', 'rgba(193,91,91,.15)', 'rgba(193,91,91,.35)'], muted: ['#9fb0c3', 'rgba(140,151,168,.12)', 'rgba(140,151,168,.28)'], }; const [fg, bg, bd] = map[tone] || map.brand; return ( {children} ); } function Delta({ v }) { if (v == null || v === 0) return –; const up = v > 0; return {up ? : }{(up ? '+' : '') + v}%; } function Card({ children, className = '', pad = true, style }) { return (
{children}
); } function StatCard({ label, value, delta, icon }) { const Ic = icon; return (
{label}
{value}
); } function Button({ children, kind = 'ghost', size = 'md', className = '', ...p }) { const base = 'inline-flex items-center justify-center gap-2 rounded-lg font-medium transition-colors whitespace-nowrap disabled:opacity-50'; const sz = size === 'sm' ? 'h-8 px-3 text-[12px]' : 'h-9 px-4 text-[13px]'; const kinds = { primary: 'bg-brand hover:bg-brand-hover text-white', ghost: 'border border-line bg-surface hover:bg-elevate text-fg', subtle: 'text-muted hover:text-fg hover:bg-elevate', }; return ; } function Search({ value, onChange, placeholder }) { return (
onChange && onChange(e.target.value)} placeholder={placeholder} className="h-9 w-full rounded-lg border border-line bg-surface pl-9 pr-3 text-[13px] text-fg placeholder:text-faint outline-none focus:border-brand/60" />
); } function Modal({ open, onClose, title, children, width = 420 }) { if (!open) return null; return (
e.stopPropagation()} className="w-full rounded-xl border border-line bg-surface2 p-5 shadow-2xl" style={{ maxWidth: width }}>
{title}
{children}
); } function PageHead({ title, subtitle, right, ro }) { return (

{title}

{ro && Somente leitura}
{subtitle &&

{subtitle}

}
{right &&
{right}
}
); } const NAV = [ ['dashboard', 'Dashboard', 'Dashboard'], ['pipeline', 'Pipeline', 'Pipeline'], ['chat', 'Chat Ao Vivo', 'Chat'], ['training', 'Treinamento', 'Training'], ['contacts', 'Contatos', 'Contacts'], ['scheduling', 'Agendamentos', 'Calendar'], ['team', 'Equipe', 'Team'], ['help', 'Ajuda', 'Help'], ['settings', 'Configurações', 'Settings'], ]; function Sidebar({ route, go, role, user, onLogout, open, onClose, verVendas }) { const isAdmin = (role || 'admin') === 'admin'; let nav = NAV.filter(([key]) => isAdmin || (key !== 'team' && key !== 'settings')); // verVendas=false esconde o menu de vendas mantendo só o Chat. A Nanda só // tem UM fluxo, então isto na prática nunca dispara hoje; mantido como // cinto de segurança caso a RLS um dia negue verVendas (falha aberta seria pior). if (verVendas === false) nav = nav.filter(([key]) => key === 'chat'); const uname = (user && user.email) || BR.usuario || 'Equipe Nanda'; const rlabel = role === 'admin' ? 'Administrador' : role === 'atendente' ? 'Atendente' : (BR.email || ''); return ( <> {/* Fundo escurecido do drawer (só mobile, quando aberto) */}
); } window.App = window.App || {}; window.App.UI = { Avatar, Badge, Delta, Card, StatCard, Button, Search, Modal, PageHead, Sidebar, initials, hueFor }; })();