From f0fb0c7492d341fb0aee92d28fa810e6cc615ebf Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 10 Jul 2026 11:10:51 -0500 Subject: [PATCH] Tomas: wizard inline para crear tipo de examen con tomas configurables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- ver_formulario_enviado.php | 240 +++++++++++++++++++++++++------------ 1 file changed, 161 insertions(+), 79 deletions(-) diff --git a/ver_formulario_enviado.php b/ver_formulario_enviado.php index 34e0d77..15ee527 100644 --- a/ver_formulario_enviado.php +++ b/ver_formulario_enviado.php @@ -355,6 +355,45 @@ function esc2(mixed $v): string { if (is_array($v)) return htmlspecialchars(implode(', ', $v), ENT_QUOTES); return htmlspecialchars((string)($v ?? ''), ENT_QUOTES); } + +function _addExamWizardHtml(string $cid): string { + return ' +
+ +
+ +
+
Nuevo tipo de examen
+
+ + +
+
+ +
+ + 1 + +
+
+
+
+ + +
+
+
+
+
'; +} ?> @@ -647,11 +686,22 @@ function esc2(mixed $v): string { $_gsecs) { if (empty($_gsecs)) continue; - $_gruposConfig[$_gk] = ['title' => $_gsecs[0]['display'] ?? $_gk, 'secs' => $_gsecs]; + $__parts = array_values(array_filter(explode('|', $_gk))); + $__isCond = !empty(array_intersect($__parts, $_examOptions)); + $__matchSel = !empty(array_intersect($__parts, $_examSel)); + if (!$__isCond || $__matchSel) { + $__title = implode(' / ', array_intersect($__parts, $_examSel)); + if (!$__title) $__title = $_gsecs[0]['display'] ?? $_gk; + $_gruposConfig[$_gk] = ['title' => $__title, 'secs' => $_gsecs]; + } } // Mostrar panel solo si al menos un grupo tiene >= 2 tomas (hay algo que configurar). // Si todos los grupos tienen 1 sola toma, el JS auto-guarda la config sin preguntar. @@ -995,26 +1045,7 @@ function esc2(mixed $v): string { -
- -
- - - -
-
-
+ -
- -
- - - -
-
-
+ -/* ── Añadir tipo de examen inline ── */ -function toggleAddExam(cid) { - var box = document.getElementById('add-exam-box-' + cid); +/* ── Wizard: añadir tipo de examen ── */ +var _aewState = {}; // {cid: {count, rows}} + +function aewOpen(cid) { + var box = document.getElementById('aew-box-' + cid); if (!box) return; - box.classList.toggle('d-none'); - if (!box.classList.contains('d-none')) { - var inp = document.getElementById('add-exam-input-' + cid); - if (inp) inp.focus(); - } + box.classList.remove('d-none'); + _aewState[cid] = { count: 1 }; + aewRenderTomas(cid); + var ni = document.getElementById('aew-name-' + cid); + if (ni) ni.focus(); } -function guardarNuevoExamen(cid) { - var inp = document.getElementById('add-exam-input-' + cid); - var msg = document.getElementById('add-exam-msg-' + cid); - if (!inp) return; - var name = inp.value.trim(); - if (!name) { if (msg) msg.innerHTML = 'Ingrese un nombre.'; return; } +function aewClose(cid) { + var box = document.getElementById('aew-box-' + cid); + if (box) box.classList.add('d-none'); +} +function aewAddToma(cid, delta) { + if (!_aewState[cid]) return; + var n = (_aewState[cid].count || 1) + delta; + if (n < 1) n = 1; if (n > 12) n = 12; + _aewState[cid].count = n; + var el = document.getElementById('aew-count-' + cid); + if (el) el.textContent = n; + aewRenderTomas(cid); +} +function aewRenderTomas(cid) { + var n = (_aewState[cid] || {}).count || 1; + var cnt = document.getElementById('aew-tomas-' + cid); + if (!cnt) return; + // Guardar valores actuales antes de re-renderizar + var prev = []; + cnt.querySelectorAll('.aew-row').forEach(function(r) { + prev.push({ + lbl: r.querySelector('.aew-lbl') ? r.querySelector('.aew-lbl').value : '', + tipo: r.querySelector('.aew-tipo') ? r.querySelector('.aew-tipo').value : 'minutos', + val: r.querySelector('.aew-val') ? r.querySelector('.aew-val').value : '', + }); + }); + var html = ''; + for (var i = 0; i < n; i++) { + var p = prev[i] || {}; + var lbl = p.lbl || (i === 0 ? 'Minuto 0' : 'Minuto ' + (i * 30)); + var tipo = p.tipo || 'minutos'; + var val = p.val !== undefined ? p.val : (i === 0 ? '0' : String(i * 30)); + html += '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
' + + '
'; + } + cnt.innerHTML = html; +} +function aewTipoChange(sel) { + var row = sel.closest('.aew-row'); + var lbl = row.querySelector('.aew-val-lbl'); + var inp = row.querySelector('.aew-val'); + if (sel.value === 'hora_fija') { lbl.textContent = 'HH:MM'; inp.placeholder = '08:00'; } + else { lbl.textContent = 'Minutos'; inp.placeholder = '0'; } +} +function aewSave(cid) { + var name = (document.getElementById('aew-name-' + cid) || {}).value; + if (name) name = name.trim(); + var msg = document.getElementById('aew-msg-' + cid); + function showErr(e) { if (msg) msg.innerHTML = '' + e + ''; } + if (!name) { showErr('Ingrese el nombre del examen.'); return; } + + var tomas = []; + document.querySelectorAll('#aew-tomas-' + cid + ' .aew-row').forEach(function(row) { + tomas.push({ + label: (row.querySelector('.aew-lbl') || {}).value || '', + tipo: (row.querySelector('.aew-tipo') || {}).value || 'minutos', + valor: (row.querySelector('.aew-val') || {}).value || '0', + }); + }); + if (!tomas.length) { showErr('Configure al menos una toma.'); return; } + for (var i = 0; i < tomas.length; i++) { + if (!tomas[i].label.trim()) { showErr('Ingrese el label de la toma ' + (i+1) + '.'); return; } + } + + var btn = document.getElementById('aew-save-' + cid); + if (btn) { btn.disabled = true; btn.innerHTML = 'Guardando…'; } + if (msg) msg.innerHTML = ''; + var base = window.location.href.split('/ver_formulario_enviado.php')[0]; - fetch(base + '/api/lab/add_exam_option.php', { + fetch(base + '/api/lab/save_tomas_config.php', { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({exam_name: name}) + body: JSON.stringify({ action: 'add_exam', exam_name: name, tomas: tomas }) }) .then(function(r) { return r.json(); }) .then(function(d) { if (d.ok) { - // Añadir radio button al grupo y seleccionarlo - var wrap = document.querySelector('[data-campo-id="' + cid + '"]'); - if (wrap) { - var div = document.createElement('div'); - div.className = 'form-check'; - div.innerHTML = '' - + '