This commit is contained in:
Lizandro Guarnizo
2026-06-16 15:03:40 -05:00
parent eaa8a23af6
commit 6be28ae5af
3 changed files with 200 additions and 3 deletions
+135
View File
@@ -211,6 +211,42 @@ $adminNombre = $_SESSION['admin_user']['full_name'] ?? $_SESSION['admin_user']['
.rec-toast.info .ico { color: #3b82f6; }
.rec-toast.warn .ico { color: #f59e0b; }
.rec-toast.error .ico { color: #ef4444; }
/* ── Historial del paciente ── */
.hist-toggle-btn {
display: flex; align-items: center; gap: 6px;
width: 100%; padding: 6px 10px; margin-top: 8px;
background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px;
font-size: .78rem; font-weight: 600; color: #475569;
cursor: pointer; text-align: left; transition: background .15s;
}
.hist-toggle-btn:hover { background: #f1f5f9; }
.hist-toggle-btn .hist-chev { margin-left: auto; transition: transform .2s; }
.hist-toggle-btn.open .hist-chev { transform: rotate(180deg); }
.hist-pac-body {
border: 1px solid #e2e8f0; border-top: none;
border-radius: 0 0 8px 8px; background: #fff;
max-height: 260px; overflow-y: auto;
}
.pac-timeline { padding: 10px 12px; }
.timeline-item {
display: flex; gap: 10px; align-items: flex-start;
padding-bottom: 10px; position: relative;
}
.timeline-item:not(:last-child)::before {
content: ''; position: absolute; left: 6px; top: 14px;
width: 2px; bottom: 0; background: #e2e8f0;
}
.timeline-dot {
width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
margin-top: 2px; border: 2px solid #fff;
box-shadow: 0 0 0 2px currentColor;
}
.timeline-content { flex: 1; min-width: 0; }
.timeline-fecha { font-size: .68rem; color: #94a3b8; }
.timeline-codigo { font-size: .82rem; font-weight: 700; }
.timeline-lugar { font-size: .73rem; color: #64748b; }
.timeline-eb { font-size: .62rem; padding: 1px 7px; border-radius: 99px; font-weight: 700; display: inline-block; margin-top: 2px; }
</style>
</head>
<body>
@@ -327,6 +363,22 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
<i class="fas fa-times"></i>
</button>
</div>
<!-- Historial colapsable del paciente -->
<div id="sec-historial-pac" class="d-none">
<button class="hist-toggle-btn" id="btn-hist-toggle" onclick="toggleHistorialPaciente()">
<i class="fas fa-history" style="color:#6366f1"></i>
Historial del paciente
<i class="fas fa-chevron-down hist-chev"></i>
</button>
<div id="hist-pac-body" class="hist-pac-body d-none">
<div id="hist-pac-content" class="pac-timeline">
<div class="text-center text-muted py-2 small">
<i class="fas fa-spinner fa-spin me-1"></i>Cargando…
</div>
</div>
</div>
</div>
</div>
</div>
@@ -802,12 +854,27 @@ function seleccionarPaciente(pac) {
document.getElementById('lbl-pac-cel').textContent =
pac.telefono || pac.celular || '';
document.getElementById('lista-pacientes-res').innerHTML = '';
// Mostrar historial del paciente
const secHist = document.getElementById('sec-historial-pac');
secHist.classList.remove('d-none');
// Resetear estado colapsado
document.getElementById('hist-pac-body').classList.add('d-none');
document.getElementById('btn-hist-toggle').classList.remove('open');
// Precargar en background (usuario decide si abre)
_historialPacienteCargado = false;
_historialPacienteId = pac.id;
}
function desvincularPaciente() {
pacienteActivo = null;
_historialPacienteId = null;
_historialPacienteCargado = false;
document.getElementById('bloque-pac-no-vinculado').classList.remove('d-none');
document.getElementById('bloque-pac-seleccionado').classList.add('d-none');
document.getElementById('sec-historial-pac').classList.add('d-none');
document.getElementById('hist-pac-body').classList.add('d-none');
document.getElementById('btn-hist-toggle').classList.remove('open');
document.getElementById('lista-pacientes-res').innerHTML = '';
document.getElementById('inp-buscar-pac').value = '';
}
@@ -816,6 +883,74 @@ function abrirNuevoPaciente(nombre) {
window.open('<?= BASE_URL ?>lab_pacientes.php?nuevo=1&nombre=' + encodeURIComponent(nombre), '_blank');
}
// ── Historial del paciente ──────────────────────────────────────
let _historialPacienteId = null;
let _historialPacienteCargado = false;
async function toggleHistorialPaciente() {
const body = document.getElementById('hist-pac-body');
const btn = document.getElementById('btn-hist-toggle');
const open = !body.classList.contains('d-none');
body.classList.toggle('d-none', open);
btn.classList.toggle('open', !open);
if (!open && !_historialPacienteCargado && _historialPacienteId) {
_historialPacienteCargado = true;
await cargarHistorialPaciente(_historialPacienteId);
}
}
async function cargarHistorialPaciente(pacienteId) {
const content = document.getElementById('hist-pac-content');
content.innerHTML = '<div class="text-center text-muted py-2 small"><i class="fas fa-spinner fa-spin me-1"></i>Cargando historial…</div>';
try {
const res = await fetch(`${API}get_historial.php?paciente_id=${pacienteId}&per_page=15&page=1`);
const json = await res.json();
if (!json.ok || !json.turnos || !json.turnos.length) {
content.innerHTML = '<div class="text-center text-muted py-3 small"><i class="fas fa-inbox me-1"></i>Sin visitas anteriores registradas</div>';
return;
}
content.innerHTML = renderHistorialTimeline(json.turnos, json.total);
} catch(_) {
content.innerHTML = '<div class="text-center text-danger py-2 small">Error al cargar historial</div>';
}
}
function renderHistorialTimeline(turnos, total) {
const ESTADO_LBL = {
espera:'Espera', en_recepcion:'Recepción', en_espera_lugar:'Esp. lugar',
en_servicio:'En servicio', finalizado:'Finalizado', ausente:'Ausente', cancelado:'Cancelado',
};
const ESTADO_STYLE = {
finalizado: 'background:#f1f5f9;color:#334155',
ausente: 'background:#fee2e2;color:#991b1b',
cancelado: 'background:#f1f5f9;color:#9ca3af',
en_servicio: 'background:#dcfce7;color:#166534',
en_espera_lugar:'background:#fde68a;color:#92400e',
en_recepcion: 'background:#dbeafe;color:#1e40af',
espera: 'background:#fef9c3;color:#78350f',
};
const totalLabel = total > turnos.length ? `<div class="text-end px-3 pb-1" style="font-size:.67rem;color:#94a3b8">Mostrando ${turnos.length} de ${total} visitas</div>` : '';
const items = turnos.map(t => {
const color = t.prioridad_color || '#6366f1';
const lugar = escHtml(t.lugar_nombre || 'Recepción');
const fecha = t.fecha_sesion || '—';
const est = t.estado || '';
const eStyle = ESTADO_STYLE[est] || 'background:#f1f5f9;color:#334155';
const eLbl = ESTADO_LBL[est] || est;
const mins = t.servicio_min != null ? `<span style="font-size:.65rem;color:#94a3b8;margin-left:4px">${t.servicio_min} min</span>` : '';
return `<div class="timeline-item">
<div class="timeline-dot" style="color:${color};background:${color}"></div>
<div class="timeline-content">
<div class="timeline-fecha">${escHtml(fecha)}</div>
<div class="timeline-codigo" style="color:${color}">${escHtml(t.codigo)}</div>
<div class="timeline-lugar">${lugar}</div>
<span class="timeline-eb" style="${eStyle}">${escHtml(eLbl)}</span>${mins}
</div>
</div>`;
}).join('');
return `<div class="pac-timeline">${items}</div>${totalLabel}`;
}
// ── Guardar solicitud ─────────────────────────────────────────
async function guardarSolicitud() {
if (!turnoActivo) return;