feat(bandeja): filtros por fecha, nombre, # orden y estado
- Inputs desde/hasta pasan al API y filtran por rango de fechas - Buscador cubre nombre, número de orden, código y examen - API usa fecha cuando se pasa, sesión actual como fallback Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4cb133010a
commit
118e98b360
@@ -91,6 +91,17 @@ if (isset($_GET['turno_id'])) {
|
||||
}
|
||||
|
||||
// ── LISTA ─────────────────────────────────────────────────────
|
||||
$desde = $_GET['desde'] ?? null;
|
||||
$hasta = $_GET['hasta'] ?? null;
|
||||
|
||||
if ($desde && $hasta) {
|
||||
$whereClause = "DATE(t.inicio_lugar_at) BETWEEN ? AND ?";
|
||||
$params = [$desde, $hasta];
|
||||
} else {
|
||||
$whereClause = "t.sesion_id = ?";
|
||||
$params = [$sesionId];
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("
|
||||
SELECT t.id, t.codigo, t.paciente_nombre, t.estado,
|
||||
t.inicio_lugar_at, t.fin_lugar_at, t.bandeja_visto_at,
|
||||
@@ -107,24 +118,17 @@ $stmt = $pdo->prepare("
|
||||
LEFT JOIN turnero_examen_items tei ON tei.solicitud_id = ts.id
|
||||
LEFT JOIN exam_tipos et ON et.id = tei.exam_tipo_id
|
||||
LEFT JOIN turnero_comentarios tc ON tc.turno_id = t.id
|
||||
WHERE t.sesion_id = ? AND t.inicio_lugar_at IS NOT NULL
|
||||
WHERE $whereClause AND t.inicio_lugar_at IS NOT NULL
|
||||
GROUP BY t.id
|
||||
ORDER BY ts.numero_orden ASC
|
||||
");
|
||||
$stmt->execute([$sesionId]);
|
||||
$stmt->execute($params);
|
||||
$todos = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$pendientes = array_values(array_filter($todos, fn($t) => $t['bandeja_visto_at'] === null));
|
||||
$vistos = array_values(array_filter($todos, fn($t) => $t['bandeja_visto_at'] !== null));
|
||||
|
||||
$stmtMp = $pdo->prepare("
|
||||
SELECT COUNT(*) FROM turnero_muestras tm
|
||||
JOIN turnero_solicitudes ts ON ts.id = tm.solicitud_id
|
||||
JOIN turnero_turnos t ON t.id = ts.turno_id
|
||||
WHERE t.sesion_id = ? AND tm.estado = 'pendiente'
|
||||
");
|
||||
$stmtMp->execute([$sesionId]);
|
||||
$muestrasPendientes = (int)$stmtMp->fetchColumn();
|
||||
$muestrasPendientes = array_sum(array_column($todos, 'muestras_pendientes'));
|
||||
|
||||
jsonOk([
|
||||
'pendientes' => $pendientes,
|
||||
|
||||
@@ -352,11 +352,13 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
|
||||
|
||||
<div class="bnd-wrap">
|
||||
<div class="bnd-topbar">
|
||||
<span class="bnd-title"><i class="fas fa-layer-group"></i> Bandeja del día</span>
|
||||
<span class="bnd-title"><i class="fas fa-layer-group"></i> Bandeja</span>
|
||||
<span class="bnd-chip bnd-chip-total" id="st-total"><i class="fas fa-users"></i> —</span>
|
||||
<span class="bnd-chip bnd-chip-pend" id="st-pend"><i class="fas fa-clock"></i> Por revisar: —</span>
|
||||
<span class="bnd-chip bnd-chip-vis" id="st-vis"><i class="fas fa-eye"></i> Vistos: —</span>
|
||||
<span class="bnd-chip bnd-chip-mp" id="st-mp"><i class="fas fa-exclamation-triangle"></i> Muestras pend.: —</span>
|
||||
<input type="date" id="bnd-desde" onchange="_bndRefrescarLista()" style="border:1px solid #cbd5e1;border-radius:6px;padding:3px 7px;font-size:.78rem;color:#475569;background:#fff;outline:none">
|
||||
<input type="date" id="bnd-hasta" onchange="_bndRefrescarLista()" style="border:1px solid #cbd5e1;border-radius:6px;padding:3px 7px;font-size:.78rem;color:#475569;background:#fff;outline:none">
|
||||
<select id="bnd-filtro-estado" onchange="_bndFiltrar()" style="border:1px solid #cbd5e1;border-radius:6px;padding:3px 8px;font-size:.78rem;color:#475569;background:#fff;cursor:pointer;outline:none">
|
||||
<option value="">Todos los estados</option>
|
||||
<option value="en_espera_lugar">En espera</option>
|
||||
@@ -374,7 +376,7 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
|
||||
<div class="bnd-body">
|
||||
<div class="bnd-list">
|
||||
<div class="bnd-search-box">
|
||||
<input type="text" id="bnd-filtro" placeholder="Buscar por nombre o examen…" oninput="_bndFiltrar()" autocomplete="off">
|
||||
<input type="text" id="bnd-filtro" placeholder="Nombre, # orden o examen…" oninput="_bndFiltrar()" autocomplete="off">
|
||||
</div>
|
||||
<div class="bnd-list-scroll" id="bnd-list-scroll">
|
||||
<div class="bnd-section-hdr">Cargando...</div>
|
||||
@@ -436,7 +438,10 @@ async function _bndRefrescarLista() {
|
||||
spin.style.transform = 'rotate(360deg)';
|
||||
setTimeout(()=>{ spin.style.transition=''; spin.style.transform=''; }, 400);
|
||||
|
||||
const res = await fetch(BND_API).then(r=>r.json()).catch(()=>null);
|
||||
const desde = document.getElementById('bnd-desde')?.value || '';
|
||||
const hasta = document.getElementById('bnd-hasta')?.value || '';
|
||||
const qs = (desde && hasta) ? `?desde=${desde}&hasta=${hasta}` : '';
|
||||
const res = await fetch(BND_API + qs).then(r=>r.json()).catch(()=>null);
|
||||
if (!res?.ok) return;
|
||||
|
||||
_bndAllData = res;
|
||||
@@ -453,7 +458,7 @@ function _bndFiltrar() {
|
||||
const q = (document.getElementById('bnd-filtro')?.value || '').toLowerCase().trim();
|
||||
const st = document.getElementById('bnd-filtro-estado')?.value || '';
|
||||
const match = t =>
|
||||
(!q || (t.paciente_nombre || '').toLowerCase().includes(q) || (t.examenes_txt || '').toLowerCase().includes(q)) &&
|
||||
(!q || (t.paciente_nombre || '').toLowerCase().includes(q) || (t.examenes_txt || '').toLowerCase().includes(q) || String(t.numero_orden || '').includes(q) || (t.codigo || '').toLowerCase().includes(q)) &&
|
||||
(!st || (st === 'muestras_pendientes' ? +t.muestras_pendientes > 0 : t.estado === st));
|
||||
|
||||
_renderLista(
|
||||
|
||||
Reference in New Issue
Block a user