/* Santos OS — Inicio (Dashboard): branch selector + clickable KPI bubbles */ const LABEL_TO_METRIC = { 'Ventas hoy':'ventas', 'Ticket promedio':'ticket', 'Captura cliente':'captura', 'Miembros activos':'miembros', 'Uptime POS':'uptime', 'Stockouts críticos':'stockouts', 'Despachos hoy':'despachos', 'Órdenes procesadas':'ordenes', 'SKUs en tránsito':'transito', 'Cadena de frío':'frio', 'Uptime WMS':'uptime', 'Lotes por vencer':'lotes', }; function KpiCard({ label, value, sub, trend, trendLabel, accent, warning, onClick }) { const T = window.T; const tc = trend==='up'?T.success:trend==='down'?T.danger:T.fg3; const ta = trend==='up'?'▲':trend==='down'?'▼':'—'; const [hover, setHover] = React.useState(false); return (
setHover(true)} onMouseLeave={()=>setHover(false)} style={{flex:1, minWidth:'45%', background:T.surface, borderRadius:16, padding:16, cursor:onClick?'pointer':'default', position:'relative', boxShadow:hover&&onClick?'0 6px 18px rgba(8,54,47,0.14)':'0 2px 8px rgba(8,54,47,0.07)', border:warning?`1.5px solid ${T.warning}`:'1px solid transparent', transform:hover&&onClick?'translateY(-1px)':'none', transition:'all .14s'}}>
{label}
{onClick && }
{value}
{sub &&
{sub}
} {trendLabel &&
{ta}{trendLabel}
}
); } function Dashboard({ user, perms, onNav, onToast }) { const T = window.T; const { Card, SectionLabel, Btn } = window; const [branch, setBranch] = React.useState('grupo'); const data = window.BRANCH_DATA[branch]; const isCedi = branch==='cedi'; return (
onNav('logout')} />
{/* Branch selector — separates CEDI / pharmacies, with Grupo aggregate */} {perms.kpis && (
{window.BRANCHES.map(b=>{ const on = branch===b.key; return ; })}
)} {/* Branch banner */} {perms.kpis && data.banner && (
onNav(data.banner.go)} style={{display:'flex', alignItems:'center', gap:12, background:data.banner.kind==='warn'?T.warningLight:T.infoLight, borderRadius:14, padding:14, marginBottom:10, border:`1px solid ${data.banner.kind==='warn'?T.warning:T.info}`, cursor:'pointer'}}> {data.banner.icon}
{data.banner.title}
{data.banner.sub}
)} {/* AI approvals (retail only) */} {perms.approveOrders && !isCedi && (
onNav('alertas')} style={{display:'flex', alignItems:'center', gap:12, background:T.infoLight, borderRadius:14, padding:14, marginBottom:16, border:`1px solid ${T.info}`, cursor:'pointer'}}> AI
2 pedidos esperan tu aprobación
Generados esta mañana · Confianza 87%
)} {!perms.kpis &&
Usa las pestañas para consultar inventario, registrar canjes y buscar clientes.
} {/* Data-driven KPI sections — each bubble deep-links to its chart */} {perms.kpis && data.sections.map(sec=>( {sec.label}
{sec.cards.map(c=>{ const metric = LABEL_TO_METRIC[c.label]; return onNav('analitica', metric):undefined} />; })}
))} Acciones rápidas
{[ ...(perms.approveOrders?[{icon:'◉', label:'Aprobar pedidos', go:'alertas', color:T.info}]:[]), {icon:'★', label:'Buscar cliente', go:'clientes', color:T.secondary}, {icon:'▢', label:'Ver inventario', go:'almacen', color:T.primary}, {icon:'↗', label:'Analítica', go:'analitica', color:T.success}, ].map(a=>( ))}
{perms.kpis && !isCedi &&
RESUMEN DEL TURNO
{[['L. 47,850','Ventas'],['12','Miembros nuevos'],['7','Canjes entregados'],['2','Aprob. pendientes']].map(([v,l])=>(
{v}
{l}
))}
onToast('✆ Resumen enviado por WhatsApp')}>✆ WhatsApp onToast('L Corte de caja registrado · cuadrado')}>L Corte de caja
}
Claude AI
{data.ai}
); } window.Dashboard = Dashboard;