El Tab se bloquea pero las letras seguían escribiéndose en el campo.
Ahora cualquier carácter no numérico trunca el valor inmediatamente.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El lector de cédula envía los campos con Tab entre ellos. Se previene
el cambio de foco en keydown. Si algo llega igualmente a inp-cel
(letras) se limpia y regresa el foco a la cédula.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El escáner envía cedula+nombre+apellidos+… en una sola ráfaga.
Se corta en el primer espacio/tab para quedarse solo con los dígitos.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cambiar_estado: permite en_espera_lugar→en_recepcion y en_servicio→en_recepcion
- Al volver de un lugar limpia lugar_destino_id, llamado_lugar_at, inicio_lugar_at,
fin_recepcion_at y atendido_lugar_por para que quede reasignable
- lugar.php: botón "A recepción" visible en en_espera_lugar y en_servicio
- resetFicha oculta el botón nuevo al limpiar la ficha
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- touch-action: manipulation directo en cada botón e input (no solo en body)
- -ms-touch-action para compatibilidad Edge legacy
- position: relative en .kiosko-wrap para contener screens absolutas
- inset: 0 en .screen.hidden para que no se salga del contenedor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Formularios con 2 campos firma (consentimiento + disentimiento)
mostraban la firma del campo 2 también en el campo 1 porque
firma_svg se usaba como fallback del primer campo. Ahora si
datos_respuestas ya tiene algún _svg, se confía solo en los datos
por-campo y se ignora el fallback global.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Usar GetSigImageB64 en el poll para actualizar el canvas del overlay
cada vez que cambia el número de puntos. SigImage/0 (SigWebRefresh)
solo devuelve el trazo actual; SigImage/1 acumula toda la firma.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Agregar <canvas id="topaz-canvas"> al overlay de ambos archivos
- SetTabletState(1, canvasCtx, 50) con contexto 2D (sin esto los trazos no se dibujan)
- Guardar timer retornado y pasarlo a SetTabletState(0, tmr) al cerrar
- NumberOfTabletPoints() en vez de GetSigTotalPoints() (función inexistente en v1.0.4)
- GetSigImageB64(callback) async en vez de llamada síncrona sin valor de retorno
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mismo fix que recepcion.php: servir el JS desde assets/js/ en vez
de localhost:47289 que no sirve archivos estáticos.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copiado de C:\Users\ZAIDA\AppData\Local\TopazSigWeb\SigWebTablet.js
en SOPORTE-3 (39 KB, versión instalada localmente).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El JS no es servido por SigREST sino instalado en AppData del usuario.
Se agrega /assets/js/SigWebTablet.js como primera URL; los puertos
localhost quedan como fallback.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Chrome bloquea scripts HTTP desde páginas HTTPS; SigWeb >=1.6.4 expone
el SDK en https://localhost:47290 para este caso. Fallback a http://47289
para instalaciones antiguas.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- cancelar_toma_pendiente: añade JOIN por paciente_id para prevenir IDOR
- cancelar_toma_pendiente: requiere turno_id para validar propiedad
- get_tomas_pendientes: porta filtros condicionales y _tomas_config de
guardar_toma.php para mostrar conteo de firmas correcto
- lugar.php: refresca sección tomas previas al completar via turneroFirmado
- lugar.php: muestra error en catch de cargarTomasPrevias en vez de silenciar
- lugar.php: limpia _tomaAlertados al cancelar toma previa
- lugar.php: pasa turno_id en POST de cancelar para ownership check
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Cuando el paciente regresa con un turno nuevo, toma de muestras muestra
las tomas en_progreso de visitas anteriores con botón Continuar o Cancelar.
Cancelar marca estado='rechazado' (campo ya existía en el enum).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Gesta/Partos/Cesáreas/Abortos ahora caben en una fila usando CSS :has(.campo-cuarto)
que activa grid de 4 columnas solo cuando el campo tiene clase campo-cuarto.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a patient selects 'Muestra pendiente' (prioridad F) at the kiosk,
the turn is immediately set to en_espera_lugar pointing to the first
active muestras location. Recepcion never sees it; toma de muestras
picks it up from its queue with no consent forms required.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_mpAutoFillHora was gated behind hayFirmaIniciada, so it never ran
on a fresh form where no signatures exist yet. Now always fills the
hora field of the first visible firma widget; scroll only when at
least one signature has already been saved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was sending 'consentimiento_turno' (plain text fallback) while the
configured template is 'consentimiento_turno_v2'. Now reads
turnero_wa_template and turnero_wa_lang from lab_config, matching
the same logic used in create_turno.php (kiosk).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add turno_id column to rips_examenes_pendientes (already migrated)
- Filter turno_id IS NULL in get_examenes_rips.php query
- New marcar_rips_usado.php marks record as consumed when loaded
- cargarExamenesRips() calls marker after loading exams into the turn
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
If the kiosk captured a numeric document number as paciente_nombre,
fire consultarExamenesRips immediately on turn open without waiting
for the receptionist to manually search the patient.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the history section required a manual click to expand and load.
Now it opens and fetches automatically when a patient is selected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
--disable-print-preview conflicted with --kiosk-printing, routing to
the OS print dialog instead of printing silently. Also added AHK
fallback script for edge cases.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Genera par de llaves RSA (cert en config/qz/)
- api/qz_sign.php firma los print jobs con SHA512
- assets/js/qz-print.js conecta QZ Tray y envía trabajo HTML
- ver_formulario_enviado.php carga QZ cuando ?autoprint=1
- Fallback a window.print() si QZ no está instalado
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Detecta si el pad físico responde (GetTabletState), si falla instanciar
SigWebTablet (posible conflicto con SigPlus), y guía paso a paso.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Detecta SigWeb al cargar; muestra badge verde solo si localhost:47289
responde. Si no hay pad, no aparece nada.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Intenta localhost:47289 primero; si falla prueba localhost:8080.
Funciona para instalaciones con puerto no estándar sin cambiar Oracle.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Detecta al cargar la página si localhost:47289 responde; si no,
oculta todos los .btn-topaz para evitar el error al usuario.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El alert() bloqueaba la UI. Ahora muestra un banner flotante de 5s
que no interrumpe el flujo y sugiere usar firma manual como alternativa.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El iframe pasa targetMs al padre via postMessage. El padre corre su propio
intervalo (5s) que dispara la notificación si el modal está cerrado.
Si el iframe alcanza el 0 primero, cancela el del padre para no duplicar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Usa Web Notifications API via postMessage iframe→parent para alertar
incluso cuando el tab está en segundo plano o la pantalla ocupada.
Pide permiso al iniciar el protocolo (primer gesto del usuario).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
La alerta y el countdown mostraban "Toma · Otro" sin el minuto.
Ahora usan _mpEffectiveLabel para mostrar ej: "Toma · Otro - 2".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sin el sort, Otro (2 min) aparecía después de Minuto 15 en schema order,
haciendo que el countdown arrancara con 15 min en vez de 2.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Agrega _mpEffectiveLabel() que añade " - N" al label cuando la sección
es Otro y _mpOtroHora tiene valor, mostrando ej: "Toma · Otro - 2".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El render iteraba $esquema en orden original del JSON — Otro siempre
quedaba de último. Ahora se re-ordena $esquema agrupando las secciones
de toma por su minuto (usando $_mpSepOrder construido del usort ya
existente) antes de entrar al foreach de render.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- sel-lugar movido a última sección (antes de acciones) para que el
usuario lo seleccione justo antes de guardar/pasar
- resetCheckboxes() ahora también limpia sel-lugar entre turnos
- pasarALugar() lee sel-lugar directamente como primera opción,
evitando que un solicitudActiva.lugar_id desactualizado cause errores
- Botón refresh (fa-sync-alt) en cabecera de consentimientos llama
refrescarConsentimientosLugar() para ver estado sin recargar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cada chip envuelto en .mp-chip-grp con CSS order = minuto
- Otro arranca en order:9999 (último); al digitar el valor se mueve
en tiempo real al lugar cronológico correcto
- Si ya tiene valor guardado (_mpOtroHora), abre posicionado
- Click handler usa .mp-chip-grp para encontrar input/unit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fecha usa COALESCE(firmado_at, enviado_at, t.creado_at) porque
turnero siempre deja enviado_at en NULL
- filtro por fecha también usa ese COALESCE para no excluir registros
- total_envios y total_completados suman turnero_consentimientos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Chip "0 min" queda marcado por defecto al abrir configurar tiempos
- Si se selecciona "Otro", bloquea guardar hasta que se ingrese la hora
- La hora de "Otro" se guarda en datos_respuestas._otro_hora
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Garantiza que la cadena de tomas siempre sea 0→15→30→... sin importar
el orden en que se guardaron en _tomas_config.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Reemplaza JSON.stringify en atributo HTML por data-atributos + event
delegation, evitando que las comillas dobles rompan el handler.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- DB: columna genero_permitido en exam_tipos (M/F/NULL)
GX,FV → solo femenino | PSA,FPSA → solo masculino
- recepcion.php: TomSelect muestra badge rojo y deshabilita opciones
incompatibles al seleccionar paciente; elimina los ya agregados
- create_solicitud.php: validación backend 422 si hay conflicto género/examen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Schema F-LAB-28: reemplaza 9 secciones hardcodeadas por 17 puntos de
tiempo (0,15,30,...,195 min, 3pm, 4pm, Otro)
- PHP: detecta sección "Otro" como toma válida (sentinel PHP_INT_MAX)
- JS/CSS: reemplaza checkboxes por chips clicables en el panel de
configuración; chip "Otro" muestra input de hora libre
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al guardar una solicitud en recepción, escribe los exámenes en la bandeja
temporal WhatsApp (rips_examenes_pendientes) con DELETE+INSERT del día.
Al volver a seleccionar el mismo paciente, get_examenes_rips los detecta
como fuente=cache y los auto-carga sin confirmación.
También fix en get_examenes_rips: exámenes con codigo_legacy=NULL ahora
se buscan por codigo como fallback (COALESCE).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Si _llamar no actualiza turnoActivo a en_servicio (fallo silencioso del
cliente), recuperarTurnoActivo() vuelve a consultar el servidor y carga
el turno correctamente, mostrando el botón rellamar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- buscar_cie10.php: busca por código o descripción, límite 12 resultados
- inp-diag: dropdown estilo empresa, Enter selecciona primero
- selectOnTab:false en TomSelect de exámenes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Añade flag $_mpSkipSec para secciones excluidas por _tomas_config; la
condición anterior dependía de !$modoEditar y nunca ocultaba nada
cuando el consentimiento está en_progreso.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PHP's PDO in silent mode returns false on prepare() when table doesn't
exist; calling ->execute() on false throws TypeError (Error, not
Exception). Changed catch to \Throwable and added explicit checks so
the real error message is returned as JSON instead of HTTP 500 empty.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El badge 1/9 ignoraba la configuración guardada e incluía todas las tomas
sin condición. Ahora filtra relevantIds por los firma-ids en _tomas_config,
igual que lo hace guardar_toma.php y el render PHP del formulario.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- migrations/20260717_cie10_diagnosticos.sql: CREATE TABLE cie10_diagnosticos
- api/lab/ingest_diagnosticos.php: POST endpoint that receives batches of
{cod, concepto} rows and upserts into cie10_diagnosticos (ON DUPLICATE KEY)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al crear un paciente nuevo desde el modal, el objeto no incluía genero
por lo que el bloque embarazada no se ocultaba para masculinos. Al editar
también se actualiza genero y se re-evalúa la visibilidad del bloque.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PHP: restaura auto-apply de _tomas_config para mostrar tomas correctas en recarga
- Badge: agrega botón 'Modificar' cuando el examen ya está configurado
- Panel: en modo modificar pre-marca las tomas guardadas y deshabilita
las ya firmadas (con ícono ✓ y opacity reducida)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PHP: elimina auto-aplicación de _tomas_config guardada; las tomas
siempre parten limpias hasta que el profesional configure manualmente
- JS: elimina auto-guardado cuando hay 1 sola toma por grupo
- JS: restaura _mpGetGroupsForExam a mostrar todos los grupos disponibles
(condicionados del examen + genéricos sin condición)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_mpGetGroupsForExam ahora solo incluye los grupos genéricos ('Toma')
cuando el examen no tiene secciones propias condicionadas.
Para Taukit/Heliprobe/etc. aparecen únicamente sus tomas.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Texto: "Marque las tomas que va a realizar."
- Título de grupo solo aparece cuando hay más de un grupo;
con un solo grupo (caso habitual) los checkboxes salen directamente
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El profesional elige manualmente cuáles tomas aplicar antes
de iniciar el protocolo, en vez de tener que desmarcar las que no usa.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al vincular un paciente con genero='M' se oculta el bloque y
se desmarca el check. Al desvincular/resetear vuelve a mostrarse.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Grid pasa de 2 a 3 columnas en modo compact; campo-full abarca las 3
- texto/textarea siguen en fila completa (campo-full)
- numero, edad, fecha, hora ocupan 1/3 → caben 3 por fila
- form-check-input 1.35em, min-height 2.2rem para área táctil cómoda en tablet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- create_turno.php: reemplaza http:// por https:// en el link enviado
por WhatsApp, evitando que Android CCT bloquee páginas HTTP
- ver_formulario_enviado.php: agrega botón "Abrir en navegador" en la
barra de acción cuando el modo es turnero, como fallback para Android
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Modal con select de prioridad (cargado desde BD) y campo opcional
de cédula/nombre. Llama a create_turno.php que ya maneja sesión,
duplicados, SSE y notificación WhatsApp.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_cola.php: quita orden por orden_peso, deja solo creado_at ASC
- recepcion.php: cards con prioridad distinta a E (general) muestran
borde izquierdo y fondo tintado con el color de la prioridad
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Campo inp-recibo aparece/desaparece al seleccionar 'Tarjeta' en forma de pago
- Se incluye en el payload como numero_recibo y se guarda en turnero_solicitudes
- Migración: ADD COLUMN numero_recibo VARCHAR(40) en turnero_solicitudes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Si eps o ciudad del paciente no existe en el select, se agrega como opción
temporal para no sobrescribir con vacío al guardar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tabla lab_ciudades creada y poblada con 86 ciudades existentes
- Módulo lab_ciudades: listado, crear, editar, activar/desactivar, eliminar
- API /api/lab/ciudades.php: GET list, POST save/toggle/delete
- Modal paciente: campo ciudad cambiado a select, cargado junto con EPS
en un solo Promise.all al iniciar; Cúcuta preseleccionada por defecto
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tabla lab_eps creada y poblada con valores existentes de lab_pacientes
- Módulo lab_eps: listado, crear, editar, activar/desactivar, eliminar
- API /api/lab/eps.php: GET list, POST save/toggle/delete
- Modal paciente en recepción: campo EPS cambiado de texto libre a select
cargado desde lab_eps al iniciar la página
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>