feat: accordion por hora, activo/finalizado, notas en detalle e informe domicilio
- 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
This commit is contained in:
+66
-14
@@ -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; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -451,10 +469,29 @@ const portal = {
|
||||
</div>`;
|
||||
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 += `<button class="fin-section-toggle" onclick="toggleFinalizados(this)">
|
||||
<i class="fas fa-check-circle text-success"></i>
|
||||
Finalizados (${cerrados.length})
|
||||
<i class="fas fa-chevron-down fin-chev"></i>
|
||||
</button>
|
||||
<div id="seccion-fin">
|
||||
${cerrados.map(item => this._cardHTML(item, false)).join('')}
|
||||
</div>`;
|
||||
}
|
||||
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 `<div class="domcard estado-${est} mb-3 p-3" id="card-${item.domicilio_id}">
|
||||
<div class="d-flex justify-content-between align-items-start mb-2">
|
||||
<div>
|
||||
<div class="domcard-header" onclick="toggleDomCard(this)">
|
||||
<div class="d-flex align-items-center gap-2 flex-wrap" style="max-width:calc(100% - 22px)">
|
||||
<span class="badge ${info.cls} text-white">${info.icon} ${info.label}</span>
|
||||
<span class="ms-1 text-muted small">🕐 ${hora}</span>
|
||||
<span class="text-muted small">🕐 ${hora}</span>
|
||||
<span class="fw-semibold small" style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap">${esc(item.paciente_nombre || '—')}</span>
|
||||
</div>
|
||||
<small class="text-muted">#${item.domicilio_id}</small>
|
||||
<i class="fas fa-chevron-down dom-chev ${expandido ? 'open' : ''}"></i>
|
||||
</div>
|
||||
|
||||
<div class="fw-bold mb-1">
|
||||
<div class="domcard-body ${expandido ? 'open' : ''}">
|
||||
<div class="fw-bold mb-1 mt-2">
|
||||
<i class="fas fa-user me-1 text-primary"></i>${esc(item.paciente_nombre || '—')}
|
||||
</div>
|
||||
<!-- Documento y fecha de nacimiento -->
|
||||
@@ -642,6 +680,7 @@ const portal = {
|
||||
<i class="fas fa-folder-open me-1"></i>Ver llenados
|
||||
</button>` : ''}
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
@@ -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 = {
|
||||
<input type="text" id="ns-acud-doc" class="nota-input"
|
||||
placeholder="Número de documento" value="${esc(fc.acudiente_documento||'')}">
|
||||
</div>
|
||||
${!esMenor ? `<label class="d-flex align-items-center gap-2 small text-muted mb-3" style="cursor:pointer">
|
||||
<input type="checkbox" id="ns-menor-toggle" onchange="notasManager._toggleAcudiente(this.checked)"
|
||||
${fc.acudiente_nombre ? 'checked' : ''}>
|
||||
<span>¿Paciente menor de edad?</span>
|
||||
</label>` : ''}
|
||||
<button class="nota-btn-guardar" style="background:#0d6efd"
|
||||
onclick="notasManager._guardarFicha()">
|
||||
<i class="fas fa-save me-2"></i>Guardar ficha clínica
|
||||
</button>`;
|
||||
|
||||
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();
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user