Tomas Prolongadas: ocultar los campos junto a su sección y aplicar visibilidad al abrir

Al ver F-LAB-28 desde bandeja aparecían secciones que no correspondían al
examen del paciente (Insulina · Minuto 0/30/60 con sus firmas sueltas).
Tres causas:

1. Una sección condicional que no se cumple ocultaba solo su encabezado
   mediante CSS; sus campos (hora, observaciones, firma) se renderizaban
   visibles y sin título. Ahora los campos llevan data-sep-id y heredan el
   estado oculto de su sección.

2. _mpApplyExamVisibility solo corría al cambiar el examen o al usar el panel
   de configuración, nunca al cargar. Un formulario ya configurado abierto
   desde bandeja o historial quedaba como lo dejó el PHP. Se llama ahora en
   el DOMContentLoaded existente.

3. _mpGetExamName usaba querySelector y devolvía solo el primer examen
   marcado, así que un paciente con Glicemia y Prolactina perdía las tomas
   del segundo. Se agrega _mpGetExamNames (todos) y la visibilidad acepta
   una lista; se corrige también la ruta de restauración desde sessionStorage,
   que restauraba varios exámenes pero aplicaba visibilidad con uno.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-04 09:51:11 -05:00
co-authored by Claude Opus 5
parent d79d33db36
commit 8948ea67d1
+51 -24
View File
@@ -1037,6 +1037,10 @@ function _addExamWizardHtml(string $cid): string {
$_saltarSeccion = false;
$_mpSkipSec = false; // toma excluida por _tomas_config; siempre ocultar sin importar modoEditar
// Atributos heredados por los campos de la sección actual. Sin esto, una
// sección cuya condición no se cumple ocultaba solo su encabezado y dejaba
// sus campos (hora, observaciones, firma) sueltos y visibles.
$_secAttr = '';
foreach ($esquema as $campo):
$tipo = $campo['tipo'] ?? '';
if ($tipo === 'separador'):
@@ -1056,6 +1060,10 @@ function _addExamWizardHtml(string $cid): string {
$_saltarSeccion = true;
$_mpSkipSec = true;
}
// La sección queda en el DOM (el JS puede mostrarla si cambian de examen)
// pero oculta, y sus campos heredan el mismo estado.
$_secAttr = ' data-sep-id="' . esc2($campo['id'] ?? '') . '"'
. (($_saltarSeccion && $modoEditar) ? ' style="display:none"' : '');
if (($_saltarSeccion && !$modoEditar) || $_mpSkipSec) continue; ?>
<div class="esquema-sep<?= $compact ? ' campo-full' : '' ?>" data-campo-id="<?= esc2($campo['id'] ?? '') ?>"
<?= ($_saltarSeccion && $modoEditar) ? 'style="max-height:0;opacity:0;overflow:hidden;pointer-events:none;margin:0!important;padding:0!important"' : '' ?>><?= esc2($campo['label'] ?? '') ?></div>
@@ -1102,8 +1110,8 @@ function _addExamWizardHtml(string $cid): string {
$_firmaGlobalPacienteUsada = true;
}
?>
<?php if ($compact): ?><div class="campo-full"><?php endif; ?>
<div class="section-title mt-3" style="color:<?= $fColor ?>">
<?php if ($compact): ?><div class="campo-full"<?= $_secAttr ?>><?php endif; ?>
<div class="section-title mt-3" style="color:<?= $fColor ?>"<?= $compact ? '' : $_secAttr ?>>
<i class="fas <?= $fIcon ?> me-1"></i><?= $fLabel ?>
</div>
<?php if ($fSvg): ?>
@@ -1205,7 +1213,7 @@ function _addExamWizardHtml(string $cid): string {
if ($tipo === 'parrafo'):
$ws = !empty($campo['flujoLibre']) ? 'normal' : 'pre-wrap';
?>
<div class="mb-3<?= $compact ? ' campo-full' : '' ?>" style="font-size:.88rem;line-height:1.75;color:#444;text-align:justify;white-space:<?= $ws ?>"><?= htmlspecialchars($campo['contenido'] ?? '', ENT_QUOTES) ?></div>
<div class="mb-3<?= $compact ? ' campo-full' : '' ?>" style="font-size:.88rem;line-height:1.75;color:#444;text-align:justify;white-space:<?= $ws ?>"<?= $_secAttr ?>><?= htmlspecialchars($campo['contenido'] ?? '', ENT_QUOTES) ?></div>
<?php continue; endif;
// ── Parrafo inline (texto con marcadores {key}) ───────
@@ -1218,7 +1226,7 @@ function _addExamWizardHtml(string $cid): string {
// Convertir saltos de línea a <br>
$rendered = nl2br(htmlspecialchars($rendered, ENT_QUOTES));
?>
<div class="mb-3<?= $compact ? ' campo-full' : '' ?>" style="font-size:.88rem;line-height:2;color:#444;text-align:justify"><?= $rendered ?></div>
<div class="mb-3<?= $compact ? ' campo-full' : '' ?>" style="font-size:.88rem;line-height:2;color:#444;text-align:justify"<?= $_secAttr ?>><?= $rendered ?></div>
<?php continue; endif;
$cid = $campo['id'] ?? null;
@@ -1252,7 +1260,7 @@ function _addExamWizardHtml(string $cid): string {
<?php endif; continue; endif; // linked
if ($tipo === 'textarea'):
?>
<div class="campo-edit campo-full" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit campo-full" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<textarea class="form-control form-control-sm" name="<?= esc2($cid) ?>"
rows="3"<?= $req ?>><?= esc2($prefill) ?></textarea>
@@ -1261,7 +1269,7 @@ function _addExamWizardHtml(string $cid): string {
if ($tipo === 'radio'):
$opts = $campo['opciones'] ?? $campo['options'] ?? [];
?>
<div class="campo-edit<?= ($compact && count($opts) > 2) ? ' campo-full' : '' ?>" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit<?= ($compact && count($opts) > 2) ? ' campo-full' : '' ?>" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<div class="d-flex flex-wrap gap-3">
<?php foreach ($opts as $opt): ?>
@@ -1283,7 +1291,7 @@ function _addExamWizardHtml(string $cid): string {
$checkedArr = is_array($prefill) ? $prefill
: (is_string($prefill) && $prefill !== '' ? (json_decode($prefill, true) ?: [$prefill]) : []);
?>
<div class="campo-edit<?= $compact ? ' campo-full' : '' ?>" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit<?= $compact ? ' campo-full' : '' ?>" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<div class="d-flex flex-wrap gap-2">
<?php foreach ($opts as $opt): ?>
@@ -1303,7 +1311,7 @@ function _addExamWizardHtml(string $cid): string {
if ($tipo === 'select'):
$opts = $campo['opciones'] ?? $campo['options'] ?? [];
?>
<div class="campo-edit" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<select class="form-select form-select-sm" name="<?= esc2($cid) ?>"<?= $req ?>>
<option value="">— Seleccione —</option>
@@ -1337,7 +1345,7 @@ function _addExamWizardHtml(string $cid): string {
$extraClase = htmlspecialchars($campo['clase'] ?? '', ENT_QUOTES);
?>
<?php if ($inputType === 'time' && isset($_signedHoraCampos[$cid])): ?>
<div class="campo-edit<?= $inputFullClass ?><?= $extraClase ? ' '.$extraClase : '' ?>" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit<?= $inputFullClass ?><?= $extraClase ? ' '.$extraClase : '' ?>" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<div class="d-flex gap-1 align-items-center">
<input type="time" class="form-control form-control-sm" readonly
@@ -1353,7 +1361,7 @@ function _addExamWizardHtml(string $cid): string {
</div>
</div>
<?php else: ?>
<div class="campo-edit<?= $inputFullClass ?><?= $extraClase ? ' '.$extraClase : '' ?>" data-campo-id="<?= esc2($cid) ?>">
<div class="campo-edit<?= $inputFullClass ?><?= $extraClase ? ' '.$extraClase : '' ?>" data-campo-id="<?= esc2($cid) ?>"<?= $_secAttr ?>>
<label><?= $label ?></label>
<input type="<?= $inputType ?>" class="form-control form-control-sm"
name="<?= esc2($cid) ?>" value="<?= esc2($prefill) ?>"<?= $req ?>
@@ -1699,7 +1707,12 @@ function _mpGetGroupsForExam(examName) {
// Visibilidad de secciones de tomas según examen seleccionado.
// Oculta TODOS los sep_ids de _mpAllGroups por defecto;
// muestra solo los del grupo cuya clave coincide con el examen.
function _mpApplyExamVisibility(selectedExam) {
// Acepta un examen o varios: un paciente puede tener Glicemia y Prolactina a la
// vez, y cada uno aporta sus propias secciones de toma.
function _mpApplyExamVisibility(selectedExams) {
var exams = selectedExams == null ? []
: (Array.isArray(selectedExams) ? selectedExams : [selectedExams]);
// 1. Todos los sep_ids que son secciones de toma
var allTomaSeps = {};
for (var gk in _mpAllGroups) {
@@ -1707,16 +1720,19 @@ function _mpApplyExamVisibility(selectedExam) {
}
if (!Object.keys(allTomaSeps).length) return;
// 2. Sep_ids del examen seleccionado
// 2. Sep_ids de todos los exámenes seleccionados
var examSeps = {};
if (selectedExam) {
var groups = _mpGetGroupsForExam(selectedExam);
exams.forEach(function(ex) {
if (!ex) return;
var groups = _mpGetGroupsForExam(ex);
for (var gk2 in groups) {
groups[gk2].forEach(function(s) { if (s.sep_id) examSeps[s.sep_id] = true; });
}
}
});
// 3. Recorrer hijos directos del contenedor de campos (.campos-grid)
// 3. Recorrer hijos directos del contenedor de campos (.campos-grid).
// Los campos llevan data-sep-id, así que se ocultan junto a su encabezado
// en vez de quedar sueltos cuando la sección no aplica.
var container = document.querySelector('.campos-grid') || document.querySelector('.doc-body');
if (!container) return;
var inHidden = false;
@@ -1724,17 +1740,23 @@ function _mpApplyExamVisibility(selectedExam) {
if (child.classList.contains('esquema-sep')) {
var cid = child.getAttribute('data-campo-id') || '';
inHidden = allTomaSeps[cid] !== undefined ? !examSeps[cid] : false;
child.style.display = inHidden ? 'none' : '';
} else {
child.style.display = inHidden ? 'none' : '';
var sid = child.getAttribute('data-sep-id');
if (sid && allTomaSeps[sid] !== undefined) inHidden = !examSeps[sid];
}
child.style.display = inHidden ? 'none' : '';
});
}
// Helper: leer examen seleccionado (funciona para radio name=_c8j2g16 y checkbox name=_c8j2g16[])
// Helper: exámenes seleccionados (radio name=_c8j2g16 o checkbox name=_c8j2g16[])
function _mpGetExamNames() {
return Array.from(document.querySelectorAll('[name="_c8j2g16"]:checked,[name="_c8j2g16[]"]:checked'))
.map(function(el) { return el.value; });
}
// Compatibilidad: primer examen seleccionado
function _mpGetExamName() {
var el = document.querySelector('[name="_c8j2g16"]:checked,[name="_c8j2g16[]"]:checked');
return el ? el.value : null;
var n = _mpGetExamNames();
return n.length ? n[0] : null;
}
function _mpSetExamChecked(name) {
var esc = name.replace(/"/g, '\\"');
@@ -1783,8 +1805,7 @@ function _mpRenderBadges() {
document.addEventListener('change', function(e) {
var el = e.target;
if (el.name.replace(/\[\]$/, '') !== '_c8j2g16') return;
var examName = _mpGetExamName();
_mpApplyExamVisibility(examName);
_mpApplyExamVisibility(_mpGetExamNames());
if (_mpModoTurnero) _mpRenderBadges();
});
@@ -1810,7 +1831,9 @@ document.addEventListener('DOMContentLoaded', function() {
if (!examName) examName = saved.split('||').filter(Boolean)[0] || '';
}
} catch(e) {}
_mpApplyExamVisibility(examName);
// Los checkboxes ya quedaron restaurados arriba: aplicar sobre todos los
// marcados, no solo el primero.
_mpApplyExamVisibility(_mpGetExamNames());
if (_mpModoTurnero) {
_mpRenderBadges();
// Auto-abrir solo si hay un examen sin configurar (nuevo). Si todos configurados, no abrir.
@@ -2188,6 +2211,10 @@ function _mpRefreshCards(signedFid, nextFid) {
// Auto-scroll y auto-fill hora a la primera firma pendiente al cargar
document.addEventListener('DOMContentLoaded', function() {
// Aplicar visibilidad al abrir: antes solo corría al cambiar el examen o al
// usar el panel de configuración, así que un formulario ya configurado que se
// abría desde bandeja o historial mostraba secciones que no correspondían.
_mpApplyExamVisibility(_mpGetExamNames());
_mpRenderCards();
setTimeout(function() {
var fw = document.querySelector('.firma-pro-widget:not([style*="display:none"])');