- 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>
El kiosko guarda la cédula en paciente_nombre del turno. Al abrir el
modal de nuevo paciente, si el valor es numérico se pone en el campo
documento (no en nombre). El foco cae en nombre para que el recepcionista
complete los datos restantes. Campo editable normalmente.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Sin empresa: usa precio_base de exam_tipos (tarifa particular)
- Panel de precios se muestra con solo seleccionar exámenes (no requiere convenio)
- Total se aplica automáticamente al campo de cobro sin clic manual
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Con video activo: layout pasa de 3 columnas (37/39/24%) a 2 (1fr/29%).
El panel central (turno-activo) se oculta via CSS; left-area (listado)
absorbe el espacio liberado y el video sube de 24% a 29%.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Búsqueda automática con debounce 300ms al escribir (sin necesidad de lupa)
- Enter: si ya hay resultados selecciona el primero, si no dispara la búsqueda
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
JSON.stringify(e) dentro de onmousedown="..." producía comillas dobles
que el parser HTML interpretaba como cierre del atributo, dejando la
función con un objeto incompleto. Ahora los resultados se guardan en
_empresaResultados[] y el handler pasa solo el índice numérico.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Items seleccionados se muestran en filas verticales con chip de CUPS/código
- Búsqueda por CUPS funciona (código CUPS incluido en texto de <option>)
- Dropdown muestra chip de CUPS junto al nombre del examen
- PHP SELECT incluye columna cups de exam_tipos
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El banner de alerta solo se cerraba vía 'Ver paciente'. Si el profesional
hacía clic en 'Siguiente toma' directamente, el banner seguía parpadeando
y sonando aunque el formulario ya estuviera abierto.
- abrirTomaProgresiva() ahora llama cerrarBannerToma() + _tomaAlertados.delete()
- renderConsentimientos() preserva alertado:true si la siguiente_toma_at no
cambió, evitando beep doble al re-sincronizar después de firmar
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PHP saltaba el render de separadores y campos hijos cuando _saltarSeccion=true,
incluso en modoEditar, así que el JS evaluar() nunca encontraba los elementos.
En modoEditar ahora se renderizan con estilo oculto inicial; JS gestiona la
visibilidad cuando el usuario marca/desmarca la condición.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Cada bloque separador+hora+observaciones+firma se envuelve en una
toma-card con 3 estados visuales: signed (verde colapsable), active
(color primario pulsante) y locked (gris opaco).
- Barra de progreso con puntos y porcentaje encima de las tarjetas.
- Al firmar: tarjeta activa pasa a signed (muestra hora anotada y
miniatura colapsable), siguiente pasa a active con scroll automático.
- Countdown de espera aparece en el header de la tarjeta bloqueada
además del banner global.
- Fix: variable 'minutos' indefinida en pct del countdown → 0.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
A) Fix bug: grupos fuera de _tomas_config contaminaban $_mpMap y bloqueaban
firmas configuradas. Ahora se vacían y sus secciones se agregan a
$_mpSkippedSepIds para que PHP no las renderice.
B) Quitar campo Resultado del esquema (14 campos eliminados del form 15 en
BD). save_tomas_config.php ya no genera campo Resultado en exámenes nuevos.
Patrón queda: separador → hora → observaciones → firma_profesional.
C) Condicionamiento implícito: con el fix de A, solo aparecen las secciones
del grupo configurado en _tomas_config, sin cambios en el esquema DB.
D) UX: reemplaza popup automático por badges bajo el campo _c8j2g16.
Cada examen seleccionado muestra badge con estado (pendiente/configurado)
y botón "Configurar tiempos" que abre el panel solo al hacer clic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Auto-select tras crear examen: buscaba input[type=radio] pero el campo
_c8j2g16 es checkbox → nunca encontraba el elemento. Usa _mpSetExamChecked.
- save_tomas_config.php: añade campo Observaciones (texto) entre Resultado
y firma_profesional, igual que las secciones Toma existentes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El panel mp-cfg-overlay no tenía forma de cerrarse. Añade botón × en
el encabezado que oculta el panel, desmarca el tipo de examen y resetea
la visibilidad de secciones.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El campo tipo examen es checkbox → HTML renderiza name="_c8j2g16[]".
Todos los querySelector y el listener comparaban name="_c8j2g16" exacto
→ nunca matcheaban → visibilidad de secciones y panel de config nunca
se activaban. Añade _mpGetExamName()/_mpSetExamChecked() que aceptan
ambas variantes y los usa en todos los puntos de uso.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tras guardar la config de tomas (_mpGuardarConfig), location.reload() borraba
el checkbox seleccionado → _mpApplyExamVisibility(null) ocultaba toda la UI.
Ahora se guarda el examen en sessionStorage antes del reload y se restaura en
DOMContentLoaded, reactivando la visibilidad de firmas y tiempos.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix 1: countdown se recupera al reabrir el modal (lee siguiente_toma_at de BD)
- Fix 2: _mpIniciarCountdown recibe timestamp exacto en vez de minutos redondeados
- Fix 3: window._fpwPreFirma se emite una sola vez (no N veces por campo firma)
- Fix 4: postMessage('turneroFirmado') unificado a 2000ms en todos los paths
- Fix 5: resumen de tomas usa hora cacheada al guardar; elimina traversal DOM frágil
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
El listener bloqueaba todo con el guard de _mpModoTurnero antes de llamar
a _mpApplyExamVisibility. Ahora la visibilidad siempre aplica al seleccionar
examen; el panel de config sigue siendo solo para modo turnero.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Los campos están en div.campos-grid (hijo de .doc-body), no directamente en .doc-body.
Elimina todos los console.log de debug y simplifica _mpApplyExamVisibility.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Los div.section-title ("Firma del profesional") no tienen data-campo-id y eran
ignorados por querySelectorAll. Ahora se itera docBody.children en orden para
que inHidden aplique a todos los hijos incluyendo los que no tienen atributo.
Agrega console.log [tomas] para diagnóstico del estado de _mpAllGroups.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lógica anterior usaba sepToExam (vacío cuando labels son genéricos "Toma · X").
Nueva lógica: reúne TODOS los sep_ids de _mpAllGroups como allTomaSeps,
luego muestra solo los del grupo que coincide con el examen seleccionado
(vía _mpGetGroupsForExam). Si el examen no tiene grupos o no hay selección,
todas las secciones de toma quedan ocultas.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _mpApplyExamVisibility(): oculta/muestra secciones en el DOM usando
sep_id de _mpAllGroups, sin depender de condicion en el esquema
- Funciona aunque la BD no tenga condiciones restauradas aún
- _restore_tomas_conditions.php: migración para restaurar condiciones
en separadores usando prefijo del label vs opciones de _c8j2g16
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Panel ya no se renderiza server-side, sino que JS lo muestra al instante
cuando el usuario selecciona un tipo de examen del selector _c8j2g16
- _mpGetGroupsForExam() filtra los grupos correspondientes al examen elegido
- Si solo hay 1 toma por grupo, auto-guarda sin mostrar panel
- Si al cargar ya hay examen seleccionado y sin _tomas_config, muestra panel
- configurar_tomas.php: guarda también _c8j2g16 (exam_type) en datos_respuestas
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Botón "Añadir tipo de examen…" abre wizard directo en el formulario
- Paso 1: nombre del examen + cantidad de tomas (1-12) con +/-
- Cada toma: label, tipo (minutos / hora fija), valor
- Al guardar llama api/lab/save_tomas_config.php y recarga la página
- Auto-selecciona el nuevo examen tras recargar (sessionStorage)
- Restaura filtrado de $_gruposConfig por examen seleccionado
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Botón "Añadir tipo de examen…" debajo del selector _c8j2g16
- Al escribir y guardar, añade la opción vía API y la selecciona al instante
- api/lab/add_exam_option.php: guarda la nueva opción en el esquema del formulario
- Migración actualizada: solo elimina condiciones de separadores (no toca el selector)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _c8j2g16 pasa a texto libre ("Tipo de examen"), sin opciones predefinidas
- Separadores de tomas sin condición → siempre visibles
- Eliminar lab_tomas_config.php (ya no necesario)
- $_gruposConfig incluye todos los grupos directamente
- Script _migrate_tomas_simplify.php para actualizar esquema en BD
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Panel de protocolo ahora tiene botón "Usar todas" para cerrar sin configurar
- Si todos los grupos ya tienen una sola toma, se guarda config silenciosamente y se recarga sin mostrar panel
- Lógica de guardado extraída a _mpGuardarConfig() compartida entre ambos botones
- Botón de acceso a lab_tomas_config.php en tarjeta del formulario es_toma_progresiva
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Feature 1 — Ciclos configurables por paciente:
- ver_formulario_enviado.php: pantalla de configuración aparece la primera
vez que el profesional abre el formulario (antes de firmar); permite
seleccionar qué tomas realizar para cada protocolo. $_mpSkippedSepIds
oculta las secciones no seleccionadas en render. $_mpMap se reconstruye
desde los grupos filtrados para que next_firma_id salte tomas omitidas.
- configurar_tomas.php (nuevo): guarda _tomas_config en datos_respuestas
del consentimiento; valida que cada grupo tenga al menos una toma.
- guardar_toma.php: aplica el filtro _tomas_config al array firmasCampos
para que el conteo de tomas firmadas/pendientes sea correcto.
Feature 2 — Gestión de tipos de examen (admin):
- lab_tomas_config.php (nuevo): página admin que muestra los exámenes
actuales con sus tomas y permite añadir nuevos tipos con su esquema
completo (separador + hora + resultado + firma_profesional por toma).
- api/lab/save_tomas_config.php (nuevo): modifica el esquema JSON del
formulario id=15; add_exam agrega opción al selector y los campos de
cada toma; delete_exam elimina la opción y los separadores exclusivos.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Al activarse cada sección de toma (carga inicial, toma inmediata,
fin de countdown), se rellena automáticamente el campo hora con la
hora actual del dispositivo. Solo actúa si el campo está vacío, por
lo que no sobreescribe valores ya ingresados manualmente.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Agrega script inline en <head> de Layout.php, lugar.php y recepcion.php
que detecta prefers-color-scheme y activa data-bs-theme="dark" en <html>
antes del primer paint (evita flash de contenido blanco)
- sidebar.php: script de fallback para páginas con head propio no actualizado
- Layout.php: corrige background hardcodeado #f8f9fa en .main-content y
reemplaza bg-white por bg-body-tertiary en barra de título
- styles.css: elimina bloque @media duplicado y contradictorio; nuevo bloque
unificado cubre @media (fallback sin JS) + [data-bs-theme="dark"] para
elementos custom (sidebar, chat); Bootstrap maneja el resto automáticamente
- Bump styles.css a v=15 en los tres templates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- guardar_toma.php: reconoce firma campo_id_svg (compat. registros históricos)
- get_consentimientos.php: mismo fix para conteo tomas_firmadas
- ver_formulario_enviado.php: $_mpMap incluye hora fija (Cortisol 3pm/4pm),
agrupa por condición de separador para no mezclar Glicemia/Cortisol,
muestra resumen de tomas al completar antes de cerrar el modal
- lugar.php: banner rojo + beep cuando el countdown de una toma llega a cero,
resetea alerta al cerrar el modal; función _playBeepLugar() compartida
DB Form 15: +10 campos (firma_profesional Minuto 60 Glicemia + campo
Resultado numérico en cada toma Glicemia y Cortisol)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- guardar_toma.php: filtrar firmas por condición del examen seleccionado; corrige
countdown espurio y detección de 'completado' cuando hay múltiples tipos de examen.
También descarta siguiente_toma_at si ya es pasado (minuto 0).
- ver_formulario_enviado.php: auto-scroll a primera firma pendiente al cargar el modal;
si el examen se selecciona y la firma no está en DOM, guarda y recarga el iframe.
Al completar tomas, cierra el modal directamente sin botón "Finalizar".
- get_cola.php: incluye siguiente_toma_at y en_toma_progresiva por turno desde
turnero_consentimientos para mostrar cuenta regresiva en tarjetas.
- lugar.php: muestra chip de cuenta regresiva en tarjetas de cola para pacientes
en toma progresiva; color cambia a warn (<2 min) y crit (¡Ahora!).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_consentimientos: tomas_total ahora filtra por examen elegido en
datos_respuestas (no cuenta todos los 13 campos globales); badge
se oculta (total=0) hasta que se seleccione un examen.
- ver_formulario_enviado: agrega f.es_toma_progresiva al SELECT y lo
usa para forzar _soloFirmaPro=true, evitando que aparezca el canvas
de firma del paciente cuando la DB indica toma progresiva.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ver_formulario_enviado.php:
- $_mpPrimeraPendiente, $_mpBloqueado y $fSvg buscaban la clave campoId_svg
pero guardar_toma.php guarda con clave campoId (sin sufijo). Se añade
fallback a ambas claves para compatibilidad hacia adelante y atrás.
lugar.php:
- new Date('2026-07-09 15:30:00') no parsea en Safari; se reemplaza el
espacio por 'T' para formato ISO antes de construir el timestamp.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Formularios con ambos tipos de firma (paciente + profesional) en modo embebido
quedaban bloqueados porque $_mostrarCanvasPro exigía $_soloFirmaPro.
Flujo corregido:
- Canvas profesional ahora se muestra en cualquier form con firma_profesional
cuando el operador está logueado en modo turnero embebido.
- El botón "Confirmar" del paciente detecta si hay canvas del profesional:
si hay, guarda como borrador (sin marcar firmado) y hace scroll al canvas pro.
- El profesional firma último con solo_profesional=true, marcando firmado y
cerrando el modal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _guardarFirmaMP ahora llama guardar_toma.php en vez del draft POST,
guardando la firma con clave campoId (sin _svg) que es la que lee
get_consentimientos para el contador X/13.
guardar_toma.php también actualiza estado→en_progreso y siguiente_toma_at,
lo que activa el countdown en lugar.php via polling SSE.
- Al completar la última toma envía postMessage turneroFirmado para cerrar
el modal automáticamente.
- Botón cerrar del modal siempre habilitado (el operador puede cerrar
en cualquier momento durante el proceso).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Agrega medico_nombre al __paciente prefilled de crear_envio_presencial.php
haciendo JOIN con medicos vía turnero_solicitudes.medico_id, de modo que
el campo linked 'Médico solicitante' del formulario id=15 (tomas prolongadas)
se auto-cargue con el médico registrado en recepción.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- get_consentimientos: skip auto-create of consentimientos when solo_muestras=1
- get_consentimientos: add paciente_id to turno query; fallback muestras fetch
when no solicitud exists but turno has paciente_id (F-turns without reception)
- lugar: badge "Solo entrega de muestras" in ficha header for prioridad F
- lugar: hide sec-consent and sec-form-embebido when solo_muestras
- lugar: skip consent polling and form embedding for F-turns
- lugar: restore sec-consent visibility on resetFicha
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add data-campo-id attributes to all editable field wrappers and separators,
then run iniciarCondiciones-equivalent JS on page load so conditional sections
(e.g. Tipo de dolor when Dolores is checked) appear/disappear without needing
to close and reopen the modal.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>