feat(bandeja): chips clickeables para muestras pend. y prog. en espera
- Chip "Muestras pend." y nuevo "Prog. en espera" son toggles de filtro - Se resaltan con borde al activarse; combinables entre sí y con el dropdown - API retorna muestras_pendientes (turnos con ≥1 muestra pendiente) y prolongadas_pendientes (toma progresiva en espera entre extracciones) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
118e98b360
commit
e3216faaa5
@@ -104,7 +104,7 @@ if ($desde && $hasta) {
|
||||
|
||||
$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,
|
||||
t.inicio_lugar_at, t.fin_lugar_at, t.bandeja_visto_at, t.muestra_espera_at,
|
||||
ts.numero_orden,
|
||||
l.nombre AS lugar_nombre,
|
||||
GROUP_CONCAT(DISTINCT et.codigo ORDER BY et.codigo SEPARATOR ' ') AS examenes_txt,
|
||||
@@ -128,15 +128,17 @@ $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));
|
||||
|
||||
$muestrasPendientes = array_sum(array_column($todos, 'muestras_pendientes'));
|
||||
$muestrasPendientes = count(array_filter($todos, fn($t) => (int)$t['muestras_pendientes'] > 0));
|
||||
$prolongadasPendientes = count(array_filter($todos, fn($t) => !empty($t['muestra_espera_at']) && empty($t['fin_lugar_at'])));
|
||||
|
||||
jsonOk([
|
||||
'pendientes' => $pendientes,
|
||||
'vistos' => $vistos,
|
||||
'stats' => [
|
||||
'total' => count($todos),
|
||||
'pendientes' => count($pendientes),
|
||||
'vistos' => count($vistos),
|
||||
'muestras_pendientes' => $muestrasPendientes,
|
||||
'total' => count($todos),
|
||||
'pendientes' => count($pendientes),
|
||||
'vistos' => count($vistos),
|
||||
'muestras_pendientes' => $muestrasPendientes,
|
||||
'prolongadas_pendientes'=> $prolongadasPendientes,
|
||||
],
|
||||
]);
|
||||
|
||||
@@ -41,7 +41,10 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
|
||||
.bnd-chip-total { background:#ede9fe; color:#5b21b6; }
|
||||
.bnd-chip-pend { background:#fef3c7; color:#92400e; }
|
||||
.bnd-chip-vis { background:#f1f5f9; color:#475569; }
|
||||
.bnd-chip-mp { background:#fff7ed; color:#c2410c; }
|
||||
.bnd-chip-mp { background:#fff7ed; color:#c2410c; cursor:pointer; transition:box-shadow .12s; }
|
||||
.bnd-chip-prog { background:#ecfdf5; color:#065f46; cursor:pointer; transition:box-shadow .12s; }
|
||||
.bnd-chip-mp.activo { box-shadow:0 0 0 2px #c2410c; }
|
||||
.bnd-chip-prog.activo { box-shadow:0 0 0 2px #065f46; }
|
||||
.bnd-refresh-btn {
|
||||
margin-left: auto;
|
||||
background: none;
|
||||
@@ -356,7 +359,8 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
|
||||
<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>
|
||||
<span class="bnd-chip bnd-chip-mp" id="st-mp" onclick="_bndToggleChip('mp')" title="Filtrar: con muestras pendientes"><i class="fas fa-exclamation-triangle"></i> Muestras pend.: —</span>
|
||||
<span class="bnd-chip bnd-chip-prog" id="st-prog" onclick="_bndToggleChip('prog')" title="Filtrar: toma progresiva en espera"><i class="fas fa-clock"></i> Prog. en espera: —</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">
|
||||
@@ -366,7 +370,6 @@ Layout::open('Bandeja del día', 'fas fa-layer-group');
|
||||
<option value="finalizado">Finalizado</option>
|
||||
<option value="ausente">Ausente</option>
|
||||
<option value="cancelado">Cancelado</option>
|
||||
<option value="muestras_pendientes">Muestras pendientes</option>
|
||||
</select>
|
||||
<button class="bnd-refresh-btn" onclick="_bndRefrescarLista()">
|
||||
<i class="fas fa-sync-alt" id="bnd-spin"></i> Actualizar
|
||||
@@ -450,16 +453,28 @@ async function _bndRefrescarLista() {
|
||||
document.getElementById('st-pend').innerHTML = `<i class="fas fa-clock"></i> Por revisar: ${s.pendientes}`;
|
||||
document.getElementById('st-vis').innerHTML = `<i class="fas fa-eye"></i> Vistos: ${s.vistos}`;
|
||||
document.getElementById('st-mp').innerHTML = `<i class="fas fa-exclamation-triangle"></i> Muestras pend.: ${s.muestras_pendientes}`;
|
||||
document.getElementById('st-prog').innerHTML = `<i class="fas fa-clock"></i> Prog. en espera: ${s.prolongadas_pendientes}`;
|
||||
|
||||
_bndFiltrar();
|
||||
}
|
||||
|
||||
const _bndChipActivo = { mp: false, prog: false };
|
||||
|
||||
function _bndToggleChip(tipo) {
|
||||
_bndChipActivo[tipo] = !_bndChipActivo[tipo];
|
||||
const id = tipo === 'mp' ? 'st-mp' : 'st-prog';
|
||||
document.getElementById(id).classList.toggle('activo', _bndChipActivo[tipo]);
|
||||
_bndFiltrar();
|
||||
}
|
||||
|
||||
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) || String(t.numero_orden || '').includes(q) || (t.codigo || '').toLowerCase().includes(q)) &&
|
||||
(!st || (st === 'muestras_pendientes' ? +t.muestras_pendientes > 0 : t.estado === st));
|
||||
(!st || t.estado === st) &&
|
||||
(!_bndChipActivo.mp || +t.muestras_pendientes > 0) &&
|
||||
(!_bndChipActivo.prog || (t.muestra_espera_at && !t.fin_lugar_at));
|
||||
|
||||
_renderLista(
|
||||
_bndAllData.pendientes?.filter(match) || [],
|
||||
|
||||
Reference in New Issue
Block a user