/* global React, ReactDOM, Sidebar, Topbar, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakColor, TweakToggle, TweakSlider, Login, supa */ const { useState, useEffect } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#d4f752", "density": "regular", "theme": "dark", "showTicker": true, "highlightCritical": true, "fontSize": 13 }/*EDITMODE-END*/; function deriveUserInfo(session) { const u = session?.user; if (!u) return null; const email = u.email || ''; const fullName = u.user_metadata?.full_name; const fromEmail = email ? email.split('@')[0].replace(/[._-]/g, ' ').replace(/\b\w/g, c => c.toUpperCase()) : ''; // Prioridade: full_name (se tiver sobrenome) > derivado do email > metadata.name > fallback const displayName = (fullName && fullName.trim().includes(' ')) ? fullName : (fromEmail || u.user_metadata?.name || 'Usuário'); const parts = displayName.split(' ').filter(Boolean); const initials = ((parts[0]?.[0] || '') + (parts.length > 1 ? parts[parts.length - 1]?.[0] || '' : '')).toUpperCase() || 'U'; return { id: u.id, email, displayName, initials, role: u.user_metadata?.role || 'Usuário' }; } function App() { const [active, setActive] = useState('dashboard'); const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const [session, setSession] = useState(null); const [bootstrapping, setBootstrapping] = useState(true); const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const userInfo = deriveUserInfo(session); window.sglUser = userInfo; // Reflete estado do drawer mobile no body (controla CSS) useEffect(() => { document.body.classList.toggle('sidebar-open', mobileMenuOpen); return () => document.body.classList.remove('sidebar-open'); }, [mobileMenuOpen]); // Navegação que também fecha o drawer mobile const navigate = (id) => { setActive(id); setMobileMenuOpen(false); }; useEffect(() => { let mounted = true; window.supa.auth.getSession().then(({ data }) => { if (!mounted) return; setSession(data.session || null); setBootstrapping(false); }).catch(() => { if (!mounted) return; setBootstrapping(false); }); const { data: listener } = window.supa.auth.onAuthStateChange((_event, newSession) => { setSession(newSession || null); }); return () => { mounted = false; listener?.subscription?.unsubscribe?.(); }; }, []); const handleLogin = (data) => { setSession(data.session || null); }; const handleLogout = async () => { try { await window.supa.auth.signOut(); } catch {} setSession(null); setActive('dashboard'); }; // Apply tweaks to CSS variables useEffect(() => { const r = document.documentElement; r.style.setProperty('--lime', t.accent); // derive softer variants r.style.setProperty('--lime-soft', t.accent + '14'); r.style.setProperty('--lime-border', t.accent + '4d'); r.style.setProperty('--row-pad', t.density === 'compact' ? '6px 10px' : t.density === 'comfy' ? '14px 14px' : '10px 12px'); r.style.setProperty('--base-fs', t.fontSize + 'px'); document.body.classList.toggle('theme-light', t.theme === 'light'); document.body.classList.toggle('hide-ticker', !t.showTicker); document.body.classList.toggle('no-crit-highlight', !t.highlightCritical); }, [t]); const renderModule = () => { switch (active) { case 'dashboard': return ; case 'prospeccao': return ; case 'ocr': return ; case 'precificacao': return ; case 'disputa': return ; case 'empenhos': return ; case 'logistica': return ; case 'financeiro': return ; case 'ia': return ; case 'integracoes': return ; case 'portais': return ; case 'pdv': return ; case 'auditoria': return ; case 'config': return ; default: return ; } }; if (bootstrapping) { return (
VERIFICANDO SESSÃO...
); } if (!session) { return ; } return (
setMobileMenuOpen(false)}>
setMobileMenuOpen(v => !v)} />
{renderModule()}
setTweak('theme', v)} /> setTweak('density', v)} /> setTweak('fontSize', v)} /> setTweak('accent', v)} /> setTweak('showTicker', v)} /> setTweak('highlightCritical', v)} />
); } ReactDOM.createRoot(document.getElementById('root')).render();