refactor: mejorar flujo de tomas prolongadas (A+B+C+D)

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>
This commit is contained in:
Lizandro Guarnizo
2026-07-16 11:20:15 -05:00
co-authored by Claude Sonnet 4.6
parent 3b61ee6f35
commit 86ec692028
2 changed files with 74 additions and 36 deletions
+7 -26
View File
@@ -85,10 +85,10 @@ if ($action === 'add_exam') {
$sepLabel = "$examName · {$h12}:{$mm} {$ampm}";
}
$sepId = $prefix . 's' . $idx . $uid;
$horaId = $prefix . 'h' . $idx . $uid;
$resId = $prefix . 'r' . $idx . $uid;
$firmaId = $prefix . 'f' . $idx . $uid;
$sepId = $prefix . 's' . $idx . $uid;
$horaId = $prefix . 'h' . $idx . $uid;
$obsId = $prefix . 'o' . $idx . $uid;
$firmaId = $prefix . 'f' . $idx . $uid;
$esquema[] = [
'id' => $sepId,
@@ -96,28 +96,9 @@ if ($action === 'add_exam') {
'label' => $sepLabel,
'condicion'=> ['campo_id' => $condCampoId, 'valores' => [$examName]],
];
$esquema[] = [
'id' => $horaId,
'tipo' => 'hora',
'label' => 'Hora de toma',
];
$esquema[] = [
'id' => $resId,
'tipo' => 'numero',
'label' => 'Resultado',
];
$esquema[] = [
'id' => $prefix . 'o' . $idx . $uid,
'tipo' => 'texto',
'label' => 'Observaciones',
'placeholder' => '',
'required' => false,
];
$esquema[] = [
'id' => $firmaId,
'tipo' => 'firma_profesional',
'label' => 'Firma del profesional',
];
$esquema[] = ['id' => $horaId, 'tipo' => 'hora', 'label' => 'Hora de toma'];
$esquema[] = ['id' => $obsId, 'tipo' => 'texto', 'label' => 'Observaciones', 'placeholder' => '', 'required' => false];
$esquema[] = ['id' => $firmaId, 'tipo' => 'firma_profesional', 'label' => 'Firma del profesional'];
}
$db->getConnection()->prepare(
+67 -10
View File
@@ -305,7 +305,12 @@ if ($modoTurnero && $embebido && $_soloFirmaPro) {
if (is_array($__rawCfg)) {
$_tomasConfig = $__rawCfg;
foreach ($_mpGroups as $__gk => &$__gsecs) {
if (!isset($_tomasConfig[$__gk])) continue;
if (!isset($_tomasConfig[$__gk])) {
// Grupo no configurado: ocultar sus secciones y vaciarlo del mapa
foreach ($__gsecs as $__s) { $_mpSkippedSepIds[$__s['sep_id']] = true; }
$__gsecs = [];
continue;
}
$__allowed = array_flip($_tomasConfig[$__gk]);
foreach ($__gsecs as $__s) {
if (!isset($__allowed[$__s['firma']])) {
@@ -369,6 +374,7 @@ function esc2(mixed $v): string {
function _addExamWizardHtml(string $cid): string {
return '
<div id="mp-exam-badges" class="mp-exam-badges"></div>
<div class="mt-2" id="aew-wrap-' . $cid . '">
<button type="button" class="btn btn-link btn-sm p-0 text-muted" onclick="aewOpen(\'' . $cid . '\')">
<i class="fas fa-plus-circle me-1"></i>Añadir tipo de examen…
@@ -607,6 +613,18 @@ function _addExamWizardHtml(string $cid): string {
transition:all .15s;cursor:pointer;user-select:none; }
.mp-cfg-item:has(.form-check-input:checked) { background:#f0fdf4;border-color:#86efac; }
.mp-cfg-item label { cursor:pointer; }
/* ── Badges de examen seleccionado ─────────────────── */
.mp-exam-badges { margin-top:.6rem; display:flex; flex-direction:column; gap:.4rem; }
.mp-exam-badge { display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
background:#f0f9ff;border:1.5px solid #bae6fd;border-radius:8px;
padding:.35rem .7rem;font-size:.82rem; }
.mp-exam-badge.configured { background:#f0fdf4;border-color:#86efac; }
.mp-exam-badge-name { font-weight:700;color:#1e3a5f; }
.mp-exam-badge-info { color:#64748b;font-size:.78rem; }
.mp-exam-badge-btn { margin-left:auto;background:<?= htmlspecialchars($docColor) ?>;color:#fff;
border:none;border-radius:6px;padding:2px 10px;font-size:.78rem;
cursor:pointer;white-space:nowrap; }
.mp-exam-badge-btn:hover { opacity:.85; }
</style>
</head>
<body>
@@ -1351,20 +1369,61 @@ function _mpSetExamChecked(name) {
if (el) el.checked = true;
}
// ── Badges de estado de examen ───────────────────────────────────────
function _mpRenderBadges() {
var wrap = document.getElementById('mp-exam-badges');
if (!wrap) return;
var checked = Array.from(document.querySelectorAll('[name="_c8j2g16[]"]:checked,[name="_c8j2g16"]:checked'));
if (!checked.length) { wrap.innerHTML = ''; return; }
var html = '';
checked.forEach(function(el) {
var name = el.value;
var groups = _mpGetGroupsForExam(name);
var totalTomas = Object.values(groups).reduce(function(s, g) { return s + g.length; }, 0);
var groupKeys = Object.keys(groups);
// Verificar si este examen ya está configurado en _mpTomasConfig
var configured = _mpTomasConfig !== null && groupKeys.some(function(k) { return _mpTomasConfig[k]; });
var tomasCount = 0;
if (configured) {
groupKeys.forEach(function(k) {
if (_mpTomasConfig[k]) tomasCount += _mpTomasConfig[k].length;
});
}
html += '<div class="mp-exam-badge' + (configured ? ' configured' : '') + '">'
+ '<span class="mp-exam-badge-name">' + name + '</span>';
if (configured) {
html += '<span class="mp-exam-badge-info"><i class="fas fa-check-circle text-success me-1"></i>'
+ tomasCount + ' toma' + (tomasCount !== 1 ? 's' : '') + ' configurada' + (tomasCount !== 1 ? 's' : '') + '</span>';
} else {
html += '<span class="mp-exam-badge-info text-warning"><i class="fas fa-clock me-1"></i>Pendiente configurar ('
+ totalTomas + ' tomas disponibles)</span>'
+ '<button class="mp-exam-badge-btn" data-exam="' + name.replace(/"/g, '&quot;') + '">'
+ '<i class="fas fa-sliders-h me-1"></i>Configurar tiempos</button>';
}
html += '</div>';
});
wrap.innerHTML = html;
}
// Escuchar selección de tipo de examen
document.addEventListener('change', function(e) {
var el = e.target;
if (el.name.replace(/\[\]$/, '') !== '_c8j2g16') return;
var examName = _mpGetExamName();
_mpApplyExamVisibility(examName);
// Panel de configuración solo en modo turnero y si aún no está configurado
if (!_mpModoTurnero || _mpTomasConfig !== null || !examName) return;
var groups = _mpGetGroupsForExam(examName);
if (!Object.keys(groups).length) return;
_mpShowCfgPanel(examName, groups);
if (_mpModoTurnero) _mpRenderBadges();
});
// Al cargar: aplicar visibilidad (sin examen = ocultar todo)
// Click en botón "Configurar tiempos" del badge
document.addEventListener('click', function(e) {
var btn = e.target.closest('.mp-exam-badge-btn');
if (!btn) return;
var examName = btn.getAttribute('data-exam');
var groups = _mpGetGroupsForExam(examName);
if (Object.keys(groups).length) _mpShowCfgPanel(examName, groups);
});
// Al cargar: aplicar visibilidad y renderizar badges
document.addEventListener('DOMContentLoaded', function() {
var examName = _mpGetExamName();
// Restaurar selección de examen tras el reload del panel de config
@@ -1379,9 +1438,7 @@ document.addEventListener('DOMContentLoaded', function() {
} catch(e) {}
}
_mpApplyExamVisibility(examName);
if (!_mpModoTurnero || _mpTomasConfig !== null || !examName) return;
var groups = _mpGetGroupsForExam(examName);
if (Object.keys(groups).length) _mpShowCfgPanel(examName, groups);
if (_mpModoTurnero) _mpRenderBadges();
});
// Botón "Usar todas"