fix: mostrar canvas para todos los campos firma en modo turnero

Antes solo el primer campo (consentimiento) tenía canvas; el segundo
(desistimiento) se omitía. Ahora cada campo firma tiene su propio widget
usando clases CSS en vez de IDs hardcodeados.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-03 11:22:18 -05:00
co-authored by Claude Sonnet 4.6
parent 597ec87964
commit 0c68dff307
+39 -39
View File
@@ -481,13 +481,13 @@ function esc2(mixed $v): string {
$fLabel = htmlspecialchars($campo['label'] ?? ($isPro ? 'Firma profesional' : 'Firma paciente'));
// Campo paciente sin firma:
// - En turnero pendiente: el PRIMER campo firma muestra el canvas, los demás se omiten.
// - En turnero pendiente: todos los campos firma muestran canvas (consentimiento + desistimiento).
// - En vista normal: omitir campos sin firma.
if (!$fSvg && !$fFoto && !$isPro) {
if ($modoTurnero && $modoEditar && !$_esquemaTieneFirmaPaciente) {
$_esquemaTieneFirmaPaciente = true; // solo el primero muestra canvas
if ($modoTurnero && $modoEditar) {
$_esquemaTieneFirmaPaciente = true;
} else {
continue; // campos firma adicionales (desistimiento) sin firma → omitir
continue; // no-turnero: omitir campos sin firma
}
}
@@ -510,20 +510,20 @@ function esc2(mixed $v): string {
<img src="<?= htmlspecialchars($fFoto) ?>" alt="Foto - <?= $fLabel ?>">
</div>
<?php elseif (!$isPro && $modoTurnero && $modoEditar): ?>
<div id="turneroFirmaWidget">
<div class="turnero-firma-item no-print" data-cid="<?= esc2($cid) ?>">
<p class="text-muted small mb-2"><i class="fas fa-pen me-1"></i>He leído el documento. Dibuje su firma:</p>
<canvas id="turneroCv" width="500" height="160"
<canvas class="turnero-cv" width="500" height="160"
style="border:2px solid #1565c0;border-radius:8px;background:#f0f4ff;
cursor:crosshair;display:block;max-width:100%;touch-action:none"></canvas>
<div class="mt-2 d-flex gap-2 flex-wrap">
<button id="turneroLimpiar" class="btn btn-outline-secondary btn-sm">
<button class="btn btn-outline-secondary btn-sm turnero-limpiar">
<i class="fas fa-eraser me-1"></i>Limpiar
</button>
<button id="turneroFirmar" class="btn btn-success fw-semibold">
<i class="fas fa-check-circle me-1"></i>Confirmar y firmar consentimiento
<button class="btn btn-success fw-semibold turnero-firmar">
<i class="fas fa-check-circle me-1"></i>Confirmar: <?= $fLabel ?>
</button>
</div>
<div id="turneroMsg" class="mt-2 small"></div>
<div class="turnero-msg mt-2 small"></div>
</div>
<?php elseif ($isPro): ?>
<?php if (!$modoTurnero && !$modoPublico && !$yaHayCanvasPro): ?>
@@ -736,7 +736,7 @@ function esc2(mixed $v): string {
<!-- ── Widget firma turnero (fallback si el esquema no tiene campo firma) ── -->
<?php if ($modoTurnero && $envio['estado'] !== 'firmado' && !$_esquemaTieneFirmaPaciente): ?>
<div class="mt-4 no-print" id="turneroFirmaWidget">
<div class="mt-4 no-print turnero-firma-item" data-cid="__firma_global">
<div class="section-title" style="color:#1565c0">
<i class="fas fa-pen me-1"></i>Firma del paciente / responsable
</div>
@@ -744,19 +744,19 @@ function esc2(mixed $v): string {
He leído y comprendido el contenido de este documento.
Por favor dibuje su firma en el recuadro:
</p>
<canvas id="turneroCv" width="500" height="160"
<canvas class="turnero-cv" width="500" height="160"
style="border:2px solid #1565c0;border-radius:8px;background:#f0f4ff;
cursor:crosshair;display:block;max-width:100%;touch-action:none">
</canvas>
<div class="mt-2 d-flex gap-2 flex-wrap">
<button id="turneroLimpiar" class="btn btn-outline-secondary btn-sm">
<button class="btn btn-outline-secondary btn-sm turnero-limpiar">
<i class="fas fa-eraser me-1"></i>Limpiar
</button>
<button id="turneroFirmar" class="btn btn-success fw-semibold">
<i class="fas fa-check-circle me-1"></i>Confirmar y firmar consentimiento
<button class="btn btn-success fw-semibold turnero-firmar">
<i class="fas fa-check-circle me-1"></i>Confirmar y firmar
</button>
</div>
<div id="turneroMsg" class="mt-2 small"></div>
<div class="turnero-msg mt-2 small"></div>
</div>
<?php elseif ($modoTurnero && $envio['estado'] === 'firmado'): ?>
<div class="alert alert-success mt-4 d-flex align-items-center gap-2 no-print">
@@ -888,16 +888,17 @@ function esc2(mixed $v): string {
});
})();
/* ── Firma de consentimiento turnero ────────────────────────────────── */
(function () {
var canvas = document.getElementById('turneroCv');
var widget = document.getElementById('turneroFirmaWidget');
/* ── Firma de consentimiento turnero (soporta múltiples campos firma) ── */
document.querySelectorAll('.turnero-firma-item').forEach(function(widget) {
var canvas = widget.querySelector('.turnero-cv');
if (!canvas) return;
var cid = widget.dataset.cid || '__firma';
var ctx = canvas.getContext('2d');
var btnLimp = document.getElementById('turneroLimpiar');
var btnFirm = document.getElementById('turneroFirmar');
var msgEl = document.getElementById('turneroMsg');
var btnLimp = widget.querySelector('.turnero-limpiar');
var btnFirm = widget.querySelector('.turnero-firmar');
var msgEl = widget.querySelector('.turnero-msg');
var drawing = false;
var btnLabel = btnFirm ? btnFirm.innerHTML : '';
(function scaleCanvas() {
var ratio = window.devicePixelRatio || 1;
@@ -928,12 +929,12 @@ function esc2(mixed $v): string {
canvas.addEventListener('touchmove', function(e){ e.preventDefault(); if(!drawing) return; var p=getPos(e); ctx.lineTo(p.x,p.y); ctx.stroke(); }, {passive:false});
canvas.addEventListener('touchend', function(){ drawing=false; });
btnLimp.addEventListener('click', function() {
if (btnLimp) btnLimp.addEventListener('click', function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
msgEl.textContent = '';
});
btnFirm.addEventListener('click', function() {
if (btnFirm) btnFirm.addEventListener('click', function() {
var png = canvas.toDataURL('image/png');
if (png.length < 1500) {
msgEl.innerHTML = '<span class="text-danger"><i class="fas fa-exclamation-triangle me-1"></i>Por favor dibuje su firma antes de confirmar.</span>';
@@ -943,23 +944,20 @@ function esc2(mixed $v): string {
btnFirm.innerHTML = '<i class="fas fa-spinner fa-spin me-1"></i>Guardando...';
msgEl.textContent = '';
// Recopilar respuestas de campos interactivos
var campos = {};
document.querySelectorAll('[name]').forEach(function(el) {
var rawName = el.name;
var isArr = rawName.slice(-2) === '[]';
var name = isArr ? rawName.slice(0, -2) : rawName;
if (el.type === 'checkbox') {
if (el.checked) {
if (!Array.isArray(campos[name])) campos[name] = [];
campos[name].push(el.value);
}
if (el.checked) { if (!Array.isArray(campos[name])) campos[name] = []; campos[name].push(el.value); }
} else if (el.type === 'radio') {
if (el.checked) campos[name] = el.value;
} else if (el.value !== '') {
campos[name] = el.value;
}
});
campos[cid + '_svg'] = png; // identificar qué campo firmó
fetch(window.location.href, {
method: 'POST',
@@ -969,26 +967,28 @@ function esc2(mixed $v): string {
.then(function(r) { return r.json(); })
.then(function(data) {
if (data.ok) {
widget.outerHTML =
'<div class="alert alert-success mt-4 d-flex align-items-center gap-2 no-print">' +
'<i class="fas fa-check-circle fs-4"></i>' +
'<div><strong>Consentimiento firmado correctamente.</strong><br>' +
'Puede cerrar esta ventana.</div></div>';
// Notificar ventana padre si está en iframe/modal
// Ocultar todos los demás widgets de firma (ya no se puede firmar dos veces)
document.querySelectorAll('.turnero-firma-item').forEach(function(w) {
w.style.display = 'none';
});
var ok = document.createElement('div');
ok.className = 'alert alert-success mt-4 d-flex align-items-center gap-2 no-print';
ok.innerHTML = '<i class="fas fa-check-circle fs-4"></i><div><strong>Firmado correctamente.</strong><br>Puede cerrar esta ventana.</div>';
widget.parentNode.insertBefore(ok, widget.nextSibling);
try { window.parent.postMessage({ type: 'turneroFirmado' }, '*'); } catch(e) {}
} else {
msgEl.innerHTML = '<span class="text-danger"><i class="fas fa-times me-1"></i>' + (data.error || 'Error al guardar') + '</span>';
btnFirm.disabled = false;
btnFirm.innerHTML = '<i class="fas fa-check-circle me-1"></i>Confirmar y firmar consentimiento';
btnFirm.innerHTML = btnLabel;
}
})
.catch(function() {
msgEl.innerHTML = '<span class="text-danger"><i class="fas fa-times me-1"></i>Error de conexión.</span>';
btnFirm.disabled = false;
btnFirm.innerHTML = '<i class="fas fa-check-circle me-1"></i>Confirmar y firmar consentimiento';
btnFirm.innerHTML = btnLabel;
});
});
})();
});
</script>
</body>
</html>