100 Commits
Author SHA1 Message Date
Lizandro GuarnizoandClaude Sonnet 4.6 339ca8a40d debug: habilitar display_errors temporalmente para diagnosticar 500
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-06 08:47:07 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3dbf40e4fa feat(formulario): firma profesional directa en modal embebido (formularios solo-pro)
- ver_formulario_enviado.php: pre-scan $_soloFirmaPro; muestra canvas pro cuando modoTurnero+embebido+sesión activa+sin firma paciente
- fpw-save JS: recopila campos del form y envía solo_profesional=true; al guardar muestra éxito y postMessage turneroFirmado
- firmar_profesional_consentimiento.php: si solo_profesional=true guarda datos_respuestas y marca estado=firmado

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:49:39 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1e2cfbaa0b refactor(lugar): embebido como botón en fila de consentimiento, no sección separada
- Eliminar sec-form-embebido como sección independiente
- En modo embebido: fila de consentimiento muestra botón "Firmar" que abre modal directamente por token
- En modo link: botones "Firmar presencial" + "WA" como antes
- abrirModalConsentimientoPorToken(token) recibe token directo sin cache

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:37:50 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 b399c3710e fix(formulario): no mostrar firma paciente si schema tiene firma_profesional
Usar _esquemaTieneFirmaAlguna (cualquier tipo firma) en lugar de
_esquemaTieneFirmaPaciente para suprimir el widget fallback.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:32:01 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a0189a61eb feat(lugar): formulario embebido como modal en lugar de iframe inline
- Botón "Abrir formulario de firma" en ficha abre modal overlay
- Modal con iframe cargando ver_formulario_enviado.php?embed=1
- postMessage 'turneroFirmado' cierra modal, refresca consentimientos y oculta botón
- Token pre-cargado al abrir ficha para apertura rápida del modal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:16:22 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 27135e4d2f fix(formulario): múltiples correcciones modo embebido/turnero
- ver_formulario_enviado.php: usar opciones??options??items como fallback de claves del schema
- ver_formulario_enviado.php: marcar _esquemaTieneFirmaPaciente en cualquier campo firma (no solo sin SVG), evita mostrar firma paciente cuando schema solo tiene firma_profesional
- ver_formulario_enviado.php: modo embebido (?embed=1) con layout compacto para iframe
- lugar.php: pasar &embed=1 al iframe src

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:15:34 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7b734195e0 fix(lugar): incluir formulario_modo en query de lugares
La columna no estaba en el SELECT, siempre quedaba 'link'.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 12:01:59 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 5dc2b0efa8 fix(turnero): corregir envío WA desde recepcion
- recepcion.php: quitar guard !solicitudActiva en enviarConsentimientosTodos (bloqueaba silenciosamente antes de guardar solicitud)
- send_consentimiento.php: eliminar requisito de solicitud y exámenes para poder reenviar; usar WhatsAppService('turnero') con rawComponents correctos (1 body param=codigo, button param=token); JOIN lab_pacientes también via t.paciente_id como fallback de teléfono

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:59:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 2dec300f3a Fix professional signature row only showing when form schema requires it
Only display the 'Falta firma enfermero' row and button when the assigned
consent form actually contains a firma_profesional field in its esquema.
get_consentimientos.php now computes requiere_firma_profesional from the
JSON schema and recepcion.php gates the row on that flag.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:55:20 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 05c7230eda fix(formularios): pre-fill fecha_hoy and edad in ver_formulario_enviado
- Modo editar: fecha_hoy → type=date prefilled with today; edad → type=number prefilled from paciente.fecha_nacimiento
- Modo vista: if no saved value, fecha_hoy shows today's date; edad calculates from DOB instead of skipping

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:47:33 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f09fcd5b4e fix(turno): no enviar WA si el lugar de recepción está en modo embebido
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:44:59 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 e1f0fe3450 refactor(formularios): split 'calculado' into two direct field types
Instead of one field with a sub-option, there are now two independent palette
items under a 'Calculados' section:
- fecha_hoy: renders type=date pre-filled with today's date (YYYY-MM-DD)
- edad: renders type=number pre-filled with age calculated from paciente.fecha_nacimiento

Both are editable by the patient and have a yellow tint.
Preview in the builder also shows the live date value for fecha_hoy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:44:11 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f8245b4d6f feat: modo embebido de formulario por lugar (link vs iframe)
- Nueva columna turnero_lugares.formulario_modo (link|embebido)
- Config: radio en modal de edición para elegir el modo
- lugar.php: muestra iframe con ver_formulario_enviado al activar turno
- API get_consent_token.php: crea/obtiene token para turno+lugar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:35:45 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 daa9827d93 feat(builder): tablet-friendly drag — pointer events + tap-to-add palette
- Palette items: onclick adds field directly (tap on tablet, no drag needed)
- Canvas reorder: PointerEvents drag (touchstart/move/end) with visual ghost
  and blue line indicator; HTML5 drag kept for mouse/desktop
- CSS: drop-above/drop-below indicators, ghost element, larger touch targets
  for handle and action buttons on coarse pointer devices
- Hide preview panel on ≤680px to give more canvas space on small tablets
- calculado added to TIPO_ICON map

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:28:28 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1385c25b30 feat(formularios): add 'calculado' field type with fecha_hoy and edad sub-types
Builder:
- New palette item 'Campo calculado' (fa-calculator)
- Editor modal lets user pick: Fecha de hoy / Edad del paciente
- Preview shows yellow-tinted input with calculator badge

form_cliente.php:
- fecha_hoy: pre-fills today's date (YYYY-MM-DD), editable by patient
- edad: calculates age from patient's fecha_nacimiento, editable
- Collected on submit like any normal input

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:23:36 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 0c68dff307 fix: mostrar canvas para todos los campos firma en modo turnero
Antes solo el primer campo (consentimiento) tenía canvas; el segundo
(desistimiento) se omitía. Ahora cada campo firma tiene su propio widget
usando clases CSS en vez de IDs hardcodeados.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:22:18 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 597ec87964 fix: redirigir UUID tokens de form_cliente.php a ver_formulario_enviado.php
El botón WA del template apunta a form_cliente.php?t={{1}}; si el token
es UUID (turnero) se redirige al flujo de consentimiento correcto.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:16:13 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 538af86407 fix(wa): enviar solo el token como parámetro del botón URL, no la URL completa
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 11:11:54 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 b47f6019cd fix(turno): no prepender +57 si el tel ya tiene código de país
573168950803 quedaba como +57573168950803 — WhatsAppService lo normaliza solo.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:47:51 -05:00
Lizandro Guarnizo 9d34c6b984 debug: mostrar teléfono de paciente por documento 2026-07-03 10:42:08 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 735d70dc50 fix(wa): enviar botón URL como componente button/url, no como header
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:34:55 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7a56ec25a0 fix(wa): usar language_code real de la plantilla (es, no es_CO)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:32:15 -05:00
Lizandro Guarnizo 61c8c0b9ca fix debug: quitar creado_at del test INSERT 2026-07-03 10:30:39 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f18104dd5d fix: quitar creado_at (columna no existe en turnero_consentimientos)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:28:43 -05:00
Lizandro Guarnizo ad0eefe31f debug: marker [usite] para verificar deploy 2026-07-03 10:26:38 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1bb520ef3f debug: agregar diagnóstico tabla consentimientos y turnos del día
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:24:46 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 434df7b741 fix(turno): crear consentimiento siempre, enviar WA solo si hay teléfono
Estado queda 'pendiente' si no hay cel; se actualiza a 'enviado' al enviar WA.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:17:16 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1a92707e3e create_turno: corregir params plantilla (solo {{1}}=código) + fix debug test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:09:52 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 707ef24572 configuracion: sección perfil WhatsApp Business (foto, about, dirección, email, webs, categoría)
- wa_profile.php: GET carga perfil desde Graph API, POST guardar campos, POST foto sube imagen
- configuracion.php tab sesión: UI con foto de perfil editable, campos del negocio y botón guardar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:08:41 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 eddfe4d16c debug_turno_wa: corregir tabla system_config para token/phone WA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 10:02:34 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f09b7d42fd debug: agregar debug_turno_wa.php para diagnosticar envío WA desde kiosko
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 09:59:53 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 d232cf69f5 create_turno: usar canal 'turnero' para envío de WA desde kiosko
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 09:57:13 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6fec24f850 create_turno: enviar turno + consentimiento en un solo WA desde el kiosko
- Al crear turno busca el formulario configurado en el desk de recepción
- Crea token de consentimiento y lo marca como 'enviado'
- Envía plantilla consentimiento_turno con nombre real, nombre formulario y link
- Fallback texto plano incluye el link si está disponible
- Tipo F (solo muestra) sigue usando plantilla sin consentimiento

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 09:41:44 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9d57bbac5c recepcion: historial paciente muestra 5 visitas por página (antes 15)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 09:16:44 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 03f02d2788 fix(webhook): skip SSE notification and DB notification for canal=turnero messages
Turnero messages were triggering the SSE event that conversations.php listens to,
causing the contact to flash briefly at the top of the list before disappearing
on the next poll (since get_conversations.php filters them out by canal).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:43:20 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3f964b424a fix(conversations): filter canal='turnero' out of individual chat message views
get_user_messages.php and get_recent_messages.php now exclude canal='turnero'
so the main bot chat only shows bot messages even for users who also have
turnero conversations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:39:07 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7eea2ff7ba fix(conversations): exclude canal='turnero' messages from main conversations list
All queries in get_conversations.php now filter (canal IS NULL OR canal='bot')
so the main chat only shows bot conversations and the turnero chat stays isolated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:35:49 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 4d04fea1de fix(turnero): save outgoing messages with canal='turnero' so they appear in chat
saveOutgoingMessage() now reads __app_meta.canal and stores it in conversations.
sendMediaById() accepts a $meta param and forwards it to saveOutgoingMessage.
chat_upload_media.php passes $extra (canal=turnero) to sendMediaById.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:32:23 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 5acd46df5a fix(turnero): route incoming messages by phone_number_id and fix WhatsAppService canal
- WhatsAppService($canal): when 'turnero', swaps phoneNumberId to whatsapp_phone_number_id_turnero
  so outgoing messages actually go from the turnero number (not the main bot)
- webhook.php: reads metadata.phone_number_id from the payload and compares it to
  whatsapp_phone_number_id_turnero; if it matches, saves canal='turnero' and skips bot processing
- Previously all incoming messages had canal=NULL/bot so Chat Turnero never saw them,
  and all outgoing messages from Chat Turnero were sent via the wrong (main bot) number

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:26:11 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 00aee615c5 lugar: cambiar label 'TOMA DE MUESTRAS' → 'ENTREGA DE MUESTRAS'
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:25:30 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 20146535c7 formularios: agregar botón Clonar para duplicar plantillas
- save_formulario.php: manejo de {clonar:true} → crea copia con "Copia de [nombre]"
- lab_formularios.php: botón icono copy en cada tarjeta + función clonarFormulario()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:21:50 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 17703f0157 fix(chat-turnero): prevent messages mixing between contacts on fast switching
Capture activeUserId at the start of each async function (fetchMessages,
loadMoreMessages, pollMessages) and discard the response if the user changed
contacts while the request was in-flight.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:19:52 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a0979e31e7 recepcion: quitar botón duplicar del historial (va en sección formatos)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:19:27 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 78e71d5926 recepcion: mostrar kiosko + paciente vinculado en dos líneas separadas
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:15:03 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c511da18bd recepcion: fix solo_muestras, reorder fields, duplicar visita, kiosko label
- create_solicitud.php: evitar SQL `IN ()` vacío cuando solo_muestras=1 sin exámenes
- recepcion.php: mover embarazada+médico después del historial del paciente
- recepcion.php: actualizar label kiosko con nombre real al vincular paciente
- recepcion.php: botón "Duplicar" en historial para copiar exámenes y pago de última visita
- recepcion.php: omitir validación de consentimientos pendientes cuando es solo_muestras
- recepcion.php: agregar alias esc() = escHtml() usado en buscarMedico

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 08:13:38 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 d3826972ad feat(turnero): selector de médico tratante en recepción, visible en toma de muestras
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:55:32 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ec614c2a89 feat(chat-turnero): backend APIs for media upload, reactions, and template messages
- chat_upload_media.php: multipart upload to WhatsApp Media API, sends image/video/audio/document
- chat_react.php: sends emoji reaction to a message via WhatsApp, updates reaction_emoji in DB
- chat_send_message.php: extended to support type=template with lang+params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:53:23 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a7ab91615f feat(chat-turnero): rich messaging UI — images, video, audio, reactions, emoji, templates
- Attach button with file preview (image thumb for images, name+size for others)
- Audio recording via MediaRecorder API with live timer; sends as voice note
- Emoji panel with 35 common emojis (medical/comms focused)
- Reaction picker on message hover — sends via chat_react.php API
- Template modal (name, lang, JSON params) — sends via chat_send_message.php type=template
- buildBubble() now renders: inline images, <video> player, <audio> player, doc links with type icon
- Shows reaction_emoji below bubble and status tick on outgoing messages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:53:23 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3b378c0d75 feat(medicos): seed 444 médicos + columnas telefonos/email en tabla y modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:51:57 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 48f9e32c22 chore(migrations): script para correr migraciones pendientes de una vez
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:48:03 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 bb6ee12e0a fix: restaurar migraciones del turnero perdidas por force push
- 20260626_activar_numero_turnero.php
- 20260626_turnero_canal_conversations.sql

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:43:21 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1574f12275 feat(medicos): módulo CRUD de médicos con tabla, búsqueda y modal edición
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:42:36 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 665fee99a9 fix(turnero): restaurar APIs del chat perdidas por force push del servidor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:41:40 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 d93dccf006 feat(turnero): agregar Verificar Paciente al menú admin/supervisor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:39:00 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 cb77425ca2 feat(turnero): vista verificar_paciente dentro del ERP con Layout
- Crea modules/turnero/views/verificar_paciente.php con Layout::open/close
- Flujo completo: cédula → OTP → éxito, mismo JS que verificar.php público
- Link del módulo ahora apunta a erp.php?m=turnero&v=verificar_paciente

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:35:00 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ff0fd3284e fix(turnero): usar plantilla correcta según tipo de turno y ajustar sidebar
- create_turno.php: tipo F usa turnero_wa_template_muestra, resto usa turnero_wa_template
- styles.css: has-active ya incluye font-size 0.82rem (verificado)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:30:06 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 4f686bd9ca fix(sidebar): restaurar diseño con colores por módulo
- nav-link.active: color-mix tintado, font-size 0.93rem, border 4px
- sidebar-section: 0.72rem base, 0.82rem cuando tiene subitem activo
- sb-group: fondo y borde tintados con --cat-color via color-mix

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:28:46 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 fd95e7b38a fix: restaurar todas las optimizaciones móvil/tablet perdidas por force push
- chat.php: recuperado y re-aplicado panel-switch móvil, viewport iOS,
  safe-area, sticky topbar, link ← Menú, botón volver
- lugar.php: panel-switch tablet (≤860px), botón ← Cola, JS mobile
- recepcion.php: panel-switch tablet (≤900px), botón ← Cola, JS mobile
- sidebar.php: soporte atributo target en links de módulo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:25:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 be4cb88420 fix(turnero): restaurar Chat Turnero en menú admin/supervisor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:19:32 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 98507ad1a5 fix(turnero): restaurar dos plantillas WhatsApp en tab Sesión
- Plantilla con consentimiento (turnero_wa_template)
- Plantilla muestra pendiente (turnero_wa_template_muestra)
- sesion_turno.php guarda ambas en lab_config

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:17:17 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 a592ddb30d fix: restaurar cambios revertidos por rebase del servidor
- verificar.php: BASE_URL absoluta en fetch, fix paste multi-dígito
- send_otp.php: mensaje SMS correcto sin dos puntos ni expiración
- module.php: Chat Turnero y Verificar Paciente para recepcionistas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:13:39 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 e1ba78edb8 fix(otp): pegar código completo distribuye dígitos en todos los campos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:12:28 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 34004b4d98 feat(turnero): opción solo entrega de muestras con prioridad y badge naranja en cola
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:07:05 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 76dda4722a feat(turnero): pago combinado con desglose por efectivo, transferencia y tarjeta
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-03 00:02:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 4626ca3f28 feat(display): nombre paciente más grande y visible en overlay de llamada
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:58:09 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 38bd211ca6 feat(kiosko): mostrar nombre/cédula en ticket y quitar posición en cola
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:53:39 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c9e5744de4 feat(turnero): campo embarazada en recepción y badge en toma de muestras
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:48:03 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 d40da57a60 fix(sidebar): mantener posición de scroll al navegar entre páginas
Guarda scrollTop en localStorage al hacer clic en un nav-link y lo
restaura en DOMContentLoaded, evitando que el menú lateral salte al
inicio en cada navegación.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:40:55 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 7475f3c58e fix(turnero): mostrar nombre del paciente en cola al vincularlo en recepción
Al vincular un paciente al turno, actualiza paciente_nombre con el
nombre_completo real de lab_pacientes. El siguiente poll de la cola
muestra el nombre en lugar de la cédula del kiosko.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:35:45 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 8074f33b32 fix(turnero): eliminar duplicados en pantalla TV al llamar turno
callKey usaba id+llamado_at: si llamado_at llegaba null en el primer
poll y con valor en el segundo, se generaban dos claves distintas para
el mismo evento y el turno se anunciaba dos veces.

Cambia callKey a String(id) — cada turno se anuncia una sola vez
por sesión de pantalla, sin importar cambios en el timestamp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:32:31 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c4154b5b61 fix(turnero): deduplicar historial de llamados por turno en pantalla TV
El array 'llamados' acumulaba una entrada por cada lugar al que pasaba
un turno (recepción + toma de muestras). Al insertar un nuevo llamado
se elimina la entrada previa del mismo turno, dejando solo el último lugar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:28:21 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 910edeb876 feat(turnero): botón de llamado por registro en lugar/toma de muestras
- Agrega botón campana por cada card en cola (solo turnos en_espera_lugar)
- Click en card abre ficha sin llamar; campana llama ese turno específico
- Llamar siguiente ahora también llama de verdad (antes solo abría ficha)
- Cards en_servicio mantienen indicador de estetoscopio sin botón

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:25:34 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6adbcc3059 feat(turnero): modal completo de paciente en recepción
- Reemplaza window.open a lab_pacientes.php por modal Bootstrap inline
- Modal incluye campos completos: datos personales, contacto (con verificador WA), ubicación y EPS
- Botón Ver/Editar en paciente vinculado carga datos desde API y abre modal en modo edición
- Botón Cambiar desvincula y enfoca el buscador
- Al crear: seleccionarPaciente() auto-vincula al turno y cierra modal
- Al editar: actualiza labels en pantalla sin perder el turno activo

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-02 23:02:24 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 062f565ab5 fix(pacientes): corregir acceso a d.found y d.user_id en verificarWhatsapp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:29:36 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6d63112d76 fix(api): convertir user_id vacío a null antes de guardar paciente
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:28:43 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 9e7637582d fix(api): agregar db() helper, corregir requireAuth() en check_whatsapp
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:27:03 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 92e4d01181 feat(sidebar): color por categoría via CSS custom property --cat-color
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:05:57 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 e90cfda3f3 feat(dashboard): accesos rápidos en dropdown por grupo, filtrado por rol
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 09:03:57 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 d6e1d083f4 revert(sidebar): eliminar sub-acordeón — restaurar sidebar y module.php a estado estable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:56:42 -05:00
Lizandro Guarnizo f724e2e94c Revert "fix(recepcion): mostrar nombre, cédula y celular en resultados de búsqueda de paciente"
This reverts commit 1af731ee44.
2026-06-24 08:54:17 -05:00
Lizandro Guarnizo 86be0669af Revert "fix(recepcion): reemplazar template literals anidados por concatenación compatible"
This reverts commit 0021af36a5.
2026-06-24 08:54:17 -05:00
Lizandro Guarnizo 3b1b7c9333 Revert "fix(sidebar): null-check en route de children para evitar TypeError en PHP 8.2"
This reverts commit ba27511414.
2026-06-24 08:54:17 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ba27511414 fix(sidebar): null-check en route de children para evitar TypeError en PHP 8.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:52:26 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 0021af36a5 fix(recepcion): reemplazar template literals anidados por concatenación compatible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:50:47 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 1af731ee44 fix(recepcion): mostrar nombre, cédula y celular en resultados de búsqueda de paciente
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:45:43 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 af584bcc26 feat(pacientes): verificar WhatsApp al ingresar teléfono, vincular user_id al guardar
fix(recepcion): mostrar nombre_completo en resultados de búsqueda de paciente

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:44:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 018d445846 fix(pacientes): tabindex ordenado en formulario, ciudad=Cúcuta por defecto, prefijo tel sin tab
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:39:51 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 bbee9c0a5c feat(sidebar): sub-acordeón para recepción y estaciones de muestras en turnero
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:35:42 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 90baff34f9 fix(turnero): agregar sidebar toggle en vistas standalone (recepcion, lugar, configuracion)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:31:08 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 da594e0021 fix(dashboard): mostrar todos los escritorios y lugares sin agrupar ni limitar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:28:06 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 5f0565eca2 feat(dashboard): quitar botón atrás, agregar accesos rápidos a recepción y lugares
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:24:36 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 6e80ce8d1c fix(turnero): agregar sidebar toggle responsivo en vistas ERP (móvil/tablet)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:23:38 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 18051a4f31 fix(sidebar): centrar labels (styles.css tenía mayor especificidad), preservar scroll al toggle
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:11:52 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 3a66576ff8 fix(sidebar): centrar label con display:block+text-align:center, chevron absolute
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:09:15 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 4a130c22cf style(sidebar): centrar labels de categoría y resaltar categoría activa con borde+fondo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 08:04:34 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 841acf9a85 feat(turnero): filtrar sidebar por rol — recep ve solo sus desks, bacteriologo ve sus estaciones
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:56:38 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 ea0de4d487 fix: página de inicio coherente con cada rol al iniciar sesión
BD: home_page asignado a roles que lo tenían NULL:
  - recepcionista → /erp.php?m=turnero&v=recepcion
  - supervisor    → /lab_dashboard.php
  - operador_bot  → /index.php
  - readonly      → /lab_ordenes.php

login.php: fallback mejorado por módulos cuando home_page no aplica
  (turnero → recepcion, lab_dashboard → dashboard, etc.)

index.php: redirige recepcionistas y roles sin whatsapp a su página
  correcta si por algún motivo llegan al panel de WhatsApp.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:52:56 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 0f07ee22c7 feat: dropdown destino muestra Toma de Muestras, Pediatría y Ginecología
Las 8 estaciones de muestras ya comparten grupo_id=1, así que se
agrupan en una sola opción 'Toma de Muestras'. Pediatría y Ginecología
tienen grupo_id=NULL y aparecen como destinos independientes.
Cualquier estación del grupo ve los turnos asignados a él.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:39:43 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 c0f99fe9bc feat: mostrar todos los lugares destino en dropdown de recepción
El dropdown solo mostraba el primer lugar tipo muestras (LIMIT 1).
Ahora carga todos los lugares activos tipo muestras, incluyendo
Pediatría y Ginecología que ya estaban en la BD.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:37:48 -05:00
Lizandro GuarnizoandClaude Sonnet 4.6 f533891c5e fix: transición no permitida al pasar a lugar desde turno en espera
Cuando la recepcionista seleccionaba un turno de la cola sin llamarlo
formalmente (via seleccionarTurno), el turno quedaba en estado espera
en BD. Al intentar pasar a lugar, espera→en_espera_lugar no es válido.

Fix: en create_solicitud.php, si el turno está en espera al guardar
la solicitud, se promueve a en_recepcion en el mismo transaction,
preservando timestamps existentes con COALESCE.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 01:36:36 -05:00