/* global React */ // Mensajería interna — versión ligera (HU.3.3) // Canal simple de comunicación CGR ↔ Institución, sin adjuntos. const { useState: useStateMs, useMemo: useMemoMs } = React; function MensajeriaScreen({ roleId, user, onOpenDetalle }) { const I = window.Icons; const [conversaciones, setConversaciones] = window.usePersistentState( 'mensajeria_' + roleId, () => (window.getConversaciones(roleId) || []).map(c => JSON.parse(JSON.stringify(c))) ); const [tab, setTab] = useStateMs('inbox'); const [q, setQ] = useStateMs(''); const [activeId, setActiveId] = useStateMs(conversaciones[0]?.id || null); const [composing, setComposing] = useStateMs(false); const ahoraTxt = () => { const d = new Date(), p = n => (n < 10 ? '0' : '') + n; return 'Hoy · ' + p(d.getHours()) + ':' + p(d.getMinutes()); }; const autorOut = (roleId === 'institucion') ? ((user && user.name) || 'Institución') + ' (' + ((user && user.initials) || 'IN') + ')' : 'C. Benítez (CGR)'; const replyTo = (convId, text) => { if (!text || !text.trim()) return; setConversaciones(list => list.map(c => c.id === convId ? { ...c, unread: 0, preview: text.trim(), mensajes: [...(c.mensajes || []), { from: 'out', author: autorOut, date: ahoraTxt(), text: text.trim(), attachments: [] }] } : c)); }; const sendNew = ({ to, subject, text }) => { if (!text || !text.trim()) return; const id = 'conv-' + Date.now().toString(36); const nueva = { id, folder: 'sent', unread: 0, with: { name: to || 'Destinatario', sub: '', initials: (to || 'D').slice(0, 2).toUpperCase(), tone: 'inst' }, subject: subject || '(sin asunto)', preview: text.trim(), compromisoId: '', compromisoText: '', mensajes: [{ from: 'out', author: autorOut, date: ahoraTxt(), text: text.trim(), attachments: [] }], }; setConversaciones(list => [nueva, ...list]); setActiveId(id); setComposing(false); setTab('sent'); }; const filtered = useMemoMs(() => { let list = conversaciones; if (tab === 'inbox') list = list.filter(c => c.folder === 'inbox'); if (tab === 'unread') list = list.filter(c => c.unread > 0); if (tab === 'sent') list = list.filter(c => c.folder === 'sent'); if (q) { list = list.filter(c => `${c.with.name} ${c.subject} ${c.preview} ${c.compromisoText || ''}` .toLowerCase().includes(q.toLowerCase()) ); } return list; }, [conversaciones, tab, q]); const active = conversaciones.find(c => c.id === activeId) || filtered[0]; const counts = useMemoMs(() => { const c = { inbox: 0, sent: 0, unread: 0 }; conversaciones.forEach(x => { c[x.folder] = (c[x.folder] || 0) + 1; c.unread += x.unread; }); return c; }, [conversaciones]); return (
{user.org}

Mensajería

Bandeja interna para enviar y recibir requerimientos, recordatorios y consultas con {roleId === 'institucion' ? ' la CGR' : ' las instituciones reportantes'} sin salir del sistema. Cada mensaje puede vincularse a una recomendación específica, queda registrado con fecha, autor y estado de lectura, y conserva la cadena completa de respuestas para trazabilidad y auditoría. Reemplaza el uso de correo electrónico para temas operativos del seguimiento.

{/* Tabs simples */}
setQ(e.target.value)} />
{/* 2-pane mailbox */}
{/* List */}
    {filtered.map(c => (
  • 0 ? ' is-unread' : ''}`} onClick={() => { setActiveId(c.id); setComposing(false); }} >
    {c.with.initials}
    {c.with.name} {c.lastDate}
    {c.subject}
    {c.compromisoId && (
    {c.compromisoId}
    )}
    {c.preview}
    {c.unread > 0 &&
    {c.unread}
    }
  • ))} {filtered.length === 0 && (
  • Sin conversaciones

    No hay mensajes con esos criterios.

  • )}
{/* Thread */}
{composing ? ( setComposing(false)} roleId={roleId} onSend={sendNew} /> ) : active ? ( ) : (

Selecciona una conversación

El hilo aparecerá aquí.

)}
); } // ---------------- Thread simple ---------------- function SimpleThread({ c, onOpenDetalle, onReply }) { const I = window.Icons; const [draft, setDraft] = useStateMs(''); const enviar = () => { if (draft.trim()) { onReply(c.id, draft); setDraft(''); } }; return ( <>
{c.with.initials}

{c.with.name}

{c.with.sub}

{c.subject}

{c.compromisoId && ( )}
{c.mensajes.map((m, i) => (
{m.from === 'in' &&
{c.with.initials}
}
{m.author} {m.date}

{m.text}

{m.from === 'out' &&
CB
}
))}
); } // ---------------- Composer simple ---------------- function SimpleComposer({ onCancel, roleId, onSend }) { const I = window.Icons; const [to, setTo] = useStateMs(roleId === 'institucion' ? 'CGR · Dirección de Análisis de Datos' : 'Seleccionar institución…'); const [subject, setSubject] = useStateMs(''); const [text, setText] = useStateMs(''); const puede = !!(to && to.indexOf('Seleccionar') === -1 && text.trim()); return ( <>

Nuevo mensaje

Quedará registrado en la bandeja del destinatario
Quedará registro permanente del envío.
); } Object.assign(window, { MensajeriaScreen });