@universe-platform/ui 0.1.0-beta.7 → 0.1.0-beta.8
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/globals.css +136 -3
- package/dist/index.d.mts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +768 -103
- package/dist/index.mjs +763 -100
- package/dist/phone.d.mts +38 -0
- package/dist/phone.d.ts +38 -0
- package/dist/phone.js +90 -0
- package/dist/phone.mjs +59 -0
- package/package.json +6 -1
package/dist/index.mjs
CHANGED
|
@@ -38,6 +38,36 @@ function cn(...inputs) {
|
|
|
38
38
|
return twMerge(clsx(inputs));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
// src/utils/whatsapp.ts
|
|
42
|
+
function openWhatsAppChat(phone, defaultCountryCode = "972") {
|
|
43
|
+
if (!phone || typeof window === "undefined") return;
|
|
44
|
+
let cleaned = phone.replace(/\D/g, "");
|
|
45
|
+
if (cleaned.startsWith("0")) {
|
|
46
|
+
cleaned = defaultCountryCode + cleaned.substring(1);
|
|
47
|
+
}
|
|
48
|
+
const appUrl = `whatsapp://send?phone=${cleaned}`;
|
|
49
|
+
const webUrl = `https://web.whatsapp.com/send?phone=${cleaned}`;
|
|
50
|
+
const start = Date.now();
|
|
51
|
+
window.location.href = appUrl;
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
if (typeof document !== "undefined" && document.hasFocus() && Date.now() - start < 2e3) {
|
|
54
|
+
window.open(webUrl, "_blank", "noopener,noreferrer");
|
|
55
|
+
}
|
|
56
|
+
}, 1200);
|
|
57
|
+
}
|
|
58
|
+
function formatPhoneDisplay(phone) {
|
|
59
|
+
if (!phone) return "";
|
|
60
|
+
const digits = phone.replace(/\D/g, "");
|
|
61
|
+
if (digits.length === 10 && digits.startsWith("05")) {
|
|
62
|
+
return `${digits.slice(0, 3)}-${digits.slice(3, 6)}-${digits.slice(6)}`;
|
|
63
|
+
}
|
|
64
|
+
if (digits.length === 12 && digits.startsWith("9725")) {
|
|
65
|
+
const local = "0" + digits.slice(3);
|
|
66
|
+
return `${local.slice(0, 3)}-${local.slice(3, 6)}-${local.slice(6)}`;
|
|
67
|
+
}
|
|
68
|
+
return phone;
|
|
69
|
+
}
|
|
70
|
+
|
|
41
71
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
42
72
|
import React6, { useState as useState5, useMemo as useMemo2, useEffect as useEffect4, useCallback as useCallback4, useRef as useRef4 } from "react";
|
|
43
73
|
|
|
@@ -889,16 +919,35 @@ var FORM_INPUTS = {
|
|
|
889
919
|
}
|
|
890
920
|
}
|
|
891
921
|
),
|
|
892
|
-
PHONE: ({ value, onChange }) =>
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
922
|
+
PHONE: ({ value, onChange, column }) => {
|
|
923
|
+
var _a;
|
|
924
|
+
const enableWhatsApp = (_a = column == null ? void 0 : column.config) == null ? void 0 : _a.enableWhatsApp;
|
|
925
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center w-full h-full px-2 gap-1.5", children: [
|
|
926
|
+
/* @__PURE__ */ jsx4(
|
|
927
|
+
"input",
|
|
928
|
+
{
|
|
929
|
+
type: "tel",
|
|
930
|
+
className: "w-full h-8 bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm flex-1",
|
|
931
|
+
value: value !== void 0 && value !== null ? String(value) : "",
|
|
932
|
+
onChange: (e) => onChange(e.target.value),
|
|
933
|
+
dir: "ltr"
|
|
934
|
+
}
|
|
935
|
+
),
|
|
936
|
+
enableWhatsApp && value && /* @__PURE__ */ jsx4(
|
|
937
|
+
"button",
|
|
938
|
+
{
|
|
939
|
+
type: "button",
|
|
940
|
+
className: "text-emerald-500 cursor-pointer hover:opacity-80 transition-opacity shrink-0 p-1 rounded hover:bg-emerald-50",
|
|
941
|
+
title: "\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4",
|
|
942
|
+
onClick: (e) => {
|
|
943
|
+
e.stopPropagation();
|
|
944
|
+
openWhatsAppChat(String(value));
|
|
945
|
+
},
|
|
946
|
+
children: /* @__PURE__ */ jsx4("svg", { className: "w-4 h-4", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
|
|
947
|
+
}
|
|
948
|
+
)
|
|
949
|
+
] });
|
|
950
|
+
},
|
|
902
951
|
GOOGLE_CONTACT: ({ value, column, rowId, onChange, context }) => {
|
|
903
952
|
const [isSyncing, setIsSyncing] = React4.useState(false);
|
|
904
953
|
const { addToast } = useToast();
|
|
@@ -1082,31 +1131,33 @@ var FORM_INPUTS = {
|
|
|
1082
1131
|
}
|
|
1083
1132
|
};
|
|
1084
1133
|
if (value && value.synced && value.url) {
|
|
1085
|
-
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-
|
|
1086
|
-
/* @__PURE__ */ jsx4("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-
|
|
1134
|
+
return /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5 h-8 px-2 group whitespace-nowrap", children: [
|
|
1135
|
+
/* @__PURE__ */ jsx4("a", { href: value.url, target: "_blank", rel: "noopener noreferrer", className: "text-blue-600 hover:underline flex-1 truncate text-xs whitespace-nowrap", children: "\u05D0\u05D9\u05E9 \u05E7\u05E9\u05E8 \u05D2\u05D5\u05D2\u05DC" }),
|
|
1087
1136
|
/* @__PURE__ */ jsx4(
|
|
1088
1137
|
"button",
|
|
1089
1138
|
{
|
|
1139
|
+
type: "button",
|
|
1090
1140
|
onClick: handleUnlink,
|
|
1091
|
-
className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1",
|
|
1141
|
+
className: "text-slate-400 hover:text-rose-500 opacity-0 group-hover:opacity-100 transition-opacity p-1 shrink-0",
|
|
1092
1142
|
title: "\u05D1\u05D8\u05DC \u05E1\u05E0\u05DB\u05E8\u05D5\u05DF",
|
|
1093
|
-
children: /* @__PURE__ */ jsx4("svg", { className: "w-
|
|
1143
|
+
children: /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
1094
1144
|
}
|
|
1095
1145
|
)
|
|
1096
1146
|
] });
|
|
1097
1147
|
}
|
|
1098
|
-
return /* @__PURE__ */ jsx4("div", { className: "flex items-center h-8 px-2", children: /* @__PURE__ */ jsxs4(
|
|
1148
|
+
return /* @__PURE__ */ jsx4("div", { className: "flex items-center h-8 px-2 whitespace-nowrap", children: /* @__PURE__ */ jsxs4(
|
|
1099
1149
|
"button",
|
|
1100
1150
|
{
|
|
1151
|
+
type: "button",
|
|
1101
1152
|
onClick: handleSync,
|
|
1102
1153
|
disabled: isSyncing,
|
|
1103
|
-
className: "flex items-center gap-1.5 px-
|
|
1154
|
+
className: "inline-flex items-center gap-1.5 px-2.5 py-1 bg-blue-50 text-blue-600 hover:bg-blue-100 border border-blue-200 rounded-md text-xs font-medium transition-colors whitespace-nowrap shrink-0 disabled:opacity-50 cursor-pointer",
|
|
1104
1155
|
children: [
|
|
1105
|
-
isSyncing ? /* @__PURE__ */ jsxs4("svg", { className: "w-3.5 h-3.5 animate-spin", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1156
|
+
isSyncing ? /* @__PURE__ */ jsxs4("svg", { className: "w-3.5 h-3.5 animate-spin shrink-0", viewBox: "0 0 24 24", fill: "none", children: [
|
|
1106
1157
|
/* @__PURE__ */ jsx4("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
1107
1158
|
/* @__PURE__ */ jsx4("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" })
|
|
1108
|
-
] }) : /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
|
|
1109
|
-
"\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC"
|
|
1159
|
+
] }) : /* @__PURE__ */ jsx4("svg", { className: "w-3.5 h-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx4("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M12 4v16m8-8H4" }) }),
|
|
1160
|
+
/* @__PURE__ */ jsx4("span", { className: "whitespace-nowrap", children: "\u05E1\u05E0\u05DB\u05E8\u05DF \u05DC\u05D2\u05D5\u05D2\u05DC" })
|
|
1110
1161
|
]
|
|
1111
1162
|
}
|
|
1112
1163
|
) });
|
|
@@ -1121,17 +1172,48 @@ var FORM_INPUTS = {
|
|
|
1121
1172
|
}
|
|
1122
1173
|
),
|
|
1123
1174
|
SUB_TABLE: ({ value, column }) => {
|
|
1175
|
+
var _a, _b;
|
|
1124
1176
|
if (!Array.isArray(value)) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
1125
1177
|
const selected = value.filter((e) => e == null ? void 0 : e.isSelected);
|
|
1126
1178
|
if (selected.length === 0) return /* @__PURE__ */ jsx4("span", { className: "px-2 py-1 flex items-center h-full text-slate-300 text-xs italic", children: "\u05E8\u05D9\u05E7" });
|
|
1127
1179
|
const displayFields = column.subTableDisplayFields || [];
|
|
1180
|
+
const isWhatsApp = ((_a = column.config) == null ? void 0 : _a.actionType) === "WHATSAPP";
|
|
1181
|
+
const actionPhoneCol = (_b = column.config) == null ? void 0 : _b.actionPhoneColumn;
|
|
1128
1182
|
return /* @__PURE__ */ jsx4("div", { className: "px-1.5 py-1 flex flex-wrap items-center gap-1 h-full", children: selected.map((entry, idx) => {
|
|
1129
|
-
var
|
|
1183
|
+
var _a2, _b2;
|
|
1130
1184
|
let label = "";
|
|
1131
|
-
if (entry._resolvedData
|
|
1132
|
-
|
|
1185
|
+
if (entry._resolvedData) {
|
|
1186
|
+
if (displayFields.length > 0) {
|
|
1187
|
+
label = displayFields.map((f) => String(entry._resolvedData[f] || "")).filter(Boolean).join(" ");
|
|
1188
|
+
} else {
|
|
1189
|
+
const firstField = Object.keys(entry._resolvedData).find((k) => k !== "_id");
|
|
1190
|
+
if (firstField) label = String(entry._resolvedData[firstField] || "");
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (!label) label = ((_a2 = entry.recordId) == null ? void 0 : _a2.slice(-6)) || "...";
|
|
1194
|
+
if (isWhatsApp) {
|
|
1195
|
+
const rawPhone = actionPhoneCol ? (_b2 = entry._resolvedData) == null ? void 0 : _b2[actionPhoneCol] : null;
|
|
1196
|
+
const phone = rawPhone ? String(rawPhone).trim() : null;
|
|
1197
|
+
if (phone) {
|
|
1198
|
+
return /* @__PURE__ */ jsxs4(
|
|
1199
|
+
"button",
|
|
1200
|
+
{
|
|
1201
|
+
type: "button",
|
|
1202
|
+
onClick: (e) => {
|
|
1203
|
+
e.stopPropagation();
|
|
1204
|
+
openWhatsAppChat(phone);
|
|
1205
|
+
},
|
|
1206
|
+
className: "inline-flex items-center gap-1 px-1.5 py-0.5 bg-emerald-50 hover:bg-emerald-100 text-emerald-800 border border-emerald-300 hover:border-emerald-400 rounded-full text-xs font-medium max-w-[150px] truncate cursor-pointer transition-colors shadow-xs",
|
|
1207
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
1208
|
+
children: [
|
|
1209
|
+
/* @__PURE__ */ jsx4("svg", { className: "w-3 h-3 text-emerald-600 shrink-0", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx4("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) }),
|
|
1210
|
+
/* @__PURE__ */ jsx4("span", { className: "truncate", children: label })
|
|
1211
|
+
]
|
|
1212
|
+
},
|
|
1213
|
+
entry.recordId || idx
|
|
1214
|
+
);
|
|
1215
|
+
}
|
|
1133
1216
|
}
|
|
1134
|
-
if (!label) label = ((_a = entry.recordId) == null ? void 0 : _a.slice(-6)) || "...";
|
|
1135
1217
|
return /* @__PURE__ */ jsx4(
|
|
1136
1218
|
"span",
|
|
1137
1219
|
{
|
|
@@ -1147,12 +1229,241 @@ var FORM_INPUTS = {
|
|
|
1147
1229
|
|
|
1148
1230
|
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
1149
1231
|
import { useState as useState4, useEffect as useEffect3, useRef as useRef3, useCallback as useCallback3 } from "react";
|
|
1232
|
+
|
|
1233
|
+
// src/utils/phone.ts
|
|
1234
|
+
function sanitizePhoneNumber(phone) {
|
|
1235
|
+
if (!phone) return "";
|
|
1236
|
+
const trimmed = phone.trim();
|
|
1237
|
+
const hasLeadingPlus = trimmed.startsWith("+");
|
|
1238
|
+
const digitsOnly = trimmed.replace(/\D/g, "");
|
|
1239
|
+
return hasLeadingPlus ? `+${digitsOnly}` : digitsOnly;
|
|
1240
|
+
}
|
|
1241
|
+
function isValidPhoneNumber(phone) {
|
|
1242
|
+
if (!phone) return false;
|
|
1243
|
+
const cleaned = sanitizePhoneNumber(phone);
|
|
1244
|
+
return /^\+?[0-9]{9,15}$/.test(cleaned);
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
// src/components/TableBlock/fields/SubTableViewer.tsx
|
|
1150
1248
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1151
|
-
function
|
|
1249
|
+
function validateCellValue(val, col) {
|
|
1152
1250
|
var _a;
|
|
1251
|
+
const colType = ((_a = col.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
1252
|
+
const isEmpty = val === void 0 || val === null || typeof val === "string" && val.trim() === "";
|
|
1253
|
+
if (col.isRequired && isEmpty) {
|
|
1254
|
+
return {
|
|
1255
|
+
isValid: false,
|
|
1256
|
+
error: `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${col.name}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`
|
|
1257
|
+
};
|
|
1258
|
+
}
|
|
1259
|
+
if (isEmpty) {
|
|
1260
|
+
return { isValid: true };
|
|
1261
|
+
}
|
|
1262
|
+
if (colType === "PHONE") {
|
|
1263
|
+
const strVal = String(val).trim();
|
|
1264
|
+
if (!isValidPhoneNumber(strVal)) {
|
|
1265
|
+
return {
|
|
1266
|
+
isValid: false,
|
|
1267
|
+
error: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`
|
|
1268
|
+
};
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
if (colType === "NUMBER" || colType === "CURRENCY") {
|
|
1272
|
+
if (typeof val === "string" && isNaN(Number(val))) {
|
|
1273
|
+
return {
|
|
1274
|
+
isValid: false,
|
|
1275
|
+
error: `\u05D4\u05E2\u05E8\u05DA \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D7\u05D9\u05D9\u05D1 \u05DC\u05D4\u05D9\u05D5\u05EA \u05DE\u05E1\u05E4\u05E8 \u05EA\u05E7\u05D9\u05DF.`
|
|
1276
|
+
};
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return { isValid: true };
|
|
1280
|
+
}
|
|
1281
|
+
function SubTableCell({
|
|
1282
|
+
record,
|
|
1283
|
+
column,
|
|
1284
|
+
targetSchema,
|
|
1285
|
+
referencedTableId,
|
|
1286
|
+
context,
|
|
1287
|
+
relationOptions,
|
|
1288
|
+
setRelationOptions,
|
|
1289
|
+
refetchRelation,
|
|
1290
|
+
onCommit
|
|
1291
|
+
}) {
|
|
1292
|
+
var _a, _b;
|
|
1293
|
+
const colType = ((_a = column.type) == null ? void 0 : _a.toUpperCase()) || "DEFAULT";
|
|
1294
|
+
const isContact = colType === "GOOGLE_CONTACT";
|
|
1295
|
+
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1296
|
+
const serverValue = (_b = record.data[column.name]) != null ? _b : colType === "BOOLEAN" ? false : "";
|
|
1297
|
+
const [draftValue, setDraftValue] = useState4(serverValue);
|
|
1298
|
+
const [isDirty, setIsDirty] = useState4(false);
|
|
1299
|
+
const [validationError, setValidationError] = useState4(null);
|
|
1300
|
+
const cellRef = useRef3(null);
|
|
1301
|
+
const draftRef = useRef3(draftValue);
|
|
1302
|
+
const isDirtyRef = useRef3(isDirty);
|
|
1303
|
+
const serverValueRef = useRef3(serverValue);
|
|
1304
|
+
const recordIdRef = useRef3(record.id);
|
|
1305
|
+
const columnRef = useRef3(column);
|
|
1306
|
+
const onCommitRef = useRef3(onCommit);
|
|
1307
|
+
const isCommittingRef = useRef3(false);
|
|
1308
|
+
const lastFailedValRef = useRef3(void 0);
|
|
1309
|
+
const { addToast } = useToast();
|
|
1310
|
+
draftRef.current = draftValue;
|
|
1311
|
+
isDirtyRef.current = isDirty;
|
|
1312
|
+
serverValueRef.current = serverValue;
|
|
1313
|
+
recordIdRef.current = record.id;
|
|
1314
|
+
columnRef.current = column;
|
|
1315
|
+
onCommitRef.current = onCommit;
|
|
1316
|
+
useEffect3(() => {
|
|
1317
|
+
if (!isDirtyRef.current) {
|
|
1318
|
+
setDraftValue(serverValue);
|
|
1319
|
+
draftRef.current = serverValue;
|
|
1320
|
+
setValidationError(null);
|
|
1321
|
+
lastFailedValRef.current = void 0;
|
|
1322
|
+
}
|
|
1323
|
+
}, [serverValue]);
|
|
1324
|
+
const commit = useCallback3(async (valToCommit) => {
|
|
1325
|
+
if (isCommittingRef.current) return false;
|
|
1326
|
+
if (!isDirtyRef.current) return true;
|
|
1327
|
+
if (valToCommit === serverValueRef.current) {
|
|
1328
|
+
setIsDirty(false);
|
|
1329
|
+
isDirtyRef.current = false;
|
|
1330
|
+
setValidationError(null);
|
|
1331
|
+
lastFailedValRef.current = void 0;
|
|
1332
|
+
return true;
|
|
1333
|
+
}
|
|
1334
|
+
const valRes = validateCellValue(valToCommit, columnRef.current);
|
|
1335
|
+
if (!valRes.isValid) {
|
|
1336
|
+
const errorMsg = valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA";
|
|
1337
|
+
setValidationError(errorMsg);
|
|
1338
|
+
if (lastFailedValRef.current !== valToCommit) {
|
|
1339
|
+
addToast({ type: "error", message: errorMsg });
|
|
1340
|
+
lastFailedValRef.current = valToCommit;
|
|
1341
|
+
}
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
try {
|
|
1345
|
+
isCommittingRef.current = true;
|
|
1346
|
+
const success = await onCommitRef.current(recordIdRef.current, columnRef.current.name, valToCommit);
|
|
1347
|
+
if (success) {
|
|
1348
|
+
setIsDirty(false);
|
|
1349
|
+
isDirtyRef.current = false;
|
|
1350
|
+
serverValueRef.current = valToCommit;
|
|
1351
|
+
setValidationError(null);
|
|
1352
|
+
lastFailedValRef.current = void 0;
|
|
1353
|
+
return true;
|
|
1354
|
+
} else {
|
|
1355
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
1356
|
+
return false;
|
|
1357
|
+
}
|
|
1358
|
+
} catch (e) {
|
|
1359
|
+
setValidationError("\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4");
|
|
1360
|
+
return false;
|
|
1361
|
+
} finally {
|
|
1362
|
+
isCommittingRef.current = false;
|
|
1363
|
+
}
|
|
1364
|
+
}, [addToast]);
|
|
1365
|
+
const discard = useCallback3(() => {
|
|
1366
|
+
setDraftValue(serverValueRef.current);
|
|
1367
|
+
draftRef.current = serverValueRef.current;
|
|
1368
|
+
setIsDirty(false);
|
|
1369
|
+
isDirtyRef.current = false;
|
|
1370
|
+
setValidationError(null);
|
|
1371
|
+
lastFailedValRef.current = void 0;
|
|
1372
|
+
}, []);
|
|
1373
|
+
useEffect3(() => {
|
|
1374
|
+
return () => {
|
|
1375
|
+
if (isDirtyRef.current && !isCommittingRef.current) {
|
|
1376
|
+
const val = draftRef.current;
|
|
1377
|
+
const orig = serverValueRef.current;
|
|
1378
|
+
if (val !== orig) {
|
|
1379
|
+
const valRes = validateCellValue(val, columnRef.current);
|
|
1380
|
+
if (valRes.isValid) {
|
|
1381
|
+
onCommitRef.current(recordIdRef.current, columnRef.current.name, val);
|
|
1382
|
+
}
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
}, []);
|
|
1387
|
+
const handleChange = (newVal) => {
|
|
1388
|
+
setDraftValue(newVal);
|
|
1389
|
+
draftRef.current = newVal;
|
|
1390
|
+
setIsDirty(true);
|
|
1391
|
+
isDirtyRef.current = true;
|
|
1392
|
+
if (validationError) {
|
|
1393
|
+
setValidationError(null);
|
|
1394
|
+
lastFailedValRef.current = void 0;
|
|
1395
|
+
}
|
|
1396
|
+
if (colType === "BOOLEAN" || colType === "GOOGLE_DRIVE_FILE") {
|
|
1397
|
+
commit(newVal);
|
|
1398
|
+
}
|
|
1399
|
+
};
|
|
1400
|
+
const handleBlur = (e) => {
|
|
1401
|
+
if (e.currentTarget.contains(e.relatedTarget)) {
|
|
1402
|
+
return;
|
|
1403
|
+
}
|
|
1404
|
+
if (isDirtyRef.current) {
|
|
1405
|
+
commit(draftRef.current);
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
const handleKeyDown = (e) => {
|
|
1409
|
+
var _a2, _b2, _c, _d;
|
|
1410
|
+
if (e.key === "Enter") {
|
|
1411
|
+
e.preventDefault();
|
|
1412
|
+
if (isDirtyRef.current) {
|
|
1413
|
+
commit(draftRef.current);
|
|
1414
|
+
}
|
|
1415
|
+
(_b2 = (_a2 = e.target) == null ? void 0 : _a2.blur) == null ? void 0 : _b2.call(_a2);
|
|
1416
|
+
} else if (e.key === "Escape") {
|
|
1417
|
+
e.preventDefault();
|
|
1418
|
+
discard();
|
|
1419
|
+
(_d = (_c = e.target) == null ? void 0 : _c.blur) == null ? void 0 : _d.call(_c);
|
|
1420
|
+
}
|
|
1421
|
+
};
|
|
1422
|
+
return /* @__PURE__ */ jsx5(
|
|
1423
|
+
"td",
|
|
1424
|
+
{
|
|
1425
|
+
ref: cellRef,
|
|
1426
|
+
onBlur: handleBlur,
|
|
1427
|
+
onKeyDown: handleKeyDown,
|
|
1428
|
+
title: validationError || void 0,
|
|
1429
|
+
className: `border border-slate-200 p-0 relative h-8 transition-colors ${isContact ? "min-w-[140px]" : ""} ${validationError ? "border-rose-400 ring-1 ring-rose-400 bg-rose-50/20" : ""}`,
|
|
1430
|
+
children: /* @__PURE__ */ jsx5(
|
|
1431
|
+
InputComponent,
|
|
1432
|
+
{
|
|
1433
|
+
value: draftValue,
|
|
1434
|
+
column,
|
|
1435
|
+
rowId: record.id,
|
|
1436
|
+
onChange: handleChange,
|
|
1437
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
1438
|
+
tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
|
|
1439
|
+
relationOptions,
|
|
1440
|
+
updateRelationOptions: (name, opts) => setRelationOptions((prev) => __spreadProps(__spreadValues({}, prev), { [name]: opts })),
|
|
1441
|
+
refetchRelation,
|
|
1442
|
+
parentRecord: { tableId: (context == null ? void 0 : context.parentTableId) || (context == null ? void 0 : context.tableId), data: context == null ? void 0 : context.rowData },
|
|
1443
|
+
rowData: record.data,
|
|
1444
|
+
tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId,
|
|
1445
|
+
updateQuietly: (rid, colName, val) => onCommitRef.current(rid, colName, val)
|
|
1446
|
+
})
|
|
1447
|
+
}
|
|
1448
|
+
)
|
|
1449
|
+
}
|
|
1450
|
+
);
|
|
1451
|
+
}
|
|
1452
|
+
function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
1453
|
+
var _a, _b;
|
|
1153
1454
|
const { addToast } = useToast();
|
|
1154
1455
|
const entries = Array.isArray(value) ? value : [];
|
|
1155
|
-
const [linkedRecords, setLinkedRecords] = useState4(
|
|
1456
|
+
const [linkedRecords, setLinkedRecords] = useState4(() => {
|
|
1457
|
+
const initial = [];
|
|
1458
|
+
if (Array.isArray(value)) {
|
|
1459
|
+
for (const entry of value) {
|
|
1460
|
+
if (entry.recordId && entry._resolvedData) {
|
|
1461
|
+
initial.push({ id: entry.recordId, data: entry._resolvedData });
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
return initial;
|
|
1466
|
+
});
|
|
1156
1467
|
const [targetSchema, setTargetSchema] = useState4(null);
|
|
1157
1468
|
const [isLoading, setIsLoading] = useState4(true);
|
|
1158
1469
|
const [isSearchOpen, setIsSearchOpen] = useState4(false);
|
|
@@ -1161,11 +1472,31 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1161
1472
|
const [isSearching, setIsSearching] = useState4(false);
|
|
1162
1473
|
const [isCreating, setIsCreating] = useState4(false);
|
|
1163
1474
|
const [newRecordData, setNewRecordData] = useState4({});
|
|
1475
|
+
const [conflictModalState, setConflictModalState] = useState4({
|
|
1476
|
+
isOpen: false,
|
|
1477
|
+
fieldName: "",
|
|
1478
|
+
matchingRecords: []
|
|
1479
|
+
});
|
|
1164
1480
|
const searchRef = useRef3(null);
|
|
1165
1481
|
const searchTimerRef = useRef3(null);
|
|
1166
1482
|
const executeAction = context == null ? void 0 : context.executeAction;
|
|
1167
1483
|
const referencedTableId = column.referencedTableId;
|
|
1168
1484
|
const fetchedIdsRef = useRef3(/* @__PURE__ */ new Set());
|
|
1485
|
+
useEffect3(() => {
|
|
1486
|
+
if (entries.length > 0) {
|
|
1487
|
+
setLinkedRecords((prev) => {
|
|
1488
|
+
const existingIds = new Set(prev.map((r) => r.id));
|
|
1489
|
+
const toAdd = [];
|
|
1490
|
+
for (const entry of entries) {
|
|
1491
|
+
if (entry.recordId && entry._resolvedData && !existingIds.has(entry.recordId)) {
|
|
1492
|
+
toAdd.push({ id: entry.recordId, data: entry._resolvedData });
|
|
1493
|
+
existingIds.add(entry.recordId);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
return toAdd.length > 0 ? [...prev, ...toAdd] : prev;
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
}, [entries]);
|
|
1169
1500
|
useEffect3(() => {
|
|
1170
1501
|
if (!referencedTableId || !executeAction) {
|
|
1171
1502
|
setIsLoading(false);
|
|
@@ -1291,20 +1622,102 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1291
1622
|
}
|
|
1292
1623
|
}
|
|
1293
1624
|
};
|
|
1294
|
-
const
|
|
1295
|
-
|
|
1296
|
-
const
|
|
1297
|
-
const
|
|
1298
|
-
|
|
1625
|
+
const handleLinkRecords = (recordsToLink) => {
|
|
1626
|
+
if (!recordsToLink || recordsToLink.length === 0) return;
|
|
1627
|
+
const existingEntryIds = new Set(entries.map((e) => e.recordId));
|
|
1628
|
+
const newEntries = [];
|
|
1629
|
+
const newRecordsToAdd = [];
|
|
1630
|
+
for (const record of recordsToLink) {
|
|
1631
|
+
fetchedIdsRef.current.add(record.id);
|
|
1632
|
+
const resolvedData = __spreadValues({}, record.data || {});
|
|
1633
|
+
targetColumns.forEach((col) => {
|
|
1634
|
+
if ((resolvedData[col.name] === void 0 || resolvedData[col.name] === null) && record[col.name] !== void 0) {
|
|
1635
|
+
resolvedData[col.name] = record[col.name];
|
|
1636
|
+
}
|
|
1637
|
+
});
|
|
1638
|
+
if (!existingEntryIds.has(record.id)) {
|
|
1639
|
+
newEntries.push({
|
|
1640
|
+
recordId: record.id,
|
|
1641
|
+
isSelected: true,
|
|
1642
|
+
_resolvedData: resolvedData
|
|
1643
|
+
});
|
|
1644
|
+
existingEntryIds.add(record.id);
|
|
1645
|
+
}
|
|
1646
|
+
newRecordsToAdd.push({
|
|
1647
|
+
id: record.id,
|
|
1648
|
+
data: resolvedData
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
const updatedEntries = [...entries, ...newEntries];
|
|
1652
|
+
updateParentLinkage(updatedEntries);
|
|
1299
1653
|
setLinkedRecords((prev) => {
|
|
1300
|
-
const
|
|
1301
|
-
|
|
1302
|
-
|
|
1654
|
+
const map = new Map(prev.map((r) => [r.id, r]));
|
|
1655
|
+
newRecordsToAdd.forEach((r) => {
|
|
1656
|
+
const existing = map.get(r.id);
|
|
1657
|
+
if (existing) {
|
|
1658
|
+
map.set(r.id, __spreadProps(__spreadValues({}, existing), {
|
|
1659
|
+
data: __spreadValues(__spreadValues({}, existing.data), r.data)
|
|
1660
|
+
}));
|
|
1661
|
+
} else {
|
|
1662
|
+
map.set(r.id, r);
|
|
1663
|
+
}
|
|
1664
|
+
});
|
|
1665
|
+
return Array.from(map.values());
|
|
1303
1666
|
});
|
|
1304
1667
|
setSearchQuery("");
|
|
1305
1668
|
setSearchResults([]);
|
|
1306
1669
|
setIsSearchOpen(false);
|
|
1307
1670
|
};
|
|
1671
|
+
const handleLinkRecord = (record) => {
|
|
1672
|
+
handleLinkRecords([record]);
|
|
1673
|
+
};
|
|
1674
|
+
const handleUniqueConflict = (conflictData) => {
|
|
1675
|
+
const rawMatching = Array.isArray(conflictData == null ? void 0 : conflictData.matchingRecords) ? conflictData.matchingRecords : [];
|
|
1676
|
+
const resolvedMatching = rawMatching.map((r) => {
|
|
1677
|
+
var _a2;
|
|
1678
|
+
const recordId = String(r.id || ((_a2 = r._id) == null ? void 0 : _a2.$oid) || r._id);
|
|
1679
|
+
let dataObj = {};
|
|
1680
|
+
if (r.data && typeof r.data === "object") {
|
|
1681
|
+
dataObj = __spreadValues({}, r.data);
|
|
1682
|
+
}
|
|
1683
|
+
targetColumns.forEach((col) => {
|
|
1684
|
+
if ((dataObj[col.name] === void 0 || dataObj[col.name] === null) && r[col.name] !== void 0) {
|
|
1685
|
+
dataObj[col.name] = r[col.name];
|
|
1686
|
+
}
|
|
1687
|
+
});
|
|
1688
|
+
return {
|
|
1689
|
+
id: recordId,
|
|
1690
|
+
data: dataObj
|
|
1691
|
+
};
|
|
1692
|
+
});
|
|
1693
|
+
setConflictModalState({
|
|
1694
|
+
isOpen: true,
|
|
1695
|
+
fieldName: (conflictData == null ? void 0 : conflictData.fieldName) || "",
|
|
1696
|
+
matchingRecords: resolvedMatching
|
|
1697
|
+
});
|
|
1698
|
+
};
|
|
1699
|
+
const handleCancelConflict = () => {
|
|
1700
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
1701
|
+
};
|
|
1702
|
+
const handleConfirmLinkConflict = async () => {
|
|
1703
|
+
const { matchingRecords } = conflictModalState;
|
|
1704
|
+
if (matchingRecords && matchingRecords.length > 0) {
|
|
1705
|
+
handleLinkRecords(matchingRecords);
|
|
1706
|
+
setNewRecordData({});
|
|
1707
|
+
setIsCreating(false);
|
|
1708
|
+
setConflictModalState({
|
|
1709
|
+
isOpen: false,
|
|
1710
|
+
fieldName: "",
|
|
1711
|
+
matchingRecords: []
|
|
1712
|
+
});
|
|
1713
|
+
addToast({
|
|
1714
|
+
type: "success",
|
|
1715
|
+
message: "\u05D4\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D5\u05E9\u05E8\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4"
|
|
1716
|
+
});
|
|
1717
|
+
} else {
|
|
1718
|
+
setConflictModalState((prev) => __spreadProps(__spreadValues({}, prev), { isOpen: false }));
|
|
1719
|
+
}
|
|
1720
|
+
};
|
|
1308
1721
|
const handleUnlinkRecord = (recordId) => {
|
|
1309
1722
|
const updated = entries.filter((e) => e.recordId !== recordId);
|
|
1310
1723
|
updateParentLinkage(updated);
|
|
@@ -1317,37 +1730,94 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1317
1730
|
);
|
|
1318
1731
|
updateParentLinkage(updated);
|
|
1319
1732
|
};
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
)
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1733
|
+
const isMountedRef = useRef3(true);
|
|
1734
|
+
useEffect3(() => {
|
|
1735
|
+
isMountedRef.current = true;
|
|
1736
|
+
return () => {
|
|
1737
|
+
isMountedRef.current = false;
|
|
1738
|
+
};
|
|
1739
|
+
}, []);
|
|
1740
|
+
const handleCommitRecordCell = async (recordId, colName, value2) => {
|
|
1741
|
+
var _a2;
|
|
1742
|
+
const previousRecord = linkedRecords.find((r) => r.id === recordId);
|
|
1743
|
+
const previousValue = (_a2 = previousRecord == null ? void 0 : previousRecord.data) == null ? void 0 : _a2[colName];
|
|
1744
|
+
if (previousValue === value2) return true;
|
|
1745
|
+
const targetCol = targetColumns.find((c) => c.name === colName);
|
|
1746
|
+
const valRes = targetCol ? validateCellValue(value2, targetCol) : { isValid: true };
|
|
1747
|
+
if (!valRes.isValid) {
|
|
1748
|
+
addToast({
|
|
1749
|
+
type: "error",
|
|
1750
|
+
message: valRes.error || "\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA"
|
|
1751
|
+
});
|
|
1752
|
+
return false;
|
|
1333
1753
|
}
|
|
1334
1754
|
if (executeAction && referencedTableId && !recordId.startsWith("temp_")) {
|
|
1335
1755
|
try {
|
|
1336
|
-
await executeAction("UPDATE_RECORD", {
|
|
1756
|
+
const res = await executeAction("UPDATE_RECORD", {
|
|
1337
1757
|
tableId: referencedTableId,
|
|
1338
1758
|
recordId,
|
|
1339
1759
|
data: { [colName]: value2 }
|
|
1340
1760
|
});
|
|
1341
|
-
if (
|
|
1342
|
-
|
|
1761
|
+
if (res && res.success === false) {
|
|
1762
|
+
const err = new Error(res.error || res.message || "Action execution failed");
|
|
1763
|
+
Object.assign(err, res);
|
|
1764
|
+
throw err;
|
|
1765
|
+
}
|
|
1766
|
+
if (isMountedRef.current) {
|
|
1767
|
+
const updatedRecords = linkedRecords.map(
|
|
1768
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
1769
|
+
);
|
|
1770
|
+
setLinkedRecords(updatedRecords);
|
|
1771
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
1772
|
+
const updatedEntries = entries.map(
|
|
1773
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
1774
|
+
);
|
|
1775
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1776
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
1777
|
+
} else {
|
|
1778
|
+
onChange(updatedEntries);
|
|
1779
|
+
}
|
|
1780
|
+
if (context == null ? void 0 : context.triggerSaveSuccess) {
|
|
1781
|
+
context.triggerSaveSuccess();
|
|
1782
|
+
}
|
|
1343
1783
|
}
|
|
1784
|
+
return true;
|
|
1344
1785
|
} catch (err) {
|
|
1345
1786
|
console.error("[SubTableViewer] Failed to auto-save linked record field", err);
|
|
1787
|
+
let errorMsg = (err == null ? void 0 : err.message) || (err == null ? void 0 : err.error) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E9\u05DE\u05D9\u05E8\u05EA \u05D4\u05E8\u05E9\u05D5\u05DE\u05D4";
|
|
1788
|
+
if ((err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || errorMsg.includes("must be unique") || errorMsg.includes("Duplicate value detected") || errorMsg.includes("\u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DE\u05EA") || errorMsg.includes("UNIQUE_CONSTRAINT_CONFLICT")) {
|
|
1789
|
+
errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05D4\u05E2\u05E8\u05DA '${value2}' \u05DB\u05D1\u05E8 \u05E7\u05D9\u05D9\u05DD \u05D1\u05E9\u05D3\u05D4 '${colName}' (\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9).`;
|
|
1790
|
+
} else if (errorMsg.includes("is required") || errorMsg.includes("\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4") || errorMsg.toLowerCase().includes("required")) {
|
|
1791
|
+
errorMsg = `\u05E9\u05D2\u05D9\u05D0\u05EA \u05D0\u05D9\u05DE\u05D5\u05EA: \u05E9\u05D3\u05D4 '${colName}' \u05D4\u05D9\u05E0\u05D5 \u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05DC\u05D0 \u05D9\u05DB\u05D5\u05DC \u05DC\u05D4\u05D9\u05E9\u05D0\u05E8 \u05E8\u05D9\u05E7.`;
|
|
1792
|
+
}
|
|
1793
|
+
addToast({
|
|
1794
|
+
type: "error",
|
|
1795
|
+
message: errorMsg
|
|
1796
|
+
});
|
|
1797
|
+
return false;
|
|
1346
1798
|
}
|
|
1799
|
+
} else {
|
|
1800
|
+
if (isMountedRef.current) {
|
|
1801
|
+
const updatedRecords = linkedRecords.map(
|
|
1802
|
+
(r) => r.id === recordId ? __spreadProps(__spreadValues({}, r), { data: __spreadProps(__spreadValues({}, r.data), { [colName]: value2 }) }) : r
|
|
1803
|
+
);
|
|
1804
|
+
setLinkedRecords(updatedRecords);
|
|
1805
|
+
const targetRecord = updatedRecords.find((r) => r.id === recordId);
|
|
1806
|
+
const updatedEntries = entries.map(
|
|
1807
|
+
(e) => e.recordId === recordId ? __spreadProps(__spreadValues({}, e), { _resolvedData: targetRecord == null ? void 0 : targetRecord.data }) : e
|
|
1808
|
+
);
|
|
1809
|
+
if (context == null ? void 0 : context.updateQuietly) {
|
|
1810
|
+
context.updateQuietly(rowId, column.name, updatedEntries);
|
|
1811
|
+
} else {
|
|
1812
|
+
onChange(updatedEntries);
|
|
1813
|
+
}
|
|
1814
|
+
}
|
|
1815
|
+
return true;
|
|
1347
1816
|
}
|
|
1348
1817
|
};
|
|
1818
|
+
const handleRecordCellChange = handleCommitRecordCell;
|
|
1349
1819
|
const handleCreateRecord = async () => {
|
|
1350
|
-
var _a2;
|
|
1820
|
+
var _a2, _b2, _c, _d, _e;
|
|
1351
1821
|
if (!executeAction || !referencedTableId) return;
|
|
1352
1822
|
for (const col of targetColumns) {
|
|
1353
1823
|
if (col.isRequired) {
|
|
@@ -1360,16 +1830,30 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1360
1830
|
return;
|
|
1361
1831
|
}
|
|
1362
1832
|
}
|
|
1833
|
+
if (((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE") {
|
|
1834
|
+
const val = newRecordData[col.name];
|
|
1835
|
+
if (val !== void 0 && val !== null && String(val).trim() !== "" && !isValidPhoneNumber(String(val))) {
|
|
1836
|
+
addToast({
|
|
1837
|
+
type: "error",
|
|
1838
|
+
message: `\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 '${col.name}' \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA.`
|
|
1839
|
+
});
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
}
|
|
1363
1843
|
}
|
|
1364
1844
|
try {
|
|
1365
1845
|
const res = await executeAction("CREATE_RECORD", {
|
|
1366
1846
|
tableId: referencedTableId,
|
|
1367
1847
|
records: [newRecordData]
|
|
1368
1848
|
});
|
|
1849
|
+
if (res && (res.error === "UNIQUE_CONSTRAINT_CONFLICT" || res.code === "UNIQUE_CONSTRAINT_CONFLICT")) {
|
|
1850
|
+
handleUniqueConflict(res);
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1369
1853
|
if (res && res.success === false) {
|
|
1370
1854
|
throw new Error(res.error || "Action execution failed");
|
|
1371
1855
|
}
|
|
1372
|
-
const created = Array.isArray(res) ? res[0] : ((
|
|
1856
|
+
const created = Array.isArray(res) ? res[0] : ((_b2 = res == null ? void 0 : res.data) == null ? void 0 : _b2[0]) || res;
|
|
1373
1857
|
if (created) {
|
|
1374
1858
|
const newRecord = {
|
|
1375
1859
|
id: String(created.id || created._id),
|
|
@@ -1380,6 +1864,12 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1380
1864
|
setNewRecordData({});
|
|
1381
1865
|
}
|
|
1382
1866
|
} catch (err) {
|
|
1867
|
+
const isConflict = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" || (err == null ? void 0 : err.code) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_c = err == null ? void 0 : err.data) == null ? void 0 : _c.error) === "UNIQUE_CONSTRAINT_CONFLICT" || ((_d = err == null ? void 0 : err.message) == null ? void 0 : _d.includes("UNIQUE_CONSTRAINT_CONFLICT"));
|
|
1868
|
+
if (isConflict) {
|
|
1869
|
+
const conflictPayload = (err == null ? void 0 : err.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err : ((_e = err == null ? void 0 : err.data) == null ? void 0 : _e.error) === "UNIQUE_CONSTRAINT_CONFLICT" ? err.data : err;
|
|
1870
|
+
handleUniqueConflict(conflictPayload);
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1383
1873
|
const msg = (err == null ? void 0 : err.message) || String(err);
|
|
1384
1874
|
addToast({
|
|
1385
1875
|
type: "error",
|
|
@@ -1466,11 +1956,23 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1466
1956
|
isLoading ? /* @__PURE__ */ jsx5("div", { className: "flex items-center justify-center py-6", children: /* @__PURE__ */ jsx5("div", { className: "w-5 h-5 border-2 border-blue-400 border-t-transparent rounded-full animate-spin" }) }) : entries.length === 0 && !isCreating ? /* @__PURE__ */ jsx5("div", { className: "text-center py-6 text-xs text-slate-400", children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA. \u05D4\u05E9\u05EA\u05DE\u05E9 \u05D1\u05D7\u05D9\u05E4\u05D5\u05E9 \u05DB\u05D3\u05D9 \u05DC\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA, \u05D0\u05D5 \u05D4\u05D5\u05E1\u05E3 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05D7\u05D3\u05E9\u05D4." }) : /* @__PURE__ */ jsx5("div", { className: "overflow-x-auto pb-1", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-xs border-collapse", children: [
|
|
1467
1957
|
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs5("tr", { className: "bg-slate-100/80", children: [
|
|
1468
1958
|
/* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 text-center w-10 font-semibold text-slate-500", children: "\u05E0\u05D1\u05D7\u05E8" }),
|
|
1469
|
-
targetColumns.map((col) =>
|
|
1959
|
+
targetColumns.map((col) => {
|
|
1960
|
+
var _a2;
|
|
1961
|
+
const isContact = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) === "GOOGLE_CONTACT";
|
|
1962
|
+
return /* @__PURE__ */ jsx5(
|
|
1963
|
+
"th",
|
|
1964
|
+
{
|
|
1965
|
+
className: `border border-slate-200 px-2 py-1.5 text-right font-semibold text-slate-600 whitespace-nowrap ${isContact ? "min-w-[140px]" : ""}`,
|
|
1966
|
+
children: col.name
|
|
1967
|
+
},
|
|
1968
|
+
col.name
|
|
1969
|
+
);
|
|
1970
|
+
}),
|
|
1470
1971
|
/* @__PURE__ */ jsx5("th", { className: "border border-slate-200 px-2 py-1.5 w-14" })
|
|
1471
1972
|
] }) }),
|
|
1472
1973
|
/* @__PURE__ */ jsxs5("tbody", { children: [
|
|
1473
1974
|
entries.map((entry) => {
|
|
1975
|
+
var _a2;
|
|
1474
1976
|
const record = linkedRecords.find((r) => r.id === entry.recordId);
|
|
1475
1977
|
return /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors", children: [
|
|
1476
1978
|
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5(
|
|
@@ -1483,61 +1985,101 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1483
1985
|
}
|
|
1484
1986
|
) }),
|
|
1485
1987
|
targetColumns.map((col) => {
|
|
1486
|
-
var
|
|
1487
|
-
const
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1988
|
+
var _a3;
|
|
1989
|
+
const isContact = ((_a3 = col.type) == null ? void 0 : _a3.toUpperCase()) === "GOOGLE_CONTACT";
|
|
1990
|
+
if (!record) {
|
|
1991
|
+
return /* @__PURE__ */ jsx5(
|
|
1992
|
+
"td",
|
|
1993
|
+
{
|
|
1994
|
+
className: `border border-slate-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
|
|
1995
|
+
children: /* @__PURE__ */ jsx5("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." })
|
|
1996
|
+
},
|
|
1997
|
+
col.name
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
return /* @__PURE__ */ jsx5(
|
|
2001
|
+
SubTableCell,
|
|
1491
2002
|
{
|
|
1492
|
-
|
|
2003
|
+
record,
|
|
1493
2004
|
column: col,
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
context
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
updateQuietly: (rid, colName, val) => handleRecordCellChange(rid, colName, val)
|
|
1505
|
-
})
|
|
1506
|
-
}
|
|
1507
|
-
) : /* @__PURE__ */ jsx5("span", { className: "text-slate-300 italic px-2", children: "\u05D8\u05D5\u05E2\u05DF..." }) }, col.name);
|
|
2005
|
+
targetSchema,
|
|
2006
|
+
referencedTableId,
|
|
2007
|
+
context,
|
|
2008
|
+
relationOptions,
|
|
2009
|
+
setRelationOptions,
|
|
2010
|
+
refetchRelation,
|
|
2011
|
+
onCommit: handleCommitRecordCell
|
|
2012
|
+
},
|
|
2013
|
+
`${record.id}_${col.name}`
|
|
2014
|
+
);
|
|
1508
2015
|
}),
|
|
1509
|
-
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */
|
|
1510
|
-
"
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
2016
|
+
/* @__PURE__ */ jsx5("td", { className: "border border-slate-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
|
|
2017
|
+
((_a2 = column.config) == null ? void 0 : _a2.actionType) === "WHATSAPP" && (() => {
|
|
2018
|
+
var _a3, _b2, _c;
|
|
2019
|
+
const actionPhoneCol = (_a3 = column.config) == null ? void 0 : _a3.actionPhoneColumn;
|
|
2020
|
+
const phone = actionPhoneCol ? ((_b2 = record == null ? void 0 : record.data) == null ? void 0 : _b2[actionPhoneCol]) || ((_c = entry._resolvedData) == null ? void 0 : _c[actionPhoneCol]) : null;
|
|
2021
|
+
if (phone) {
|
|
2022
|
+
return /* @__PURE__ */ jsx5(
|
|
2023
|
+
"button",
|
|
2024
|
+
{
|
|
2025
|
+
type: "button",
|
|
2026
|
+
onClick: (e) => {
|
|
2027
|
+
e.stopPropagation();
|
|
2028
|
+
openWhatsAppChat(String(phone));
|
|
2029
|
+
},
|
|
2030
|
+
className: "text-emerald-500 hover:text-emerald-600 p-0.5 rounded hover:bg-emerald-50 transition-colors cursor-pointer",
|
|
2031
|
+
title: `\u05E4\u05EA\u05D9\u05D7\u05EA \u05D5\u05D5\u05D0\u05D8\u05E1\u05D0\u05E4 (${phone})`,
|
|
2032
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { d: "M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51a5.816 5.816 0 00-.571-.01c-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z" }) })
|
|
2033
|
+
}
|
|
2034
|
+
);
|
|
2035
|
+
}
|
|
2036
|
+
return null;
|
|
2037
|
+
})(),
|
|
2038
|
+
/* @__PURE__ */ jsx5(
|
|
2039
|
+
"button",
|
|
2040
|
+
{
|
|
2041
|
+
type: "button",
|
|
2042
|
+
onClick: (e) => {
|
|
2043
|
+
e.stopPropagation();
|
|
2044
|
+
handleUnlinkRecord(entry.recordId);
|
|
2045
|
+
},
|
|
2046
|
+
className: "text-slate-400 hover:text-rose-500 p-0.5 rounded transition-colors cursor-pointer inline-flex items-center justify-center",
|
|
2047
|
+
title: "\u05D4\u05E1\u05E8 \u05E7\u05D9\u05E9\u05D5\u05E8",
|
|
2048
|
+
children: /* @__PURE__ */ jsx5("svg", { className: "w-3.5 h-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M6 18L18 6M6 6l12 12" }) })
|
|
2049
|
+
}
|
|
2050
|
+
)
|
|
2051
|
+
] }) })
|
|
1519
2052
|
] }, entry.recordId);
|
|
1520
2053
|
}),
|
|
1521
2054
|
isCreating && /* @__PURE__ */ jsxs5("tr", { className: "bg-emerald-50/40", children: [
|
|
1522
2055
|
/* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-2 py-1 text-center", children: /* @__PURE__ */ jsx5("span", { className: "text-emerald-500 font-bold text-[10px]", children: "\u05D7\u05D3\u05E9" }) }),
|
|
1523
2056
|
targetColumns.map((col) => {
|
|
1524
|
-
var _a2,
|
|
2057
|
+
var _a2, _b2;
|
|
1525
2058
|
const colType = ((_a2 = col.type) == null ? void 0 : _a2.toUpperCase()) || "DEFAULT";
|
|
1526
2059
|
const InputComponent = FORM_INPUTS[colType] || FORM_INPUTS.DEFAULT;
|
|
1527
|
-
|
|
1528
|
-
|
|
2060
|
+
const isContact = colType === "GOOGLE_CONTACT";
|
|
2061
|
+
return /* @__PURE__ */ jsx5(
|
|
2062
|
+
"td",
|
|
1529
2063
|
{
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
2064
|
+
className: `border border-emerald-200 p-0 relative h-8 ${isContact ? "min-w-[140px]" : ""}`,
|
|
2065
|
+
children: /* @__PURE__ */ jsx5(
|
|
2066
|
+
InputComponent,
|
|
2067
|
+
{
|
|
2068
|
+
value: (_b2 = newRecordData[col.name]) != null ? _b2 : colType === "BOOLEAN" ? false : "",
|
|
2069
|
+
column: col,
|
|
2070
|
+
rowId: "new_record",
|
|
2071
|
+
onChange: (v) => setNewRecordData((prev) => __spreadProps(__spreadValues({}, prev), { [col.name]: v })),
|
|
2072
|
+
context: __spreadProps(__spreadValues({}, context), {
|
|
2073
|
+
tableName: (targetSchema == null ? void 0 : targetSchema.name) || (targetSchema == null ? void 0 : targetSchema.tableName) || (targetSchema == null ? void 0 : targetSchema.title) || (targetSchema == null ? void 0 : targetSchema.id) || "Table",
|
|
2074
|
+
relationOptions,
|
|
2075
|
+
refetchRelation,
|
|
2076
|
+
tableId: (targetSchema == null ? void 0 : targetSchema.tableMetaId) || (targetSchema == null ? void 0 : targetSchema.id) || referencedTableId
|
|
2077
|
+
})
|
|
2078
|
+
}
|
|
2079
|
+
)
|
|
2080
|
+
},
|
|
2081
|
+
`new_${col.name}`
|
|
2082
|
+
);
|
|
1541
2083
|
}),
|
|
1542
2084
|
/* @__PURE__ */ jsx5("td", { className: "border border-emerald-200 px-1 py-1 text-center", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-center gap-1", children: [
|
|
1543
2085
|
/* @__PURE__ */ jsx5(
|
|
@@ -1565,7 +2107,102 @@ function SubTableViewer({ rowId, column, value, onChange, context }) {
|
|
|
1565
2107
|
] }) })
|
|
1566
2108
|
] })
|
|
1567
2109
|
] })
|
|
1568
|
-
] }) })
|
|
2110
|
+
] }) }),
|
|
2111
|
+
conflictModalState.isOpen && /* @__PURE__ */ jsx5(
|
|
2112
|
+
"div",
|
|
2113
|
+
{
|
|
2114
|
+
className: "fixed inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/60 backdrop-blur-sm animate-in fade-in duration-200",
|
|
2115
|
+
dir: "rtl",
|
|
2116
|
+
onClick: handleCancelConflict,
|
|
2117
|
+
children: /* @__PURE__ */ jsxs5(
|
|
2118
|
+
"div",
|
|
2119
|
+
{
|
|
2120
|
+
className: "bg-white rounded-xl shadow-2xl w-full max-w-lg sm:max-w-xl overflow-hidden border border-slate-200 animate-in fade-in zoom-in-95 duration-200",
|
|
2121
|
+
onClick: (e) => e.stopPropagation(),
|
|
2122
|
+
children: [
|
|
2123
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-5 border-b border-slate-100 flex items-center gap-3", children: [
|
|
2124
|
+
/* @__PURE__ */ jsx5("div", { className: "w-10 h-10 rounded-full bg-blue-50 border border-blue-200 flex items-center justify-center text-blue-600 flex-shrink-0", children: /* @__PURE__ */ jsx5("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }) }),
|
|
2125
|
+
/* @__PURE__ */ jsxs5("div", { children: [
|
|
2126
|
+
/* @__PURE__ */ jsx5("h3", { className: "text-base font-bold text-slate-800", children: conflictModalState.matchingRecords.length > 1 ? "\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" : "\u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05D1\u05D8\u05D1\u05DC\u05D4" }),
|
|
2127
|
+
/* @__PURE__ */ jsx5("p", { className: "text-xs text-slate-500", children: "\u05E0\u05DE\u05E6\u05D0\u05D4 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E7\u05D9\u05D9\u05DE\u05EA \u05E2\u05DD \u05D0\u05D5\u05EA\u05D5 \u05E2\u05E8\u05DA \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" })
|
|
2128
|
+
] })
|
|
2129
|
+
] }),
|
|
2130
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-5 space-y-3", children: [
|
|
2131
|
+
/* @__PURE__ */ jsxs5("p", { className: "text-sm text-slate-700 leading-relaxed", children: [
|
|
2132
|
+
"\u05E7\u05D9\u05D9\u05DE\u05EA \u05DB\u05D1\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4 \u05E2\u05DD \u05D4\u05E2\u05E8\u05DA \u05E9\u05E0\u05D1\u05D7\u05E8 \u05D1\u05E9\u05D3\u05D4",
|
|
2133
|
+
" ",
|
|
2134
|
+
/* @__PURE__ */ jsx5("span", { className: "font-bold text-slate-900 bg-slate-100 px-1.5 py-0.5 rounded border border-slate-200", children: conflictModalState.fieldName }),
|
|
2135
|
+
". \u05D4\u05D0\u05DD \u05EA\u05E8\u05E6\u05D4 \u05DC\u05E7\u05E9\u05E8 \u05D0\u05D5\u05EA\u05D4 \u05DC\u05EA\u05EA-\u05D4\u05D8\u05D1\u05DC\u05D4 \u05D1\u05DE\u05E7\u05D5\u05DD \u05DC\u05D9\u05E6\u05D5\u05E8 \u05D7\u05D3\u05E9\u05D4?"
|
|
2136
|
+
] }),
|
|
2137
|
+
conflictModalState.matchingRecords.length > 1 && /* @__PURE__ */ jsxs5("div", { className: "p-3 bg-blue-50 border border-blue-200 rounded-lg text-xs font-semibold text-blue-800", children: [
|
|
2138
|
+
"\u05E0\u05DE\u05E6\u05D0\u05D5 ",
|
|
2139
|
+
conflictModalState.matchingRecords.length,
|
|
2140
|
+
" \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05E7\u05D9\u05D9\u05DE\u05D5\u05EA. \u05D4\u05D0\u05DD \u05DC\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF?"
|
|
2141
|
+
] }),
|
|
2142
|
+
conflictModalState.matchingRecords.length > 0 && /* @__PURE__ */ jsx5("div", { className: "overflow-x-auto border border-slate-200 rounded-lg max-h-48 text-xs bg-white", children: /* @__PURE__ */ jsxs5("table", { className: "w-full text-right border-collapse", children: [
|
|
2143
|
+
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsx5("tr", { className: "bg-slate-100 text-slate-700 font-semibold border-b whitespace-nowrap", children: (targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(((_b = conflictModalState.matchingRecords[0]) == null ? void 0 : _b.data) || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }))).map((col) => /* @__PURE__ */ jsx5(
|
|
2144
|
+
"th",
|
|
2145
|
+
{
|
|
2146
|
+
className: "bg-slate-100 text-slate-700 font-semibold p-2 border-b whitespace-nowrap",
|
|
2147
|
+
children: col.name
|
|
2148
|
+
},
|
|
2149
|
+
col.name
|
|
2150
|
+
)) }) }),
|
|
2151
|
+
/* @__PURE__ */ jsx5("tbody", { children: conflictModalState.matchingRecords.map((r, idx) => {
|
|
2152
|
+
const cols = targetColumns.length > 0 ? targetColumns.filter((c) => c.name !== "_id" && c.name !== "id") : Object.keys(r.data || {}).filter((k) => k !== "_id" && k !== "id").map((name) => ({ name }));
|
|
2153
|
+
return /* @__PURE__ */ jsx5("tr", { className: "hover:bg-slate-50/80 transition-colors", children: cols.map((col) => {
|
|
2154
|
+
var _a2;
|
|
2155
|
+
const rawVal = (_a2 = r.data) == null ? void 0 : _a2[col.name];
|
|
2156
|
+
let displayVal = "-";
|
|
2157
|
+
if (rawVal !== void 0 && rawVal !== null && rawVal !== "") {
|
|
2158
|
+
if (typeof rawVal === "boolean") {
|
|
2159
|
+
displayVal = rawVal ? "\u05DB\u05DF" : "\u05DC\u05D0";
|
|
2160
|
+
} else if (typeof rawVal === "object") {
|
|
2161
|
+
displayVal = Array.isArray(rawVal) ? rawVal.join(", ") : JSON.stringify(rawVal);
|
|
2162
|
+
} else {
|
|
2163
|
+
displayVal = String(rawVal);
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
return /* @__PURE__ */ jsx5(
|
|
2167
|
+
"td",
|
|
2168
|
+
{
|
|
2169
|
+
className: "p-2 border-b border-slate-100 whitespace-nowrap text-slate-800",
|
|
2170
|
+
children: displayVal
|
|
2171
|
+
},
|
|
2172
|
+
col.name
|
|
2173
|
+
);
|
|
2174
|
+
}) }, r.id || idx);
|
|
2175
|
+
}) })
|
|
2176
|
+
] }) })
|
|
2177
|
+
] }),
|
|
2178
|
+
/* @__PURE__ */ jsxs5("div", { className: "p-4 bg-slate-50 border-t border-slate-100 flex items-center justify-end gap-2.5", children: [
|
|
2179
|
+
/* @__PURE__ */ jsx5(
|
|
2180
|
+
"button",
|
|
2181
|
+
{
|
|
2182
|
+
type: "button",
|
|
2183
|
+
onClick: handleCancelConflict,
|
|
2184
|
+
className: "px-4 py-2 text-sm font-medium text-slate-700 hover:bg-slate-200/70 rounded-lg border border-slate-300 transition-colors cursor-pointer",
|
|
2185
|
+
children: "\u05D1\u05D9\u05D8\u05D5\u05DC"
|
|
2186
|
+
}
|
|
2187
|
+
),
|
|
2188
|
+
/* @__PURE__ */ jsxs5(
|
|
2189
|
+
"button",
|
|
2190
|
+
{
|
|
2191
|
+
type: "button",
|
|
2192
|
+
onClick: handleConfirmLinkConflict,
|
|
2193
|
+
className: "px-4 py-2 text-sm font-semibold text-white bg-blue-600 hover:bg-blue-700 rounded-lg shadow transition-colors flex items-center gap-1.5 cursor-pointer",
|
|
2194
|
+
children: [
|
|
2195
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" }) }),
|
|
2196
|
+
conflictModalState.matchingRecords.length > 1 ? "\u05E7\u05E9\u05E8 \u05D0\u05EA \u05DB\u05D5\u05DC\u05DF" : "\u05E7\u05E9\u05E8 \u05E8\u05E9\u05D5\u05DE\u05D4"
|
|
2197
|
+
]
|
|
2198
|
+
}
|
|
2199
|
+
)
|
|
2200
|
+
] })
|
|
2201
|
+
]
|
|
2202
|
+
}
|
|
2203
|
+
)
|
|
2204
|
+
}
|
|
2205
|
+
)
|
|
1569
2206
|
] });
|
|
1570
2207
|
}
|
|
1571
2208
|
|
|
@@ -2171,7 +2808,7 @@ function TableBlockClient({
|
|
|
2171
2808
|
const formatPayload = (payload) => {
|
|
2172
2809
|
const formatted = {};
|
|
2173
2810
|
(localColumns || []).forEach((col) => {
|
|
2174
|
-
var _a, _b;
|
|
2811
|
+
var _a, _b, _c;
|
|
2175
2812
|
if (["_id", "id", "createdAt", "updatedAt", "orgId", "tableId", "isSelected"].includes(col.name)) return;
|
|
2176
2813
|
let val = payload[col.name];
|
|
2177
2814
|
if (val !== void 0) {
|
|
@@ -2181,7 +2818,9 @@ function TableBlockClient({
|
|
|
2181
2818
|
if (((_a = col.type) == null ? void 0 : _a.toUpperCase()) === "NUMBER") {
|
|
2182
2819
|
val = val === "" ? 0 : Number(val);
|
|
2183
2820
|
if (isNaN(val)) val = 0;
|
|
2184
|
-
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "
|
|
2821
|
+
} else if (((_b = col.type) == null ? void 0 : _b.toUpperCase()) === "PHONE") {
|
|
2822
|
+
val = sanitizePhoneNumber(String(val));
|
|
2823
|
+
} else if (((_c = col.type) == null ? void 0 : _c.toUpperCase()) === "SUB_TABLE" && Array.isArray(val)) {
|
|
2185
2824
|
val = val.map((item) => {
|
|
2186
2825
|
const _a2 = item, { _resolvedData } = _a2, rest = __objRest(_a2, ["_resolvedData"]);
|
|
2187
2826
|
return rest;
|
|
@@ -2195,7 +2834,7 @@ function TableBlockClient({
|
|
|
2195
2834
|
};
|
|
2196
2835
|
const hasChanges = dirty.added.length > 0 || Object.keys(dirty.modified).length > 0 || dirty.deleted.length > 0;
|
|
2197
2836
|
const handleSave = async () => {
|
|
2198
|
-
var _a;
|
|
2837
|
+
var _a, _b;
|
|
2199
2838
|
if (!hasChanges) {
|
|
2200
2839
|
return;
|
|
2201
2840
|
}
|
|
@@ -2218,6 +2857,28 @@ function TableBlockClient({
|
|
|
2218
2857
|
}
|
|
2219
2858
|
}
|
|
2220
2859
|
}
|
|
2860
|
+
const phoneCols = (localColumns || []).filter((c) => {
|
|
2861
|
+
var _a2;
|
|
2862
|
+
return ((_a2 = c.type) == null ? void 0 : _a2.toUpperCase()) === "PHONE";
|
|
2863
|
+
});
|
|
2864
|
+
for (const col of phoneCols) {
|
|
2865
|
+
for (const row of dirty.added) {
|
|
2866
|
+
const val = row.data[col.name];
|
|
2867
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
2868
|
+
showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2872
|
+
for (const [rowId, mods] of Object.entries(dirty.modified)) {
|
|
2873
|
+
const rowData = ((_b = data.find((r) => r.id === rowId)) == null ? void 0 : _b.data) || {};
|
|
2874
|
+
const mergedData = __spreadValues(__spreadValues({}, rowData), mods);
|
|
2875
|
+
const val = mergedData[col.name];
|
|
2876
|
+
if (!isEmpty(val) && !isValidPhoneNumber(val)) {
|
|
2877
|
+
showError(`\u05DE\u05E1\u05E4\u05E8 \u05D4\u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05E9\u05D3\u05D4 "${col.name}" \u05D0\u05D9\u05E0\u05D5 \u05EA\u05E7\u05D9\u05DF. \u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05DE\u05E1\u05E4\u05E8 \u05D1\u05D0\u05D5\u05E8\u05DA 9-15 \u05E1\u05E4\u05E8\u05D5\u05EA (\u05DC\u05D3\u05D5\u05D2\u05DE\u05D4 0501234567 \u05D0\u05D5 +972501234567).`, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D5\u05D5\u05DC\u05D9\u05D3\u05E6\u05D9\u05D4");
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
}
|
|
2221
2882
|
setIsSaving(true);
|
|
2222
2883
|
try {
|
|
2223
2884
|
if (!executeAction) {
|
|
@@ -2880,5 +3541,7 @@ export {
|
|
|
2880
3541
|
ToastProvider,
|
|
2881
3542
|
UNIVERSE_COMPONENTS,
|
|
2882
3543
|
cn,
|
|
3544
|
+
formatPhoneDisplay,
|
|
3545
|
+
openWhatsAppChat,
|
|
2883
3546
|
useToast
|
|
2884
3547
|
};
|