/* global React */ // Alertas del sistema — centro de control del administrador. // Bandeja (lista única con filtros + acciones) + Configuración de reglas. const { useState: useStateAl, useMemo: useMemoAl } = React; const SEV_META = { dark: { grupo: 'vencidas', label: 'Vencida' }, danger: { grupo: 'urgentes', label: 'Urgente' }, warn: { grupo: 'proximas', label: 'Recordatorio' }, info: { grupo: 'proximas', label: 'Aviso' }, muted: { grupo: 'sistema', label: 'Sistema' }, }; const SEV_RANK = { dark: 0, danger: 1, warn: 2, info: 3, muted: 4 }; const TIPO_META = { vencimiento: { icon: 'Clock', label: 'Vencimiento' }, sin_avance: { icon: 'AlertTriangle', label: 'Sin avance' }, devolucion: { icon: 'AlertCircle', label: 'Devolución' }, sistema: { icon: 'Settings', label: 'Sistema' }, }; function codeLabel(c) { return c === 'sin' ? '—' : c === 'devol' ? '↩' : c; } function AlertasScreen({ roleId, user, onOpenDetalle }) { const I = window.Icons; const all = window.getAlertas ? (window.getAlertas(roleId) || []) : (window.ALERTAS_ADMIN || []); const org = (user && user.org) || 'Contraloría General de la República'; const esAdmin = roleId !== 'institucion'; const [tab, setTab] = useStateAl('bandeja'); const [readMap, setReadMap] = window.usePersistentState('alertas_read_' + roleId, () => { const m = {}; all.forEach(a => { m[a.id] = a.read; }); return m; }); const [sel, setSel] = useStateAl({}); const [q, setQ] = useStateAl(''); const [sev, setSev] = useStateAl('todas'); const [tipo, setTipo] = useStateAl('todos'); const [inst, setInst] = useStateAl('todas'); const [soloNoLeidas, setSolo] = useStateAl(false); const [orden, setOrden] = useStateAl('urgencia'); const [cfg, setCfg] = window.usePersistentState('alertas_cfg', () => (window.ALERTAS_CONFIG || []).reduce((m, h) => { m[h.code] = h.enabled; return m; }, {})); const [pol, setPol] = window.usePersistentState('alertas_pol', { escala: true, copiaAdmin: true, resumen: true }); const grupoDe = (a) => (SEV_META[a.severity] || SEV_META.info).grupo; const isRead = (a) => !!readMap[a.id]; const counts = useMemoAl(() => { const c = { todas: all.length, noLeidas: 0, vencidas: 0, urgentes: 0, proximas: 0, sistema: 0 }; all.forEach(a => { if (!readMap[a.id]) c.noLeidas++; const g = grupoDe(a); if (c[g] != null) c[g]++; }); return c; }, [all, readMap]); const instituciones = useMemoAl(() => { const s = []; all.forEach(a => { if (a.institucion && s.indexOf(a.institucion) === -1) s.push(a.institucion); }); return s.sort(); }, [all]); const filtered = useMemoAl(() => { let list = all.filter(a => { if (sev !== 'todas' && grupoDe(a) !== sev) return false; if (tipo !== 'todos' && a.tipo !== tipo) return false; if (inst !== 'todas' && a.institucion !== inst) return false; if (soloNoLeidas && readMap[a.id]) return false; if (q.trim()) { const t = (a.recomendacion + ' ' + a.institucion + ' ' + a.compromisoId).toLowerCase(); if (t.indexOf(q.trim().toLowerCase()) === -1) return false; } return true; }); if (orden === 'urgencia') list = [...list].sort((a, b) => (SEV_RANK[a.severity] - SEV_RANK[b.severity])); return list; }, [all, sev, tipo, inst, soloNoLeidas, q, orden, readMap]); const selIds = Object.keys(sel).filter(k => sel[k]); const toggleSel = (id) => setSel(s => ({ ...s, [id]: !s[id] })); const clearSel = () => setSel({}); const selectAllVisible = () => { const s = {}; filtered.forEach(a => { s[a.id] = true; }); setSel(s); }; const toggleRead = (id) => setReadMap(m => ({ ...m, [id]: !m[id] })); const markRead = (ids) => setReadMap(m => { const n = { ...m }; ids.forEach(id => { n[id] = true; }); return n; }); const markAllRead = () => markRead(all.map(a => a.id)); const limpiarFiltros = () => { setQ(''); setSev('todas'); setTipo('todos'); setInst('todas'); setSolo(false); }; return (
Centro de control de las notificaciones automáticas sobre los plazos de carga de avances. Filtra, prioriza y gestiona todas las alertas desde un solo lugar; cada una enlaza al compromiso correspondiente.
Ajusta la búsqueda o limpia los filtros para ver el conjunto completo.
Definí qué avisos dispara el sistema sobre el plazo interno de cada acción y por qué canales.
Reglas globales de qué pasa cuando una alerta no se atiende y cómo se mantiene informado al administrador.