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 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-07-03 11:23:36 -05:00
co-authored by Claude Sonnet 4.6
parent 0c68dff307
commit 1385c25b30
2 changed files with 62 additions and 0 deletions
+28
View File
@@ -555,6 +555,34 @@ function renderCampos(esquema, prefilled) {
<label class="form-check-label">${esc(o)}</label>
</div>`).join('');
html += wrapOpen + `<div class="mb-3">${lbl}${opts}${linkedNote}</div>` + 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 + `<div class="mb-3">${lbl}
<input type="${inputType}" class="form-control" style="background:#fff9e6;border-color:#ffc107"
name="${c.id}" value="${esc(calcVal)}" ${req}
placeholder="${c.calc_tipo === 'edad' ? 'Edad en años' : 'Fecha'}">
<small class="text-warning-emphasis"><i class="fas fa-calculator me-1"></i>Prellenado automáticamente — puedes modificarlo</small>
</div>` + wrapClose;
} else {
const t = c.tipo === 'numero' ? 'number'
: (c.tipo === 'fecha' || c.linked_key === 'fecha_nacimiento') ? 'date'