From 506f3469b49d234fe17ece824715d953ff53777b Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 23 Jun 2026 09:51:58 -0500 Subject: [PATCH] =?UTF-8?q?Kiosko:=20auto-turno=20solo=20por=20esc=C3=A1ne?= =?UTF-8?q?r=20(r=C3=A1faga=20<35ms=20o=20Enter),=20nunca=20a=20mano?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Escribir manualmente ya no dispara el turno: la persona oprime el botón. El lector de cédula sí lo dispara porque mete los dígitos en ráfaga (<35ms entre cada uno) o termina con Enter. Guard contra doble envío. Co-Authored-By: Claude Opus 4.8 --- modules/turnero/views/kiosko.php | 57 ++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/modules/turnero/views/kiosko.php b/modules/turnero/views/kiosko.php index fbb9d7d..285fa3b 100644 --- a/modules/turnero/views/kiosko.php +++ b/modules/turnero/views/kiosko.php @@ -503,20 +503,44 @@ unset($p); }); } - // ── Scanner detector (un solo listener, fuera de seleccionarPrioridad) ── - let _timerAutoSubmit = null; - let _lastKeyAt = 0; + // ── Detector de escáner ────────────────────────────────────────── + // Escribir a mano NUNCA dispara el turno (la persona oprime el botón). + // Solo el lector de cédula lo dispara: mete los dígitos en ráfaga + // (<35 ms entre cada uno, imposible a mano) y/o termina con Enter. + let _keyTimes = []; // timestamps de cada pulsación + let _timerRafaga = null; let _timerInactividad = null; + const _inpCedula = document.getElementById('inp-cedula'); - document.getElementById('inp-cedula').addEventListener('input', () => { - clearTimeout(_timerAutoSubmit); + // Solo es ráfaga de escáner si TODAS las pulsaciones (≥5) llegaron <35 ms + function esRafagaScanner() { + if (_keyTimes.length < 5) return false; + for (let i = 1; i < _keyTimes.length; i++) { + if (_keyTimes[i] - _keyTimes[i - 1] > 35) return false; + } + return true; + } + + _inpCedula.addEventListener('input', () => { resetInactividad(); - const now = Date.now(); - const gap = now - _lastKeyAt; - _lastKeyAt = now; - const val = document.getElementById('inp-cedula').value.trim(); - if (/^\d{5,15}$/.test(val) && gap < 80) { - _timerAutoSubmit = setTimeout(() => confirmarTurno(), 300); + _keyTimes.push(Date.now()); + if (_keyTimes.length > 25) _keyTimes.shift(); + + // Tras una breve pausa revisamos: si fue ráfaga → escáner → disparar. + // Si fue escritura a mano (gaps grandes) esRafagaScanner() = false → no dispara. + clearTimeout(_timerRafaga); + _timerRafaga = setTimeout(() => { + const val = _inpCedula.value.trim(); + if (/^\d{5,15}$/.test(val) && esRafagaScanner()) confirmarTurno(); + }, 120); + }); + + // El lector casi siempre envía Enter al final → disparar de inmediato. + _inpCedula.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + e.preventDefault(); + const val = _inpCedula.value.trim(); + if (/^\d{5,15}$/.test(val)) confirmarTurno(); } }); @@ -540,14 +564,18 @@ unset($p); const inpCedula = document.getElementById('inp-cedula'); inpCedula.focus(); inpCedula.value = ''; - _lastKeyAt = 0; - clearTimeout(_timerAutoSubmit); + _keyTimes = []; + clearTimeout(_timerRafaga); resetInactividad(); } function volverPrioridades() { clearTimeout(_timerInactividad); mostrar('screen-prio'); } + let _enviando = false; async function confirmarTurno() { + if (_enviando) return; // evita doble disparo (ráfaga + Enter) + clearTimeout(_timerRafaga); + clearTimeout(_timerInactividad); const cedula = document.getElementById('inp-cedula').value.trim(); const cel = document.getElementById('inp-cel').value.trim(); @@ -555,6 +583,7 @@ unset($p); if (!/^\d{5,15}$/.test(cedula)) { mostrarError('La cédula debe tener solo dígitos (mínimo 5).'); return; } if (cel && !/^\+?\d{7,15}$/.test(cel.replace(/\s/g,''))) { mostrarError('Ingrese un número de WhatsApp válido.'); return; } + _enviando = true; setSpinner(true); try { const res = await fetch(API_URL, { @@ -568,6 +597,8 @@ unset($p); } catch (err) { mostrarError(err.message); setSpinner(false); + } finally { + _enviando = false; } }