From da640680d34956ef3ea10312a8cbb69b5fe31a65 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Wed, 25 Mar 2026 14:06:42 -0500 Subject: [PATCH] feat: accordion por hora, activo/finalizado, notas en detalle e informe domicilio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - enfermero_portal: cards colapsables con toggle en cabecera, ordenadas por hora_programada - enfermero_portal: sección 'Finalizados' colapsada abajo para completado/cancelado - enfermero_portal: acudiente en ficha clínica solo si fecha nacimiento confirma menor de edad - lab_domicilios: notas del enfermero read-only en panel de detalle (cargarNotasDetalle) - lab_domicilios: botón 'Informe' abre modal con datos del paciente + ficha clínica + notas libres --- enfermero_portal.php | 80 +++++++++++++++++---- lab_domicilios.php | 164 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+), 14 deletions(-) diff --git a/enfermero_portal.php b/enfermero_portal.php index 773ff73..03f695f 100644 --- a/enfermero_portal.php +++ b/enfermero_portal.php @@ -166,6 +166,24 @@ $hoy = date('Y-m-d'); border-radius:10px; padding:10px; } .nota-btn-guardar { width:100%; border:none; border-radius:10px; padding:13px; font-weight:800; font-size:.92rem; color:#fff; cursor:pointer; } + + /* ── Acordeón domicilios ── */ + .domcard-header { cursor:pointer; user-select:none; display:flex; align-items:center; + justify-content:space-between; padding:8px 0 6px; + border-bottom:1px solid #f0f2f5; } + .domcard-header .dom-chev { transition:transform .2s; font-size:.68rem; color:#9ca3af; + flex-shrink:0; margin-left:6px; } + .domcard-header .dom-chev.open { transform:rotate(180deg); } + .domcard-body { display:none; padding-top:10px; } + .domcard-body.open { display:block; } + .fin-section-toggle { width:100%; background:#f3f4f6; border:1px solid #e5e7eb; + border-radius:10px; padding:9px 14px; font-size:.8rem; + font-weight:700; color:#6b7280; cursor:pointer; text-align:left; + display:flex; align-items:center; gap:8px; margin-top:6px; } + .fin-section-toggle .fin-chev { margin-left:auto; font-size:.68rem; + transition:transform .2s; } + .fin-section-toggle.open .fin-chev { transform:rotate(180deg); } + #seccion-fin { display:none; } @@ -451,10 +469,29 @@ const portal = { `; return; } - lista.innerHTML = this._agenda.map(item => this._cardHTML(item)).join(''); + const ACTIVOS = ['programado','confirmado','en_camino','en_domicilio']; + const CERRADOS = ['completado','cancelado']; + const sorted = [...this._agenda].sort((a,b) => + (a.hora_programada||'99:99').localeCompare(b.hora_programada||'99:99')); + const activos = sorted.filter(i => ACTIVOS.includes(i.domicilio_estado||'programado')); + const cerrados = sorted.filter(i => CERRADOS.includes(i.domicilio_estado||'')); + + let html = activos.map((item, idx) => this._cardHTML(item, idx === 0)).join(''); + + if (cerrados.length) { + html += ` +
+ ${cerrados.map(item => this._cardHTML(item, false)).join('')} +
`; + } + lista.innerHTML = html; }, - _cardHTML(item) { + _cardHTML(item, expandido = false) { const est = item.domicilio_estado || 'programado'; const info = ESTADOS_LABEL[est] || { label: est, icon:'📌', cls:'bg-secondary' }; const hora = item.hora_programada ? item.hora_programada.slice(0,5) : '—'; @@ -521,15 +558,16 @@ const portal = { : ''; return `
-
-
+
+
${info.icon} ${info.label} - 🕐 ${hora} + 🕐 ${hora} + ${esc(item.paciente_nombre || '—')}
- #${item.domicilio_id} +
- -
+
+
${esc(item.paciente_nombre || '—')}
@@ -642,6 +680,7 @@ const portal = { Ver llenados ` : ''}
+
`; }, @@ -756,6 +795,23 @@ function esc(s) { ({ '<':'<','>':'>','&':'&','"':'"',"'":''' }[c])); } +// ── Acordeón domicilios ──────────────────────────────────────────────────── +function toggleDomCard(headerEl) { + const body = headerEl.nextElementSibling; + const chev = headerEl.querySelector('.dom-chev'); + const open = body.classList.toggle('open'); + if (chev) chev.classList.toggle('open', open); +} + +function toggleFinalizados(btnEl) { + const sec = document.getElementById('seccion-fin'); + const chev = btnEl.querySelector('.fin-chev'); + const open = btnEl.classList.toggle('open'); + if (sec) sec.style.display = open ? '' : 'none'; + if (chev) chev.classList.toggle('open', open); +} +// ────────────────────────────────────────────────────────────────────────── + // Resolver ruta de imagen: evita duplicar "uploads/media/" function resImg(f) { if (!f) return ''; @@ -2109,18 +2165,14 @@ const notasManager = {
- ${!esMenor ? `` : ''} `; if (!esMenor && fc.acudiente_nombre) { - document.getElementById('ns-acudiente-bloque').classList.remove('d-none'); + // paciente no reconocido como menor por fecha de nacimiento + // pero tenía datos del acudiente guardados → se mantienen ocultos } this._abrirSheet(); }, diff --git a/lab_domicilios.php b/lab_domicilios.php index bfe1331..2cc51ce 100644 --- a/lab_domicilios.php +++ b/lab_domicilios.php @@ -140,6 +140,10 @@ $domIdParam = (int)($_GET['id'] ?? 0);
Detalle
+
+ + + + ` : ''} `; + cargarNotasDetalle(id); } function cerrarDetalle() { domSeleccionado = null; + _domActual = null; document.querySelectorAll('.dom-row').forEach(r => r.classList.remove('table-active')); document.getElementById('detail-id').textContent = ''; document.getElementById('btn-editar-dom').classList.add('d-none'); + document.getElementById('btn-informe-dom').classList.add('d-none'); document.getElementById('detail-body').innerHTML = '
Selecciona un domicilio
'; } +// ── Notas del enfermero (read-only en detalle) ──────────────────────────── +async function cargarNotasDetalle(domId) { + try { + const r = await fetch(`api/lab/get_notas_domicilio.php?domicilio_id=${domId}`); + const d = await r.json(); + if (!d.success) return; + const c = d.clinica || {}; + const libres = d.libres || []; + const hayFicha = c.antecedentes || c.medicamentos || c.acudiente_nombre; + const hayLibres = libres.length > 0; + if (!hayFicha && !hayLibres) return; + + let html = `
+
+
+ `; + + if (hayFicha) { + html += `
+
+ Ficha clínica +
`; + if (c.antecedentes) html += `
Antecedentes: ${esc(c.antecedentes)}
`; + if (c.medicamentos) html += `
Medicamentos: ${esc(c.medicamentos)}
`; + if (c.acudiente_nombre) html += `
Acudiente: ${esc(c.acudiente_nombre)}${c.acudiente_documento ? ' · ' + esc(c.acudiente_documento) : ''}
`; + html += `
`; + } + + libres.forEach(n => { + html += `
+
${esc(n.titulo||'Sin título')}
+
${n.cuerpo||''}
+ ${n.imagen_path ? `` : ''} +
${esc(n.created_at||'')}
+
`; + }); + + html += `
`; + document.getElementById('detail-body').insertAdjacentHTML('beforeend', html); + } catch(e) { /* silencioso */ } +} + +// ── Informe del domicilio ───────────────────────────────────────────────── +async function verInformeDom() { + if (!_domActual) return; + const dom = _domActual; + + // Llenar datos básicos del paciente + document.getElementById('inf-nombre').textContent = dom.paciente_nombre || '—'; + document.getElementById('inf-tipodoc').textContent = dom.paciente_tipo_documento || '—'; + document.getElementById('inf-numdoc').textContent = dom.paciente_numero_documento || '—'; + document.getElementById('inf-telefono').textContent= dom.paciente_telefono || '—'; + document.getElementById('inf-correo').textContent = dom.paciente_email || '—'; + document.getElementById('inf-direccion').textContent = (dom.direccion||'') + (dom.barrio ? ', ' + dom.barrio : ''); + document.getElementById('inf-seguro').textContent = dom.tipo_cliente === 'seguro' + ? ('Seguro' + (dom.seguro_nombre ? ' — ' + dom.seguro_nombre : '')) + : 'Particular'; + document.getElementById('inf-examenes').textContent = dom.examenes_solicitados || '—'; + document.getElementById('inf-fecha').textContent = (dom.fecha_programada||'') + ' ' + (dom.hora_programada||''); + + // Limpiar campos clínicos mientras cargamos + ['inf-antecedentes','inf-medicamentos','inf-acudiente','inf-notas-libres'].forEach(id => { + const el = document.getElementById(id); + if (el) el.innerHTML = 'Cargando...'; + }); + + const _modalInforme = bootstrap.Modal.getOrCreateInstance('#modalInformeDom'); + _modalInforme.show(); + + try { + const r = await fetch(`api/lab/get_notas_domicilio.php?domicilio_id=${dom.id}`); + const d = await r.json(); + const c = d.success ? (d.clinica||{}) : {}; + const libres = d.success ? (d.libres||[]) : []; + + document.getElementById('inf-antecedentes').textContent = c.antecedentes || '—'; + document.getElementById('inf-medicamentos').textContent = c.medicamentos || '—'; + + if (c.acudiente_nombre) { + document.getElementById('inf-acudiente').innerHTML = + `${esc(c.acudiente_nombre)} · ${esc(c.acudiente_documento||'')}`; + document.getElementById('inf-fila-acudiente').classList.remove('d-none'); + } else { + document.getElementById('inf-fila-acudiente').classList.add('d-none'); + document.getElementById('inf-acudiente').textContent = ''; + } + + if (libres.length) { + document.getElementById('inf-notas-libres').innerHTML = libres.map(n => + `
+
${esc(n.titulo||'Sin título')}
+
${n.cuerpo||''}
+ ${n.imagen_path ? `` : ''} +
` + ).join(''); + } else { + document.getElementById('inf-notas-libres').textContent = '—'; + } + } catch(e) { + document.getElementById('inf-antecedentes').textContent = '—'; + document.getElementById('inf-medicamentos').textContent = '—'; + document.getElementById('inf-notas-libres').textContent = '—'; + } +} +// ────────────────────────────────────────────────────────────────────────── + // ── Asignación rápida ────────────────────────────────────────────────────── async function mostrarAsignacion(domId) { document.getElementById('asig-dom-id').value = domId;