feat(turnero): buscador y paginación en tab de examenes

Filtrado en tiempo real + paginación client-side (15 por página).
Categorías vacías se ocultan automáticamente al buscar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-07 22:53:16 -05:00
co-authored by Claude Sonnet 4.6
parent 18d50a3a16
commit 333e856f38
+62 -1
View File
@@ -466,7 +466,13 @@ $tab = $_GET['tab'] ?? 'lugares';
TAB 2 — EXÁMENES Y CONSENTIMIENTOS
════════════════════════════════════════ -->
<?php elseif ($tab === 'examenes'): ?>
<p class="section-title">Tipos de examen y sus formularios de consentimiento</p>
<div class="d-flex align-items-center gap-3 mb-3">
<p class="section-title mb-0">Tipos de examen y sus formularios de consentimiento</p>
<div class="ms-auto" style="min-width:220px">
<input type="search" id="exam-buscar" class="form-control form-control-sm"
placeholder="Buscar examen…" autocomplete="off">
</div>
</div>
<?php
// Agrupar por categoría
$categorias = [];
@@ -475,6 +481,7 @@ $tab = $_GET['tab'] ?? 'lugares';
$categorias[$cat][] = $et;
}
?>
<div id="exam-lista">
<?php foreach ($categorias as $cat => $items): ?>
<div class="mb-3">
<div class="fw-semibold text-uppercase small text-secondary mb-1" style="font-size:.7rem;letter-spacing:.07em">
@@ -513,6 +520,8 @@ $tab = $_GET['tab'] ?? 'lugares';
<?php endforeach; ?>
</div>
<?php endforeach; ?>
</div><!-- #exam-lista -->
<div id="exam-pager"></div>
<?php if (empty($examTipos)): ?>
<p class="text-muted text-center py-3">No hay tipos de examen configurados</p>
<?php endif; ?>
@@ -1203,6 +1212,58 @@ async function eliminarExamen(id, nombre) {
} catch (e) { toast('Error de conexión', 'error'); }
}
// ─────────────────────────────────────────────────────────────
// BUSCADOR + PAGINADOR — Tab examenes
// ─────────────────────────────────────────────────────────────
(function () {
const PAGE = 15;
let page = 1, q = '';
function update() {
const lista = document.getElementById('exam-lista');
if (!lista) return;
const rows = Array.from(lista.querySelectorAll('.item-row'));
const term = q.toLowerCase();
const matched = rows.filter(r => r.textContent.toLowerCase().includes(term));
rows.forEach(r => r.hidden = true);
const start = (page - 1) * PAGE;
matched.slice(start, start + PAGE).forEach(r => r.hidden = false);
// Ocultar categorías vacías
lista.querySelectorAll('.mb-3').forEach(cat => {
cat.hidden = Array.from(cat.querySelectorAll('.item-row')).every(r => r.hidden);
});
renderPager(matched.length);
}
function renderPager(total) {
const el = document.getElementById('exam-pager');
if (!el) return;
const pages = Math.ceil(total / PAGE);
if (pages <= 1) { el.innerHTML = total ? `<small class="text-muted">${total} resultado${total!==1?'s':''}</small>` : ''; return; }
const prev = `<button class="btn btn-sm btn-outline-secondary" ${page===1?'disabled':''} onclick="examPag(${page-1})"><i class="fas fa-chevron-left"></i></button>`;
const next = `<button class="btn btn-sm btn-outline-secondary" ${page===pages?'disabled':''} onclick="examPag(${page+1})"><i class="fas fa-chevron-right"></i></button>`;
el.innerHTML = `<div class="d-flex align-items-center gap-2 mt-2">
<small class="text-muted">${total} resultados</small>
<div class="ms-auto d-flex align-items-center gap-1">
${prev}
<span class="small px-1">Página ${page} de ${pages}</span>
${next}
</div>
</div>`;
}
window.examPag = function (p) { page = p; update(); };
document.addEventListener('DOMContentLoaded', () => {
const inp = document.getElementById('exam-buscar');
if (inp) inp.addEventListener('input', () => { q = inp.value; page = 1; update(); });
update();
});
})();
// ─────────────────────────────────────────────────────────────
// TAB 3: PRIORIDADES
// ─────────────────────────────────────────────────────────────