Kiosko: auto-turno solo por escáner (ráfaga <35ms o Enter), nunca a mano

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 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-23 09:51:58 -05:00
co-authored by Claude Opus 4.8
parent 71d29f35fa
commit 506f3469b4
+44 -13
View File
@@ -503,20 +503,44 @@ unset($p);
}); });
} }
// ── Scanner detector (un solo listener, fuera de seleccionarPrioridad) ── // ── Detector de escáner ──────────────────────────────────────────
let _timerAutoSubmit = null; // Escribir a mano NUNCA dispara el turno (la persona oprime el botón).
let _lastKeyAt = 0; // 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; let _timerInactividad = null;
const _inpCedula = document.getElementById('inp-cedula');
document.getElementById('inp-cedula').addEventListener('input', () => { // Solo es ráfaga de escáner si TODAS las pulsaciones (≥5) llegaron <35 ms
clearTimeout(_timerAutoSubmit); 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(); resetInactividad();
const now = Date.now(); _keyTimes.push(Date.now());
const gap = now - _lastKeyAt; if (_keyTimes.length > 25) _keyTimes.shift();
_lastKeyAt = now;
const val = document.getElementById('inp-cedula').value.trim(); // Tras una breve pausa revisamos: si fue ráfaga → escáner → disparar.
if (/^\d{5,15}$/.test(val) && gap < 80) { // Si fue escritura a mano (gaps grandes) esRafagaScanner() = false → no dispara.
_timerAutoSubmit = setTimeout(() => confirmarTurno(), 300); 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'); const inpCedula = document.getElementById('inp-cedula');
inpCedula.focus(); inpCedula.focus();
inpCedula.value = ''; inpCedula.value = '';
_lastKeyAt = 0; _keyTimes = [];
clearTimeout(_timerAutoSubmit); clearTimeout(_timerRafaga);
resetInactividad(); resetInactividad();
} }
function volverPrioridades() { clearTimeout(_timerInactividad); mostrar('screen-prio'); } function volverPrioridades() { clearTimeout(_timerInactividad); mostrar('screen-prio'); }
let _enviando = false;
async function confirmarTurno() { 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 cedula = document.getElementById('inp-cedula').value.trim();
const cel = document.getElementById('inp-cel').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 (!/^\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; } if (cel && !/^\+?\d{7,15}$/.test(cel.replace(/\s/g,''))) { mostrarError('Ingrese un número de WhatsApp válido.'); return; }
_enviando = true;
setSpinner(true); setSpinner(true);
try { try {
const res = await fetch(API_URL, { const res = await fetch(API_URL, {
@@ -568,6 +597,8 @@ unset($p);
} catch (err) { } catch (err) {
mostrarError(err.message); mostrarError(err.message);
setSpinner(false); setSpinner(false);
} finally {
_enviando = false;
} }
} }