/* global React */ const { useState: useStateT } = React; // ---------------- KPI Card ---------------- function KpiCard({ icon, label, num, sub, tone, gauge }) { const I = window.Icons; return (
{React.createElement(I[icon], { size: 16 })}
{label}
{num}
{gauge != null && }
{sub &&
{sub}
}
); } // Small SVG arc for % gauges function KpiArc({ value, tone }) { const r = 22, c = 2 * Math.PI * r; const offset = c * (1 - value / 100); const color = tone === 'ok' ? 'var(--sem-success)' : tone === 'warn' ? 'var(--sem-warning-bg)' : tone === 'danger' ? 'var(--sem-danger)' : 'var(--cgr-primary)'; return ( ); } // ---------------- Mecanismo Stacked Bar ---------------- function MecanismoStacked({ items }) { return (
{items.map(m => { const okPct = (m.ok / m.total) * 100; const prPct = (m.partial / m.total) * 100; const bdPct = (m.bad / m.total) * 100; return (
{m.label} {m.total}
{m.ok} {m.partial} {m.bad}
); })}
); } // ---------------- Horizontal Inst Bar Chart ---------------- function InstBars({ items, max }) { return (
{items.slice(0, 6).map(it => { const w = (it.total / max) * 100; const tone = it.cumpl >= 75 ? 'is-ok' : it.cumpl >= 55 ? 'is-warn' : 'is-danger'; return (
{it.inst}
{it.total}
{it.cumpl}%
); })}
); } // ---------------- Sparkline (evolution) ---------------- function Sparkline({ data, w = 320, h = 100 }) { if (!data.length) return null; const pad = 4; const min = Math.min(...data.map(d => d.v)) - 4; const max = Math.max(...data.map(d => d.v)) + 4; const step = (w - pad * 2) / (data.length - 1); const pts = data.map((d, i) => { const x = pad + i * step; const y = h - pad - ((d.v - min) / (max - min)) * (h - pad * 2); return [x, y]; }); const pathD = pts.map((p, i) => (i === 0 ? 'M' : 'L') + p[0].toFixed(1) + ' ' + p[1].toFixed(1)).join(' '); const areaD = pathD + ` L${pts[pts.length - 1][0]} ${h - pad} L${pts[0][0]} ${h - pad} Z`; const last = pts[pts.length - 1]; return ( ); } // ---------------- Filter chip / select ---------------- function FilterSelect({ icon, label, value }) { const I = window.Icons; return ( ); } // ---------------- Status pill mapping ---------------- function StatusPill({ estado }) { const I = window.Icons; const map = { ok: { cls: 'is-ok', icon: 'CheckCircle2', label: 'Cumplido' }, partial: { cls: 'is-warn', icon: 'AlertCircle', label: 'Parcial' }, bad: { cls: 'is-danger', icon: 'XCircle', label: 'No cumplido' }, overdue: { cls: 'is-dark', icon: 'AlertTriangle',label: 'Vencido s/avance' }, }; const s = map[estado] || map.partial; return ( {React.createElement(I[s.icon], { size: 11 })} {s.label} ); } // ---------------- TABLERO SCREEN ---------------- function TableroScreen({ onOpenDetalle }) { const I = window.Icons; const [filter, setFilter] = useStateT('todos'); const compromisos = window.COMPROMISOS; const maxInst = Math.max(...window.INST_RANKING.map(i => i.total)); return (
{/* Page header */}
CGR · Dirección de Análisis de Datos

Tablero de Control

Estado consolidado del cumplimiento país en los tres mecanismos — MESICIC, UNCAC y OCDE — actualizado al 21 de mayo de 2026.

{/* Filters */}
{/* KPI bento */}
{/* Charts row */}

Distribución por mecanismo

3 mecanismos activos

Top 6 instituciones con más compromisos

Evolución del cumplimiento

17 meses
62%
↑ 21 pts vs. ene 2025
{/* Tabla principal */}

Compromisos · vista detallada

Mostrando {compromisos.length} de 527 · ordenados por proximidad de vencimiento
{compromisos.map(c => ( onOpenDetalle && onOpenDetalle(c.id)}> ))}
ID Recomendación Mecanismo Institución responsable Vence Estado
{c.id} {c.text} {c.mecanismo} {c.ronda} {c.inst} {c.vence}
{c.d < 0 ? `D+${Math.abs(c.d)} (vencido)` : c.d === 0 ? 'Hoy' : `D-${c.d}`}
Página 1 de 44 · 12 por página
); } Object.assign(window, { TableroScreen, StatusPill });