@asteby/metacore-runtime-react 37.0.4 → 37.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/action-modal-dispatcher.d.ts.map +1 -1
  3. package/dist/action-modal-dispatcher.js +62 -25
  4. package/dist/branch-create-gate.d.ts +25 -0
  5. package/dist/branch-create-gate.d.ts.map +1 -0
  6. package/dist/branch-create-gate.js +24 -0
  7. package/dist/dialogs/dynamic-record.d.ts.map +1 -1
  8. package/dist/dialogs/dynamic-record.js +20 -6
  9. package/dist/dynamic-form-schema.d.ts +9 -0
  10. package/dist/dynamic-form-schema.d.ts.map +1 -1
  11. package/dist/dynamic-form-schema.js +45 -0
  12. package/dist/dynamic-form.js +12 -2
  13. package/dist/dynamic-line-items.d.ts +6 -1
  14. package/dist/dynamic-line-items.d.ts.map +1 -1
  15. package/dist/dynamic-line-items.js +38 -15
  16. package/dist/dynamic-table.d.ts.map +1 -1
  17. package/dist/dynamic-table.js +35 -0
  18. package/dist/field-validation-ui.d.ts +22 -0
  19. package/dist/field-validation-ui.d.ts.map +1 -0
  20. package/dist/field-validation-ui.js +123 -0
  21. package/dist/index.d.ts +3 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +3 -1
  24. package/package.json +3 -3
  25. package/src/__tests__/field-validation-ui.test.ts +57 -0
  26. package/src/__tests__/line-item-formulas.test.ts +43 -0
  27. package/src/action-modal-dispatcher.tsx +82 -21
  28. package/src/branch-create-gate.tsx +40 -0
  29. package/src/dialogs/dynamic-record.tsx +21 -6
  30. package/src/dynamic-form-schema.ts +51 -0
  31. package/src/dynamic-form.tsx +12 -4
  32. package/src/dynamic-line-items.tsx +74 -12
  33. package/src/dynamic-table.tsx +34 -0
  34. package/src/field-validation-ui.ts +140 -0
  35. package/src/index.ts +15 -0
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAkGnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BAw0CnB"}
1
+ {"version":3,"file":"dynamic-table.d.ts","sourceRoot":"","sources":["../src/dynamic-table.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAKH,KAAK,SAAS,EAajB,MAAM,uBAAuB,CAAA;AAgC9B,OAAO,KAAK,EAAsB,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAkGnF,MAAM,WAAW,iBAAiB;IAC9B,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6DAA6D;IAC7D,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC5B,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,IAAI,CAAA;IAC/B,cAAc,CAAC,EAAE,GAAG,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACpC,YAAY,CAAC,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAA;IAC/B;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;;;;;;;;;OAaG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;IACjC;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,QAAQ,EACR,gBAAgB,EAChB,aAAoB,EACpB,UAAU,EACV,UAAU,EACV,aAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,cAAc,EACd,cAAc,EACd,YAAiB,EACjB,iBAA4C,EAC5C,QAAQ,EACR,QAAQ,EACR,UAAU,EAAE,cAAc,EAC1B,cAAc,EAAE,kBAA0B,GAC7C,EAAE,iBAAiB,+BA02CnB"}
@@ -193,6 +193,36 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
193
193
  // been adopted, where `dynamicFilters`/`pagination` already mirror the URL,
194
194
  // so the write is a no-op and the filter never gets stripped.
195
195
  const [urlSynced, setUrlSynced] = useState(false);
196
+ // Keys that left `defaultFilters` (e.g. branch_id when switching to
197
+ // "Todas las sucursales"). The URL write effect used to carry-through every
198
+ // leftover `f_*` from location — that resurrected the locked branch filter
199
+ // forever after the host dropped it from defaultFilters.
200
+ const prevDefaultFilterKeys = useRef(new Set());
201
+ const releasedDefaultFilterKeys = useRef(new Set());
202
+ useEffect(() => {
203
+ const next = new Set(Object.keys(defaultFilters ?? {}));
204
+ const prev = prevDefaultFilterKeys.current;
205
+ const released = new Set();
206
+ prev.forEach((k) => {
207
+ if (!next.has(k))
208
+ released.add(k);
209
+ });
210
+ releasedDefaultFilterKeys.current = released;
211
+ if (released.size > 0) {
212
+ setDynamicFilters((df) => {
213
+ let changed = false;
214
+ const copy = { ...df };
215
+ released.forEach((k) => {
216
+ if (k in copy) {
217
+ delete copy[k];
218
+ changed = true;
219
+ }
220
+ });
221
+ return changed ? copy : df;
222
+ });
223
+ }
224
+ prevDefaultFilterKeys.current = next;
225
+ }, [defaultFilters]);
196
226
  useEffect(() => {
197
227
  if (prevBranchId.current !== currentBranch?.id) {
198
228
  prevBranchId.current = currentBranch?.id;
@@ -349,11 +379,16 @@ export function DynamicTable({ model, endpoint, mutationEndpoint, enableUrlSync
349
379
  // Sidebar deep-links (CxC→CxP) push f_party_type=eq:supplier before React
350
380
  // re-renders with matching defaultFilters; without this carry-through the
351
381
  // write effect races and strips the filter down to bare ?view=list.
382
+ // Do NOT resurrect keys the host just released from defaultFilters
383
+ // (branch_id when switching to "all" — otherwise San Felipe sticks).
352
384
  current.forEach((value, key) => {
353
385
  if (!key.startsWith('f_'))
354
386
  return;
355
387
  if (params.has(key))
356
388
  return;
389
+ const filterKey = key.substring(2);
390
+ if (releasedDefaultFilterKeys.current.has(filterKey))
391
+ return;
357
392
  params.set(key, value);
358
393
  });
359
394
  const search = params.toString();
@@ -0,0 +1,22 @@
1
+ import type { ActionFieldDef } from './types';
2
+ import type { Translate } from './server-error';
3
+ /**
4
+ * Resolve a validation path (`customer_id`, `lines.0.unit_price`) to a
5
+ * human label using the action/modal field schema. Nested line-item paths
6
+ * become "Renglones → Precio unitario (fila 1)".
7
+ */
8
+ export declare function labelForValidationPath(path: string, fields: readonly ActionFieldDef[] | undefined, t?: Translate): string;
9
+ /** Build `{path: label}` covering scalar fields and `parent.N.child` templates
10
+ * used by localizeFieldErrorMap (exact keys win when present). */
11
+ export declare function labelsForValidationFields(fields: readonly ActionFieldDef[] | undefined, t?: Translate): Record<string, string>;
12
+ /**
13
+ * Toast description: one "Label: message" line per error. Re-resolves labels
14
+ * for dotted line-item paths so operators see e.g.
15
+ * "Precio unitario (fila 1): es obligatorio" instead of a bare headline.
16
+ */
17
+ export declare function formatFieldErrorsDescription(errors: Record<string, string>, fields?: readonly ActionFieldDef[], t?: Translate): string | undefined;
18
+ /** Drop `key` and every `key.*` / `key.N.*` entry after the operator edits that field. */
19
+ export declare function clearFieldErrorTree(prev: Record<string, string>, key: string): Record<string, string>;
20
+ /** Slice `parent.0.child` errors into `{ "0.child": msg }` for DynamicLineItems. */
21
+ export declare function lineItemErrorsFor(parentKey: string, errors: Record<string, string> | undefined): Record<string, string>;
22
+ //# sourceMappingURL=field-validation-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"field-validation-ui.d.ts","sourceRoot":"","sources":["../src/field-validation-ui.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAiB/C;;;;GAIG;AACH,wBAAgB,sBAAsB,CAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAC7C,CAAC,CAAC,EAAE,SAAS,GACd,MAAM,CAwCR;AAED;mEACmE;AACnE,wBAAgB,yBAAyB,CACrC,MAAM,EAAE,SAAS,cAAc,EAAE,GAAG,SAAS,EAC7C,CAAC,CAAC,EAAE,SAAS,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,CAAC,EAAE,SAAS,cAAc,EAAE,EAClC,CAAC,CAAC,EAAE,SAAS,GACd,MAAM,GAAG,SAAS,CAYpB;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,GAAG,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,GAC3C,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQxB"}
@@ -0,0 +1,123 @@
1
+ function itemFieldsOf(field) {
2
+ const raw = field.itemFields ?? field.item_fields;
3
+ return Array.isArray(raw) ? raw : [];
4
+ }
5
+ function translateLabel(raw, t) {
6
+ if (!raw)
7
+ return '';
8
+ if (!t)
9
+ return raw;
10
+ return t(raw, { defaultValue: raw });
11
+ }
12
+ function humanizeToken(key) {
13
+ return key.replace(/[._-]+/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase());
14
+ }
15
+ /**
16
+ * Resolve a validation path (`customer_id`, `lines.0.unit_price`) to a
17
+ * human label using the action/modal field schema. Nested line-item paths
18
+ * become "Renglones → Precio unitario (fila 1)".
19
+ */
20
+ export function labelForValidationPath(path, fields, t) {
21
+ if (!path)
22
+ return '';
23
+ const parts = path.split('.');
24
+ if (!fields?.length)
25
+ return humanizeToken(path);
26
+ let cursor = fields;
27
+ const bits = [];
28
+ let i = 0;
29
+ while (i < parts.length && cursor) {
30
+ const seg = parts[i];
31
+ if (/^\d+$/.test(seg)) {
32
+ const row = Number(seg) + 1;
33
+ const nextKey = parts[i + 1];
34
+ if (nextKey && cursor) {
35
+ const col = cursor.find((f) => f.key === nextKey);
36
+ const colLabel = translateLabel(col?.label, t) || humanizeToken(nextKey);
37
+ bits.push(`${colLabel} (fila ${row})`);
38
+ i += 2;
39
+ cursor = undefined;
40
+ continue;
41
+ }
42
+ bits.push(`fila ${row}`);
43
+ i += 1;
44
+ continue;
45
+ }
46
+ const field = cursor.find((f) => f.key === seg);
47
+ if (!field) {
48
+ bits.push(humanizeToken(parts.slice(i).join('.')));
49
+ break;
50
+ }
51
+ bits.push(translateLabel(field.label, t) || humanizeToken(seg));
52
+ const nested = itemFieldsOf(field);
53
+ cursor = nested.length ? nested : undefined;
54
+ i += 1;
55
+ if (!cursor && i < parts.length) {
56
+ bits.push(humanizeToken(parts.slice(i).join('.')));
57
+ break;
58
+ }
59
+ }
60
+ return bits.join(' → ');
61
+ }
62
+ /** Build `{path: label}` covering scalar fields and `parent.N.child` templates
63
+ * used by localizeFieldErrorMap (exact keys win when present). */
64
+ export function labelsForValidationFields(fields, t) {
65
+ const out = {};
66
+ if (!fields)
67
+ return out;
68
+ for (const f of fields) {
69
+ if (!f.key)
70
+ continue;
71
+ out[f.key] = translateLabel(f.label, t) || humanizeToken(f.key);
72
+ for (const child of itemFieldsOf(f)) {
73
+ if (!child.key)
74
+ continue;
75
+ out[`${f.key}.${child.key}`] = translateLabel(child.label, t) || humanizeToken(child.key);
76
+ }
77
+ }
78
+ return out;
79
+ }
80
+ /**
81
+ * Toast description: one "Label: message" line per error. Re-resolves labels
82
+ * for dotted line-item paths so operators see e.g.
83
+ * "Precio unitario (fila 1): es obligatorio" instead of a bare headline.
84
+ */
85
+ export function formatFieldErrorsDescription(errors, fields, t) {
86
+ const entries = Object.entries(errors);
87
+ if (!entries.length)
88
+ return undefined;
89
+ return entries
90
+ .map(([path, msg]) => {
91
+ const label = labelForValidationPath(path, fields, t);
92
+ // localizeFieldIssue already prefixes "{{label}}: …" — avoid
93
+ // "Label: Label: msg" when the message already starts with the label.
94
+ if (label && msg.toLowerCase().startsWith(label.toLowerCase()))
95
+ return msg;
96
+ return label ? `${label}: ${msg}` : msg;
97
+ })
98
+ .join(' · ');
99
+ }
100
+ /** Drop `key` and every `key.*` / `key.N.*` entry after the operator edits that field. */
101
+ export function clearFieldErrorTree(prev, key) {
102
+ if (!prev[key] && !Object.keys(prev).some((k) => k.startsWith(`${key}.`)))
103
+ return prev;
104
+ const next = {};
105
+ for (const [k, v] of Object.entries(prev)) {
106
+ if (k === key || k.startsWith(`${key}.`))
107
+ continue;
108
+ next[k] = v;
109
+ }
110
+ return next;
111
+ }
112
+ /** Slice `parent.0.child` errors into `{ "0.child": msg }` for DynamicLineItems. */
113
+ export function lineItemErrorsFor(parentKey, errors) {
114
+ if (!errors)
115
+ return {};
116
+ const prefix = `${parentKey}.`;
117
+ const out = {};
118
+ for (const [k, v] of Object.entries(errors)) {
119
+ if (k.startsWith(prefix))
120
+ out[k.slice(prefix.length)] = v;
121
+ }
122
+ return out;
123
+ }
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './options-context';
4
4
  export { extractServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap, toastServerError, toastServerSuccess, type ExtractedError, type Translate, type FieldIssue, } from './server-error';
5
5
  export { parseRuleString, fieldValidationOf, checkValue, validateValues, bagHasErrors, type ValidationSpec, } from './validator';
6
6
  export { VALIDATION_CATALOGS, validationCatalog, validationMessageKey } from './validation-catalog';
7
+ export { labelForValidationPath, labelsForValidationFields, formatFieldErrorsDescription, clearFieldErrorTree, lineItemErrorsFor, } from './field-validation-ui';
7
8
  export * from './dynamic-table';
8
9
  export { DynamicKanban, type DynamicKanbanProps, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
9
10
  export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, type StageAutomation, type StageAutomationAction, type StageAutomationActionType, type NewStageAutomation, type UseStageAutomationsResult, type StageAutomationsButtonProps, } from './stage-automations';
@@ -70,7 +71,8 @@ export { registerModelExtension, getModelExtension, clearModelExtensions, type M
70
71
  export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
71
72
  export { useOptionsResolver, projectOption, type ResolvedOption, type OptionsMeta, type UseOptionsResolverArgs, type UseOptionsResolverResult, } from './use-options-resolver';
72
73
  export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, type OrgConfigBridge, } from './use-org-config-bridge';
73
- export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, } from './dynamic-form-schema';
74
+ export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
75
+ export { BranchCreateGateProvider, useBranchCreateGate, type BranchCreateGateApi, } from './branch-create-gate';
74
76
  export { ActivityValueRenderer, type ActivityValueRendererProps, } from './activity-value-renderer';
75
77
  export { ActivityDiff, type ActivityEvent, type ActivityDiffProps, } from './activity-diff';
76
78
  export { RecordHistory, type RecordHistoryProps, } from './record-history';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,KAAK,cAAc,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACnG,OAAO,EACH,sBAAsB,EACtB,yBAAyB,EACzB,4BAA4B,EAC5B,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,cAAc,EACd,KAAK,mBAAmB,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACvB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,mBAAmB,EACnB,MAAM,EACN,oBAAoB,EACpB,OAAO,EACP,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,wBAAwB,GAChC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,SAAS,GACjB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,GAC9B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,GACtC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AACnE,OAAO,EACH,OAAO,EACP,QAAQ,EACR,cAAc,EACd,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,SAAS,IAAI,uBAAuB,GAC5C,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,YAAY,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,QAAQ,GACX,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,mBAAmB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACH,qBAAqB,EACrB,KAAK,0BAA0B,GAClC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,gBAAgB,EAChB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,KAAK,mBAAmB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA"}
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ export * from './options-context';
9
9
  export { extractServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap, toastServerError, toastServerSuccess, } from './server-error';
10
10
  export { parseRuleString, fieldValidationOf, checkValue, validateValues, bagHasErrors, } from './validator';
11
11
  export { VALIDATION_CATALOGS, validationCatalog, validationMessageKey } from './validation-catalog';
12
+ export { labelForValidationPath, labelsForValidationFields, formatFieldErrorsDescription, clearFieldErrorTree, lineItemErrorsFor, } from './field-validation-ui';
12
13
  export * from './dynamic-table';
13
14
  export { DynamicKanban, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
14
15
  export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, } from './stage-automations';
@@ -70,7 +71,8 @@ export { registerModelExtension, getModelExtension, clearModelExtensions, } from
70
71
  export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
71
72
  export { useOptionsResolver, projectOption, } from './use-options-resolver';
72
73
  export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, } from './use-org-config-bridge';
73
- export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, } from './dynamic-form-schema';
74
+ export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
75
+ export { BranchCreateGateProvider, useBranchCreateGate, } from './branch-create-gate';
74
76
  export { ActivityValueRenderer, } from './activity-value-renderer';
75
77
  export { ActivityDiff, } from './activity-diff';
76
78
  export { RecordHistory, } from './record-history';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "37.0.4",
3
+ "version": "37.1.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -67,8 +67,8 @@
67
67
  "typescript": "^6.0.0",
68
68
  "vitest": "^4.0.0",
69
69
  "zustand": "^5.0.0",
70
- "@asteby/metacore-sdk": "3.7.0",
71
- "@asteby/metacore-ui": "2.17.3"
70
+ "@asteby/metacore-ui": "2.17.3",
71
+ "@asteby/metacore-sdk": "3.7.0"
72
72
  },
73
73
  "scripts": {
74
74
  "build": "tsc -p tsconfig.json",
@@ -0,0 +1,57 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ clearFieldErrorTree,
4
+ formatFieldErrorsDescription,
5
+ labelForValidationPath,
6
+ lineItemErrorsFor,
7
+ } from '../field-validation-ui'
8
+ import type { ActionFieldDef } from '../types'
9
+
10
+ const fields: ActionFieldDef[] = [
11
+ { key: 'customer_id', label: 'Cliente', type: 'dynamic_select', required: true },
12
+ {
13
+ key: 'lines',
14
+ label: 'Renglones',
15
+ type: 'array',
16
+ required: true,
17
+ itemFields: [
18
+ { key: 'product_id', label: 'Producto', type: 'dynamic_select', required: true },
19
+ { key: 'unit_price', label: 'Precio unitario', type: 'number', required: true },
20
+ ],
21
+ },
22
+ ]
23
+
24
+ describe('field-validation-ui', () => {
25
+ it('labels dotted line-item paths with fila N', () => {
26
+ expect(labelForValidationPath('lines.0.unit_price', fields)).toBe(
27
+ 'Renglones → Precio unitario (fila 1)',
28
+ )
29
+ })
30
+
31
+ it('formats toast description with field labels', () => {
32
+ const desc = formatFieldErrorsDescription(
33
+ { 'lines.0.unit_price': 'es obligatorio' },
34
+ fields,
35
+ )
36
+ expect(desc).toContain('Precio unitario (fila 1)')
37
+ expect(desc).toContain('es obligatorio')
38
+ })
39
+
40
+ it('slices parent errors for DynamicLineItems', () => {
41
+ expect(
42
+ lineItemErrorsFor('lines', {
43
+ 'lines.0.unit_price': 'required',
44
+ customer_id: 'required',
45
+ }),
46
+ ).toEqual({ '0.unit_price': 'required' })
47
+ })
48
+
49
+ it('clears dotted children when parent key edits', () => {
50
+ expect(
51
+ clearFieldErrorTree(
52
+ { 'lines.0.unit_price': 'x', customer_id: 'y' },
53
+ 'lines',
54
+ ),
55
+ ).toEqual({ customer_id: 'y' })
56
+ })
57
+ })
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { applyLineItemRowFormulas } from '../dynamic-form-schema'
3
+ import type { ActionFieldDef } from '../types'
4
+
5
+ const fields: ActionFieldDef[] = [
6
+ { key: 'product_id', label: 'Producto', type: 'dynamic_select' },
7
+ { key: 'qty', label: 'Cantidad', type: 'number' },
8
+ { key: 'unit_price', label: 'Precio', type: 'number' },
9
+ { key: 'discount', label: 'Descuento', type: 'number' },
10
+ { key: 'subtotal', label: 'Importe', type: 'number' },
11
+ ]
12
+
13
+ describe('applyLineItemRowFormulas', () => {
14
+ it('computes qty * unit_price - discount into subtotal', () => {
15
+ const row = applyLineItemRowFormulas(fields, {
16
+ product_id: 'p1',
17
+ qty: 3,
18
+ unit_price: 10,
19
+ discount: 5,
20
+ subtotal: 0,
21
+ })
22
+ expect(row.subtotal).toBe(25)
23
+ })
24
+
25
+ it('treats blank discount as 0', () => {
26
+ const row = applyLineItemRowFormulas(fields, {
27
+ qty: '2',
28
+ unit_price: '12.5',
29
+ discount: '',
30
+ subtotal: '',
31
+ })
32
+ expect(row.subtotal).toBe(25)
33
+ })
34
+
35
+ it('is a no-op without an amount column', () => {
36
+ const lean: ActionFieldDef[] = [
37
+ { key: 'qty', label: 'Cantidad', type: 'number' },
38
+ { key: 'unit_price', label: 'Precio', type: 'number' },
39
+ ]
40
+ const input = { qty: 2, unit_price: 5 }
41
+ expect(applyLineItemRowFormulas(lean, input)).toBe(input)
42
+ })
43
+ })
@@ -38,8 +38,16 @@ import {
38
38
  import { Loader2 } from 'lucide-react'
39
39
  import { toast } from 'sonner'
40
40
  import { toastServerError, toastServerSuccess, extractFieldErrors, localizeFieldErrorMap } from './server-error'
41
+ import { useBranchCreateGate } from './branch-create-gate'
41
42
  import type { Translate } from './server-error'
42
43
  import { validateValues, bagHasErrors } from './validator'
44
+ import {
45
+ clearFieldErrorTree,
46
+ formatFieldErrorsDescription,
47
+ labelsForValidationFields,
48
+ labelForValidationPath,
49
+ lineItemErrorsFor,
50
+ } from './field-validation-ui'
43
51
  import { validationCatalog } from './validation-catalog'
44
52
  import { useApi } from './api-context'
45
53
  import { DynamicIcon } from './dynamic-icon'
@@ -581,6 +589,7 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
581
589
  // defaultValue keeps an already-localized string unchanged.
582
590
  const tl = (s: string) => t(s, { defaultValue: s })
583
591
  const api = useApi()
592
+ const branchGate = useBranchCreateGate()
584
593
  const [formData, setFormData] = useState<Record<string, any>>({})
585
594
  const [executing, setExecuting] = useState(false)
586
595
  // Per-field validation errors (localized), shown inline under each input.
@@ -621,41 +630,69 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
621
630
 
622
631
  const updateField = (key: string, value: any) => {
623
632
  setFormData((prev: Record<string, any>) => ({ ...prev, [key]: value }))
624
- setFieldErrors(prev => {
625
- if (!prev[key]) return prev
626
- const next = { ...prev }
627
- delete next[key]
628
- return next
629
- })
633
+ setFieldErrors((prev) => clearFieldErrorTree(prev, key))
630
634
  }
631
635
 
632
636
  const lang = i18n.language
633
637
  const handleActionError = (err: unknown) => {
638
+ const labels = labelsForValidationFields(action.fields, t)
634
639
  const localized = localizeActionFieldErrors(err, action.fields, t, lang)
635
640
  if (localized) {
636
- setFieldErrors(localized)
637
- toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }))
641
+ // Enrich labels for dotted line-item paths before toasting.
642
+ const withPathLabels: Record<string, string> = {}
643
+ for (const [path, msg] of Object.entries(localized)) {
644
+ withPathLabels[path] = msg
645
+ if (!labels[path]) labels[path] = labelForValidationPath(path, action.fields, t)
646
+ }
647
+ setFieldErrors(withPathLabels)
648
+ toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }), {
649
+ description: formatFieldErrorsDescription(withPathLabels, action.fields, t),
650
+ })
638
651
  return
639
652
  }
640
- toastServerError(err, { t, language: lang })
653
+ toastServerError(err, { t, language: lang, labels })
641
654
  }
642
655
 
643
656
  const execute = async () => {
644
657
  if (action.fields) {
645
658
  const bag = validateValues(action.fields, formData)
646
659
  if (bagHasErrors(bag)) {
647
- const labels: Record<string, string> = {}
648
- for (const f of action.fields) labels[f.key] = tl(f.label)
649
- setFieldErrors(localizeFieldErrorMap(bag, t, { labels, language: lang }))
650
- toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }))
660
+ const labels = labelsForValidationFields(action.fields, (k, o) => t(k, o))
661
+ // Exact dotted keys (`lines.0.qty`) need path-aware labels.
662
+ for (const path of Object.keys(bag)) {
663
+ if (!labels[path]) labels[path] = labelForValidationPath(path, action.fields, t)
664
+ }
665
+ const next = localizeFieldErrorMap(bag, t, { labels, language: lang })
666
+ setFieldErrors(next)
667
+ toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }), {
668
+ description: formatFieldErrorsDescription(next, action.fields, t),
669
+ })
651
670
  return
652
671
  }
653
672
  }
654
673
  setFieldErrors({})
655
674
  setExecuting(true)
656
675
  try {
657
- const url = buildActionUrl(endpoint, model, record.id, action.key)
658
- const res = await api.post(url, formData)
676
+ let payload: Record<string, any> = { ...formData }
677
+ // Create-placement actions (and any create with no record) may need a
678
+ // host branch stamp when the sidebar is on "Todas". Skip when the
679
+ // form already collected branch_id, or the host has no gate.
680
+ const isCreatePlacement =
681
+ action.placement === 'create' ||
682
+ record?.id == null ||
683
+ record?.id === '' ||
684
+ record?.id === 'undefined'
685
+ if (
686
+ branchGate &&
687
+ isCreatePlacement &&
688
+ (payload.branch_id == null || payload.branch_id === '')
689
+ ) {
690
+ const branchId = await branchGate.ensureBranchForCreate(model)
691
+ if (branchId === null) return
692
+ if (branchId) payload = { ...payload, branch_id: branchId }
693
+ }
694
+ const url = buildActionUrl(endpoint, model, record?.id, action.key)
695
+ const res = await api.post(url, payload)
659
696
  if (res.data.success) {
660
697
  toastServerSuccess(res.data, { t })
661
698
  onOpenChange(false)
@@ -727,7 +764,14 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
727
764
  <FieldLabel htmlFor={field.key} required={field.required}>
728
765
  {tl(field.label)}
729
766
  </FieldLabel>
730
- {renderField(field, formData[field.key], (v: any) => updateField(field.key, v), formData, record)}
767
+ {renderField(
768
+ field,
769
+ formData[field.key],
770
+ (v: any) => updateField(field.key, v),
771
+ formData,
772
+ record,
773
+ fieldErrors,
774
+ )}
731
775
  {fieldErrors[field.key] && (
732
776
  <p className="text-destructive text-xs mt-1">{fieldErrors[field.key]}</p>
733
777
  )}
@@ -1011,17 +1055,30 @@ function renderField(
1011
1055
  // then treated as having no resolvable dependency).
1012
1056
  formValues?: Record<string, any>,
1013
1057
  record?: Record<string, any>,
1058
+ fieldErrors?: Record<string, string>,
1014
1059
  ) {
1015
1060
  // Repeatable line-items group → row grid (value is an array of row objects).
1016
1061
  // The header form values flow in so a cell can depend on a header field.
1017
1062
  if (isLineItemsField(field)) {
1018
- return <DynamicLineItems field={applyPrefillLock(field)} value={value} onChange={onChange} formValues={formValues} />
1063
+ return (
1064
+ <DynamicLineItems
1065
+ field={applyPrefillLock(field)}
1066
+ value={value}
1067
+ onChange={onChange}
1068
+ formValues={formValues}
1069
+ errors={lineItemErrorsFor(field.key, fieldErrors)}
1070
+ />
1071
+ )
1019
1072
  }
1020
1073
  // Resolve the widget the same way DynamicForm does (explicit widget wins,
1021
1074
  // else inferred from type) so action modals and the standalone form stay in
1022
1075
  // lockstep — previously this switch keyed off `field.type` and silently
1023
1076
  // dropped `dynamic_select` to a plain text input.
1024
1077
  const widget = resolveWidget(field)
1078
+ const invalid = !!(fieldErrors && fieldErrors[field.key])
1079
+ const invalidCls = invalid
1080
+ ? 'border-destructive ring-1 ring-destructive/30 focus-visible:ring-destructive'
1081
+ : ''
1025
1082
  if (widget === 'dynamic_select') {
1026
1083
  // A header-level dynamic_select may itself depend on another header
1027
1084
  // field; resolve its filter_value from the form context.
@@ -1035,6 +1092,7 @@ function renderField(
1035
1092
  onChange={onChange}
1036
1093
  dependsValue={dependsValue}
1037
1094
  seedOption={seedOptionFromRecord(field, value, record)}
1095
+ invalid={invalid}
1038
1096
  />
1039
1097
  )
1040
1098
  }
@@ -1045,11 +1103,11 @@ function renderField(
1045
1103
  }
1046
1104
  switch (widget) {
1047
1105
  case 'textarea':
1048
- return <Textarea id={field.key} value={value || ''} onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)} placeholder={field.placeholder} />
1106
+ return <Textarea id={field.key} value={value || ''} onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => onChange(e.target.value)} placeholder={field.placeholder} aria-invalid={invalid || undefined} className={invalidCls || undefined} />
1049
1107
  case 'select':
1050
1108
  return (
1051
1109
  <Select value={value || ''} onValueChange={onChange}>
1052
- <SelectTrigger className="w-full"><SelectValue placeholder={field.placeholder || 'Seleccionar...'} /></SelectTrigger>
1110
+ <SelectTrigger className={'w-full' + (invalidCls ? ` ${invalidCls}` : '')} aria-invalid={invalid || undefined}><SelectValue placeholder={field.placeholder || 'Seleccionar...'} /></SelectTrigger>
1053
1111
  <SelectContent>
1054
1112
  {field.options?.map((opt) => <SelectItem key={opt.value} value={opt.value}>{opt.label}</SelectItem>)}
1055
1113
  </SelectContent>
@@ -1058,12 +1116,15 @@ function renderField(
1058
1116
  case 'switch':
1059
1117
  return <Switch id={field.key} checked={!!value} onCheckedChange={onChange} />
1060
1118
  case 'number':
1061
- return <Input id={field.key} type="number" value={value ?? ''} onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.valueAsNumber || '')} placeholder={field.placeholder} />
1119
+ return <Input id={field.key} type="number" value={value ?? ''} onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
1120
+ const n = e.target.valueAsNumber
1121
+ onChange(e.target.value === '' || !Number.isFinite(n) ? '' : n)
1122
+ }} placeholder={field.placeholder} aria-invalid={invalid || undefined} className={invalidCls || undefined} />
1062
1123
  case 'date':
1063
1124
  // Modern shadcn Calendar in a Popover (portaled, never clipped by the
1064
1125
  // modal) instead of the native, dated, easily-cut <input type=date>.
1065
1126
  return <DynamicDateField field={field} value={value} onChange={onChange} />
1066
1127
  default:
1067
- return <Input id={field.key} type={field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : 'text'} value={value || ''} onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.value)} placeholder={field.placeholder} />
1128
+ return <Input id={field.key} type={field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : 'text'} value={value || ''} onChange={(e: React.ChangeEvent<HTMLInputElement>) => onChange(e.target.value)} placeholder={field.placeholder} aria-invalid={invalid || undefined} className={invalidCls || undefined} />
1068
1129
  }
1069
1130
  }