Muestra el detalle de cada toma (tipo, quien la recibió, tiempo) cuando un
turno tuvo varias, para explicar tiempos de servicio prolongados. Los
documentos firmados ahora se abren en un modal en vez de nueva pestaña,
preservando los filtros de búsqueda activos.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- save_domicilio.php: permite editar si el enfermero está asignado (no solo si lo creó)
- enfermero_portal.php: botón Editar en domcard, método abrirEditar() pre-carga el modal existente
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ai_chat.php: cuenta tokens reales desde Gemini usageMetadata, persiste en lab_config, bloquea con HTTP 402 al agotar 1.000.000
- dashboard.php: _actualizarTokens() actualiza barra visual, _bloquearLIA() deshabilita input+mic y muestra aviso de soporte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LIA: saludo de voz al abrir (1x/día), auto-escucha 3s, olas animadas
- Gráfica de barras (Chart.js) con facturación real + proyección lineal
- Exportar a Excel (.xls con HTML table, se abre directo en Excel)
- Botón "Informe WA": envía resumen del día por WhatsApp a número elegido
- Diseño accesible: texto más grande, botones claros para usuario adulto
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
API: agrega por_prioridad con último código llamado a muestras por letra.
Vista: badges con color de prioridad mostrando "A: A-023", "B: B-011", etc.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- API: agrega tipo_documento y numero_documento al SELECT
- Vista: línea 1 = nombre BD + CC/doc, línea 2 gris = Kiosko: nombre
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- APIs: total_min = creado_at → fin_lugar_at (solo finalizados)
- Dashboard: KPI card 'Total prom. puerta a puerta' + columna Total en tabla
- Historial: columna Total en tabla
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Usaba ['id'] sobre un int → sesionId=0 → sin resultados.
Cambiado a sesionHoy() que sí retorna array con 'id'.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_bandeja.php: contar estado='rechazada' (no 'pendiente')
- chip renombrado a "Muestras rechaz." con ícono fa-flask
- card muestra badge rojo con ícono y cantidad cuando hay rechazadas
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Elimina el lookup innecesario en users/$userId que nunca se usaba.
Ahora sigue el mismo patrón que recepción: BD telefono → paciente_cel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El paciente siempre tiene celular registrado; el error ocurría porque se
requería match en users. Ahora usa paciente_cel como fallback final.
Revierte la guarda del frontend del commit anterior.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Si turnoActivo.paciente_cel está vacío, _ofrecerEncuesta retorna sin
mostrar la barra, evitando el error de WA al intentar enviar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Si el nombre registrado en BD difiere del ingresado en kiosko, muestra
ambos: el BD como principal y el kiosko en gris debajo.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- esc() ahora escapa backticks (`) para evitar que nombres de paciente
con backticks rompan el template literal
- onclick simplificado: eliminado .replace(/'/g,\\'\\\\\\'\\'') que era JS
inválido (backslash fuera de string literal dentro de ${}); esc() ya
convierte comillas simples a '
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al olvidar una toma los tiempos del ciclo anterior quedaban en la DB,
haciendo que al re-firmar la toma reseteada las demás aparecieran
inmediatamente (sin countdown) y el profesional tuviera que firmar 3
veces en vez de 1.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
bin2hex(random_bytes(16)) genera hex sin guiones que no pasa la validación
de ver_formulario_enviado.php — el formulario adicional daba token inválido
al intentar firmar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El timer de 1s solo escaneaba chips en la cola principal. Los pacientes
en espera entre extracciones (muestra_espera_at IS NOT NULL) viven en el
panel de espera sin chip, por lo que nunca sonaba. Se añade un chip oculto
con data-toma-at en cada fila del panel; el timer existente lo detecta y
dispara banner + sonido en todas las tablets del grupo.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Chip "Muestras pend." y nuevo "Prog. en espera" son toggles de filtro
- Se resaltan con borde al activarse; combinables entre sí y con el dropdown
- API retorna muestras_pendientes (turnos con ≥1 muestra pendiente) y
prolongadas_pendientes (toma progresiva en espera entre extracciones)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Inputs desde/hasta pasan al API y filtran por rango de fechas
- Buscador cubre nombre, número de orden, código y examen
- API usa fecha cuando se pasa, sesión actual como fallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Añade conteo de muestras_pendientes por turno en la lista y opción
de filtro en el selector de estados de la bandeja del día.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Recepción ve en una barra inferior qué turno atiende cada estación de
toma de muestras (verde = ocupada, gris = libre), cuántos están en
espera y cuántos en espera entre muestras progresivas. Se refresca cada 7 s.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al llamar un paciente de toma progresiva desde la espera, ahora se
actualiza lugar_destino_id al puesto que llama, se pone llamado_lugar_at
para que el display anuncie al paciente, y se notifica por SSE. El JS
abre la ficha y muestra el toast igual que un llamar normal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Badge junto al título "Exámenes solicitados" que muestra cuántos
exámenes lleva el turno actual. Se actualiza en tiempo real al
agregar o quitar ítems del TomSelect.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
login.php y index.php enviaban a v=recepcion a cualquier usuario con el
módulo turnero que no fuera bacteriólogo, incluyendo superadmin, admin
y supervisor. Esto causaba que al cerrar sesión y volver a entrar, el
admin aterrizaba en recepción en vez del dashboard.
Ahora:
- bacteriologo → lugar_id=1
- superadmin/admin/supervisor → v=dashboard
- recepcionista/otros → v=recepcion (comportamiento previo correcto)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>