From 23bda70cb841a57318964a37a952f38c6e07728d Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 17 Mar 2026 13:34:18 -0500 Subject: [PATCH] firma: tabs canvas/foto, drag&drop, fallback seguro, aviso builder --- form_cliente.php | 95 ++++++++++++++++++++++++++++++-------- lab_formulario_builder.php | 34 ++++++++------ 2 files changed, 96 insertions(+), 33 deletions(-) diff --git a/form_cliente.php b/form_cliente.php index 9b2eea1..0b0c088 100644 --- a/form_cliente.php +++ b/form_cliente.php @@ -301,6 +301,8 @@ const API = 'api/lab/submit_formulario.php'; let _data = null; // respuesta de verificar token let _cfg = {}; // config de diseño del laboratorio let _firmaDibujada = false; +let _firmaModosGlobal = null; // modos del topbar (columna firma_modos en DB) +let _hasInlineFirma = false; // true si el esquema tiene campos tipo firma/firma_profesional // ══════════════════════════════════════════════════════════════════════ // HELPERS @@ -357,6 +359,20 @@ const firma = (() => { canvas.addEventListener('touchstart', e => { e.preventDefault(); drawing=true; const p=getPos(e); lastX=p.x; lastY=p.y; }, {passive:false}); canvas.addEventListener('touchmove', e => { e.preventDefault(); if (!drawing) return; trazo(getPos(e)); }, {passive:false}); canvas.addEventListener('touchend', ()=> { drawing=false; ctx.beginPath(); }); + + // Drag & drop en área de foto global + const fotoDrop = $('firma-foto-drop'); + if (fotoDrop) { + fotoDrop.addEventListener('dragover', e => { e.preventDefault(); fotoDrop.classList.add('dragover'); }); + fotoDrop.addEventListener('dragleave', () => fotoDrop.classList.remove('dragover')); + fotoDrop.addEventListener('drop', e => { + e.preventDefault(); + fotoDrop.classList.remove('dragover'); + const file = e.dataTransfer.files?.[0]; + if (!file || !file.type.startsWith('image/')) return; + _onFotoChange({ files: [file] }); + }); + } } function trazo(p) { @@ -438,7 +454,11 @@ function renderCampos(esquema, prefilled) { return; } if (c.tipo === 'firma' || c.tipo === 'firma_profesional') { - html += renderFirmaInline(c.id, c.modos || ['canvas', 'foto'], c.label, c.required, c.tipo === 'firma_profesional'); + // firma del paciente usa firma_modos global (topbar); profesional usa sus propios modos + const modos = (c.tipo === 'firma' && _firmaModosGlobal) + ? _firmaModosGlobal + : (c.modos || ['canvas']); + html += renderFirmaInline(c.id, modos, c.label, c.required, c.tipo === 'firma_profesional'); return; } if (c.tipo === 'parrafo') { @@ -553,6 +573,7 @@ const _fw = {}; // { fieldId: { canvas, ctx, hasFirma, foto, drawing, lastX, la function renderFirmaInline(fid, modos, label, required, isPro) { const hasCanvas = (modos||[]).includes('canvas'); const hasFoto = (modos||[]).includes('foto'); + const hasBoth = hasCanvas && hasFoto; const borderC = isPro ? '#198754' : '#1565c0'; const bgC = isPro ? '#f0fff4' : '#fff'; const iconC = isPro ? 'fa-user-md' : 'fa-signature'; @@ -565,6 +586,16 @@ function renderFirmaInline(fid, modos, label, required, isPro) { `; let html = `

${lbl}`; + // Tabs cuando ambos modos están activos + if (hasBoth) { + html += `
+ + +
`; + } + if (hasCanvas) { html += `

✍️ Dibuja la firma con el dedo o el mouse.

@@ -581,11 +612,11 @@ function renderFirmaInline(fid, modos, label, required, isPro) { } if (hasFoto) { - html += `
-

📷 Adjunta una foto de la firma.

+ html += ``; } else if (c.tipo === 'firma' || c.tipo === 'firma_profesional') { - const cm = c.modos || ['canvas']; - html += `
- -
-
- - + if (c.tipo === 'firma_profesional') { + const cm = c.modos || ['canvas']; + html += `
+ +
+
+ + +
+
+ + +
-
- - -
-
-
`; +
`; + } else { + html += `
+ + Los modos del paciente (✍️ Dibujar / 📷 Foto) se configuran + desde el panel superior (sección Firma del paciente). +
`; + } } $('campo-editor-body').innerHTML = html;