From e634eb89328f59fd1a6eb6748676b52c058ea631 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Mon, 27 Jul 2026 22:31:11 -0500 Subject: [PATCH] =?UTF-8?q?turnero:=20panel=20especialidades=20(ginecolog?= =?UTF-8?q?=C3=ADa/pediatr=C3=ADa)=20en=20toma=20de=20muestras?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Sección en la parte superior de lugar.php muestra pacientes esperando en Ginecología y Pediatría (inicio_lugar_at IS NOT NULL, fin_lugar_at IS NULL) - Chips de acceso rápido (botones) al tope de la cola para navegar directo - Contadores de espera actualizados cada 30s - Clicking en un paciente o "Ir →" navega a esa vista completa para atenderlo - Solo aparece si existen esos lugares en DB y hay pacientes esperando - Nuevo: get_especialidades.php para consultar pacientes de lugares especiales Co-Authored-By: Claude Sonnet 4.6 --- modules/turnero/api/get_especialidades.php | 46 ++++++++ modules/turnero/views/lugar.php | 116 +++++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 modules/turnero/api/get_especialidades.php diff --git a/modules/turnero/api/get_especialidades.php b/modules/turnero/api/get_especialidades.php new file mode 100644 index 0000000..8886739 --- /dev/null +++ b/modules/turnero/api/get_especialidades.php @@ -0,0 +1,46 @@ + []]); + +$sesionId = (int)($pdo->query( + "SELECT id FROM turnero_sesiones ORDER BY id DESC LIMIT 1" +)->fetchColumn() ?: 0); + +if (!$sesionId) jsonOk(['grupos' => []]); + +$in = implode(',', $ids); +$lugares = $pdo->query( + "SELECT id, nombre FROM turnero_lugares WHERE id IN ($in) AND activo=1 ORDER BY sort_order" +)->fetchAll(PDO::FETCH_ASSOC); + +$grupos = []; +foreach ($lugares as $l) { + $lid = (int)$l['id']; + $stmt = $pdo->prepare(" + SELECT t.id, t.paciente_nombre, t.inicio_lugar_at, ts.numero_orden + FROM turnero_turnos t + JOIN turnero_solicitudes ts ON ts.turno_id = t.id + WHERE t.sesion_id = ? AND t.lugar_destino_id = ? + AND t.inicio_lugar_at IS NOT NULL AND t.fin_lugar_at IS NULL + ORDER BY ts.numero_orden ASC + "); + $stmt->execute([$sesionId, $lid]); + $grupos[] = [ + 'lugar_id' => $lid, + 'lugar_nombre' => $l['nombre'], + 'pacientes' => $stmt->fetchAll(PDO::FETCH_ASSOC), + ]; +} + +jsonOk(['grupos' => $grupos]); diff --git a/modules/turnero/views/lugar.php b/modules/turnero/views/lugar.php index a89849a..713cf46 100644 --- a/modules/turnero/views/lugar.php +++ b/modules/turnero/views/lugar.php @@ -82,6 +82,16 @@ try { $stmt->execute([(int)($_SESSION['admin_user']['id'] ?? 0)]); $adminFirmaSvg = $stmt->fetchColumn() ?: null; } catch (\Throwable $_) {} + +// Especialidades (Ginecología, Pediatría) — excluir el lugar actual +$especialidades = []; +foreach ($lugares as $_el) { + $_en = mb_strtolower($_el['nombre']); + if ((str_contains($_en, 'ginecol') || str_contains($_en, 'pediatr')) + && (int)$_el['id'] !== $lugarIdParam) { + $especialidades[] = $_el; + } +} ?> @@ -148,6 +158,49 @@ try { .cola-items { flex: 1; overflow-y: auto; padding: .5rem; } + /* ── Especialidades en cola ── */ + .esp-toplinks { + display: flex; gap: .35rem; flex-wrap: wrap; flex-shrink: 0; + padding: .45rem .75rem; background: #fff; + border-bottom: 1px solid #f1f5f9; + } + .esp-toplink { + display: inline-flex; align-items: center; gap: .3rem; + padding: .2rem .6rem; border-radius: 99px; font-size: .75rem; font-weight: 600; + color: var(--esp-c, #64748b); + border: 1.5px solid color-mix(in srgb, var(--esp-c, #64748b) 30%, transparent); + background: color-mix(in srgb, var(--esp-c, #64748b) 8%, #fff); + text-decoration: none; white-space: nowrap; transition: background .12s; + } + .esp-toplink:hover { background: color-mix(in srgb, var(--esp-c) 18%, #fff); } + .esp-toplink .esp-cnt { + background: var(--esp-c); color: #fff; border-radius: 99px; + padding: 0 5px; font-size: .65rem; min-width: 16px; text-align: center; + } + #esp-panel { flex-shrink: 0; border-bottom: 2px solid #e2e8f0; } + .esp-grupo { padding: .35rem .6rem; } + .esp-grupo + .esp-grupo { border-top: 1px solid #f1f5f9; } + .esp-grupo-hdr { + display: flex; align-items: center; gap: .35rem; + font-size: .72rem; font-weight: 700; color: #475569; margin-bottom: .2rem; + } + .esp-grupo-count { + background: var(--esp-gc); color: #fff; border-radius: 99px; padding: 0 5px; font-size: .65rem; + } + .esp-grupo-ir { + margin-left: auto; font-size: .7rem; font-weight: 600; + color: var(--esp-gc); text-decoration: none; + } + .esp-grupo-ir:hover { text-decoration: underline; } + .esp-pac-row { + display: flex; align-items: center; gap: .4rem; + padding: .18rem .25rem; border-radius: 5px; font-size: .77rem; + text-decoration: none; color: #1e293b; transition: background .1s; + } + .esp-pac-row:hover { background: #f1f5f9; } + .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; } + .cola-section-sep { font-size: .65rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700; color: #94a3b8; padding: .3rem .4rem .15rem; margin-top: .25rem; @@ -605,6 +658,24 @@ require_once __DIR__ . '/../../../shared/components/sidebar.php'; Llamar siguiente + + + + +
@@ -928,6 +999,7 @@ const BASE_WA = ''; const LUGAR_NOMBRE = document.getElementById('lbl-lugar-titulo')?.textContent || ''; const LUGAR_FORM_MODO = ''; const LUGAR_TIPO = ''; +const ESP_LUGARES = ; // ── Arranque ────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { @@ -937,7 +1009,9 @@ document.addEventListener('DOMContentLoaded', () => { function iniciarPuesto() { recuperarTurnoActivo(); cargarCola(); + _cargarEspecialidades(); pollingColaId = setInterval(cargarCola, 7000); + setInterval(_cargarEspecialidades, 30000); document.addEventListener('visibilitychange', () => { if (document.hidden) { @@ -946,6 +1020,7 @@ function iniciarPuesto() { pollingColaId = pollingConsentId = null; } else if (lugarId) { cargarCola(); + _cargarEspecialidades(); pollingColaId = setInterval(cargarCola, 7000); } }); @@ -2321,6 +2396,47 @@ function mostrarToast(msg, type = 'info', duration = 2500) { function mostrarError(msg) { mostrarToast(msg, 'error', 4000); } function mostrarLlamando(cod) { mostrarToast('Llamando turno ' + cod + '…', 'info', 2000); } +async function _cargarEspecialidades() { + if (!ESP_LUGARES.length) return; + try { + const qs = ESP_LUGARES.map(l => `ids[]=${l.id}`).join('&'); + const res = await fetch(`${API}get_especialidades.php?${qs}`); + const j = await res.json(); + if (j.ok) _renderEspecialidades(j.grupos); + } catch {} +} + +function _renderEspecialidades(grupos) { + const panel = document.getElementById('esp-panel'); + if (!panel) return; + let html = ''; + for (const g of grupos) { + const esGine = g.lugar_nombre.toLowerCase().includes('ginecol'); + const color = esGine ? '#ec4899' : '#0ea5e9'; + const icon = esGine ? 'fa-venus' : 'fa-child'; + const url = `${BASE_WA}erp.php?m=turnero&v=lugar&lugar_id=${g.lugar_id}`; + const cnt = document.getElementById(`esp-cnt-${g.lugar_id}`); + if (cnt) cnt.textContent = g.pacientes.length; + if (!g.pacientes.length) continue; + html += `
+
+ + ${escHtml(g.lugar_nombre)} + ${g.pacientes.length} + Ir +
+ ${g.pacientes.map(p => ` + + #${p.numero_orden} + ${escHtml(p.paciente_nombre)} + ${formatHora(p.inicio_lugar_at)} + `).join('')} +
`; + } + panel.innerHTML = html; + panel.style.display = html ? '' : 'none'; +} + /* ── Ocupación exclusiva del puesto ──────────────────────────── */ (function(_ID, _NOMBRE, _VIEW, _PARAM) { if (!_ID) return;