/* JRN — Portal: Home de empresas + Visualizador de dashboard */
/* Card de empresa com dashboards revelados por hover OU clique */
function CompanyCard({ company, dashboards, mode, active, onActivate, onDeactivate, onOpen }) {
const accessible = dashboards.length;
const hoverMode = mode === 'hover';
const handlers = hoverMode
? { onMouseEnter: onActivate, onMouseLeave: onDeactivate }
: { onClick: () => (active ? onDeactivate() : onActivate()) };
return (
{accessible} {accessible === 1 ? 'painel' : 'painéis'}
{company.nome}
{company.tipo}
{!hoverMode && (
{active ? 'Ocultar painéis' : 'Ver painéis'}
)}
{/* Lista de dashboards */}
Painéis liberados
{dashboards.length === 0 && (
Nenhum painel liberado para você nesta empresa.
)}
{dashboards.map(d => (
))}
);
}
function PortalHome({ user, empresas, mode, onOpen }) {
const [activeId, setActiveId] = useState(null);
const totalPaineis = (empresas || []).reduce((s, c) => s + (c.dashboards || []).length, 0);
return (
{(empresas || []).map(c => (
setActiveId(c.id)}
onDeactivate={() => setActiveId(id => (id === c.id ? null : id))}
onOpen={onOpen}
/>
))}
{(!empresas || empresas.length === 0) && (
)}
);
}
/* ---- Conteúdo ilustrativo do relatório, varia por categoria ---- */
function reportContent(dash) {
const meses = ['Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun'];
const presets = {
Financeiro: {
kpis: [['Receita (mês)', 'R$ 8,4 mi', '+6,2%', true], ['Margem EBITDA', '23,8%', '+1,4 p.p.', true], ['Custo operacional', 'R$ 5,1 mi', '+2,1%', false], ['Resultado líquido', 'R$ 1,9 mi', '+9,0%', true]],
bars: meses.map((l, i) => ({ l, v: 5 + Math.sin(i) + i * 0.6 })),
line: [62, 65, 61, 70, 73, 78], donut: 76, donutL: 'Meta de margem',
},
Comercial: {
kpis: [['Vendas (mês)', 'R$ 12,6 mi', '+11,4%', true], ['Ticket médio', 'R$ 84,2 mil', '+3,1%', true], ['Conversão', '28,5%', '-1,2 p.p.', false], ['Pipeline', 'R$ 41 mi', '+7,8%', true]],
bars: meses.map((l, i) => ({ l, v: 8 + (i % 3) + i * 0.8 })),
line: [40, 52, 48, 61, 66, 72], donut: 84, donutL: 'Atingimento da meta',
},
Operacional: {
kpis: [['Produção', '14,2 mil t', '+4,6%', true], ['OEE', '81,3%', '+2,0 p.p.', true], ['Refugo', '2,1%', '-0,4 p.p.', true], ['Prazo médio', '6,2 dias', '+0,3 d', false]],
bars: meses.map((l, i) => ({ l, v: 10 + Math.cos(i) * 2 + i * 0.5 })),
line: [70, 74, 72, 78, 80, 81], donut: 81, donutL: 'Eficiência (OEE)',
},
'RH & Pessoas': {
kpis: [['Headcount', '1.284', '+12', true], ['Turnover', '1,8%', '-0,3 p.p.', true], ['Absenteísmo', '2,4%', '+0,2 p.p.', false], ['eNPS', '+47', '+5', true]],
bars: meses.map((l, i) => ({ l, v: 1200 + i * 18 })),
line: [38, 41, 40, 44, 46, 47], donut: 92, donutL: 'Posições preenchidas',
},
Diretoria: {
kpis: [['Receita consolidada', 'R$ 58,1 mi', '+8,3%', true], ['EBITDA grupo', 'R$ 14,2 mi', '+5,1%', true], ['Empresas no verde', '5 de 7', '+1', true], ['Caixa', 'R$ 31 mi', '+4,4%', true]],
bars: meses.map((l, i) => ({ l, v: 40 + i * 3 + (i % 2) * 4 })),
line: [44, 48, 51, 53, 55, 58], donut: 71, donutL: 'Metas do grupo',
},
};
return presets[dash.categoria] || presets.Financeiro;
}
function DashboardViewer({ dashboard, user, empresas, onBack }) {
// Tenta encontrar nos dados da sessão; cai de volta no estático
const company = (empresas || []).find(c => c.id === dashboard.companyId)
|| COMPANIES.find(c => c.id === dashboard.companyId)
|| { cor: '#15233f', corSoft: '#eef1f6', nome: dashboard.companyId, logo: '', tipo: '' };
const accent = company.cor;
const [loading, setLoading] = useState(true);
const c = reportContent(dashboard);
useEffect(() => {
setLoading(true);
const t = setTimeout(() => setLoading(false), 850);
return () => clearTimeout(t);
}, [dashboard.id]);
return (
{company.nome} · {dashboard.categoria}
{dashboard.nome}
{ setLoading(true); setTimeout(() => setLoading(false), 700); }}>Atualizar
Abrir no Power BI
app.powerbi.com · relatório embarcado (iframe)
{dashboard.atualizacao && (
Dados de {dashboard.atualizacao.split('-').reverse().join('/')}
)}
{loading ? (
Carregando relatório do Power BI…
) : (
{c.kpis.map((k, i) => (
))}
| Unidade | Realizado | Meta | Variação | Status |
{['Sede', 'Filial Norte', 'Filial Sul', 'Operação Leste'].map((u, i) => (
| {u} |
R$ {(2.1 + i * 0.7).toFixed(1)} mi |
R$ {(2.4 + i * 0.6).toFixed(1)} mi |
{i % 2 ? '+' : '−'}{(3 + i).toFixed(1)}% |
|
))}
)}
Conteúdo ilustrativo. Em produção, esta área embarca o relatório real do Power BI via iframe seguro, respeitando as permissões do usuário.
);
}
Object.assign(window, { PortalHome, DashboardViewer });