diff --git a/modules/turnero/api/get_cola.php b/modules/turnero/api/get_cola.php index 7a0cb8c..933d877 100644 --- a/modules/turnero/api/get_cola.php +++ b/modules/turnero/api/get_cola.php @@ -83,7 +83,8 @@ if ($area === 'recepcion') { LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id WHERE t.sesion_id = ? AND t.estado = 'en_espera_lugar' - AND t.lugar_destino_id IN ($inLugares)) + AND t.lugar_destino_id IN ($inLugares) + AND t.muestra_espera_at IS NULL) UNION ALL (SELECT $cols FROM turnero_turnos t @@ -91,7 +92,8 @@ if ($area === 'recepcion') { LEFT JOIN turnero_solicitudes s ON s.turno_id = t.id WHERE t.sesion_id = ? AND t.estado = 'en_servicio' - AND t.lugar_destino_id = ?) + AND t.lugar_destino_id = ? + AND t.muestra_espera_at IS NULL) ) AS cola_union ORDER BY solo_muestras DESC, orden_peso ASC, creado_at ASC" ); @@ -126,7 +128,7 @@ if (!empty($cola)) { $campoLlamado = $area === 'recepcion' ? 'llamado_recepcion_at' : 'llamado_lugar_at'; $estadoActivo = $area === 'recepcion' ? "'en_recepcion'" : "'en_servicio'"; // Activo: para lugar filtrar SOLO por esta estación (ya fue asignada al llamar) -$filtroActivo = $area === 'lugar' ? 'AND t.lugar_destino_id = ?' : ''; +$filtroActivo = $area === 'lugar' ? 'AND t.lugar_destino_id = ? AND t.muestra_espera_at IS NULL' : ''; $bindActivo = $area === 'lugar' ? [$sesionId, $lugarId] : [$sesionId]; $stmt = $pdo->prepare( @@ -173,12 +175,33 @@ $stmt = $pdo->prepare( $stmt->execute([$sesionId]); $stats = $stmt->fetch(PDO::FETCH_ASSOC); +// ── Pacientes en espera entre muestras (toma progresiva) ───── +$enEsperaMuestra = []; +if ($area === 'lugar') { + $stmtEsp = $pdo->prepare(" + SELECT t.id, t.paciente_nombre, ts.numero_orden, t.muestra_espera_at, + (SELECT tc.siguiente_toma_at + FROM turnero_consentimientos tc + JOIN lab_formularios f ON f.id = tc.formulario_id AND f.es_toma_progresiva = 1 + WHERE tc.turno_id = t.id AND tc.estado = 'en_progreso' + ORDER BY tc.siguiente_toma_at ASC LIMIT 1) AS siguiente_toma_at + FROM turnero_turnos t + JOIN turnero_solicitudes ts ON ts.turno_id = t.id + WHERE t.sesion_id = ? AND t.lugar_destino_id IN ($inLugares) + AND t.muestra_espera_at IS NOT NULL AND t.fin_lugar_at IS NULL + ORDER BY t.muestra_espera_at ASC + "); + $stmtEsp->execute([$sesionId]); + $enEsperaMuestra = $stmtEsp->fetchAll(PDO::FETCH_ASSOC); +} + jsonOk([ - 'sesion_id' => $sesionId, - 'area' => $area, - 'lugar_id' => $lugarId, - 'activo' => $activo, - 'cola' => $cola, - 'stats' => $stats, - 'timestamp' => date('c'), + 'sesion_id' => $sesionId, + 'area' => $area, + 'lugar_id' => $lugarId, + 'activo' => $activo, + 'cola' => $cola, + 'en_espera_muestra' => $enEsperaMuestra, + 'stats' => $stats, + 'timestamp' => date('c'), ]); diff --git a/modules/turnero/api/llamar_desde_espera.php b/modules/turnero/api/llamar_desde_espera.php new file mode 100644 index 0000000..36a404c --- /dev/null +++ b/modules/turnero/api/llamar_desde_espera.php @@ -0,0 +1,19 @@ +prepare( + "UPDATE turnero_turnos SET muestra_espera_at = NULL WHERE id = ? AND muestra_espera_at IS NOT NULL" +)->execute([$turnoId]); + +jsonOk([], 'Paciente de vuelta en cola'); diff --git a/modules/turnero/api/poner_en_espera_muestra.php b/modules/turnero/api/poner_en_espera_muestra.php new file mode 100644 index 0000000..bcbb39d --- /dev/null +++ b/modules/turnero/api/poner_en_espera_muestra.php @@ -0,0 +1,20 @@ +prepare( + "UPDATE turnero_turnos SET muestra_espera_at = NOW() + WHERE id = ? AND estado = 'en_servicio' AND muestra_espera_at IS NULL" +)->execute([$turnoId]); + +jsonOk([], 'Paciente enviado a sala de espera'); diff --git a/modules/turnero/views/lugar.php b/modules/turnero/views/lugar.php index 713cf46..9dafcc2 100644 --- a/modules/turnero/views/lugar.php +++ b/modules/turnero/views/lugar.php @@ -201,6 +201,33 @@ foreach ($lugares as $_el) { .esp-pac-orden { font-weight: 700; font-family: monospace; color: var(--esp-gc); font-size: .7rem; flex-shrink: 0; } .esp-pac-hora { margin-left: auto; font-size: .68rem; color: #94a3b8; flex-shrink: 0; } + /* ── Sala de espera entre muestras ── */ + #espera-muestras-panel { flex-shrink: 0; border-bottom: 2px solid #fde68a; background: #fffbeb; } + .espera-m-hdr { + display: flex; align-items: center; gap: .4rem; + padding: .4rem .75rem .25rem; font-size: .72rem; font-weight: 700; color: #92400e; + } + .espera-m-count { + background: #f97316; color: #fff; border-radius: 99px; padding: 0 6px; font-size: .65rem; + } + .espera-m-row { + display: flex; align-items: center; gap: .5rem; + padding: .22rem .75rem; font-size: .78rem; color: #1e293b; + border-top: 1px solid #fde68a; + } + .espera-m-orden { font-weight: 700; font-family: monospace; color: #f97316; font-size: .7rem; flex-shrink: 0; } + .espera-m-cd { font-size: .71rem; font-weight: 700; flex-shrink: 0; white-space: nowrap; } + .espera-m-cd.ok { color: #16a34a; } + .espera-m-cd.warn { color: #d97706; } + .espera-m-cd.crit { color: #dc2626; animation: parpadeo-alerta .8s infinite; } + .btn-llamar-espera { + margin-left: auto; flex-shrink: 0; + padding: .18rem .55rem; font-size: .72rem; font-weight: 700; + border: 1.5px solid #22c55e; color: #16a34a; background: #fff; + border-radius: 7px; cursor: pointer; transition: background .1s; + } + .btn-llamar-espera:hover { background: #f0fdf4; } + .cola-section-sep { font-size: .65rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: #94a3b8; padding: .3rem .4rem .15rem; margin-top: .25rem; @@ -676,6 +703,8 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php';
+ +