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:
co-authored by
Claude Sonnet 4.6
parent
8bc9cbdd35
commit
814bd2ce5c
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* POST /modules/turnero/api/cancelar_toma_pendiente.php
|
||||
* Marca una toma progresiva en_progreso como rechazada (paciente no quiere continuar).
|
||||
* Body: { consentimiento_id }
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('POST');
|
||||
requireTurnero();
|
||||
|
||||
$body = inputJson();
|
||||
$consentId = (int)($body['consentimiento_id'] ?? 0);
|
||||
if (!$consentId) jsonError('consentimiento_id requerido.');
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare(
|
||||
"UPDATE turnero_consentimientos
|
||||
SET estado = 'rechazado'
|
||||
WHERE id = ? AND estado = 'en_progreso'"
|
||||
);
|
||||
$stmt->execute([$consentId]);
|
||||
|
||||
if ($stmt->rowCount() === 0) jsonError('No se encontró toma en progreso con ese id.', 404);
|
||||
|
||||
jsonOk(['cancelado' => true]);
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
/**
|
||||
* GET /modules/turnero/api/get_tomas_pendientes_paciente.php?turno_id=X
|
||||
* Devuelve tomas progresivas en_progreso del mismo paciente en turnos anteriores.
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('GET');
|
||||
requireTurnero();
|
||||
|
||||
$turnoId = (int)($_GET['turno_id'] ?? 0);
|
||||
if (!$turnoId) jsonError('turno_id requerido.');
|
||||
|
||||
$pdo = db();
|
||||
|
||||
// Obtener paciente_id del turno actual
|
||||
$row = $pdo->prepare("SELECT paciente_id FROM turnero_turnos WHERE id = ? LIMIT 1");
|
||||
$row->execute([$turnoId]);
|
||||
$t = $row->fetchColumn();
|
||||
|
||||
if (!$t) jsonOk(['tomas' => []]);
|
||||
|
||||
$pacienteId = (int)$t;
|
||||
|
||||
$stmt = $pdo->prepare(
|
||||
"SELECT tc.id, tc.turno_id, tc.token, tc.siguiente_toma_at, tc.toma_inicio_at,
|
||||
tc.datos_respuestas, f.nombre AS formulario_nombre, f.esquema,
|
||||
tt.codigo AS turno_codigo, tt.creado_at AS turno_fecha
|
||||
FROM turnero_consentimientos tc
|
||||
JOIN lab_formularios f ON f.id = tc.formulario_id AND f.es_toma_progresiva = 1
|
||||
JOIN turnero_turnos tt ON tt.id = tc.turno_id
|
||||
WHERE tt.paciente_id = ?
|
||||
AND tc.turno_id != ?
|
||||
AND tc.estado = 'en_progreso'
|
||||
ORDER BY tc.id DESC
|
||||
LIMIT 10"
|
||||
);
|
||||
$stmt->execute([$pacienteId, $turnoId]);
|
||||
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$tomas = [];
|
||||
foreach ($rows as $r) {
|
||||
$esquema = json_decode($r['esquema'] ?? '[]', true) ?: [];
|
||||
$datos = json_decode($r['datos_respuestas'] ?? '[]', true) ?: [];
|
||||
|
||||
// Contar firmas totales y hechas
|
||||
$totalFirmas = 0;
|
||||
$firmasHechas = 0;
|
||||
foreach ($esquema as $c) {
|
||||
if (($c['tipo'] ?? '') === 'firma_profesional') {
|
||||
$totalFirmas++;
|
||||
if (!empty($datos[$c['id']]) && strlen($datos[$c['id']]) > 10) $firmasHechas++;
|
||||
}
|
||||
}
|
||||
|
||||
$tomas[] = [
|
||||
'id' => (int)$r['id'],
|
||||
'turno_id' => (int)$r['turno_id'],
|
||||
'token' => $r['token'],
|
||||
'formulario_nombre' => $r['formulario_nombre'],
|
||||
'siguiente_toma_at' => $r['siguiente_toma_at'],
|
||||
'toma_inicio_at' => $r['toma_inicio_at'],
|
||||
'turno_codigo' => $r['turno_codigo'],
|
||||
'turno_fecha' => $r['turno_fecha'],
|
||||
'tomas_firmadas' => $firmasHechas,
|
||||
'tomas_total' => $totalFirmas,
|
||||
];
|
||||
}
|
||||
|
||||
jsonOk(['tomas' => $tomas]);
|
||||
@@ -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', {
|
||||
|
||||
Reference in New Issue
Block a user