@oondemand/oon-core-front 0.3.42 → 0.3.44
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.
- package/dist/index.d.ts +50 -1
- package/dist/index.js +400 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
1
5
|
// src/start.tsx
|
|
2
6
|
import { StrictMode } from "react";
|
|
3
7
|
import { createRoot } from "react-dom/client";
|
|
@@ -677,15 +681,30 @@ function formOptions(field) {
|
|
|
677
681
|
}
|
|
678
682
|
return void 0;
|
|
679
683
|
}
|
|
684
|
+
function formReadonly(field) {
|
|
685
|
+
const raw = field;
|
|
686
|
+
return Boolean(raw.readonly || raw.immutable || raw.computed);
|
|
687
|
+
}
|
|
688
|
+
function formComputed(field) {
|
|
689
|
+
const raw = field;
|
|
690
|
+
if (!raw.computed || typeof raw.computed !== "object" || Array.isArray(raw.computed)) return void 0;
|
|
691
|
+
return raw.computed;
|
|
692
|
+
}
|
|
680
693
|
function formFieldsFromMeta(fields) {
|
|
681
|
-
return fields.filter(isEditableField).map((field) =>
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
694
|
+
return fields.filter(isEditableField).map((field) => {
|
|
695
|
+
const computed = formComputed(field);
|
|
696
|
+
const readonly = formReadonly(field);
|
|
697
|
+
return {
|
|
698
|
+
field: field.name,
|
|
699
|
+
label: fieldLabel(field),
|
|
700
|
+
kind: field.kind,
|
|
701
|
+
required: formRequired(field),
|
|
702
|
+
options: formOptions(field),
|
|
703
|
+
ref: field.ref,
|
|
704
|
+
...readonly ? { readonly: true } : {},
|
|
705
|
+
...computed ? { computed } : {}
|
|
706
|
+
};
|
|
707
|
+
});
|
|
689
708
|
}
|
|
690
709
|
function formatCell(value, kind) {
|
|
691
710
|
if (value == null || value === "") return "\u2014";
|
|
@@ -964,6 +983,264 @@ function DataGrid({
|
|
|
964
983
|
import { useEffect as useEffect4, useMemo as useMemo4, useState as useState5 } from "react";
|
|
965
984
|
import { Box as Box4, Button as Button4, Flex as Flex4, Heading as Heading2, Input as Input3, NativeSelect as NativeSelect2, SimpleGrid, Stack as Stack2, Text as Text5, Textarea } from "@chakra-ui/react";
|
|
966
985
|
|
|
986
|
+
// src/domain/domainExpressions.ts
|
|
987
|
+
var DomainExpressionError = class extends Error {
|
|
988
|
+
constructor(message, options = {}) {
|
|
989
|
+
super(message);
|
|
990
|
+
__publicField(this, "code");
|
|
991
|
+
__publicField(this, "field");
|
|
992
|
+
this.name = "DomainExpressionError";
|
|
993
|
+
this.code = options.code ?? "OON_DOMAIN_EXPRESSION_INVALID";
|
|
994
|
+
this.field = options.field;
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
var NUMERIC_KINDS = /* @__PURE__ */ new Set(["number", "currency", "currencyConverted"]);
|
|
998
|
+
function hasOwn(object, key) {
|
|
999
|
+
return Object.prototype.hasOwnProperty.call(object, key);
|
|
1000
|
+
}
|
|
1001
|
+
function isEmpty(value) {
|
|
1002
|
+
return value === null || value === void 0 || typeof value === "string" && !value.trim();
|
|
1003
|
+
}
|
|
1004
|
+
function getFieldValue(record, fieldPath) {
|
|
1005
|
+
const parts = String(fieldPath).split(".");
|
|
1006
|
+
let current = record;
|
|
1007
|
+
for (const part of parts) {
|
|
1008
|
+
if (["__proto__", "prototype", "constructor"].includes(part)) return void 0;
|
|
1009
|
+
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
1010
|
+
current = current[part];
|
|
1011
|
+
}
|
|
1012
|
+
return current;
|
|
1013
|
+
}
|
|
1014
|
+
function toNumber(value, context = {}) {
|
|
1015
|
+
if (isEmpty(value)) return context.nullAsZero ? 0 : null;
|
|
1016
|
+
const numeric = typeof value === "number" ? value : Number(value);
|
|
1017
|
+
if (!Number.isFinite(numeric)) {
|
|
1018
|
+
throw new DomainExpressionError(
|
|
1019
|
+
`A f\xF3rmula do campo ${context.field ?? "calculado"} recebeu um valor n\xE3o num\xE9rico.`,
|
|
1020
|
+
{ code: "OON_DOMAIN_FORMULA_ERROR", field: context.field }
|
|
1021
|
+
);
|
|
1022
|
+
}
|
|
1023
|
+
return numeric;
|
|
1024
|
+
}
|
|
1025
|
+
function numericArguments(args, record, context) {
|
|
1026
|
+
const values = args.map((arg) => evaluateDomainExpression(arg, record, context));
|
|
1027
|
+
if (!context.nullAsZero && values.some(isEmpty)) return null;
|
|
1028
|
+
return values.map((value) => toNumber(value, context) ?? 0);
|
|
1029
|
+
}
|
|
1030
|
+
function compareValues(leftValue, rightValue, operator) {
|
|
1031
|
+
let left = leftValue;
|
|
1032
|
+
let right = rightValue;
|
|
1033
|
+
if (["gt", "gte", "lt", "lte"].includes(operator)) {
|
|
1034
|
+
const leftNumber = Number(left);
|
|
1035
|
+
const rightNumber = Number(right);
|
|
1036
|
+
if (Number.isFinite(leftNumber) && Number.isFinite(rightNumber)) {
|
|
1037
|
+
left = leftNumber;
|
|
1038
|
+
right = rightNumber;
|
|
1039
|
+
}
|
|
1040
|
+
}
|
|
1041
|
+
switch (operator) {
|
|
1042
|
+
case "eq":
|
|
1043
|
+
return Object.is(left, right);
|
|
1044
|
+
case "neq":
|
|
1045
|
+
return !Object.is(left, right);
|
|
1046
|
+
case "gt":
|
|
1047
|
+
return left > right;
|
|
1048
|
+
case "gte":
|
|
1049
|
+
return left >= right;
|
|
1050
|
+
case "lt":
|
|
1051
|
+
return left < right;
|
|
1052
|
+
case "lte":
|
|
1053
|
+
return left <= right;
|
|
1054
|
+
default:
|
|
1055
|
+
return false;
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
function evaluateDomainExpression(expression, record = {}, context = {}) {
|
|
1059
|
+
if (!expression || typeof expression !== "object" || Array.isArray(expression)) {
|
|
1060
|
+
throw new DomainExpressionError("Express\xE3o declarativa inv\xE1lida.", { field: context.field });
|
|
1061
|
+
}
|
|
1062
|
+
if (hasOwn(expression, "value")) return expression.value;
|
|
1063
|
+
if (hasOwn(expression, "field")) return getFieldValue(record, expression.field);
|
|
1064
|
+
const operation = expression;
|
|
1065
|
+
const args = Array.isArray(operation.args) ? operation.args : [];
|
|
1066
|
+
switch (operation.op) {
|
|
1067
|
+
case "add": {
|
|
1068
|
+
const values = numericArguments(args, record, context);
|
|
1069
|
+
return values === null ? null : values.reduce((total, value) => total + value, 0);
|
|
1070
|
+
}
|
|
1071
|
+
case "subtract": {
|
|
1072
|
+
const values = numericArguments(args, record, context);
|
|
1073
|
+
return values === null ? null : values.slice(1).reduce((total, value) => total - value, values[0] ?? 0);
|
|
1074
|
+
}
|
|
1075
|
+
case "multiply": {
|
|
1076
|
+
const values = numericArguments(args, record, context);
|
|
1077
|
+
return values === null ? null : values.reduce((total, value) => total * value, 1);
|
|
1078
|
+
}
|
|
1079
|
+
case "divide": {
|
|
1080
|
+
const values = numericArguments(args, record, context);
|
|
1081
|
+
if (values === null) return null;
|
|
1082
|
+
return values.slice(1).reduce((total, divisor) => {
|
|
1083
|
+
if (divisor === 0) {
|
|
1084
|
+
throw new DomainExpressionError(
|
|
1085
|
+
`A f\xF3rmula do campo ${context.field ?? "calculado"} tentou dividir por zero.`,
|
|
1086
|
+
{ code: "OON_DOMAIN_FORMULA_ERROR", field: context.field }
|
|
1087
|
+
);
|
|
1088
|
+
}
|
|
1089
|
+
return total / divisor;
|
|
1090
|
+
}, values[0] ?? 0);
|
|
1091
|
+
}
|
|
1092
|
+
case "min": {
|
|
1093
|
+
const values = numericArguments(args, record, context);
|
|
1094
|
+
return values === null ? null : Math.min(...values);
|
|
1095
|
+
}
|
|
1096
|
+
case "max": {
|
|
1097
|
+
const values = numericArguments(args, record, context);
|
|
1098
|
+
return values === null ? null : Math.max(...values);
|
|
1099
|
+
}
|
|
1100
|
+
case "abs": {
|
|
1101
|
+
const values = numericArguments(args, record, context);
|
|
1102
|
+
return values === null ? null : Math.abs(values[0] ?? 0);
|
|
1103
|
+
}
|
|
1104
|
+
case "negate": {
|
|
1105
|
+
const values = numericArguments(args, record, context);
|
|
1106
|
+
return values === null ? null : -(values[0] ?? 0);
|
|
1107
|
+
}
|
|
1108
|
+
case "coalesce": {
|
|
1109
|
+
for (const arg of args) {
|
|
1110
|
+
const value = evaluateDomainExpression(arg, record, context);
|
|
1111
|
+
if (!isEmpty(value)) return value;
|
|
1112
|
+
}
|
|
1113
|
+
return null;
|
|
1114
|
+
}
|
|
1115
|
+
case "eq":
|
|
1116
|
+
case "neq":
|
|
1117
|
+
case "gt":
|
|
1118
|
+
case "gte":
|
|
1119
|
+
case "lt":
|
|
1120
|
+
case "lte":
|
|
1121
|
+
return compareValues(
|
|
1122
|
+
evaluateDomainExpression(args[0], record, context),
|
|
1123
|
+
evaluateDomainExpression(args[1], record, context),
|
|
1124
|
+
operation.op
|
|
1125
|
+
);
|
|
1126
|
+
case "and":
|
|
1127
|
+
return args.every((arg) => Boolean(evaluateDomainExpression(arg, record, context)));
|
|
1128
|
+
case "or":
|
|
1129
|
+
return args.some((arg) => Boolean(evaluateDomainExpression(arg, record, context)));
|
|
1130
|
+
case "not":
|
|
1131
|
+
return !Boolean(evaluateDomainExpression(args[0], record, context));
|
|
1132
|
+
case "present":
|
|
1133
|
+
return !isEmpty(evaluateDomainExpression(args[0], record, context));
|
|
1134
|
+
case "in": {
|
|
1135
|
+
const value = evaluateDomainExpression(args[0], record, context);
|
|
1136
|
+
const list = evaluateDomainExpression(args[1], record, context);
|
|
1137
|
+
return Array.isArray(list) && list.some((item) => Object.is(item, value));
|
|
1138
|
+
}
|
|
1139
|
+
default:
|
|
1140
|
+
throw new DomainExpressionError(`Operador declarativo n\xE3o suportado: ${String(operation.op)}.`, {
|
|
1141
|
+
field: context.field
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
}
|
|
1145
|
+
function roundValue(value, precision = 0) {
|
|
1146
|
+
if (value === null || value === void 0) return value;
|
|
1147
|
+
const numeric = toNumber(value);
|
|
1148
|
+
if (numeric === null) return null;
|
|
1149
|
+
const factor = 10 ** precision;
|
|
1150
|
+
return Math.round((numeric + Number.EPSILON) * factor) / factor;
|
|
1151
|
+
}
|
|
1152
|
+
function expressionFieldReferences(expression, references = /* @__PURE__ */ new Set()) {
|
|
1153
|
+
if (hasOwn(expression, "field")) references.add(expression.field);
|
|
1154
|
+
if (hasOwn(expression, "op")) {
|
|
1155
|
+
for (const argument of expression.args ?? []) {
|
|
1156
|
+
expressionFieldReferences(argument, references);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
return references;
|
|
1160
|
+
}
|
|
1161
|
+
function orderComputedFields(fields) {
|
|
1162
|
+
const computed = fields.filter((field) => field.computed);
|
|
1163
|
+
const computedByName = new Map(computed.map((field) => [field.field, field]));
|
|
1164
|
+
const allNames = new Set(fields.map((field) => field.field));
|
|
1165
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
1166
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1167
|
+
const ordered = [];
|
|
1168
|
+
const visit = (field) => {
|
|
1169
|
+
if (visited.has(field.field)) return;
|
|
1170
|
+
if (visiting.has(field.field)) {
|
|
1171
|
+
throw new DomainExpressionError(`Depend\xEAncia circular em campos calculados envolvendo ${field.field}.`, {
|
|
1172
|
+
field: field.field
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
visiting.add(field.field);
|
|
1176
|
+
for (const reference of expressionFieldReferences(field.computed.expression)) {
|
|
1177
|
+
if (!allNames.has(reference)) {
|
|
1178
|
+
throw new DomainExpressionError(`A f\xF3rmula de ${field.field} referencia o campo inexistente ${reference}.`, {
|
|
1179
|
+
field: field.field
|
|
1180
|
+
});
|
|
1181
|
+
}
|
|
1182
|
+
const dependency = computedByName.get(reference);
|
|
1183
|
+
if (dependency) visit(dependency);
|
|
1184
|
+
}
|
|
1185
|
+
visiting.delete(field.field);
|
|
1186
|
+
visited.add(field.field);
|
|
1187
|
+
ordered.push(field);
|
|
1188
|
+
};
|
|
1189
|
+
computed.forEach(visit);
|
|
1190
|
+
return ordered;
|
|
1191
|
+
}
|
|
1192
|
+
function coerceDomainFormValue(value, kind) {
|
|
1193
|
+
if (value === "") return void 0;
|
|
1194
|
+
if (NUMERIC_KINDS.has(kind ?? "")) return Number(value);
|
|
1195
|
+
if (kind === "boolean") return value === "true";
|
|
1196
|
+
return value;
|
|
1197
|
+
}
|
|
1198
|
+
function displayFormValue(value) {
|
|
1199
|
+
if (value === null || value === void 0) return "";
|
|
1200
|
+
return String(value);
|
|
1201
|
+
}
|
|
1202
|
+
function applyReactiveFormulas(fields, currentValues) {
|
|
1203
|
+
const values = { ...currentValues };
|
|
1204
|
+
const errors = {};
|
|
1205
|
+
const record = {};
|
|
1206
|
+
for (const field of fields) {
|
|
1207
|
+
record[field.field] = coerceDomainFormValue(values[field.field] ?? "", field.kind);
|
|
1208
|
+
}
|
|
1209
|
+
let ordered;
|
|
1210
|
+
try {
|
|
1211
|
+
ordered = orderComputedFields(fields);
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
const issue = error instanceof DomainExpressionError ? error : new DomainExpressionError(String(error));
|
|
1214
|
+
if (issue.field) errors[issue.field] = issue.message;
|
|
1215
|
+
return { values, errors };
|
|
1216
|
+
}
|
|
1217
|
+
for (const field of ordered) {
|
|
1218
|
+
try {
|
|
1219
|
+
const computed = field.computed;
|
|
1220
|
+
const value = evaluateDomainExpression(computed.expression, record, {
|
|
1221
|
+
field: field.field,
|
|
1222
|
+
nullAsZero: computed.nullAsZero !== false
|
|
1223
|
+
});
|
|
1224
|
+
const normalized2 = value === null || value === void 0 ? value : roundValue(value, computed.precision ?? 2);
|
|
1225
|
+
record[field.field] = normalized2;
|
|
1226
|
+
values[field.field] = displayFormValue(normalized2);
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
const issue = error instanceof DomainExpressionError ? error : new DomainExpressionError(String(error), { field: field.field });
|
|
1229
|
+
errors[field.field] = issue.message;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
return { values, errors };
|
|
1233
|
+
}
|
|
1234
|
+
function buildDomainMutationPayload(fields, values) {
|
|
1235
|
+
const payload = {};
|
|
1236
|
+
for (const field of fields) {
|
|
1237
|
+
if (field.readonly || field.computed) continue;
|
|
1238
|
+
const value = coerceDomainFormValue(values[field.field] ?? "", field.kind);
|
|
1239
|
+
if (value !== void 0) payload[field.field] = value;
|
|
1240
|
+
}
|
|
1241
|
+
return payload;
|
|
1242
|
+
}
|
|
1243
|
+
|
|
967
1244
|
// src/components/internal/ReferenceSelect.tsx
|
|
968
1245
|
import { useEffect as useEffect3, useMemo as useMemo3, useRef, useState as useState4 } from "react";
|
|
969
1246
|
import { Box as Box3, Button as Button3, Flex as Flex3, Input as Input2, Spinner as Spinner2, Stack, Text as Text4 } from "@chakra-ui/react";
|
|
@@ -1512,16 +1789,16 @@ function toValue(value, kind) {
|
|
|
1512
1789
|
function initialFieldValue(field, value) {
|
|
1513
1790
|
return normalizeMaskedValue(toValue(value, field.kind), resolveInputMask(field));
|
|
1514
1791
|
}
|
|
1515
|
-
function
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
if (kind === "boolean") return value === "true";
|
|
1519
|
-
return value;
|
|
1792
|
+
function initialReactiveValues(fields, initialValues) {
|
|
1793
|
+
const initial = Object.fromEntries(fields.map((field) => [field.field, initialFieldValue(field, initialValues?.[field.field])]));
|
|
1794
|
+
return applyReactiveFormulas(fields, initial);
|
|
1520
1795
|
}
|
|
1521
1796
|
function validate(fields, values) {
|
|
1522
1797
|
const errors = {};
|
|
1523
1798
|
fields.forEach((field) => {
|
|
1524
|
-
if (field.required && !(values[field.field] ?? "").trim())
|
|
1799
|
+
if (!field.readonly && !field.computed && field.required && !(values[field.field] ?? "").trim()) {
|
|
1800
|
+
errors[field.field] = `${fieldLabel({ name: field.field, label: field.label })} \xE9 obrigat\xF3rio.`;
|
|
1801
|
+
}
|
|
1525
1802
|
});
|
|
1526
1803
|
return errors;
|
|
1527
1804
|
}
|
|
@@ -1572,21 +1849,22 @@ function focusField(field) {
|
|
|
1572
1849
|
function isMultiline(field) {
|
|
1573
1850
|
return field.multiline === true || /observa|descricao|mensagem|detalhe|necessidade/i.test(field.field);
|
|
1574
1851
|
}
|
|
1575
|
-
function Label({ id, label, required }) {
|
|
1852
|
+
function Label({ id, label, required, readonly }) {
|
|
1576
1853
|
return /* @__PURE__ */ jsx9("label", { htmlFor: id, children: /* @__PURE__ */ jsxs5(Text5, { as: "span", display: "block", mb: "6px", color: "#475467", fontSize: "11px", fontWeight: "600", children: [
|
|
1577
1854
|
label,
|
|
1578
|
-
required ? /* @__PURE__ */ jsx9(Text5, { as: "span", color: "#DC2626", children: " *" }) : null
|
|
1855
|
+
required && !readonly ? /* @__PURE__ */ jsx9(Text5, { as: "span", color: "#DC2626", children: " *" }) : null,
|
|
1856
|
+
readonly ? /* @__PURE__ */ jsx9(Text5, { as: "span", ml: "5px", color: "#98A2B3", fontSize: "9px", fontWeight: "500", children: "somente leitura" }) : null
|
|
1579
1857
|
] }) });
|
|
1580
1858
|
}
|
|
1581
1859
|
function ErrorText({ id, text }) {
|
|
1582
1860
|
return text ? /* @__PURE__ */ jsx9(Text5, { id, role: "alert", mt: "5px", color: "#DC2626", fontSize: "10px", fontWeight: "500", children: text }) : null;
|
|
1583
1861
|
}
|
|
1584
|
-
var controlProps = (invalid) => ({
|
|
1862
|
+
var controlProps = (invalid, readonly = false) => ({
|
|
1585
1863
|
minH: "37px",
|
|
1586
1864
|
px: "10px",
|
|
1587
1865
|
py: "8px",
|
|
1588
1866
|
color: "#475467",
|
|
1589
|
-
bg: "white",
|
|
1867
|
+
bg: readonly ? "#F8FAFC" : "white",
|
|
1590
1868
|
borderColor: invalid ? "#DC2626" : "#D5DDE3",
|
|
1591
1869
|
borderRadius: "6px",
|
|
1592
1870
|
boxShadow: invalid ? "0 0 0 3px rgba(220,38,38,.08)" : void 0,
|
|
@@ -1616,11 +1894,14 @@ function resolveReference(field, values) {
|
|
|
1616
1894
|
});
|
|
1617
1895
|
return { filters, disabled: missing.length > 0 };
|
|
1618
1896
|
}
|
|
1619
|
-
function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submitting, error, onSubmit, onCancel, onFieldChange }) {
|
|
1620
|
-
const
|
|
1897
|
+
function DynamicForm({ title, eyebrow = "Cadastro", fields: rawFields, initialValues, submitting, error, onSubmit, onCancel, onFieldChange }) {
|
|
1898
|
+
const fields = rawFields;
|
|
1899
|
+
const initial = initialReactiveValues(fields, initialValues);
|
|
1900
|
+
const [values, setValues] = useState5(initial.values);
|
|
1901
|
+
const [formulaErrors, setFormulaErrors] = useState5(initial.errors);
|
|
1621
1902
|
const [errors, setErrors] = useState5({});
|
|
1622
1903
|
const [dismissed, setDismissed] = useState5(false);
|
|
1623
|
-
const items = useMemo4(() => buildItems(fields), [
|
|
1904
|
+
const items = useMemo4(() => buildItems(fields), [rawFields]);
|
|
1624
1905
|
useEffect4(() => {
|
|
1625
1906
|
const listener = (event) => {
|
|
1626
1907
|
if (event.key !== "Escape" || event.defaultPrevented || submitting) return;
|
|
@@ -1642,8 +1923,9 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
|
|
|
1642
1923
|
if (first) focusField(first.field);
|
|
1643
1924
|
}, [error]);
|
|
1644
1925
|
const change = (fieldName, value) => {
|
|
1645
|
-
const
|
|
1646
|
-
|
|
1926
|
+
const selected = fields.find((field) => field.field === fieldName);
|
|
1927
|
+
if (selected?.readonly || selected?.computed) return;
|
|
1928
|
+
const dependentFields = fields.filter(
|
|
1647
1929
|
(candidate) => Object.values(candidate.referenceFilterFrom ?? {}).includes(fieldName)
|
|
1648
1930
|
);
|
|
1649
1931
|
setValues((current) => {
|
|
@@ -1652,7 +1934,9 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
|
|
|
1652
1934
|
if (changed) dependentFields.forEach((candidate) => {
|
|
1653
1935
|
next[candidate.field] = "";
|
|
1654
1936
|
});
|
|
1655
|
-
|
|
1937
|
+
const reactive = applyReactiveFormulas(fields, next);
|
|
1938
|
+
setFormulaErrors(reactive.errors);
|
|
1939
|
+
return reactive.values;
|
|
1656
1940
|
});
|
|
1657
1941
|
setErrors((current) => {
|
|
1658
1942
|
const next = { ...current };
|
|
@@ -1673,23 +1957,19 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
|
|
|
1673
1957
|
if (first) focusField(first.field);
|
|
1674
1958
|
return;
|
|
1675
1959
|
}
|
|
1676
|
-
const payload = {};
|
|
1677
|
-
fields.forEach((field) => {
|
|
1678
|
-
const value = coerce(values[field.field] ?? "", field.kind);
|
|
1679
|
-
if (value !== void 0) payload[field.field] = value;
|
|
1680
|
-
});
|
|
1681
1960
|
setErrors({});
|
|
1682
|
-
onSubmit(
|
|
1961
|
+
onSubmit(buildDomainMutationPayload(fields, values));
|
|
1683
1962
|
};
|
|
1684
1963
|
const renderField = (field, grouped = false) => {
|
|
1685
1964
|
const label = fieldLabel({ name: field.field, label: field.label });
|
|
1686
|
-
const message = errors[field.field];
|
|
1965
|
+
const message = errors[field.field] ?? formulaErrors[field.field];
|
|
1687
1966
|
const id = idFor(field.field);
|
|
1688
1967
|
const errorId = message ? errorIdFor(field.field) : void 0;
|
|
1689
1968
|
const multiline = isMultiline(field);
|
|
1690
1969
|
const span = field.span === 2 || multiline;
|
|
1970
|
+
const readonly = Boolean(field.readonly || field.computed);
|
|
1691
1971
|
const wrap = (control, showLabel = true) => /* @__PURE__ */ jsxs5(Box4, { minW: grouped ? "150px" : void 0, flex: grouped ? "0 1 auto" : void 0, gridColumn: !grouped && span ? "1 / -1" : void 0, children: [
|
|
1692
|
-
showLabel ? /* @__PURE__ */ jsx9(Label, { id, label, required: field.required }) : null,
|
|
1972
|
+
showLabel ? /* @__PURE__ */ jsx9(Label, { id, label, required: field.required, readonly }) : null,
|
|
1693
1973
|
control,
|
|
1694
1974
|
/* @__PURE__ */ jsx9(ErrorText, { id: errorId, text: message })
|
|
1695
1975
|
] }, field.field);
|
|
@@ -1698,89 +1978,46 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
|
|
|
1698
1978
|
const uncheckedValue = String(field.uncheckedValue ?? false);
|
|
1699
1979
|
const checked = (values[field.field] ?? uncheckedValue) === checkedValue;
|
|
1700
1980
|
return wrap(
|
|
1701
|
-
/* @__PURE__ */ jsxs5(
|
|
1702
|
-
|
|
1703
|
-
{
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
alignItems: "center",
|
|
1709
|
-
gap: "8px",
|
|
1710
|
-
color: "#344054",
|
|
1711
|
-
bg: checked ? "#F0F7FF" : "white",
|
|
1712
|
-
borderWidth: "1px",
|
|
1713
|
-
borderColor: message ? "#DC2626" : checked ? "#8FC9E7" : "#D5DDE3",
|
|
1714
|
-
borderRadius: "7px",
|
|
1715
|
-
cursor: "pointer",
|
|
1716
|
-
transition: "background .15s ease, border-color .15s ease",
|
|
1717
|
-
_hover: { borderColor: "#8FC9E7", bg: "#F7FBFE" },
|
|
1718
|
-
children: [
|
|
1719
|
-
/* @__PURE__ */ jsx9(
|
|
1720
|
-
"input",
|
|
1721
|
-
{
|
|
1722
|
-
id,
|
|
1723
|
-
type: "checkbox",
|
|
1724
|
-
checked,
|
|
1725
|
-
"aria-invalid": !!message,
|
|
1726
|
-
"aria-describedby": errorId,
|
|
1727
|
-
style: { width: 16, height: 16, accentColor: "#0474AF", cursor: "pointer" },
|
|
1728
|
-
onChange: (event) => change(field.field, event.currentTarget.checked ? checkedValue : uncheckedValue)
|
|
1729
|
-
}
|
|
1730
|
-
),
|
|
1731
|
-
/* @__PURE__ */ jsxs5(Text5, { as: "span", fontSize: "11px", fontWeight: "600", children: [
|
|
1732
|
-
label,
|
|
1733
|
-
field.required ? /* @__PURE__ */ jsx9(Text5, { as: "span", color: "#DC2626", children: " *" }) : null
|
|
1734
|
-
] })
|
|
1735
|
-
]
|
|
1736
|
-
}
|
|
1737
|
-
),
|
|
1981
|
+
/* @__PURE__ */ jsxs5(Box4, { as: "label", display: "flex", minH: "37px", px: "11px", alignItems: "center", gap: "8px", color: "#344054", bg: readonly ? "#F8FAFC" : checked ? "#F0F7FF" : "white", borderWidth: "1px", borderColor: message ? "#DC2626" : checked ? "#8FC9E7" : "#D5DDE3", borderRadius: "7px", cursor: readonly ? "not-allowed" : "pointer", transition: "background .15s ease, border-color .15s ease", children: [
|
|
1982
|
+
/* @__PURE__ */ jsx9("input", { id, type: "checkbox", checked, disabled: readonly, "aria-invalid": !!message, "aria-describedby": errorId, style: { width: 16, height: 16, accentColor: "#0474AF", cursor: readonly ? "not-allowed" : "pointer" }, onChange: (event) => change(field.field, event.currentTarget.checked ? checkedValue : uncheckedValue) }),
|
|
1983
|
+
/* @__PURE__ */ jsxs5(Text5, { as: "span", fontSize: "11px", fontWeight: "600", children: [
|
|
1984
|
+
label,
|
|
1985
|
+
field.required && !readonly ? /* @__PURE__ */ jsx9(Text5, { as: "span", color: "#DC2626", children: " *" }) : null
|
|
1986
|
+
] })
|
|
1987
|
+
] }),
|
|
1738
1988
|
false
|
|
1739
1989
|
);
|
|
1740
1990
|
}
|
|
1741
1991
|
if (field.kind === "ref" && field.ref) {
|
|
1742
1992
|
const reference = resolveReference(field, values);
|
|
1743
|
-
return wrap(/* @__PURE__ */ jsx9(ReferenceSelect, { field: field.field, inputId: id, errorId, label, refModel: field.ref, value: values[field.field] ?? "", initialValue: initialValues?.[field.field], required: field.required, invalid: !!message, error: message, filters: reference.filters, emptyFields: field.referenceEmptyFields, disabled: reference.disabled, disabledMessage: field.referenceDisabledMessage, onChange: (value2) => change(field.field, value2) }));
|
|
1993
|
+
return wrap(/* @__PURE__ */ jsx9(ReferenceSelect, { field: field.field, inputId: id, errorId, label, refModel: field.ref, value: values[field.field] ?? "", initialValue: initialValues?.[field.field], required: field.required && !readonly, invalid: !!message, error: message, filters: reference.filters, emptyFields: field.referenceEmptyFields, disabled: readonly || reference.disabled, disabledMessage: field.referenceDisabledMessage, onChange: (value2) => change(field.field, value2) }));
|
|
1744
1994
|
}
|
|
1745
|
-
if (field.kind === "enum" && field.options?.length) return wrap(/* @__PURE__ */ jsxs5(NativeSelect2.Root, { size: "sm", children: [
|
|
1746
|
-
/* @__PURE__ */ jsxs5(NativeSelect2.Field, { id, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), onChange: (event) => change(field.field, event.currentTarget.value), children: [
|
|
1995
|
+
if (field.kind === "enum" && field.options?.length) return wrap(/* @__PURE__ */ jsxs5(NativeSelect2.Root, { size: "sm", disabled: readonly, children: [
|
|
1996
|
+
/* @__PURE__ */ jsxs5(NativeSelect2.Field, { id, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message, readonly), onChange: (event) => change(field.field, event.currentTarget.value), children: [
|
|
1747
1997
|
/* @__PURE__ */ jsx9("option", { value: "", children: "\u2014 Selecione \u2014" }),
|
|
1748
1998
|
field.options.map((option) => /* @__PURE__ */ jsx9("option", { value: option, children: option }, option))
|
|
1749
1999
|
] }),
|
|
1750
2000
|
/* @__PURE__ */ jsx9(NativeSelect2.Indicator, {})
|
|
1751
2001
|
] }));
|
|
1752
|
-
if (field.kind === "boolean") return wrap(/* @__PURE__ */ jsxs5(NativeSelect2.Root, { size: "sm", children: [
|
|
1753
|
-
/* @__PURE__ */ jsxs5(NativeSelect2.Field, { id, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), onChange: (event) => change(field.field, event.currentTarget.value), children: [
|
|
2002
|
+
if (field.kind === "boolean") return wrap(/* @__PURE__ */ jsxs5(NativeSelect2.Root, { size: "sm", disabled: readonly, children: [
|
|
2003
|
+
/* @__PURE__ */ jsxs5(NativeSelect2.Field, { id, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message, readonly), onChange: (event) => change(field.field, event.currentTarget.value), children: [
|
|
1754
2004
|
/* @__PURE__ */ jsx9("option", { value: "", children: "\u2014 Selecione \u2014" }),
|
|
1755
2005
|
/* @__PURE__ */ jsx9("option", { value: "true", children: "Sim" }),
|
|
1756
2006
|
/* @__PURE__ */ jsx9("option", { value: "false", children: "N\xE3o" })
|
|
1757
2007
|
] }),
|
|
1758
2008
|
/* @__PURE__ */ jsx9(NativeSelect2.Indicator, {})
|
|
1759
2009
|
] }));
|
|
1760
|
-
if (multiline) return wrap(/* @__PURE__ */ jsx9(Textarea, { id, rows: field.rows ?? 4, resize: "vertical", "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message), lineHeight: "1.5", onChange: (event) => change(field.field, event.currentTarget.value) }));
|
|
2010
|
+
if (multiline) return wrap(/* @__PURE__ */ jsx9(Textarea, { id, rows: field.rows ?? 4, resize: "vertical", readOnly: readonly, "aria-invalid": !!message, "aria-describedby": errorId, value: values[field.field] ?? "", ...controlProps(!!message, readonly), lineHeight: "1.5", onChange: (event) => change(field.field, event.currentTarget.value) }));
|
|
1761
2011
|
const mask = resolveInputMask(field);
|
|
1762
|
-
const
|
|
2012
|
+
const numeric = ["number", "currency", "currencyConverted"].includes(field.kind ?? "");
|
|
2013
|
+
const type = mask ? "text" : field.kind === "date" ? "date" : numeric ? "number" : "text";
|
|
1763
2014
|
const value = values[field.field] ?? "";
|
|
1764
2015
|
return wrap(
|
|
1765
|
-
/* @__PURE__ */ jsx9(
|
|
1766
|
-
Input3,
|
|
1767
|
-
{
|
|
1768
|
-
id,
|
|
1769
|
-
type,
|
|
1770
|
-
step: type === "number" ? "any" : void 0,
|
|
1771
|
-
inputMode: inputModeForMask(mask),
|
|
1772
|
-
maxLength: maxLengthForMask(mask),
|
|
1773
|
-
autoComplete: "off",
|
|
1774
|
-
"aria-invalid": !!message,
|
|
1775
|
-
"aria-describedby": errorId,
|
|
1776
|
-
value: mask ? formatMaskedValue(value, mask) : value,
|
|
1777
|
-
...controlProps(!!message),
|
|
1778
|
-
onChange: (event) => change(field.field, parseMaskedInput(event.currentTarget.value, mask))
|
|
1779
|
-
}
|
|
1780
|
-
)
|
|
2016
|
+
/* @__PURE__ */ jsx9(Input3, { id, type, step: type === "number" ? "any" : void 0, inputMode: inputModeForMask(mask), maxLength: maxLengthForMask(mask), autoComplete: "off", readOnly: readonly, "aria-invalid": !!message, "aria-describedby": errorId, value: mask ? formatMaskedValue(value, mask) : value, ...controlProps(!!message, readonly), onChange: (event) => change(field.field, parseMaskedInput(event.currentTarget.value, mask)) })
|
|
1781
2017
|
);
|
|
1782
2018
|
};
|
|
1783
|
-
const
|
|
2019
|
+
const combinedErrors = { ...formulaErrors, ...errors };
|
|
2020
|
+
const invalid = fields.filter((field) => combinedErrors[field.field]);
|
|
1784
2021
|
const generic = dismissed ? null : messageOf(error);
|
|
1785
2022
|
return /* @__PURE__ */ jsx9(Flex4, { position: "fixed", inset: 0, zIndex: 1e3, align: "center", justify: "center", p: { base: 2, md: 6 }, bg: "rgba(15,23,42,.48)", backdropFilter: "blur(2px)", onMouseDown: (event) => {
|
|
1786
2023
|
if (event.currentTarget === event.target && !submitting) onCancel();
|
|
@@ -1797,12 +2034,12 @@ function DynamicForm({ title, eyebrow = "Cadastro", fields, initialValues, submi
|
|
|
1797
2034
|
invalid.length ? /* @__PURE__ */ jsxs5(Box4, { role: "alert", p: "11px 13px", color: "#9B1C1C", bg: "#FFF5F5", borderWidth: "1px", borderColor: "#FECACA", borderLeftWidth: "4px", borderLeftColor: "#DC2626", borderRadius: "8px", fontSize: "11px", children: [
|
|
1798
2035
|
/* @__PURE__ */ jsxs5(Flex4, { align: "center", gap: "7px", children: [
|
|
1799
2036
|
/* @__PURE__ */ jsx9(AlertIcon, {}),
|
|
1800
|
-
/* @__PURE__ */ jsx9(Text5, { as: "strong", children: "
|
|
2037
|
+
/* @__PURE__ */ jsx9(Text5, { as: "strong", children: "Revise os campos abaixo:" })
|
|
1801
2038
|
] }),
|
|
1802
2039
|
/* @__PURE__ */ jsx9(Box4, { as: "ul", mt: "7px", mb: 0, pl: "20px", display: "grid", gap: "3px", children: invalid.map((field) => /* @__PURE__ */ jsx9("li", { children: /* @__PURE__ */ jsxs5(Button4, { type: "button", variant: "plain", minH: "auto", h: "auto", p: 0, color: "#B42318", fontSize: "10px", fontWeight: "400", textDecoration: "underline", onClick: () => focusField(field.field), children: [
|
|
1803
2040
|
fieldLabel({ name: field.field, label: field.label }),
|
|
1804
2041
|
": ",
|
|
1805
|
-
|
|
2042
|
+
combinedErrors[field.field]
|
|
1806
2043
|
] }) }, field.field)) })
|
|
1807
2044
|
] }) : null,
|
|
1808
2045
|
generic && !invalid.length ? /* @__PURE__ */ jsxs5(Flex4, { role: "alert", p: "10px 12px", align: "center", gap: 2, color: "#B42318", bg: "#FEF3F2", borderWidth: "1px", borderColor: "#FECDCA", borderRadius: "7px", fontSize: "11px", children: [
|
|
@@ -2241,6 +2478,18 @@ function CoreRowAction({ action, row, parent, onOpenDetail, onRefresh, onUpdate
|
|
|
2241
2478
|
|
|
2242
2479
|
// src/components/internal/CoreRelatedGrid.tsx
|
|
2243
2480
|
import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
2481
|
+
function parentValueAt(parent, path) {
|
|
2482
|
+
return path.split(".").reduce((current, part) => {
|
|
2483
|
+
if (!current || typeof current !== "object") return void 0;
|
|
2484
|
+
return current[part];
|
|
2485
|
+
}, parent);
|
|
2486
|
+
}
|
|
2487
|
+
function mergeCreateFields(schemaFields, overrides, foreignKey) {
|
|
2488
|
+
const base = schemaFields.filter((field) => ![foreignKey, "_id", "createdAt", "updatedAt"].includes(field.field));
|
|
2489
|
+
if (!overrides?.length) return base;
|
|
2490
|
+
const byName = new Map(base.map((field) => [field.field, field]));
|
|
2491
|
+
return overrides.map((override) => ({ ...byName.get(override.field) ?? {}, ...override }));
|
|
2492
|
+
}
|
|
2244
2493
|
function CoreRelatedGrid({
|
|
2245
2494
|
tab: rawTab,
|
|
2246
2495
|
parent,
|
|
@@ -2265,6 +2514,17 @@ function CoreRelatedGrid({
|
|
|
2265
2514
|
() => (tab.columns?.length ? tab.columns : schema?.fields.slice(0, 8).map((field) => field.name) ?? []).map((column) => normalizeColumn(column, schema)).filter((column) => !column.hidden),
|
|
2266
2515
|
[tab.columns, schema]
|
|
2267
2516
|
);
|
|
2517
|
+
const schemaFormFields = useMemo5(() => formFieldsFromMeta(schema?.fields ?? []), [schema?.fields]);
|
|
2518
|
+
const createFields = useMemo5(
|
|
2519
|
+
() => mergeCreateFields(schemaFormFields, tab.create?.fields, relation?.foreignKey),
|
|
2520
|
+
[schemaFormFields, tab.create?.fields, relation?.foreignKey]
|
|
2521
|
+
);
|
|
2522
|
+
const createInitialValues = useMemo5(() => {
|
|
2523
|
+
const inherited = Object.fromEntries(
|
|
2524
|
+
Object.entries(tab.create?.initialValuesFromParent ?? {}).map(([field, path]) => [field, parentValueAt(parent, path)])
|
|
2525
|
+
);
|
|
2526
|
+
return { ...tab.create?.initialValues ?? {}, ...inherited };
|
|
2527
|
+
}, [tab.create?.initialValues, tab.create?.initialValuesFromParent, parent]);
|
|
2268
2528
|
const [drafts, setDrafts] = useState7({});
|
|
2269
2529
|
const [errors, setErrors] = useState7({});
|
|
2270
2530
|
const [creating, setCreating] = useState7(false);
|
|
@@ -2283,7 +2543,7 @@ function CoreRelatedGrid({
|
|
|
2283
2543
|
});
|
|
2284
2544
|
const createMutation = useMutation({
|
|
2285
2545
|
mutationFn: (values) => resource.create({
|
|
2286
|
-
...
|
|
2546
|
+
...createInitialValues,
|
|
2287
2547
|
...values,
|
|
2288
2548
|
...relation && parentValue != null ? { [relation.foreignKey]: parentValue } : {}
|
|
2289
2549
|
}),
|
|
@@ -2305,7 +2565,6 @@ function CoreRelatedGrid({
|
|
|
2305
2565
|
...current,
|
|
2306
2566
|
[id]: { ...current[id] ?? {}, [field]: value }
|
|
2307
2567
|
}));
|
|
2308
|
-
const createFields = tab.create?.fields?.length ? tab.create.fields : formFieldsFromMeta(schema?.fields ?? []).filter((field) => ![relation.foreignKey, "_id", "createdAt", "updatedAt"].includes(field.field));
|
|
2309
2568
|
return /* @__PURE__ */ jsxs9(Box7, { children: [
|
|
2310
2569
|
canCreate ? /* @__PURE__ */ jsx14(Flex5, { justify: "flex-end", mb: "10px", children: /* @__PURE__ */ jsx14(Button6, { size: "sm", colorPalette: "brand", onClick: () => {
|
|
2311
2570
|
setCreateError(null);
|
|
@@ -2382,7 +2641,7 @@ function CoreRelatedGrid({
|
|
|
2382
2641
|
title: tab.create?.label ?? `Novo ${schema?.singular ?? relation.model}`,
|
|
2383
2642
|
eyebrow: "Registro relacionado",
|
|
2384
2643
|
fields: createFields,
|
|
2385
|
-
initialValues:
|
|
2644
|
+
initialValues: createInitialValues,
|
|
2386
2645
|
submitting: createMutation.isPending,
|
|
2387
2646
|
error: createError,
|
|
2388
2647
|
onSubmit: (values) => createMutation.mutate(values),
|
|
@@ -2397,12 +2656,6 @@ function CoreRelatedGrid({
|
|
|
2397
2656
|
|
|
2398
2657
|
// src/components/internal/CoreTabbedDetail.tsx
|
|
2399
2658
|
import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2400
|
-
function coerce2(value, kind) {
|
|
2401
|
-
if (value === "") return void 0;
|
|
2402
|
-
if (["number", "currency", "currencyConverted"].includes(kind ?? "")) return Number(value);
|
|
2403
|
-
if (kind === "boolean") return value === "true";
|
|
2404
|
-
return value;
|
|
2405
|
-
}
|
|
2406
2659
|
function toValue2(value, kind) {
|
|
2407
2660
|
if (value == null) return "";
|
|
2408
2661
|
if (kind === "date") {
|
|
@@ -2421,6 +2674,10 @@ function toValue2(value, kind) {
|
|
|
2421
2674
|
function initialFieldValue2(field, value) {
|
|
2422
2675
|
return normalizeMaskedValue(toValue2(value, field.kind), resolveInputMask(field));
|
|
2423
2676
|
}
|
|
2677
|
+
function initialReactiveValues2(fields, parent) {
|
|
2678
|
+
const initial = Object.fromEntries(fields.map((field) => [field.field, initialFieldValue2(field, parent[field.field])]));
|
|
2679
|
+
return applyReactiveFormulas(fields, initial);
|
|
2680
|
+
}
|
|
2424
2681
|
function isMultiline2(field) {
|
|
2425
2682
|
return /observa|descricao|mensagem|detalhe|necessidade/i.test(field.field);
|
|
2426
2683
|
}
|
|
@@ -2465,7 +2722,7 @@ function fieldErrorsOf(error) {
|
|
|
2465
2722
|
function requiredErrors(fields, values) {
|
|
2466
2723
|
const errors = {};
|
|
2467
2724
|
fields.forEach((field) => {
|
|
2468
|
-
if (field.required && !(values[field.field] ?? "").trim()) {
|
|
2725
|
+
if (!field.readonly && !field.computed && field.required && !(values[field.field] ?? "").trim()) {
|
|
2469
2726
|
errors[field.field] = `${fieldLabel({ name: field.field, label: field.label })} \xE9 obrigat\xF3rio.`;
|
|
2470
2727
|
}
|
|
2471
2728
|
});
|
|
@@ -2483,9 +2740,11 @@ function resolveReference2(field, values) {
|
|
|
2483
2740
|
}
|
|
2484
2741
|
function FieldLabel({ field, htmlFor }) {
|
|
2485
2742
|
const label = fieldLabel({ name: field.field, label: field.label });
|
|
2743
|
+
const readonly = Boolean(field.readonly || field.computed);
|
|
2486
2744
|
return /* @__PURE__ */ jsx15("label", { htmlFor, children: /* @__PURE__ */ jsxs10(Text9, { as: "span", display: "block", mb: "5px", color: "#475467", fontSize: "11px", fontWeight: "600", children: [
|
|
2487
2745
|
label,
|
|
2488
|
-
field.required ? /* @__PURE__ */ jsx15(Text9, { as: "span", color: "#DC2626", children: " *" }) : null
|
|
2746
|
+
field.required && !readonly ? /* @__PURE__ */ jsx15(Text9, { as: "span", color: "#DC2626", children: " *" }) : null,
|
|
2747
|
+
readonly ? /* @__PURE__ */ jsx15(Text9, { as: "span", ml: "5px", color: "#98A2B3", fontSize: "9px", fontWeight: "500", children: "somente leitura" }) : null
|
|
2489
2748
|
] }) });
|
|
2490
2749
|
}
|
|
2491
2750
|
function ErrorText2({ id, message }) {
|
|
@@ -2502,11 +2761,13 @@ function FieldControl({
|
|
|
2502
2761
|
const label = fieldLabel({ name: field.field, label: field.label });
|
|
2503
2762
|
const inputId = `oon-detail-field-${field.field.replace(/[^a-zA-Z0-9_-]/g, "-")}`;
|
|
2504
2763
|
const errorId = `${inputId}-error`;
|
|
2764
|
+
const readonly = Boolean(field.readonly || field.computed);
|
|
2505
2765
|
const invalidProps = {
|
|
2506
2766
|
"aria-invalid": error ? true : void 0,
|
|
2507
2767
|
"aria-describedby": error ? errorId : void 0,
|
|
2508
2768
|
borderColor: error ? "#DC2626" : void 0,
|
|
2509
|
-
boxShadow: error ? "0 0 0 3px rgba(220,38,38,.08)" : void 0
|
|
2769
|
+
boxShadow: error ? "0 0 0 3px rgba(220,38,38,.08)" : void 0,
|
|
2770
|
+
bg: readonly ? "#F8FAFC" : void 0
|
|
2510
2771
|
};
|
|
2511
2772
|
if (field.widget === "checkbox") {
|
|
2512
2773
|
const checkedValue = String(field.checkedValue ?? true);
|
|
@@ -2523,11 +2784,11 @@ function FieldControl({
|
|
|
2523
2784
|
alignItems: "center",
|
|
2524
2785
|
gap: "8px",
|
|
2525
2786
|
color: "#344054",
|
|
2526
|
-
bg: checked ? "#F0F7FF" : "white",
|
|
2787
|
+
bg: readonly ? "#F8FAFC" : checked ? "#F0F7FF" : "white",
|
|
2527
2788
|
borderWidth: "1px",
|
|
2528
2789
|
borderColor: error ? "#DC2626" : checked ? "#8FC9E7" : "#D5DDE3",
|
|
2529
2790
|
borderRadius: "7px",
|
|
2530
|
-
cursor: "pointer",
|
|
2791
|
+
cursor: readonly ? "not-allowed" : "pointer",
|
|
2531
2792
|
children: [
|
|
2532
2793
|
/* @__PURE__ */ jsx15(
|
|
2533
2794
|
"input",
|
|
@@ -2535,9 +2796,10 @@ function FieldControl({
|
|
|
2535
2796
|
id: inputId,
|
|
2536
2797
|
type: "checkbox",
|
|
2537
2798
|
checked,
|
|
2799
|
+
disabled: readonly,
|
|
2538
2800
|
"aria-invalid": error ? true : void 0,
|
|
2539
2801
|
"aria-describedby": error ? errorId : void 0,
|
|
2540
|
-
style: { width: 16, height: 16, accentColor: "#0474AF", cursor: "pointer" },
|
|
2802
|
+
style: { width: 16, height: 16, accentColor: "#0474AF", cursor: readonly ? "not-allowed" : "pointer" },
|
|
2541
2803
|
onChange: (event) => onChange(event.currentTarget.checked ? checkedValue : uncheckedValue)
|
|
2542
2804
|
}
|
|
2543
2805
|
),
|
|
@@ -2562,12 +2824,12 @@ function FieldControl({
|
|
|
2562
2824
|
refModel: field.ref,
|
|
2563
2825
|
value,
|
|
2564
2826
|
initialValue,
|
|
2565
|
-
required: field.required,
|
|
2827
|
+
required: field.required && !readonly,
|
|
2566
2828
|
invalid: !!error,
|
|
2567
2829
|
error,
|
|
2568
2830
|
filters: reference.filters,
|
|
2569
2831
|
emptyFields: field.referenceEmptyFields,
|
|
2570
|
-
disabled: reference.disabled,
|
|
2832
|
+
disabled: readonly || reference.disabled,
|
|
2571
2833
|
disabledMessage: field.referenceDisabledMessage,
|
|
2572
2834
|
onChange
|
|
2573
2835
|
}
|
|
@@ -2575,28 +2837,29 @@ function FieldControl({
|
|
|
2575
2837
|
] });
|
|
2576
2838
|
}
|
|
2577
2839
|
const mask = resolveInputMask(field);
|
|
2578
|
-
const control = field.kind === "enum" && field.options?.length ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
|
|
2840
|
+
const control = field.kind === "enum" && field.options?.length ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", disabled: readonly, children: [
|
|
2579
2841
|
/* @__PURE__ */ jsxs10(NativeSelect4.Field, { id: inputId, value, ...invalidProps, onChange: (event) => onChange(event.currentTarget.value), children: [
|
|
2580
2842
|
/* @__PURE__ */ jsx15("option", { value: "", children: "\u2014 Selecione \u2014" }),
|
|
2581
2843
|
field.options.map((option) => /* @__PURE__ */ jsx15("option", { value: option, children: option }, option))
|
|
2582
2844
|
] }),
|
|
2583
2845
|
/* @__PURE__ */ jsx15(NativeSelect4.Indicator, {})
|
|
2584
|
-
] }) : field.kind === "boolean" ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", children: [
|
|
2846
|
+
] }) : field.kind === "boolean" ? /* @__PURE__ */ jsxs10(NativeSelect4.Root, { size: "sm", disabled: readonly, children: [
|
|
2585
2847
|
/* @__PURE__ */ jsxs10(NativeSelect4.Field, { id: inputId, value, ...invalidProps, onChange: (event) => onChange(event.currentTarget.value), children: [
|
|
2586
2848
|
/* @__PURE__ */ jsx15("option", { value: "", children: "\u2014 Selecione \u2014" }),
|
|
2587
2849
|
/* @__PURE__ */ jsx15("option", { value: "true", children: "Sim" }),
|
|
2588
2850
|
/* @__PURE__ */ jsx15("option", { value: "false", children: "N\xE3o" })
|
|
2589
2851
|
] }),
|
|
2590
2852
|
/* @__PURE__ */ jsx15(NativeSelect4.Indicator, {})
|
|
2591
|
-
] }) : isMultiline2(field) ? /* @__PURE__ */ jsx15(Textarea3, { id: inputId, rows: 4, resize: "vertical", value, ...invalidProps, onChange: (event) => onChange(event.currentTarget.value) }) : /* @__PURE__ */ jsx15(
|
|
2853
|
+
] }) : isMultiline2(field) ? /* @__PURE__ */ jsx15(Textarea3, { id: inputId, rows: 4, resize: "vertical", readOnly: readonly, value, ...invalidProps, onChange: (event) => onChange(event.currentTarget.value) }) : /* @__PURE__ */ jsx15(
|
|
2592
2854
|
Input5,
|
|
2593
2855
|
{
|
|
2594
2856
|
id: inputId,
|
|
2595
2857
|
size: "sm",
|
|
2596
|
-
type: mask ? "text" : field.kind === "date" ? "date" : field.kind
|
|
2597
|
-
step: !mask && field.kind
|
|
2858
|
+
type: mask ? "text" : field.kind === "date" ? "date" : ["number", "currency", "currencyConverted"].includes(field.kind ?? "") ? "number" : "text",
|
|
2859
|
+
step: !mask && ["number", "currency", "currencyConverted"].includes(field.kind ?? "") ? "any" : void 0,
|
|
2598
2860
|
inputMode: inputModeForMask(mask),
|
|
2599
2861
|
maxLength: maxLengthForMask(mask),
|
|
2862
|
+
readOnly: readonly,
|
|
2600
2863
|
value: mask ? formatMaskedValue(value, mask) : value,
|
|
2601
2864
|
...invalidProps,
|
|
2602
2865
|
onChange: (event) => onChange(parseMaskedInput(event.currentTarget.value, mask))
|
|
@@ -2645,17 +2908,23 @@ function InlineParentForm({
|
|
|
2645
2908
|
externalSubmit = false
|
|
2646
2909
|
}) {
|
|
2647
2910
|
const fields = rawFields;
|
|
2648
|
-
const
|
|
2911
|
+
const initial = initialReactiveValues2(fields, parent);
|
|
2912
|
+
const [values, setValues] = useState8(initial.values);
|
|
2913
|
+
const [formulaErrors, setFormulaErrors] = useState8(initial.errors);
|
|
2649
2914
|
const [saving, setSaving] = useState8(false);
|
|
2650
2915
|
const [error, setError] = useState8(null);
|
|
2651
2916
|
const [fieldErrors, setFieldErrors] = useState8({});
|
|
2652
2917
|
useEffect5(() => {
|
|
2653
|
-
|
|
2918
|
+
const next = initialReactiveValues2(fields, parent);
|
|
2919
|
+
setValues(next.values);
|
|
2920
|
+
setFormulaErrors(next.errors);
|
|
2654
2921
|
setError(null);
|
|
2655
2922
|
setFieldErrors({});
|
|
2656
2923
|
}, [parent, rawFields]);
|
|
2657
2924
|
const fieldsByName = useMemo6(() => new Map(fields.map((field) => [field.field, field])), [rawFields]);
|
|
2658
2925
|
const change = (fieldName, value) => {
|
|
2926
|
+
const selected = fieldsByName.get(fieldName);
|
|
2927
|
+
if (selected?.readonly || selected?.computed) return;
|
|
2659
2928
|
const dependentFields = fields.filter(
|
|
2660
2929
|
(candidate) => Object.values(candidate.referenceFilterFrom ?? {}).includes(fieldName)
|
|
2661
2930
|
);
|
|
@@ -2665,7 +2934,9 @@ function InlineParentForm({
|
|
|
2665
2934
|
if (changed) dependentFields.forEach((candidate) => {
|
|
2666
2935
|
next[candidate.field] = "";
|
|
2667
2936
|
});
|
|
2668
|
-
|
|
2937
|
+
const reactive = applyReactiveFormulas(fields, next);
|
|
2938
|
+
setFormulaErrors(reactive.errors);
|
|
2939
|
+
return reactive.values;
|
|
2669
2940
|
});
|
|
2670
2941
|
setFieldErrors((current) => {
|
|
2671
2942
|
const next = { ...current };
|
|
@@ -2675,6 +2946,7 @@ function InlineParentForm({
|
|
|
2675
2946
|
});
|
|
2676
2947
|
setError(null);
|
|
2677
2948
|
};
|
|
2949
|
+
const combinedErrors = { ...formulaErrors, ...fieldErrors };
|
|
2678
2950
|
const renderFields = () => {
|
|
2679
2951
|
if (groups?.length) {
|
|
2680
2952
|
return /* @__PURE__ */ jsx15(Stack3, { gap: "14px", children: groups.map((group) => /* @__PURE__ */ jsx15(
|
|
@@ -2684,7 +2956,7 @@ function InlineParentForm({
|
|
|
2684
2956
|
fields: group.fields.map((field) => fieldsByName.get(field)).filter(Boolean),
|
|
2685
2957
|
values,
|
|
2686
2958
|
initialValues: parent,
|
|
2687
|
-
errors:
|
|
2959
|
+
errors: combinedErrors,
|
|
2688
2960
|
onChange: change
|
|
2689
2961
|
},
|
|
2690
2962
|
`${group.label}-${group.fields.join("-")}`
|
|
@@ -2697,7 +2969,7 @@ function InlineParentForm({
|
|
|
2697
2969
|
value: values[field.field] ?? "",
|
|
2698
2970
|
values,
|
|
2699
2971
|
initialValue: parent[field.field],
|
|
2700
|
-
error:
|
|
2972
|
+
error: combinedErrors[field.field],
|
|
2701
2973
|
onChange: (value) => change(field.field, value)
|
|
2702
2974
|
},
|
|
2703
2975
|
field.field
|
|
@@ -2720,9 +2992,7 @@ function InlineParentForm({
|
|
|
2720
2992
|
setError(null);
|
|
2721
2993
|
setFieldErrors({});
|
|
2722
2994
|
try {
|
|
2723
|
-
const payload =
|
|
2724
|
-
fields.map((field) => [field.field, coerce2(values[field.field] ?? "", field.kind)]).filter(([, value]) => value !== void 0)
|
|
2725
|
-
);
|
|
2995
|
+
const payload = buildDomainMutationPayload(fields, values);
|
|
2726
2996
|
const saved = parent._id ? await resource.update(String(parent._id), payload) : await resource.create(payload);
|
|
2727
2997
|
onSaved(saved);
|
|
2728
2998
|
} catch (requestError) {
|
|
@@ -5339,12 +5609,17 @@ export {
|
|
|
5339
5609
|
CorePipeline,
|
|
5340
5610
|
CoreRelationField,
|
|
5341
5611
|
CoreToolbar,
|
|
5612
|
+
DomainExpressionError,
|
|
5342
5613
|
PermissionGate,
|
|
5614
|
+
applyReactiveFormulas,
|
|
5615
|
+
buildDomainMutationPayload,
|
|
5616
|
+
coerceDomainFormValue,
|
|
5343
5617
|
defineCollectionView,
|
|
5344
5618
|
defineDashboard,
|
|
5345
5619
|
defineDocumentView,
|
|
5346
5620
|
defineOonModule,
|
|
5347
5621
|
definePipelineView,
|
|
5622
|
+
evaluateDomainExpression,
|
|
5348
5623
|
manifestToConfig,
|
|
5349
5624
|
oonCoreFront,
|
|
5350
5625
|
start,
|