feat(nakui): Fase 7 del ERP — pulido (cierra el plan maestro)

Validación inline: al fallar un submit por campos required vacíos, el
form los marca (label destructivo + mensaje debajo), no sólo un toast.
MetaApp.form_errors + validate_required_fields. Secciones de formulario:
FieldSpec.section agrupa campos bajo encabezados; abrir_form del CRM las
usa. Campos condicionales y pulido puramente visual: scope-out conciente.

El plan docs/nakui-erp-masterplan.md queda completo (7/7 fases). Tests
verdes (meta-schema 16, meta-runtime 70, meta-form 8, nakui-ui 14);
clippy limpio en las libs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
sergio
2026-05-21 19:43:44 +00:00
parent b13486e240
commit c56ef25546
9 changed files with 168 additions and 12 deletions
@@ -297,6 +297,10 @@ pub struct FieldSpec {
/// kinds. `Module::validate` exige que un Select las tenga.
#[serde(default)]
pub options: Vec<SelectOption>,
/// Sección del formulario a la que pertenece el campo. Campos
/// consecutivos con la misma sección se agrupan bajo un encabezado.
#[serde(default)]
pub section: Option<String>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
@@ -591,6 +595,7 @@ mod tests {
help: None,
ref_entity: None,
options: Vec::new(),
section: None,
},
FieldSpec {
name: "email".into(),
@@ -601,6 +606,7 @@ mod tests {
help: Some("Opcional".into()),
ref_entity: None,
options: Vec::new(),
section: None,
},
],
}],
@@ -660,6 +666,7 @@ mod tests {
help: None,
ref_entity: None,
options: Vec::new(),
section: None,
}],
on_submit: Action::SeedEntity {
entity: "customer".into(),
@@ -753,6 +760,7 @@ mod tests {
help: None,
ref_entity: None,
options: Vec::new(),
section: None,
}],
on_submit: Action::SeedEntity {
entity: "customer".into(),
@@ -784,6 +792,7 @@ mod tests {
help: None,
ref_entity: Some("supplier".into()),
options: Vec::new(),
section: None,
}],
on_submit: Action::SeedEntity {
entity: "customer".into(),
@@ -816,6 +825,7 @@ mod tests {
help: None,
ref_entity: None,
options: Vec::new(),
section: None,
}],
on_submit: Action::SeedEntity {
entity: "customer".into(),
@@ -856,6 +866,7 @@ mod tests {
label: None,
},
],
section: None,
}],
on_submit: Action::SeedEntity {
entity: "customer".into(),