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) {