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