/* global React */ const { useState: useStateD } = React; const TITULO_DETALLE_DEFAULT = 'Fortalecimiento del régimen de declaración jurada de funcionarios públicos'; const ARCHIVOS_DEFAULT = [ { name: 'reporte_MESICIC_RondaV_PRY.pdf', size: '2.4 MB' }, { name: 'matriz_cobertura_DJBe_2025.xlsx', size: '318 KB' }, ]; const ACCIONES_DEFAULT = [ { descripcion: 'Ampliar la cobertura del sistema de declaración jurada electrónica (DJB-e) al 100% de los funcionarios obligados.', estado: 'partial', instituciones: [ { inst: 'Secretaría Nacional Anticorrupción', rol: 'Líder', plazo: '2026-06-12', responsable: 'u-005' }, { inst: 'Ministerio de Hacienda', rol: 'Apoyo', plazo: '2026-06-30', responsable: null }, ], avances: [ { fecha: '2026-05-10', autor: 'R. Mendoza', inst: 'SENAC', texto: 'Cobertura DJB-e alcanzó el 76% de los obligados; se sumó el módulo de carga masiva.', archivos: [{ name: 'cobertura_djbe_may2026.xlsx', size: '214 KB' }] }, ], }, { descripcion: 'Implementar el módulo de verificación cruzada con la base patrimonial de la SET.', estado: 'pending', instituciones: [ { inst: 'Ministerio de Hacienda', rol: 'Líder', plazo: '2026-09-30', responsable: null }, ], avances: [], }, { descripcion: 'Habilitar el mecanismo de consulta pública con anonimización parcial y protección de datos.', estado: 'pending', instituciones: [ { inst: 'Contraloría General de la República', rol: 'Coordinación', plazo: '2026-08-15', responsable: null }, ], avances: [], }, ]; const RESULTADOS_DEFAULT = '217.000 declaraciones presentadas electrónicamente · 32 verificaciones sustantivas iniciadas · 4 procesos administrativos derivados a Fiscalía.'; const JUSTIF_DEFAULT = 'La Contraloría General de la República implementó en 2025 la plataforma DJB-e con cobertura del 76% de los obligados. Quedan pendientes los módulos de verificación cruzada con la base patrimonial de la SET y el sistema de consulta pública con anonimización parcial — ambos en fase de desarrollo.'; const ALERTAS_DEF = [ { code: 'D-7', label: 'Aviso de proximidad' }, { code: 'D-3', label: 'Recordatorio' }, { code: 'D-1', label: 'Urgencia' }, { code: 'D', label: 'Vencimiento' }, { code: 'D+1', label: 'Sin avance (escalamiento)' }, ]; const MECANISMOS = ['MESICIC', 'UNCAC', 'OCDE']; const TIPOS_INFORME = ['Informe', 'Informe tratado', 'Anexo', 'Evidencia', 'Resolución', 'Acta']; const INFORMES_DEFAULT = [ { name: 'informe_de_avance_DJBe_2026Q1.pdf', tipo: 'Informe tratado', size: '2.1 MB', fecha: '2026-05-12' }, { name: 'matriz_cobertura_institucional.xlsx', tipo: 'Anexo', size: '318 KB', fecha: '2026-05-10' }, { name: 'resolucion_CGR_114-2026.pdf', tipo: 'Resolución', size: '540 KB', fecha: '2026-04-28' }, ]; const ESTADO_OPTS = [ { v: 'pending', l: 'Pendiente' }, { v: 'partial', l: 'Parcial' }, { v: 'ok', l: 'Cumplido' }, { v: 'bad', l: 'No cumplido' }, { v: 'overdue', l: 'Vencido s/avance' }, ]; function DetalleScreen({ onBack, onOpenTablero }) { const I = window.Icons; const d = window.COMP_DETAIL; const [tab, setTab] = useStateD('info'); const buildData = () => ({ id: d.id, idInternacional: d.idInternacional, mecanismo: d.mecanismo, ronda: d.ronda, recibida: d.recibida, vence: d.vence, titulo: d.titulo || TITULO_DETALLE_DEFAULT, estado: d.estado, eje: d.eje, tipo: d.tipo, evaluacion: d.evaluacion, recomendacion: d.recomendacion, archivos: ARCHIVOS_DEFAULT.map(a => ({ ...a })), acciones: ACCIONES_DEFAULT.map(a => ({ ...a })), resultados: RESULTADOS_DEFAULT, justificacion: JUSTIF_DEFAULT, informes: INFORMES_DEFAULT.map(a => ({ ...a })), alertas: { 'D-7': true, 'D-3': true, 'D-1': true, 'D': true, 'D+1': true }, }); const [data, setData] = window.usePersistentState('detalle_' + d.id, buildData); const [heroEdit, setHeroEdit] = useStateD(false); const [confirmDel, setConfirmDel] = useStateD(false); const update = (k, v) => setData(s => ({ ...s, [k]: v })); const removeArchivo = (i) => setData(s => ({ ...s, archivos: s.archivos.filter((_, idx) => idx !== i) })); const setAccion = (i, k, v) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === i ? { ...a, [k]: v } : a) })); const addAccion = () => setData(s => ({ ...s, acciones: [...s.acciones, { descripcion: '', estado: 'pending', instituciones: [{ inst: '', rol: 'Líder', plazo: '', responsable: null }], avances: [] }] })); const removeAccion = (i) => setData(s => ({ ...s, acciones: s.acciones.filter((_, idx) => idx !== i) })); const setAccionInst = (ai, ii, k, v) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, instituciones: a.instituciones.map((r, j) => j === ii ? { ...r, [k]: v } : r) } : a) })); const addAccionInst = (ai) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, instituciones: [...a.instituciones, { inst: '', rol: 'Apoyo', plazo: '', responsable: null }] } : a) })); const removeAccionInst = (ai, ii) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, instituciones: a.instituciones.filter((_, j) => j !== ii) } : a) })); const setAccionInstResponsable = (ai, ii, uid) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, instituciones: a.instituciones.map((r, j) => j === ii ? { ...r, responsable: uid } : r) } : a) })); const addAvanceAccion = (ai, payload) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, avances: [{ fecha: new Date().toISOString().slice(0, 10), autor: payload.autor || 'C. Benítez', inst: payload.inst || '', texto: payload.texto, archivos: payload.archivos || [] }, ...a.avances] } : a) })); const removeAvanceAccion = (ai, k) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, avances: a.avances.filter((_, j) => j !== k) } : a) })); const editAvanceAccion = (ai, k, texto) => setData(s => ({ ...s, acciones: s.acciones.map((a, idx) => idx === ai ? { ...a, avances: a.avances.map((av, j) => j === k ? { ...av, texto } : av) } : a) })); const toggleAlerta = (code) => setData(s => ({ ...s, alertas: { ...s.alertas, [code]: !s.alertas[code] } })); const removeInforme = (i) => setData(s => ({ ...s, informes: s.informes.filter((_, idx) => idx !== i) })); const addInforme = (payload) => setData(s => ({ ...s, informes: [{ fecha: new Date().toISOString().slice(0, 10), tipo: payload.tipo || 'Informe', name: payload.name, size: payload.size || '—' }, ...s.informes] })); const [heroErr, setHeroErr] = useStateD({}); const otrosComp = (window.COMPROMISOS || []).filter(c => c.id !== d.id); const guardarHero = () => { const e = {}; const id = (data.id || '').trim(); const idInt = (data.idInternacional || '').trim(); if (!id) e.id = 'Ingresa el ID interno.'; else if (otrosComp.some(c => (c.id || '').toLowerCase() === id.toLowerCase())) e.id = 'Ese ID interno ya está en uso por otro compromiso.'; if (!idInt) e.idInternacional = 'Ingresa el ID internacional.'; else if (otrosComp.some(c => (c.idInternacional || '').toLowerCase() === idInt.toLowerCase())) e.idInternacional = 'Ese ID internacional ya está en uso por otro compromiso.'; if (!(data.mecanismo || '').trim()) e.mecanismo = 'Indica el mecanismo.'; setHeroErr(e); if (Object.keys(e).length === 0) setHeroEdit(false); }; const abrirHeroEdit = () => { setHeroErr({}); setHeroEdit(true); }; const cancelarHeroEdit = () => { setHeroErr({}); setHeroEdit(false); }; return (
Compromisos {data.mecanismo} · {data.ronda} {data.id}
{/* Hero card */}
{heroEdit ? (
) : ( <>
ID interno{data.id} ID internacional{data.idInternacional} Mecanismo · Ronda {data.mecanismo} {data.ronda}

{data.titulo}

Recibida {data.recibida} Vence {data.vence} {data.acciones.length} acciones
)} {confirmDel && (
¿Eliminar esta recomendación y todo su seguimiento? Esta acción no se puede deshacer.
)}
{/* Tabs */}
{tab === 'info' && } {tab === 'acc' && } {tab === 'av' && } {tab === 'al' && } {tab === 'msg' && } {tab === 'res' && }
); } function Tab({ id, label, icon, active, onSel, badge }) { const I = window.Icons; const Ico = I[icon] || I.FileText; return ( ); } // ---------- Encabezado de sección con acciones (editar / eliminar) ---------- function SectionCard({ label, sub, editing, onEdit, onDone, onDelete, children }) { const I = window.Icons; return (
{label}
{sub &&

{sub}

}
{editing ? ( ) : ( <> {onEdit && } {onDelete && } )}
{children}
); } // ---------- Información (base) ---------- function TabInfo({ data, update, removeArchivo }) { const I = window.Icons; const [eRec, setERec] = useStateD(false); const [eClas, setEClas] = useStateD(false); const [eFiles, setEFiles] = useStateD(false); return ( <> setERec(true)} onDone={() => setERec(false)}> {eRec ?