const { useState } = React;
// ─── Weather Icon ────────────────────────────────────────────────────────────
function WeatherIcon({ icon, size = 22 }) {
const icons = { sun:'☀', partly:'⛅', rain:'🌧', storm:'⛈', cloud:'☁' };
return {icons[icon] || '🌤'} ;
}
// ─── Weather Card ────────────────────────────────────────────────────────────
function WeatherCard({ w, idx }) {
const isAlert = w.rain > 20;
return (
{idx === 0 && (
HOJE+1
)}
{w.day}
{w.max}° {w.min}°
{w.rain > 0 ? `${w.rain}mm` : '—'}
{isAlert &&
⚠ IMPACTO
}
);
}
// ─── Sparkline with trend ────────────────────────────────────────────────────
function SparkWithTrend({ data, w = 72, h = 26 }) {
const rising = data[data.length-1] > data[0];
return ;
}
// ─── Purchase Row ────────────────────────────────────────────────────────────
function PurchaseRow({ r, idx }) {
const recVariant = { danger:'danger', success:'success', primary:'primary', warning:'warning' }[r.recKey] || 'default';
const trendIcon = r.trend === 'up' ? '▲' : r.trend === 'down' ? '▼' : '→';
const trendColor = r.trend === 'up' ? C.danger : r.trend === 'down' ? C.success : C.textSub;
const isUrgent = r.recKey === 'danger';
return (
{r.item}
{r.priceStr}
{r.var7d > 0 ? '+' : ''}{r.var7d.toFixed(1)}%
{r.var30d > 0 ? '+' : ''}{r.var30d.toFixed(1)}%
{trendIcon}
{r.budgetImpact}
= 80 ? C.success : r.confidence >= 65 ? C.warning : C.danger, borderRadius:2 }} />
{r.confidence}%
);
}
// ─── Forecast Scenario Card ──────────────────────────────────────────────────
function ScenarioCard({ label, prob, date, delta, color, pct }) {
return (
{label}
P{prob}
{date}
{delta} dias vs. baseline
Probabilidade: {pct}%
);
}
// ─── Discipline Trend Alert ──────────────────────────────────────────────────
function DisciplineTrendAlert({ name, slope, days7, status }) {
const color = statusColor(status);
return (
{name}
Tendência 7 dias: {slope > 0 ? '+' : ''}{slope}pp/sem
−{days7} dias
impacto crítico
);
}
// ─── Screen 2: Dashboard IA Preditivo ────────────────────────────────────────
function Screen2IA() {
const { weather, purchaseRecs } = window.SIGP_DATA;
const [activeTab, setActiveTab] = useState('compras');
const tabs = [
{ id:'compras', label:'Recomendações de Compra' },
{ id:'clima', label:'Previsão Climática' },
{ id:'forecast', label:'Forecast de Conclusão' },
{ id:'alertas', label:'Alertas por Disciplina' },
];
return (
{/* ── Alert box ── */}
🌧
Alerta Climático — IA detectou impacto nos próximos 14 dias
Qua 27/05 (28mm) e Qui 28/05 (42mm): suspensão provável de concretagens descobertas e armações externas — impacto estimado +2 dias no Caminho Crítico (Fundações Bloco A).
Ter 02/06 (35mm) e Qua 03/06 (55mm): segunda janela crítica — risco de alagamento nas cavas das fundações. Recomendação: adiantar concretagem do pilar C7 para 26/05.
IMPACTO
+2d
Caminho Crítico
{/* ── Tabs ── */}
{tabs.map(t => (
setActiveTab(t.id)} style={{
padding:'7px 14px', fontSize:11.5, fontWeight: activeTab===t.id ? 700 : 500,
background: activeTab===t.id ? C.primary : C.card,
color: activeTab===t.id ? '#fff' : C.textSub,
border:`1px solid ${activeTab===t.id ? C.primary : C.border}`,
borderRadius:5, cursor:'pointer', fontFamily:'inherit',
}}>{t.label}
))}
{/* ── Climate Tab ── */}
{activeTab === 'clima' && (
{weather.map((w, i) => )}
⚠ 4 dias com precipitação >20mm nos próximos 14 dias. Atividades externas afetadas: concretagem, armação, aterro compactado, montagem de estrutura metálica.
)}
{/* ── Purchase Tab ── */}
{activeTab === 'compras' && (
Insumo
Preço Atual
Var 7d
Var 30d
Tendência
Trend
Recomendação IA
Impacto Orçamento
Confiança
{purchaseRecs.map((r, i) => )}
Modelos: ARIMA + LSTM · Dados: B3, CEPEA/ESALQ, ANP, PTAX-BACEN · Atualização: 22/05/2026 18:00
)}
{/* ── Forecast Tab ── */}
{activeTab === 'forecast' && (
{[
{ l:'Variabilidade de prazo', v:'σ = 8,4 semanas' },
{ l:'Variabilidade de custo', v:'σ = R$ 12,3M' },
{ l:'Histórico de atraso', v:'+1,8 sem/mês tendência' },
{ l:'Impacto climático', v:'+2 dias/mês (MS)' },
{ l:'Risco R-001 (câmbio)', v:'15% prob. gatilho' },
{ l:'Risco R-002 (caldeira)', v:'65% prob. atraso' },
].map(({l,v}) => (
))}
)}
{/* ── Alerts Tab ── */}
{activeTab === 'alertas' && (
{[
{ icon:'🔴', action:'Emitir PO caldeira até 30/05', owner:'Ger. Suprimentos', impact:'Evita +22 sem no cronograma' },
{ icon:'🟡', action:'Adicionar turno noturno civil', owner:'Ger. Obras', impact:'Recupera 5 dias em 3 semanas' },
{ icon:'🟡', action:'Antecipar entrega aço CA-50', owner:'Compras', impact:'Reduz risco de interrupção' },
{ icon:'🟠', action:'Contratar topógrafo adicional', owner:'Ger. Civil', impact:'Desbloqueia 3 frentes de trabalho' },
{ icon:'🔵', action:'Fechar hedge EUR/BRL agora', owner:'CFO', impact:'Bloqueia variação de R$ 420k' },
].map(({icon,action,owner,impact}) => (
{icon}
{action}
{owner} · {impact}
))}
)}
);
}
Object.assign(window, { Screen2IA });