@universe-platform/ui 0.1.0-beta.5 → 0.1.0-beta.6
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 +223 -2
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +599 -34
- package/dist/index.mjs +599 -34
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -704,15 +704,19 @@ var FORM_INPUTS = {
|
|
|
704
704
|
DATE: ({ value, onChange, column }) => /* @__PURE__ */ jsx4(DatePickerCell, { value, onChange, column }),
|
|
705
705
|
CURRENCY: ({ value, column, onChange }) => {
|
|
706
706
|
const symbol = getCurrencySymbol(column.currencySymbol);
|
|
707
|
+
const [isFocused, setIsFocused] = React4.useState(false);
|
|
708
|
+
const displayValue = !isFocused && value !== void 0 && value !== null && value !== "" && !isNaN(Number(value)) ? new Intl.NumberFormat("en-US").format(Number(value)) : value !== void 0 && value !== null ? value : "";
|
|
707
709
|
return /* @__PURE__ */ jsxs4("div", { className: "relative w-full h-full", children: [
|
|
708
710
|
symbol && /* @__PURE__ */ jsx4("span", { className: "absolute left-2 top-1/2 -translate-y-1/2 text-slate-400 pointer-events-none text-sm", children: symbol }),
|
|
709
711
|
/* @__PURE__ */ jsx4(
|
|
710
712
|
"input",
|
|
711
713
|
{
|
|
712
|
-
type: "number",
|
|
714
|
+
type: isFocused ? "number" : "text",
|
|
713
715
|
step: "any",
|
|
714
716
|
className: `w-full h-8 ${symbol ? "pl-6 pr-2" : "px-2"} bg-transparent focus:bg-white focus:outline-none focus:ring-1 focus:ring-blue-400 text-sm`,
|
|
715
|
-
value:
|
|
717
|
+
value: displayValue,
|
|
718
|
+
onFocus: () => setIsFocused(true),
|
|
719
|
+
onBlur: () => setIsFocused(false),
|
|
716
720
|
onChange: (e) => {
|
|
717
721
|
const val = e.target.value;
|
|
718
722
|
onChange(val === "" ? "" : Number(val));
|
|
@@ -863,6 +867,7 @@ var FORM_INPUTS = {
|
|
|
863
867
|
};
|
|
864
868
|
|
|
865
869
|
// src/components/TableBlock/TableBlockClient.tsx
|
|
870
|
+
import { X as X4, Copy as Copy2 } from "lucide-react";
|
|
866
871
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
867
872
|
function TableBlockClient({
|
|
868
873
|
data: initialRecords,
|
|
@@ -880,6 +885,68 @@ function TableBlockClient({
|
|
|
880
885
|
"data-testid": dataTestId
|
|
881
886
|
}) {
|
|
882
887
|
const { showError, addToast } = useToast();
|
|
888
|
+
const [columnWidths, setColumnWidths] = useState4({});
|
|
889
|
+
const [isMounted, setIsMounted] = useState4(false);
|
|
890
|
+
const tableKey = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
891
|
+
const [page, setPage] = useState4(1);
|
|
892
|
+
const [limit, setLimit] = useState4(50);
|
|
893
|
+
const [totalRecords, setTotalRecords] = useState4(0);
|
|
894
|
+
const [totalPages, setTotalPages] = useState4(1);
|
|
895
|
+
useEffect2(() => {
|
|
896
|
+
if (typeof window !== "undefined") {
|
|
897
|
+
const savedWidths = localStorage.getItem(`table_widths_${tableKey}`);
|
|
898
|
+
if (savedWidths) {
|
|
899
|
+
try {
|
|
900
|
+
setColumnWidths(JSON.parse(savedWidths));
|
|
901
|
+
} catch (e) {
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
const savedSummary = localStorage.getItem(`table_summary_${tableKey}`);
|
|
905
|
+
if (savedSummary !== null) {
|
|
906
|
+
setShowSummary(savedSummary === "true");
|
|
907
|
+
}
|
|
908
|
+
const savedLimit = localStorage.getItem(`table_limit_${tableKey}`);
|
|
909
|
+
if (savedLimit) {
|
|
910
|
+
const parsed = parseInt(savedLimit, 10);
|
|
911
|
+
if ([20, 50, 100].includes(parsed)) {
|
|
912
|
+
setLimit(parsed);
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
setIsMounted(true);
|
|
917
|
+
}, [tableKey]);
|
|
918
|
+
const [showSummary, setShowSummary] = useState4(false);
|
|
919
|
+
const toggleSummary = () => {
|
|
920
|
+
setShowSummary((prev) => {
|
|
921
|
+
const next = !prev;
|
|
922
|
+
const tableKey2 = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
923
|
+
localStorage.setItem(`table_summary_${tableKey2}`, String(next));
|
|
924
|
+
return next;
|
|
925
|
+
});
|
|
926
|
+
};
|
|
927
|
+
const [resizingCol, setResizingCol] = useState4(null);
|
|
928
|
+
useEffect2(() => {
|
|
929
|
+
if (!resizingCol) return;
|
|
930
|
+
const handleMouseMove = (e) => {
|
|
931
|
+
const diffX = resizingCol.startX - e.clientX;
|
|
932
|
+
const newWidth = Math.max(100, Math.min(500, resizingCol.startWidth + diffX));
|
|
933
|
+
setColumnWidths((prev) => __spreadProps(__spreadValues({}, prev), { [resizingCol.name]: newWidth }));
|
|
934
|
+
};
|
|
935
|
+
const handleMouseUp = () => {
|
|
936
|
+
setResizingCol(null);
|
|
937
|
+
setColumnWidths((prev) => {
|
|
938
|
+
const tableKey2 = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id) || (schema == null ? void 0 : schema.name) || "default";
|
|
939
|
+
localStorage.setItem(`table_widths_${tableKey2}`, JSON.stringify(prev));
|
|
940
|
+
return prev;
|
|
941
|
+
});
|
|
942
|
+
};
|
|
943
|
+
document.addEventListener("mousemove", handleMouseMove);
|
|
944
|
+
document.addEventListener("mouseup", handleMouseUp);
|
|
945
|
+
return () => {
|
|
946
|
+
document.removeEventListener("mousemove", handleMouseMove);
|
|
947
|
+
document.removeEventListener("mouseup", handleMouseUp);
|
|
948
|
+
};
|
|
949
|
+
}, [resizingCol, schema]);
|
|
883
950
|
const normalizeRecords = (records) => {
|
|
884
951
|
return (records || []).map((row) => {
|
|
885
952
|
var _c;
|
|
@@ -905,12 +972,32 @@ function TableBlockClient({
|
|
|
905
972
|
return __spreadProps(__spreadValues({}, row), { id: String(row.id || ""), data: rowData });
|
|
906
973
|
});
|
|
907
974
|
};
|
|
975
|
+
const mergeColumnDefs = useCallback3((existingCols, incomingCols) => {
|
|
976
|
+
if (!incomingCols || incomingCols.length === 0) return existingCols || [];
|
|
977
|
+
if (!existingCols || existingCols.length === 0) return incomingCols;
|
|
978
|
+
const existingMap = new Map(existingCols.map((c) => [c.name, c]));
|
|
979
|
+
const merged = incomingCols.map((inc) => {
|
|
980
|
+
const ext = existingMap.get(inc.name);
|
|
981
|
+
if (ext) {
|
|
982
|
+
existingMap.delete(inc.name);
|
|
983
|
+
return __spreadValues(__spreadValues({}, ext), inc);
|
|
984
|
+
}
|
|
985
|
+
return inc;
|
|
986
|
+
});
|
|
987
|
+
for (const [, extCol] of existingMap) {
|
|
988
|
+
merged.push(extCol);
|
|
989
|
+
}
|
|
990
|
+
return merged.sort((a, b) => {
|
|
991
|
+
var _a, _b;
|
|
992
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
993
|
+
});
|
|
994
|
+
}, []);
|
|
908
995
|
const [localColumns, setLocalColumns] = useState4(() => (schema == null ? void 0 : schema.columns) || []);
|
|
909
996
|
useEffect2(() => {
|
|
910
997
|
if ((schema == null ? void 0 : schema.columns) && schema.columns.length > 0) {
|
|
911
|
-
setLocalColumns(schema.columns);
|
|
998
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, schema.columns));
|
|
912
999
|
}
|
|
913
|
-
}, [schema == null ? void 0 : schema.columns]);
|
|
1000
|
+
}, [schema == null ? void 0 : schema.columns, mergeColumnDefs]);
|
|
914
1001
|
const [dirty, setDirty] = useState4({ added: [], modified: {}, deleted: [] });
|
|
915
1002
|
const dirtyRef = useRef3(dirty);
|
|
916
1003
|
useEffect2(() => {
|
|
@@ -957,29 +1044,57 @@ function TableBlockClient({
|
|
|
957
1044
|
setBaseRecordsMap(map);
|
|
958
1045
|
}
|
|
959
1046
|
}, [initialRecords]);
|
|
960
|
-
|
|
1047
|
+
const refetchTableData = useCallback3((targetPage) => {
|
|
961
1048
|
const tableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
962
|
-
if (!tableId || !executeAction) return;
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1049
|
+
if (!tableId || !executeAction) return Promise.resolve();
|
|
1050
|
+
const activePage = targetPage !== void 0 ? targetPage : page;
|
|
1051
|
+
const skip = (activePage - 1) * limit;
|
|
1052
|
+
return executeAction("FETCH_TABLE_DATA", { tableId, page: activePage, limit, skip }).then((res) => {
|
|
1053
|
+
var _a;
|
|
1054
|
+
if (res) {
|
|
1055
|
+
if (((_a = res.schema) == null ? void 0 : _a.columns) && res.schema.columns.length > 0) {
|
|
1056
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, res.schema.columns));
|
|
1057
|
+
}
|
|
1058
|
+
if (res.records && Array.isArray(res.records)) {
|
|
1059
|
+
const norm = normalizeRecords(res.records);
|
|
1060
|
+
const map = /* @__PURE__ */ new Map();
|
|
1061
|
+
norm.forEach((r) => map.set(r.id, __spreadValues({}, r.data)));
|
|
1062
|
+
setBaseRecordsMap(map);
|
|
1063
|
+
setData(norm);
|
|
1064
|
+
}
|
|
1065
|
+
if (res.meta) {
|
|
1066
|
+
const total = typeof res.meta.totalRecords === "number" ? res.meta.totalRecords : 0;
|
|
1067
|
+
const pages = typeof res.meta.totalPages === "number" ? res.meta.totalPages : Math.ceil(total / limit) || 1;
|
|
1068
|
+
setTotalRecords(total);
|
|
1069
|
+
setTotalPages(pages);
|
|
1070
|
+
if (activePage > pages && pages >= 1) {
|
|
1071
|
+
setPage(pages);
|
|
976
1072
|
}
|
|
1073
|
+
} else if (res.records && Array.isArray(res.records)) {
|
|
1074
|
+
setTotalRecords(res.records.length);
|
|
1075
|
+
setTotalPages(Math.ceil(res.records.length / limit) || 1);
|
|
977
1076
|
}
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
|
|
1077
|
+
}
|
|
1078
|
+
}).catch((err) => {
|
|
1079
|
+
console.error("[TableBlock] Failed to auto-fetch table data:", err);
|
|
1080
|
+
});
|
|
1081
|
+
}, [schema == null ? void 0 : schema.tableMetaId, schema == null ? void 0 : schema.tableId, schema == null ? void 0 : schema.id, page, limit, executeAction, mergeWithDirty, mergeColumnDefs]);
|
|
1082
|
+
useEffect2(() => {
|
|
1083
|
+
refetchTableData();
|
|
1084
|
+
}, [refetchTableData]);
|
|
1085
|
+
const handleLimitChange = (newLimit) => {
|
|
1086
|
+
setLimit(newLimit);
|
|
1087
|
+
setPage(1);
|
|
1088
|
+
if (typeof window !== "undefined") {
|
|
1089
|
+
localStorage.setItem(`table_limit_${tableKey}`, String(newLimit));
|
|
981
1090
|
}
|
|
982
|
-
}
|
|
1091
|
+
};
|
|
1092
|
+
const handlePrevPage = () => {
|
|
1093
|
+
setPage((prev) => Math.max(1, prev - 1));
|
|
1094
|
+
};
|
|
1095
|
+
const handleNextPage = () => {
|
|
1096
|
+
setPage((prev) => Math.min(totalPages, prev + 1));
|
|
1097
|
+
};
|
|
983
1098
|
useEffect2(() => {
|
|
984
1099
|
if (error) {
|
|
985
1100
|
showError(error, "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E8\u05DB\u05D9\u05D1");
|
|
@@ -1026,10 +1141,144 @@ function TableBlockClient({
|
|
|
1026
1141
|
refetchRelation(col.name);
|
|
1027
1142
|
});
|
|
1028
1143
|
}, [schemaColsString, refetchRelation]);
|
|
1144
|
+
const normalizedColumns = useMemo2(() => {
|
|
1145
|
+
return (localColumns || []).map((col, idx) => {
|
|
1146
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1147
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1148
|
+
const isProtected = isRequired || isUnique;
|
|
1149
|
+
return __spreadProps(__spreadValues({}, col), {
|
|
1150
|
+
order: typeof col.order === "number" ? col.order : idx,
|
|
1151
|
+
isHidden: isProtected ? false : Boolean(col.isHidden)
|
|
1152
|
+
});
|
|
1153
|
+
}).sort((a, b) => {
|
|
1154
|
+
var _a, _b;
|
|
1155
|
+
return ((_a = a.order) != null ? _a : 0) - ((_b = b.order) != null ? _b : 0);
|
|
1156
|
+
});
|
|
1157
|
+
}, [localColumns]);
|
|
1029
1158
|
const filteredColumns = useMemo2(() => {
|
|
1030
1159
|
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1031
|
-
return
|
|
1032
|
-
}, [
|
|
1160
|
+
return normalizedColumns.filter((col) => !systemFields.includes(col.name) && !col.isHidden);
|
|
1161
|
+
}, [normalizedColumns]);
|
|
1162
|
+
const customizableColumns = useMemo2(() => {
|
|
1163
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1164
|
+
return normalizedColumns.filter((col) => !systemFields.includes(col.name));
|
|
1165
|
+
}, [normalizedColumns]);
|
|
1166
|
+
const [isColumnsDropdownOpen, setIsColumnsDropdownOpen] = useState4(false);
|
|
1167
|
+
const dropdownRef = useRef3(null);
|
|
1168
|
+
useEffect2(() => {
|
|
1169
|
+
const handleClickOutside = (e) => {
|
|
1170
|
+
if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
|
|
1171
|
+
setIsColumnsDropdownOpen(false);
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
if (isColumnsDropdownOpen) {
|
|
1175
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
1176
|
+
}
|
|
1177
|
+
return () => {
|
|
1178
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
1179
|
+
};
|
|
1180
|
+
}, [isColumnsDropdownOpen]);
|
|
1181
|
+
const handleShowAllColumns = async () => {
|
|
1182
|
+
var _a;
|
|
1183
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1184
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1185
|
+
const updatedCustomCols = customizableColumns.map((col) => __spreadProps(__spreadValues({}, col), {
|
|
1186
|
+
isHidden: false
|
|
1187
|
+
}));
|
|
1188
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1189
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1190
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1191
|
+
if (targetTableId && executeAction) {
|
|
1192
|
+
try {
|
|
1193
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1194
|
+
tableId: targetTableId,
|
|
1195
|
+
tableMetaId: targetTableId,
|
|
1196
|
+
columns: fullUpdatedColumns
|
|
1197
|
+
});
|
|
1198
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1199
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1200
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1201
|
+
}
|
|
1202
|
+
} catch (err) {
|
|
1203
|
+
console.error("[TableBlock] Failed to save show all columns:", err);
|
|
1204
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D4\u05E6\u05D2\u05EA \u05DB\u05DC \u05D4\u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1205
|
+
}
|
|
1206
|
+
}
|
|
1207
|
+
};
|
|
1208
|
+
const handleToggleColumnVisibility = async (colName, isVisible) => {
|
|
1209
|
+
var _a;
|
|
1210
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1211
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1212
|
+
const updatedCustomCols = customizableColumns.map((col) => {
|
|
1213
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1214
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1215
|
+
const isProtected = isRequired || isUnique;
|
|
1216
|
+
if (col.name === colName) {
|
|
1217
|
+
if (isProtected) {
|
|
1218
|
+
return __spreadProps(__spreadValues({}, col), { isHidden: false });
|
|
1219
|
+
}
|
|
1220
|
+
return __spreadProps(__spreadValues({}, col), { isHidden: !isVisible });
|
|
1221
|
+
}
|
|
1222
|
+
return __spreadProps(__spreadValues({}, col), {
|
|
1223
|
+
isHidden: isProtected ? false : Boolean(col.isHidden)
|
|
1224
|
+
});
|
|
1225
|
+
});
|
|
1226
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1227
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1228
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1229
|
+
if (targetTableId && executeAction) {
|
|
1230
|
+
try {
|
|
1231
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1232
|
+
tableId: targetTableId,
|
|
1233
|
+
tableMetaId: targetTableId,
|
|
1234
|
+
columns: fullUpdatedColumns
|
|
1235
|
+
});
|
|
1236
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1237
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1238
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1239
|
+
}
|
|
1240
|
+
} catch (err) {
|
|
1241
|
+
console.error("[TableBlock] Failed to save column visibility:", err);
|
|
1242
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05D4\u05E1\u05EA\u05E8\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
};
|
|
1246
|
+
const [draggedColName, setDraggedColName] = useState4(null);
|
|
1247
|
+
const [dragOverColName, setDragOverColName] = useState4(null);
|
|
1248
|
+
const handleColumnReorder = async (draggedName, dropTargetName) => {
|
|
1249
|
+
var _a;
|
|
1250
|
+
if (draggedName === dropTargetName) return;
|
|
1251
|
+
const currentCustomCols = [...customizableColumns];
|
|
1252
|
+
const fromIndex = currentCustomCols.findIndex((c) => c.name === draggedName);
|
|
1253
|
+
const toIndex = currentCustomCols.findIndex((c) => c.name === dropTargetName);
|
|
1254
|
+
if (fromIndex === -1 || toIndex === -1 || fromIndex === toIndex) return;
|
|
1255
|
+
const [draggedItem] = currentCustomCols.splice(fromIndex, 1);
|
|
1256
|
+
currentCustomCols.splice(toIndex, 0, draggedItem);
|
|
1257
|
+
const updatedCustomCols = currentCustomCols.map((col, idx) => __spreadProps(__spreadValues({}, col), {
|
|
1258
|
+
order: idx
|
|
1259
|
+
}));
|
|
1260
|
+
const systemFields = ["_id", "createdAt", "updatedAt", "orgId", "tableId"];
|
|
1261
|
+
const systemCols = (localColumns || []).filter((c) => systemFields.includes(c.name));
|
|
1262
|
+
const fullUpdatedColumns = [...systemCols, ...updatedCustomCols];
|
|
1263
|
+
setLocalColumns(fullUpdatedColumns);
|
|
1264
|
+
const targetTableId = (schema == null ? void 0 : schema.tableMetaId) || (schema == null ? void 0 : schema.tableId) || (schema == null ? void 0 : schema.id);
|
|
1265
|
+
if (targetTableId && executeAction) {
|
|
1266
|
+
try {
|
|
1267
|
+
const res = await executeAction("UPDATE_TABLE_COLUMNS", {
|
|
1268
|
+
tableId: targetTableId,
|
|
1269
|
+
tableMetaId: targetTableId,
|
|
1270
|
+
columns: fullUpdatedColumns
|
|
1271
|
+
});
|
|
1272
|
+
const returnedCols = (res == null ? void 0 : res.columns) || ((_a = res == null ? void 0 : res.data) == null ? void 0 : _a.columns);
|
|
1273
|
+
if (returnedCols && Array.isArray(returnedCols)) {
|
|
1274
|
+
setLocalColumns((prev) => mergeColumnDefs(prev, returnedCols));
|
|
1275
|
+
}
|
|
1276
|
+
} catch (err) {
|
|
1277
|
+
console.error("[TableBlock] Failed to save column reorder:", err);
|
|
1278
|
+
showError((err == null ? void 0 : err.message) || String(err), "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05D3\u05DB\u05D5\u05DF \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D5\u05EA");
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
};
|
|
1033
1282
|
const generateTempId = () => `temp_${Math.random().toString(36).substr(2, 9)}`;
|
|
1034
1283
|
const handleAddRow = () => {
|
|
1035
1284
|
const defaultData = {};
|
|
@@ -1059,6 +1308,34 @@ function TableBlockClient({
|
|
|
1059
1308
|
setData((prev) => [newRow, ...prev]);
|
|
1060
1309
|
setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
|
|
1061
1310
|
};
|
|
1311
|
+
const handleDuplicateRow = () => {
|
|
1312
|
+
if (selectedIds.size !== 1) return;
|
|
1313
|
+
const targetId = Array.from(selectedIds)[0];
|
|
1314
|
+
const sourceRow = data.find((r) => r.id === targetId);
|
|
1315
|
+
if (!sourceRow) return;
|
|
1316
|
+
const uniqueColNames = new Set(
|
|
1317
|
+
(localColumns || []).filter((c) => c.isUnique === true || String(c.isUnique) === "true").map((c) => c.name)
|
|
1318
|
+
);
|
|
1319
|
+
const fieldsToScrub = /* @__PURE__ */ new Set(["id", "_id", "createdAt", "updatedAt", "created_at", "updated_at"]);
|
|
1320
|
+
const clonedData = __spreadValues({}, sourceRow.data);
|
|
1321
|
+
Object.keys(clonedData).forEach((key) => {
|
|
1322
|
+
var _a;
|
|
1323
|
+
if (fieldsToScrub.has(key) || uniqueColNames.has(key)) {
|
|
1324
|
+
const col = (localColumns || []).find((c) => c.name === key);
|
|
1325
|
+
const typeUpper = (_a = col == null ? void 0 : col.type) == null ? void 0 : _a.toUpperCase();
|
|
1326
|
+
if (typeUpper === "NUMBER" || typeUpper === "CURRENCY") {
|
|
1327
|
+
clonedData[key] = 0;
|
|
1328
|
+
} else if (typeUpper === "BOOLEAN") {
|
|
1329
|
+
clonedData[key] = false;
|
|
1330
|
+
} else {
|
|
1331
|
+
clonedData[key] = "";
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
});
|
|
1335
|
+
const newRow = { id: generateTempId(), data: clonedData };
|
|
1336
|
+
setData((prev) => [newRow, ...prev]);
|
|
1337
|
+
setDirty((prev) => __spreadProps(__spreadValues({}, prev), { added: [newRow, ...prev.added] }));
|
|
1338
|
+
};
|
|
1062
1339
|
const handleCellChange = (rowId, colName, value) => {
|
|
1063
1340
|
setData((prev) => prev.map(
|
|
1064
1341
|
(row) => row.id === rowId ? __spreadProps(__spreadValues({}, row), { data: __spreadProps(__spreadValues({}, row.data), { [colName]: value }) }) : row
|
|
@@ -1279,6 +1556,7 @@ function TableBlockClient({
|
|
|
1279
1556
|
return next;
|
|
1280
1557
|
});
|
|
1281
1558
|
setDirty({ added: [], modified: {}, deleted: [] });
|
|
1559
|
+
await refetchTableData();
|
|
1282
1560
|
setIsSaveSuccess(true);
|
|
1283
1561
|
setTimeout(() => {
|
|
1284
1562
|
setIsSaveSuccess(false);
|
|
@@ -1302,12 +1580,30 @@ function TableBlockClient({
|
|
|
1302
1580
|
}, [data, searchQuery]);
|
|
1303
1581
|
const isUpdatingActive = Boolean(isUpdating || isSaving);
|
|
1304
1582
|
const errorMessage = error ? typeof error === "string" ? error : error.message || String(error) : null;
|
|
1583
|
+
const columnTotals = useMemo2(() => {
|
|
1584
|
+
const totals = {};
|
|
1585
|
+
if (!showSummary) return totals;
|
|
1586
|
+
filteredColumns.forEach((col) => {
|
|
1587
|
+
var _a;
|
|
1588
|
+
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1589
|
+
if (typeUpper === "CURRENCY" || typeUpper === "NUMBER") {
|
|
1590
|
+
const sum = filteredData.reduce((acc, row) => {
|
|
1591
|
+
var _a2;
|
|
1592
|
+
const val = (_a2 = row.data) == null ? void 0 : _a2[col.name];
|
|
1593
|
+
const num = Number(val);
|
|
1594
|
+
return acc + (isNaN(num) ? 0 : num);
|
|
1595
|
+
}, 0);
|
|
1596
|
+
totals[col.name] = sum;
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
return totals;
|
|
1600
|
+
}, [filteredData, filteredColumns, showSummary]);
|
|
1305
1601
|
return /* @__PURE__ */ jsxs5(
|
|
1306
1602
|
"div",
|
|
1307
1603
|
{
|
|
1308
1604
|
id: componentId,
|
|
1309
1605
|
"data-testid": dataTestId || (componentId ? `table-block-${componentId}` : void 0),
|
|
1310
|
-
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs overflow-hidden ${className}`,
|
|
1606
|
+
className: `flex flex-col w-full bg-white border border-slate-200 rounded-xl shadow-xs min-h-[350px] overflow-hidden ${className}`,
|
|
1311
1607
|
dir: "rtl",
|
|
1312
1608
|
children: [
|
|
1313
1609
|
errorMessage && /* @__PURE__ */ jsx5("div", { className: "p-3 bg-rose-50 border-b border-rose-200 text-rose-700 text-sm flex items-center justify-between", children: /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
@@ -1327,6 +1623,16 @@ function TableBlockClient({
|
|
|
1327
1623
|
children: /* @__PURE__ */ jsx5("svg", { className: "w-4.5 h-4.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5", d: "M12 4v16m8-8H4" }) })
|
|
1328
1624
|
}
|
|
1329
1625
|
),
|
|
1626
|
+
/* @__PURE__ */ jsx5(
|
|
1627
|
+
"button",
|
|
1628
|
+
{
|
|
1629
|
+
onClick: handleDuplicateRow,
|
|
1630
|
+
disabled: isLoading || isUpdatingActive || selectedIds.size !== 1,
|
|
1631
|
+
className: "w-9 h-9 bg-blue-50 hover:bg-blue-100 border border-blue-200 text-blue-700 rounded-lg shadow-2xs flex items-center justify-center transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
1632
|
+
title: "\u05E9\u05DB\u05E4\u05DC \u05E9\u05D5\u05E8\u05D4 \u05E0\u05D1\u05D7\u05E8\u05EA",
|
|
1633
|
+
children: /* @__PURE__ */ jsx5(Copy2, { className: "w-4 h-4 text-blue-600 shrink-0" })
|
|
1634
|
+
}
|
|
1635
|
+
),
|
|
1330
1636
|
/* @__PURE__ */ jsxs5(
|
|
1331
1637
|
"button",
|
|
1332
1638
|
{
|
|
@@ -1340,6 +1646,112 @@ function TableBlockClient({
|
|
|
1340
1646
|
]
|
|
1341
1647
|
}
|
|
1342
1648
|
),
|
|
1649
|
+
/* @__PURE__ */ jsxs5(
|
|
1650
|
+
"button",
|
|
1651
|
+
{
|
|
1652
|
+
onClick: toggleSummary,
|
|
1653
|
+
disabled: isLoading || isUpdatingActive,
|
|
1654
|
+
className: `h-9 px-3 border font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer ${showSummary ? "bg-indigo-50 border-indigo-200 text-indigo-700 hover:bg-indigo-100" : "bg-white border-slate-300 text-slate-700 hover:bg-slate-100"}`,
|
|
1655
|
+
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E9\u05D5\u05E8\u05EA \u05E1\u05D9\u05DB\u05D5\u05DD",
|
|
1656
|
+
children: [
|
|
1657
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M4 6h16M4 10h16M4 14h16M4 18h16" }) }),
|
|
1658
|
+
/* @__PURE__ */ jsx5("span", { className: "hidden sm:inline", children: "\u05E1\u05DB\u05D9\u05DE\u05D4" })
|
|
1659
|
+
]
|
|
1660
|
+
}
|
|
1661
|
+
),
|
|
1662
|
+
/* @__PURE__ */ jsxs5("div", { className: "relative", ref: dropdownRef, children: [
|
|
1663
|
+
/* @__PURE__ */ jsxs5(
|
|
1664
|
+
"button",
|
|
1665
|
+
{
|
|
1666
|
+
onClick: () => setIsColumnsDropdownOpen((prev) => !prev),
|
|
1667
|
+
disabled: isLoading || isUpdatingActive,
|
|
1668
|
+
className: "h-9 px-3 bg-white hover:bg-slate-100 border border-slate-300 text-slate-700 font-semibold rounded-lg shadow-2xs flex items-center gap-1.5 text-xs transition-all disabled:opacity-40 disabled:pointer-events-none cursor-pointer",
|
|
1669
|
+
title: "\u05D4\u05E6\u05D2/\u05D4\u05E1\u05EA\u05E8 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA",
|
|
1670
|
+
children: [
|
|
1671
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-slate-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2" }) }),
|
|
1672
|
+
/* @__PURE__ */ jsx5("svg", { className: `w-3.5 h-3.5 text-slate-500 transition-transform ${isColumnsDropdownOpen ? "rotate-180" : ""}`, fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M19 9l-7 7-7-7" }) })
|
|
1673
|
+
]
|
|
1674
|
+
}
|
|
1675
|
+
),
|
|
1676
|
+
isColumnsDropdownOpen && /* @__PURE__ */ jsxs5("div", { className: "absolute right-0 top-full mt-1.5 w-56 bg-white border border-slate-200 rounded-xl shadow-xl z-50 p-1.5 dir-rtl animate-in fade-in slide-in-from-top-2 duration-150", children: [
|
|
1677
|
+
/* @__PURE__ */ jsxs5("div", { className: "px-2 py-1.5 text-xs font-bold text-slate-500 border-b border-slate-100 mb-1 flex items-center justify-between", children: [
|
|
1678
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1679
|
+
/* @__PURE__ */ jsx5("span", { children: "\u05D4\u05E6\u05D2\u05EA \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA" }),
|
|
1680
|
+
/* @__PURE__ */ jsxs5("span", { className: "text-[10px] font-normal text-slate-400", children: [
|
|
1681
|
+
"(",
|
|
1682
|
+
customizableColumns.filter((c) => !c.isHidden).length,
|
|
1683
|
+
"/",
|
|
1684
|
+
customizableColumns.length,
|
|
1685
|
+
")"
|
|
1686
|
+
] })
|
|
1687
|
+
] }),
|
|
1688
|
+
/* @__PURE__ */ jsx5(
|
|
1689
|
+
"button",
|
|
1690
|
+
{
|
|
1691
|
+
type: "button",
|
|
1692
|
+
onClick: handleShowAllColumns,
|
|
1693
|
+
className: "text-xs text-brand hover:text-brand-hover font-semibold hover:underline cursor-pointer",
|
|
1694
|
+
children: "\u05D4\u05E6\u05D2 \u05D4\u05DB\u05DC"
|
|
1695
|
+
}
|
|
1696
|
+
)
|
|
1697
|
+
] }),
|
|
1698
|
+
/* @__PURE__ */ jsx5("div", { className: "max-h-60 overflow-y-auto space-y-0.5", children: customizableColumns.map((col) => {
|
|
1699
|
+
const isRequired = col.isRequired === true || String(col.isRequired) === "true";
|
|
1700
|
+
const isUnique = col.isUnique === true || String(col.isUnique) === "true";
|
|
1701
|
+
const isProtected = isRequired || isUnique;
|
|
1702
|
+
const isVisible = !col.isHidden;
|
|
1703
|
+
let protectedExplanation = "";
|
|
1704
|
+
if (isRequired && isUnique) {
|
|
1705
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 \u05D5\u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1706
|
+
} else if (isRequired) {
|
|
1707
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1708
|
+
} else if (isUnique) {
|
|
1709
|
+
protectedExplanation = "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9 - \u05DC\u05D0 \u05E0\u05D9\u05EA\u05DF \u05DC\u05D4\u05D5\u05E8\u05D9\u05D3 \u05E2\u05DE\u05D5\u05D3\u05D4 \u05D6\u05D5 \u05DE\u05D4\u05EA\u05E6\u05D5\u05D2\u05D4";
|
|
1710
|
+
}
|
|
1711
|
+
const badgeLabel = isRequired && isUnique ? "\u05D7\u05D5\u05D1\u05D4 + \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9" : isRequired ? "\u05E9\u05D3\u05D4 \u05D7\u05D5\u05D1\u05D4" : "\u05E9\u05D3\u05D4 \u05D9\u05D9\u05D7\u05D5\u05D3\u05D9";
|
|
1712
|
+
return /* @__PURE__ */ jsxs5(
|
|
1713
|
+
"div",
|
|
1714
|
+
{
|
|
1715
|
+
onClick: () => {
|
|
1716
|
+
if (!isProtected) {
|
|
1717
|
+
handleToggleColumnVisibility(col.name, !isVisible);
|
|
1718
|
+
}
|
|
1719
|
+
},
|
|
1720
|
+
title: isProtected ? protectedExplanation : void 0,
|
|
1721
|
+
className: `group flex items-center justify-between px-2.5 py-1.5 rounded-lg text-xs transition-colors select-none ${isProtected ? "opacity-75 bg-slate-50 border border-slate-100/70 cursor-not-allowed" : "hover:bg-slate-100 active:bg-slate-200 cursor-pointer"}`,
|
|
1722
|
+
children: [
|
|
1723
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
1724
|
+
/* @__PURE__ */ jsx5(
|
|
1725
|
+
"input",
|
|
1726
|
+
{
|
|
1727
|
+
type: "checkbox",
|
|
1728
|
+
checked: isVisible,
|
|
1729
|
+
disabled: isProtected,
|
|
1730
|
+
onChange: () => {
|
|
1731
|
+
},
|
|
1732
|
+
className: "w-3.5 h-3.5 rounded border-slate-300 text-brand focus:ring-brand/20 cursor-pointer disabled:cursor-not-allowed disabled:opacity-60"
|
|
1733
|
+
}
|
|
1734
|
+
),
|
|
1735
|
+
/* @__PURE__ */ jsx5("span", { className: `font-medium truncate ${isProtected ? "text-slate-500" : "text-slate-700"}`, children: col.name })
|
|
1736
|
+
] }),
|
|
1737
|
+
isProtected && /* @__PURE__ */ jsxs5(
|
|
1738
|
+
"div",
|
|
1739
|
+
{
|
|
1740
|
+
className: "flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] font-semibold bg-amber-50 text-amber-800 border border-amber-200/80 cursor-help",
|
|
1741
|
+
title: protectedExplanation,
|
|
1742
|
+
children: [
|
|
1743
|
+
/* @__PURE__ */ jsx5("svg", { className: "w-3 h-3 text-amber-600 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: "2.2", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z" }) }),
|
|
1744
|
+
/* @__PURE__ */ jsx5("span", { children: badgeLabel })
|
|
1745
|
+
]
|
|
1746
|
+
}
|
|
1747
|
+
)
|
|
1748
|
+
]
|
|
1749
|
+
},
|
|
1750
|
+
col.name
|
|
1751
|
+
);
|
|
1752
|
+
}) })
|
|
1753
|
+
] })
|
|
1754
|
+
] }),
|
|
1343
1755
|
/* @__PURE__ */ jsx5("div", { className: "h-5 w-px bg-slate-300 mx-1 hidden sm:block" }),
|
|
1344
1756
|
/* @__PURE__ */ jsxs5("div", { className: "relative flex-1 sm:w-64 max-w-xs", children: [
|
|
1345
1757
|
/* @__PURE__ */ jsx5(
|
|
@@ -1352,7 +1764,16 @@ function TableBlockClient({
|
|
|
1352
1764
|
className: "w-full h-9 px-3 pr-9 text-xs border border-slate-300 rounded-lg bg-white shadow-2xs focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 text-slate-800 disabled:opacity-50"
|
|
1353
1765
|
}
|
|
1354
1766
|
),
|
|
1355
|
-
|
|
1767
|
+
searchQuery ? /* @__PURE__ */ jsx5(
|
|
1768
|
+
"button",
|
|
1769
|
+
{
|
|
1770
|
+
type: "button",
|
|
1771
|
+
onClick: () => setSearchQuery(""),
|
|
1772
|
+
className: "absolute right-2.5 top-2.5 text-slate-400 hover:text-slate-600 transition-colors p-0.5 rounded-full hover:bg-slate-100 cursor-pointer",
|
|
1773
|
+
title: "Clear search",
|
|
1774
|
+
children: /* @__PURE__ */ jsx5(X4, { className: "w-3.5 h-3.5" })
|
|
1775
|
+
}
|
|
1776
|
+
) : /* @__PURE__ */ jsx5("svg", { className: "w-4 h-4 text-slate-400 absolute right-2.5 top-2.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) })
|
|
1356
1777
|
] })
|
|
1357
1778
|
] }),
|
|
1358
1779
|
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3", children: [
|
|
@@ -1374,14 +1795,14 @@ function TableBlockClient({
|
|
|
1374
1795
|
)
|
|
1375
1796
|
] })
|
|
1376
1797
|
] }),
|
|
1377
|
-
/* @__PURE__ */ jsxs5("div", { className:
|
|
1798
|
+
/* @__PURE__ */ jsxs5("div", { className: `overflow-x-auto relative min-h-[260px] flex-1 transition-opacity duration-200 ${isMounted ? "opacity-100" : "opacity-0"}`, children: [
|
|
1378
1799
|
isLoading && /* @__PURE__ */ jsxs5("div", { className: "absolute inset-0 bg-white/80 backdrop-blur-xs z-20 flex flex-col items-center justify-center gap-2", children: [
|
|
1379
1800
|
/* @__PURE__ */ jsx5("div", { className: "w-6 h-6 border-2 border-brand border-t-transparent rounded-full animate-spin" }),
|
|
1380
1801
|
/* @__PURE__ */ jsx5("span", { className: "text-sm font-medium text-slate-600", children: "\u05D8\u05D5\u05E2\u05DF \u05E0\u05EA\u05D5\u05E0\u05D9\u05DD..." })
|
|
1381
1802
|
] }),
|
|
1382
|
-
/* @__PURE__ */ jsxs5("table", { className: "w-full text-sm text-right border-collapse", children: [
|
|
1803
|
+
/* @__PURE__ */ jsxs5("table", { className: "w-full text-sm text-right border-collapse table-auto", children: [
|
|
1383
1804
|
/* @__PURE__ */ jsx5("thead", { className: "bg-slate-100/80 text-slate-700 sticky top-0 z-10", children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1384
|
-
/* @__PURE__ */ jsx5("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center", children: /* @__PURE__ */ jsx5(
|
|
1805
|
+
/* @__PURE__ */ jsx5("th", { className: "border-b border-l border-slate-200 p-2.5 w-10 text-center shrink-0", style: { width: 50, minWidth: 50, maxWidth: 50 }, children: /* @__PURE__ */ jsx5(
|
|
1385
1806
|
"input",
|
|
1386
1807
|
{
|
|
1387
1808
|
type: "checkbox",
|
|
@@ -1391,9 +1812,79 @@ function TableBlockClient({
|
|
|
1391
1812
|
className: "w-4 h-4 rounded border-slate-300 text-brand"
|
|
1392
1813
|
}
|
|
1393
1814
|
) }),
|
|
1394
|
-
filteredColumns.map((col) =>
|
|
1815
|
+
filteredColumns.map((col) => {
|
|
1816
|
+
const isDragging = draggedColName === col.name;
|
|
1817
|
+
const isDragOver = dragOverColName === col.name;
|
|
1818
|
+
const currentWidth = columnWidths[col.name] || 200;
|
|
1819
|
+
return /* @__PURE__ */ jsxs5(
|
|
1820
|
+
"th",
|
|
1821
|
+
{
|
|
1822
|
+
style: { width: currentWidth, minWidth: currentWidth, maxWidth: currentWidth },
|
|
1823
|
+
draggable: !isLoading && !isUpdatingActive,
|
|
1824
|
+
onDragStart: (e) => {
|
|
1825
|
+
e.dataTransfer.setData("text/plain", col.name);
|
|
1826
|
+
e.dataTransfer.effectAllowed = "move";
|
|
1827
|
+
setDraggedColName(col.name);
|
|
1828
|
+
},
|
|
1829
|
+
onDragOver: (e) => {
|
|
1830
|
+
e.preventDefault();
|
|
1831
|
+
e.dataTransfer.dropEffect = "move";
|
|
1832
|
+
if (dragOverColName !== col.name) {
|
|
1833
|
+
setDragOverColName(col.name);
|
|
1834
|
+
}
|
|
1835
|
+
},
|
|
1836
|
+
onDragLeave: () => {
|
|
1837
|
+
if (dragOverColName === col.name) {
|
|
1838
|
+
setDragOverColName(null);
|
|
1839
|
+
}
|
|
1840
|
+
},
|
|
1841
|
+
onDrop: (e) => {
|
|
1842
|
+
e.preventDefault();
|
|
1843
|
+
if (draggedColName && draggedColName !== col.name) {
|
|
1844
|
+
handleColumnReorder(draggedColName, col.name);
|
|
1845
|
+
}
|
|
1846
|
+
setDraggedColName(null);
|
|
1847
|
+
setDragOverColName(null);
|
|
1848
|
+
},
|
|
1849
|
+
onDragEnd: () => {
|
|
1850
|
+
setDraggedColName(null);
|
|
1851
|
+
setDragOverColName(null);
|
|
1852
|
+
},
|
|
1853
|
+
className: `relative border-b border-l border-slate-200 px-4 py-2.5 font-semibold text-slate-700 whitespace-nowrap select-none cursor-grab active:cursor-grabbing transition-colors ${isDragging ? "opacity-40 bg-slate-200 border-dashed border-2 border-brand" : ""} ${isDragOver ? "bg-blue-50 border-r-4 border-r-brand text-brand font-bold" : "hover:bg-slate-200/60"}`,
|
|
1854
|
+
children: [
|
|
1855
|
+
/* @__PURE__ */ jsx5(
|
|
1856
|
+
"div",
|
|
1857
|
+
{
|
|
1858
|
+
onMouseDown: (e) => {
|
|
1859
|
+
e.preventDefault();
|
|
1860
|
+
e.stopPropagation();
|
|
1861
|
+
setResizingCol({ name: col.name, startWidth: currentWidth, startX: e.clientX });
|
|
1862
|
+
},
|
|
1863
|
+
className: "absolute left-0 top-0 bottom-0 w-1.5 cursor-col-resize hover:bg-brand active:bg-brand-hover z-20",
|
|
1864
|
+
title: "\u05E9\u05E0\u05D4 \u05D2\u05D5\u05D3\u05DC \u05E2\u05DE\u05D5\u05D3\u05D4"
|
|
1865
|
+
}
|
|
1866
|
+
),
|
|
1867
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between gap-2 group overflow-hidden", title: "\u05D2\u05E8\u05D5\u05E8 \u05DC\u05E9\u05D9\u05E0\u05D5\u05D9 \u05E1\u05D3\u05E8 \u05D4\u05E2\u05DE\u05D5\u05D3\u05D4", children: [
|
|
1868
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: col.name }),
|
|
1869
|
+
/* @__PURE__ */ jsx5(
|
|
1870
|
+
"svg",
|
|
1871
|
+
{
|
|
1872
|
+
className: "w-3.5 h-3.5 text-slate-400 opacity-40 group-hover:opacity-100 transition-opacity shrink-0 cursor-grab",
|
|
1873
|
+
fill: "none",
|
|
1874
|
+
viewBox: "0 0 24 24",
|
|
1875
|
+
stroke: "currentColor",
|
|
1876
|
+
children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2", d: "M8 9h.01M8 15h.01M16 9h.01M16 15h.01" })
|
|
1877
|
+
}
|
|
1878
|
+
)
|
|
1879
|
+
] })
|
|
1880
|
+
]
|
|
1881
|
+
},
|
|
1882
|
+
col.name
|
|
1883
|
+
);
|
|
1884
|
+
}),
|
|
1885
|
+
/* @__PURE__ */ jsx5("th", { className: "w-full min-w-[50px] border-b border-slate-200 pointer-events-none" })
|
|
1395
1886
|
] }) }),
|
|
1396
|
-
/* @__PURE__ */ jsx5("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: filteredColumns.length +
|
|
1887
|
+
/* @__PURE__ */ jsx5("tbody", { className: "bg-white", children: (isStateEmpty || filteredData.length === 0) && !isLoading ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsx5("td", { colSpan: filteredColumns.length + 2, className: "text-center py-12 text-slate-400", children: /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center gap-2", children: [
|
|
1397
1888
|
/* @__PURE__ */ jsx5("svg", { className: "w-8 h-8 text-slate-300", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx5("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M20 13V6a2 2 0 00-2-2H6a2 2 0 00-2 2v7m16 0v5a2 2 0 01-2 2H6a2 2 0 01-2-2v-5m16 0h-2.586a1 1 0 00-.707.293l-2.414 2.414a1 1 0 01-.707.293h-3.172a1 1 0 01-.707-.293l-2.414-2.414A1 1 0 006.586 13H4" }) }),
|
|
1398
1889
|
/* @__PURE__ */ jsx5("span", { children: "\u05D0\u05D9\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DC\u05D4\u05E6\u05D2\u05D4." })
|
|
1399
1890
|
] }) }) }) : filteredData.map((row) => /* @__PURE__ */ jsxs5("tr", { className: "hover:bg-blue-50/30 transition-colors group", children: [
|
|
@@ -1439,8 +1930,82 @@ function TableBlockClient({
|
|
|
1439
1930
|
}
|
|
1440
1931
|
}
|
|
1441
1932
|
) }, col.name);
|
|
1442
|
-
})
|
|
1443
|
-
|
|
1933
|
+
}),
|
|
1934
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-white pointer-events-none" })
|
|
1935
|
+
] }, row.id)) }),
|
|
1936
|
+
showSummary && filteredData.length > 0 && /* @__PURE__ */ jsx5("tfoot", { className: "bg-slate-50 border-t-2 border-slate-300 sticky bottom-0 z-10 shadow-[0_-2px_4px_rgba(0,0,0,0.02)]", children: /* @__PURE__ */ jsxs5("tr", { children: [
|
|
1937
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-1.5 text-center font-bold text-slate-600 text-xs", children: '\u05E1\u05D4"\u05DB' }),
|
|
1938
|
+
filteredColumns.map((col) => {
|
|
1939
|
+
var _a;
|
|
1940
|
+
const typeUpper = (_a = col.type) == null ? void 0 : _a.toUpperCase();
|
|
1941
|
+
const isNumeric = typeUpper === "CURRENCY" || typeUpper === "NUMBER";
|
|
1942
|
+
const total = columnTotals[col.name];
|
|
1943
|
+
let displayVal = "";
|
|
1944
|
+
if (isNumeric && total !== void 0) {
|
|
1945
|
+
displayVal = new Intl.NumberFormat("en-US").format(total);
|
|
1946
|
+
if (typeUpper === "CURRENCY") {
|
|
1947
|
+
const symbol = getCurrencySymbol(col.currencySymbol);
|
|
1948
|
+
displayVal = symbol ? `${symbol} ${displayVal}` : displayVal;
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
return /* @__PURE__ */ jsx5("td", { className: "border-b border-l border-slate-200 p-2 text-sm font-semibold text-slate-700 bg-slate-50 relative", children: isNumeric && /* @__PURE__ */ jsx5("div", { className: "flex items-center text-right justify-start", children: /* @__PURE__ */ jsx5("span", { className: "truncate", children: displayVal }) }) }, col.name);
|
|
1952
|
+
}),
|
|
1953
|
+
/* @__PURE__ */ jsx5("td", { className: "border-b border-slate-200 bg-slate-50 pointer-events-none" })
|
|
1954
|
+
] }) })
|
|
1955
|
+
] })
|
|
1956
|
+
] }),
|
|
1957
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 px-4 py-3 bg-slate-50 border-t border-slate-200 text-xs text-slate-600 rounded-b-xl", children: [
|
|
1958
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1959
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium text-slate-700", children: "\u05E9\u05D5\u05E8\u05D5\u05EA \u05DC\u05E2\u05DE\u05D5\u05D3:" }),
|
|
1960
|
+
/* @__PURE__ */ jsxs5(
|
|
1961
|
+
"select",
|
|
1962
|
+
{
|
|
1963
|
+
value: limit,
|
|
1964
|
+
onChange: (e) => handleLimitChange(Number(e.target.value)),
|
|
1965
|
+
disabled: isLoading || isUpdatingActive,
|
|
1966
|
+
className: "bg-white border border-slate-300 rounded-lg px-2.5 py-1 text-slate-700 font-semibold shadow-2xs cursor-pointer focus:outline-none focus:ring-2 focus:ring-brand disabled:opacity-50",
|
|
1967
|
+
children: [
|
|
1968
|
+
/* @__PURE__ */ jsx5("option", { value: 20, children: "20" }),
|
|
1969
|
+
/* @__PURE__ */ jsx5("option", { value: 50, children: "50" }),
|
|
1970
|
+
/* @__PURE__ */ jsx5("option", { value: 100, children: "100" })
|
|
1971
|
+
]
|
|
1972
|
+
}
|
|
1973
|
+
)
|
|
1974
|
+
] }),
|
|
1975
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-4", children: [
|
|
1976
|
+
/* @__PURE__ */ jsxs5("span", { className: "font-medium text-slate-600", children: [
|
|
1977
|
+
"\u05E2\u05DE\u05D5\u05D3 ",
|
|
1978
|
+
/* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: page }),
|
|
1979
|
+
" \u05DE\u05EA\u05D5\u05DA ",
|
|
1980
|
+
/* @__PURE__ */ jsx5("strong", { className: "text-slate-900", children: totalPages || 1 }),
|
|
1981
|
+
totalRecords > 0 && /* @__PURE__ */ jsxs5("span", { className: "text-slate-500 font-normal", children: [
|
|
1982
|
+
" (",
|
|
1983
|
+
totalRecords,
|
|
1984
|
+
' \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D1\u05E1\u05D4"\u05DB)'
|
|
1985
|
+
] })
|
|
1986
|
+
] }),
|
|
1987
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-1.5", children: [
|
|
1988
|
+
/* @__PURE__ */ jsx5(
|
|
1989
|
+
"button",
|
|
1990
|
+
{
|
|
1991
|
+
onClick: handlePrevPage,
|
|
1992
|
+
disabled: page <= 1 || isLoading || isUpdatingActive,
|
|
1993
|
+
className: "px-3 py-1.5 bg-white border border-slate-300 hover:bg-slate-100 font-semibold text-slate-700 rounded-lg shadow-2xs disabled:opacity-40 disabled:pointer-events-none transition-colors cursor-pointer",
|
|
1994
|
+
title: "\u05E2\u05DE\u05D5\u05D3 \u05E7\u05D5\u05D3\u05DD",
|
|
1995
|
+
children: "\u05D4\u05E7\u05D5\u05D3\u05DD"
|
|
1996
|
+
}
|
|
1997
|
+
),
|
|
1998
|
+
/* @__PURE__ */ jsx5(
|
|
1999
|
+
"button",
|
|
2000
|
+
{
|
|
2001
|
+
onClick: handleNextPage,
|
|
2002
|
+
disabled: page >= totalPages || isLoading || isUpdatingActive,
|
|
2003
|
+
className: "px-3 py-1.5 bg-white border border-slate-300 hover:bg-slate-100 font-semibold text-slate-700 rounded-lg shadow-2xs disabled:opacity-40 disabled:pointer-events-none transition-colors cursor-pointer",
|
|
2004
|
+
title: "\u05E2\u05DE\u05D5\u05D3 \u05D4\u05D1\u05D0",
|
|
2005
|
+
children: "\u05D4\u05D1\u05D0"
|
|
2006
|
+
}
|
|
2007
|
+
)
|
|
2008
|
+
] })
|
|
1444
2009
|
] })
|
|
1445
2010
|
] })
|
|
1446
2011
|
]
|