Tomas: añadir tipo de examen inline sin página separada
- 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>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
4e6da5d7eb
commit
be55a087aa
@@ -22,14 +22,6 @@ foreach ($esquema as &$campo) {
|
||||
$id = $campo['id'] ?? '';
|
||||
$tipo = $campo['tipo'] ?? '';
|
||||
|
||||
// Campo selector → texto libre
|
||||
if ($id === '_c8j2g16') {
|
||||
$campo['tipo'] = 'texto';
|
||||
$campo['label'] = 'Tipo de examen';
|
||||
unset($campo['options'], $campo['multiple'], $campo['required']);
|
||||
$cambios++;
|
||||
}
|
||||
|
||||
// Separadores con condición sobre _c8j2g16 → quitar condición
|
||||
if ($tipo === 'separador' && isset($campo['condicion'])) {
|
||||
$condCampo = $campo['condicion']['campo_id'] ?? '';
|
||||
@@ -49,8 +41,8 @@ $pdo->prepare("UPDATE lab_formularios SET esquema = ? WHERE id = 15")
|
||||
echo '<p style="font-family:sans-serif;padding:2rem">
|
||||
<span style="color:green;font-size:1.2rem">✅ Migración completada</span><br><br>
|
||||
<strong>' . $cambios . ' campos modificados</strong>:<br>
|
||||
• Campo _c8j2g16 → texto libre "Tipo de examen"<br>
|
||||
• Condiciones eliminadas de separadores de tomas<br><br>
|
||||
• Condiciones eliminadas de separadores de tomas<br>
|
||||
• Campo _c8j2g16 conservado como selector (+ botón "Añadir tipo")<br><br>
|
||||
<small style="color:#666">Este archivo fue eliminado automáticamente.</small><br><br>
|
||||
<a href="lab_formularios.php" style="color:#0d6efd">← Volver a Formularios</a>
|
||||
</p>';
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* POST /api/lab/add_exam_option.php
|
||||
* Añade una opción al campo selector de tipo de examen (_c8j2g16) del formulario id=15.
|
||||
* Body JSON: { exam_name: string }
|
||||
*/
|
||||
require_once __DIR__ . '/_helpers.php';
|
||||
requireMethod('POST');
|
||||
requireAdmin();
|
||||
|
||||
$body = inputJson();
|
||||
$examName = trim($body['exam_name'] ?? '');
|
||||
|
||||
if (!$examName) jsonError('exam_name requerido.');
|
||||
if (strlen($examName) > 80) jsonError('Nombre demasiado largo (máx 80 chars).');
|
||||
if (!preg_match('/\S/', $examName)) jsonError('Nombre inválido.');
|
||||
|
||||
$db = Database::getInstance();
|
||||
$row = $db->fetch("SELECT esquema FROM lab_formularios WHERE id = 15 LIMIT 1");
|
||||
if (!$row) jsonError('Formulario no encontrado.', 404);
|
||||
|
||||
$esquema = json_decode($row['esquema'], true);
|
||||
if (!is_array($esquema)) jsonError('Esquema inválido.', 500);
|
||||
|
||||
$updated = false;
|
||||
foreach ($esquema as &$campo) {
|
||||
if (($campo['id'] ?? '') !== '_c8j2g16') continue;
|
||||
$opts = $campo['options'] ?? [];
|
||||
if (in_array($examName, $opts, true)) jsonError("El tipo \"$examName\" ya existe.");
|
||||
$opts[] = $examName;
|
||||
$campo['options'] = $opts;
|
||||
$updated = true;
|
||||
break;
|
||||
}
|
||||
unset($campo);
|
||||
|
||||
if (!$updated) jsonError('Campo selector de examen no encontrado en el formulario.', 500);
|
||||
|
||||
$db->getConnection()->prepare("UPDATE lab_formularios SET esquema = ? WHERE id = 15")
|
||||
->execute([json_encode($esquema, JSON_UNESCAPED_UNICODE)]);
|
||||
|
||||
jsonOk(['exam_name' => $examName], "Tipo \"$examName\" añadido.");
|
||||
@@ -994,6 +994,28 @@ function esc2(mixed $v): string {
|
||||
<label class="form-check-label"><?= esc2($opt) ?></label>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php if ($cid === '_c8j2g16'): ?>
|
||||
<div class="mt-2" id="add-exam-wrap-<?= esc2($cid) ?>">
|
||||
<button type="button" class="btn btn-link btn-sm p-0 text-muted"
|
||||
onclick="toggleAddExam('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-plus-circle me-1"></i>Añadir tipo de examen…
|
||||
</button>
|
||||
<div id="add-exam-box-<?= esc2($cid) ?>" class="d-none mt-1 d-flex gap-2">
|
||||
<input type="text" id="add-exam-input-<?= esc2($cid) ?>"
|
||||
class="form-control form-control-sm" style="max-width:260px"
|
||||
placeholder="Nombre del tipo de examen">
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
onclick="guardarNuevoExamen('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-check me-1"></i>Guardar
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm"
|
||||
onclick="toggleAddExam('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="add-exam-msg-<?= esc2($cid) ?>" class="small mt-1"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php continue; endif;
|
||||
if ($tipo === 'checkbox' || $tipo === 'lista_marcable'):
|
||||
@@ -1013,6 +1035,28 @@ function esc2(mixed $v): string {
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if ($cid === '_c8j2g16'): ?>
|
||||
<div class="mt-2" id="add-exam-wrap-<?= esc2($cid) ?>">
|
||||
<button type="button" class="btn btn-link btn-sm p-0 text-muted"
|
||||
onclick="toggleAddExam('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-plus-circle me-1"></i>Añadir tipo de examen…
|
||||
</button>
|
||||
<div id="add-exam-box-<?= esc2($cid) ?>" class="d-none mt-1 d-flex gap-2">
|
||||
<input type="text" id="add-exam-input-<?= esc2($cid) ?>"
|
||||
class="form-control form-control-sm" style="max-width:260px"
|
||||
placeholder="Nombre del tipo de examen">
|
||||
<button type="button" class="btn btn-success btn-sm"
|
||||
onclick="guardarNuevoExamen('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-check me-1"></i>Guardar
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm"
|
||||
onclick="toggleAddExam('<?= esc2($cid) ?>')">
|
||||
<i class="fas fa-times"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div id="add-exam-msg-<?= esc2($cid) ?>" class="small mt-1"></div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php continue; endif;
|
||||
if ($tipo === 'select'):
|
||||
@@ -1283,6 +1327,58 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
})();
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
/* ── Añadir tipo de examen inline ── */
|
||||
function toggleAddExam(cid) {
|
||||
var box = document.getElementById('add-exam-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();
|
||||
}
|
||||
}
|
||||
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 = '<span class="text-danger">Ingrese un nombre.</span>'; return; }
|
||||
var base = window.location.href.split('/ver_formulario_enviado.php')[0];
|
||||
fetch(base + '/api/lab/add_exam_option.php', {
|
||||
method: 'POST', headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({exam_name: name})
|
||||
})
|
||||
.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 = '<input class="form-check-input" type="radio" name="' + cid + '" value="' + name.replace(/"/g, '"') + '" checked>'
|
||||
+ '<label class="form-check-label">' + name.replace(/</g, '<') + '</label>';
|
||||
// Insertar antes del bloque add-exam-wrap
|
||||
var addWrap = document.getElementById('add-exam-wrap-' + cid);
|
||||
wrap.insertBefore(div, addWrap);
|
||||
// Disparar evento change para condiciones de visibilidad
|
||||
div.querySelector('input').dispatchEvent(new Event('change', {bubbles: true}));
|
||||
}
|
||||
inp.value = '';
|
||||
if (msg) msg.innerHTML = '<span class="text-success"><i class="fas fa-check me-1"></i>Añadido.</span>';
|
||||
setTimeout(function() {
|
||||
toggleAddExam(cid);
|
||||
if (msg) msg.innerHTML = '';
|
||||
}, 1500);
|
||||
} else {
|
||||
if (msg) msg.innerHTML = '<span class="text-danger">' + (d.error || 'Error') + '</span>';
|
||||
}
|
||||
})
|
||||
.catch(function() {
|
||||
if (msg) msg.innerHTML = '<span class="text-danger">Error de conexión.</span>';
|
||||
});
|
||||
}
|
||||
|
||||
window._muestrasMap = <?= json_encode($_mpMap, JSON_UNESCAPED_UNICODE) ?>;
|
||||
window._mpSavedFirmas = {};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user