feat(turnero): mostrar tomas prolongadas pendientes de visita anterior

Cuando el paciente regresa con un turno nuevo, toma de muestras muestra
las tomas en_progreso de visitas anteriores con botón Continuar o Cancelar.
Cancelar marca estado='rechazado' (campo ya existía en el enum).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-21 20:37:17 -05:00
co-authored by Claude Sonnet 4.6
parent 8bc9cbdd35
commit 814bd2ce5c
3 changed files with 177 additions and 0 deletions
+83
View File
@@ -324,6 +324,22 @@ try {
.consent-row .acciones-consent { display: flex; gap: .3rem; flex-shrink: 0; }
.consent-row .acciones-consent .btn { font-size: .72rem; padding: 2px 9px; border-radius: 7px; }
/* ── Tomas pendientes de visita anterior ── */
#sec-tomas-prev { display:none; }
.tomas-prev-hdr { font-size:.78rem; font-weight:700; color:#92400e;
background:#fff7ed; border:1px solid #fed7aa;
border-radius:8px 8px 0 0; padding:6px 12px;
display:flex; align-items:center; gap:6px; }
.tomas-prev-list { border:1px solid #fed7aa; border-top:none;
border-radius:0 0 8px 8px; overflow:hidden; }
.toma-prev-row { display:flex; align-items:center; gap:.6rem;
padding:.45rem .7rem; background:#fffbeb;
font-size:.83rem; color:#78350f; }
.toma-prev-row + .toma-prev-row { border-top:1px solid #fde68a; }
.toma-prev-row .nom-form { flex:1; font-weight:500; }
.toma-prev-row .acciones-consent { display:flex; gap:.3rem; flex-shrink:0; }
.toma-prev-row .acciones-consent .btn { font-size:.72rem; padding:2px 9px; border-radius:7px; }
/* ── Barra de acciones ── */
.ficha-acciones {
position: sticky; bottom: 0;
@@ -699,6 +715,15 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
</iframe>
</div>
<!-- ── Tomas progresivas pendientes de visita anterior ── -->
<div class="ficha-sec" id="sec-tomas-prev">
<div class="tomas-prev-hdr">
<i class="fas fa-hourglass-half"></i>
Tomas pendientes de visita anterior
</div>
<div class="tomas-prev-list" id="lista-tomas-prev"></div>
</div>
<!-- ── Consentimientos ── -->
<div class="ficha-sec" id="sec-consent">
<div class="ficha-sec-hdr"><i class="fas fa-file-signature"></i>Consentimientos informados</div>
@@ -1213,6 +1238,7 @@ async function cargarFichaSolicitud(turnoId) {
renderMuestras(json.muestras || []);
cargarComentarios(turnoId);
draftRestaurar(turnoId);
cargarTomasPrevias(turnoId);
} catch (_) {}
}
@@ -1452,6 +1478,63 @@ async function actualizarConsentimientos(turnoId) {
} catch (_) {}
}
// ── Tomas progresivas pendientes de visita anterior ──────────
async function cargarTomasPrevias(turnoId) {
const sec = document.getElementById('sec-tomas-prev');
const list = document.getElementById('lista-tomas-prev');
sec.style.display = 'none';
list.innerHTML = '';
if (!turnoId) return;
try {
const res = await fetch(`${API}get_tomas_pendientes_paciente.php?turno_id=${turnoId}`);
const json = await res.json();
if (!json.ok || !json.tomas?.length) return;
list.innerHTML = json.tomas.map(t => {
const token = escHtml(t.token || '');
const fNom = escHtml(t.formulario_nombre || 'Toma');
const turno = escHtml(t.turno_codigo || '');
const fecha = t.turno_fecha ? escHtml(t.turno_fecha.slice(0,10)) : '';
const prog = t.tomas_total > 0
? `<span class="toma-progreso">${t.tomas_firmadas}/${t.tomas_total}</span>` : '';
return `<div class="toma-prev-row" data-consent-id="${t.id}">
<i class="fas fa-hourglass-half"></i>
<span class="nom-form">${fNom}</span>
${prog}
<span class="c-badge" style="font-size:.65rem;opacity:.7">Turno ${turno} · ${fecha}</span>
<div class="acciones-consent">
<button class="btn btn-primary" onclick="abrirTomaProgresiva('${token}',${t.turno_id},0)">
<i class="fas fa-flask me-1"></i>Continuar
</button>
<button class="btn btn-outline-secondary" title="Paciente no quiere continuar"
onclick="cancelarTomaPrevia(${t.id}, this)">
<i class="fas fa-ban me-1"></i>Cancelar
</button>
</div>
</div>`;
}).join('');
sec.style.display = '';
} catch (_) {}
}
async function cancelarTomaPrevia(consentId, btn) {
if (!confirm('¿El paciente no quiere continuar la toma? Se marcará como cancelada.')) return;
btn.disabled = true;
try {
const res = await fetch(`${API}cancelar_toma_pendiente.php`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ consentimiento_id: consentId }),
});
const json = await res.json();
if (!json.ok) { mostrarError(json.error); btn.disabled = false; return; }
// Quitar fila
const row = document.querySelector(`.toma-prev-row[data-consent-id="${consentId}"]`);
if (row) row.remove();
const list = document.getElementById('lista-tomas-prev');
if (list && !list.children.length) document.getElementById('sec-tomas-prev').style.display = 'none';
} catch (e) { mostrarError(e.message); btn.disabled = false; }
}
async function reenviarConsentimiento(turnoId) {
try {
const res = await fetch(API + 'send_consentimiento.php', {