From 1385c25b307e2370d7217a7e34ac5db6e11d61d6 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:23:32 -0500 Subject: [PATCH] feat(formularios): add 'calculado' field type with fecha_hoy and edad sub-types Builder: - New palette item 'Campo calculado' (fa-calculator) - Editor modal lets user pick: Fecha de hoy / Edad del paciente - Preview shows yellow-tinted input with calculator badge form_cliente.php: - fecha_hoy: pre-fills today's date (YYYY-MM-DD), editable by patient - edad: calculates age from patient's fecha_nacimiento, editable - Collected on submit like any normal input Co-Authored-By: Claude Sonnet 4.6 --- form_cliente.php | 28 ++++++++++++++++++++++++++++ lab_formulario_builder.php | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/form_cliente.php b/form_cliente.php index 35368f3..b04100e 100644 --- a/form_cliente.php +++ b/form_cliente.php @@ -555,6 +555,34 @@ function renderCampos(esquema, prefilled) { `).join(''); html += wrapOpen + `
${lbl}${opts}${linkedNote}
` + wrapClose; + } else if (c.tipo === 'calculado') { + // Pre-calcular valor según sub-tipo + let calcVal = pad[c.id] || ''; + if (!calcVal) { + if ((c.calc_tipo || 'fecha_hoy') === 'fecha_hoy') { + const now = new Date(); + calcVal = now.getFullYear() + '-' + + String(now.getMonth()+1).padStart(2,'0') + '-' + + String(now.getDate()).padStart(2,'0'); + } else if (c.calc_tipo === 'edad') { + const fnac = pad['__paciente']?.fecha_nacimiento || pad.fecha_nacimiento || ''; + if (fnac) { + const hoy = new Date(); + const bday = new Date(fnac); + let edad = hoy.getFullYear() - bday.getFullYear(); + const m = hoy.getMonth() - bday.getMonth(); + if (m < 0 || (m === 0 && hoy.getDate() < bday.getDate())) edad--; + calcVal = edad >= 0 ? String(edad) : ''; + } + } + } + const inputType = c.calc_tipo === 'edad' ? 'number' : 'date'; + html += wrapOpen + `
${lbl} + + Prellenado automáticamente — puedes modificarlo +
` + wrapClose; } else { const t = c.tipo === 'numero' ? 'number' : (c.tipo === 'fecha' || c.linked_key === 'fecha_nacimiento') ? 'date' diff --git a/lab_formulario_builder.php b/lab_formulario_builder.php index 0b6da64..ea059ca 100644 --- a/lab_formulario_builder.php +++ b/lab_formulario_builder.php @@ -478,6 +478,7 @@ const TIPOS_CAMPO = [ { tipo:'parrafo', label:'Párrafo de texto', icon:'fa-paragraph' }, { tipo:'parrafo_inline', label:'Párrafo con campos', icon:'fa-align-left' }, { tipo:'lista_marcable', label:'Lista marcable', icon:'fa-list-ol' }, + { tipo:'calculado', label:'Campo calculado', icon:'fa-calculator' }, ]; const TIPOS_LINKED = [ { key:'nombre_completo', label:'Nombre completo', icon:'fa-user' }, @@ -765,6 +766,16 @@ function renderCampoPreview(c) { ).join(''); return `
${lbl}${items}
`; } + if (c.tipo === 'calculado') { + const subLabel = c.calc_tipo === 'edad' ? 'Edad (años) — calculada del paciente' + : 'Fecha de hoy — prellenada y editable'; + const t = c.calc_tipo === 'edad' ? 'number' : 'date'; + return `
+ ${lbl} + + Campo calculado — editable por el paciente +
`; + } const t = c.tipo==='numero'?'number':c.tipo==='fecha'?'date':c.tipo==='hora'?'time':'text'; return `
${lbl}
`; @@ -878,6 +889,26 @@ function abrirEditorCampo(idx) { `; + } else if (c.tipo === 'calculado') { + const isFecha = (c.calc_tipo || 'fecha_hoy') === 'fecha_hoy'; + html += `
+ +
+
+ + +
+
+ + +
+
+
El campo se pre-llena automáticamente pero el paciente puede editarlo.
+
+
+ + +
`; } else if (c.tipo === 'firma' || c.tipo === 'firma_profesional') { if (c.tipo === 'firma_profesional') { const cm = c.modos || ['canvas']; @@ -964,6 +995,9 @@ function aplicarCampo() { const items = document.getElementById('ce-items'); if (items) c.items = items.value.split('\n').map(s=>s.trim()).filter(Boolean); + const calcTipo = document.querySelector('input[name="ce-calc-tipo"]:checked'); + if (calcTipo) c.calc_tipo = calcTipo.value; + const modoCanvas = document.getElementById('ce-modo-canvas'); const modoFoto = document.getElementById('ce-modo-foto'); if (modoCanvas !== null || modoFoto !== null) {