@agilo/medusa-analytics-plugin 1.0.0 → 1.2.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,10 +7,10 @@ const icons = require("@medusajs/icons");
7
7
  const lucideReact = require("lucide-react");
8
8
  const dateFns = require("date-fns");
9
9
  const reactAriaComponents = require("react-aria-components");
10
+ const reactRouterDom = require("react-router-dom");
10
11
  const recharts = require("recharts");
11
12
  const clsx = require("clsx");
12
13
  const tailwindMerge = require("tailwind-merge");
13
- const reactRouterDom = require("react-router-dom");
14
14
  const reactQuery = require("@tanstack/react-query");
15
15
  function _interopNamespace(e) {
16
16
  if (e && e.__esModule) return e;
@@ -675,68 +675,65 @@ const LineChart = ({
675
675
  const isDark = useDarkMode();
676
676
  const isSingleDataPoint = data && data.length === 1;
677
677
  if (isSingleDataPoint) {
678
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
679
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-muted mb-2", children: "Single day selected - showing as bar chart for better visibility" }) }),
680
- /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { aspect: 16 / 9, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, margin: { left: 20 }, children: [
681
- /* @__PURE__ */ jsxRuntime.jsx(
682
- recharts.CartesianGrid,
683
- {
684
- strokeDasharray: "3 3",
685
- stroke: isDark ? "#374151" : "#E5E7EB"
686
- }
687
- ),
688
- /* @__PURE__ */ jsxRuntime.jsx(
689
- recharts.XAxis,
690
- {
691
- dataKey: xAxisDataKey,
692
- tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
693
- axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
694
- tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
695
- tickMargin: 10
696
- }
697
- ),
698
- /* @__PURE__ */ jsxRuntime.jsx(
699
- recharts.YAxis,
700
- {
701
- tickFormatter: yAxisTickFormatter,
702
- allowDecimals: false,
703
- tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
704
- axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
705
- tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" }
706
- }
707
- ),
708
- /* @__PURE__ */ jsxRuntime.jsx(
709
- recharts.Tooltip,
710
- {
711
- cursor: {
712
- fill: isDark ? "rgba(55, 65, 81, 0.2)" : "rgba(243, 244, 246, 0.5)"
713
- },
714
- formatter: (value) => yAxisTickFormatter ? yAxisTickFormatter(value) : value,
715
- contentStyle: {
716
- backgroundColor: isDark ? "#1F2937" : "#FFFFFF",
717
- border: `1px solid ${isDark ? "#374151" : "#E5E7EB"}`,
718
- borderRadius: "0.5rem",
719
- color: isDark ? "#F9FAFB" : "#111827",
720
- boxShadow: isDark ? "0 4px 6px -1px rgba(0, 0, 0, 0.3)" : "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
721
- },
722
- labelStyle: {
723
- color: isDark ? "#F9FAFB" : "#111827",
724
- fontWeight: "500",
725
- marginBottom: "4px"
726
- }
727
- }
728
- ),
729
- /* @__PURE__ */ jsxRuntime.jsx(
730
- recharts.Bar,
731
- {
732
- dataKey: yAxisDataKey,
733
- fill: lineColor,
734
- radius: [4, 4, 0, 0],
735
- maxBarSize: 60
678
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { aspect: 16 / 9, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, margin: { left: 20 }, children: [
679
+ /* @__PURE__ */ jsxRuntime.jsx(
680
+ recharts.CartesianGrid,
681
+ {
682
+ strokeDasharray: "3 3",
683
+ stroke: isDark ? "#374151" : "#E5E7EB"
684
+ }
685
+ ),
686
+ /* @__PURE__ */ jsxRuntime.jsx(
687
+ recharts.XAxis,
688
+ {
689
+ dataKey: xAxisDataKey,
690
+ tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
691
+ axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
692
+ tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
693
+ tickMargin: 10
694
+ }
695
+ ),
696
+ /* @__PURE__ */ jsxRuntime.jsx(
697
+ recharts.YAxis,
698
+ {
699
+ tickFormatter: yAxisTickFormatter,
700
+ allowDecimals: false,
701
+ tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
702
+ axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
703
+ tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" }
704
+ }
705
+ ),
706
+ /* @__PURE__ */ jsxRuntime.jsx(
707
+ recharts.Tooltip,
708
+ {
709
+ cursor: {
710
+ fill: isDark ? "rgba(55, 65, 81, 0.2)" : "rgba(243, 244, 246, 0.5)"
711
+ },
712
+ formatter: (value) => yAxisTickFormatter ? yAxisTickFormatter(value) : value,
713
+ contentStyle: {
714
+ backgroundColor: isDark ? "#1F2937" : "#FFFFFF",
715
+ border: `1px solid ${isDark ? "#374151" : "#E5E7EB"}`,
716
+ borderRadius: "0.5rem",
717
+ color: isDark ? "#F9FAFB" : "#111827",
718
+ boxShadow: isDark ? "0 4px 6px -1px rgba(0, 0, 0, 0.3)" : "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
719
+ },
720
+ labelStyle: {
721
+ color: isDark ? "#F9FAFB" : "#111827",
722
+ fontWeight: "500",
723
+ marginBottom: "4px"
736
724
  }
737
- )
738
- ] }) })
739
- ] });
725
+ }
726
+ ),
727
+ /* @__PURE__ */ jsxRuntime.jsx(
728
+ recharts.Bar,
729
+ {
730
+ dataKey: yAxisDataKey,
731
+ fill: lineColor,
732
+ radius: [4, 4, 0, 0],
733
+ maxBarSize: 60
734
+ }
735
+ )
736
+ ] }) }) });
740
737
  }
741
738
  return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { aspect: 16 / 9, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, margin: { left: 20 }, children: [
742
739
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -975,23 +972,23 @@ const PieChart = ({ data, dataKey }) => {
975
972
  )
976
973
  ] }) });
977
974
  };
978
- const columnHelper$1 = ui.createDataTableColumnHelper();
979
- const columns$1 = [
980
- columnHelper$1.accessor("sku", {
975
+ const columnHelper$3 = ui.createDataTableColumnHelper();
976
+ const columns$2 = [
977
+ columnHelper$3.accessor("sku", {
981
978
  header: "SKU",
982
979
  enableSorting: true,
983
980
  sortLabel: "SKU",
984
981
  sortAscLabel: "A-Z",
985
982
  sortDescLabel: "Z-A"
986
983
  }),
987
- columnHelper$1.accessor("variantName", {
984
+ columnHelper$3.accessor("variantName", {
988
985
  header: "Variant Name",
989
986
  enableSorting: true,
990
987
  sortLabel: "Variant Name",
991
988
  sortAscLabel: "A-Z",
992
989
  sortDescLabel: "Z-A"
993
990
  }),
994
- columnHelper$1.accessor("inventoryQuantity", {
991
+ columnHelper$3.accessor("inventoryQuantity", {
995
992
  header: "Inventory",
996
993
  enableSorting: true,
997
994
  sortLabel: "Inventory",
@@ -1003,10 +1000,10 @@ const columns$1 = [
1003
1000
  }
1004
1001
  })
1005
1002
  ];
1006
- const PAGE_SIZE = 10;
1003
+ const PAGE_SIZE$1 = 10;
1007
1004
  const ProductsTable = ({ products }) => {
1008
1005
  const [pagination, setPagination] = React__namespace.useState({
1009
- pageSize: PAGE_SIZE,
1006
+ pageSize: PAGE_SIZE$1,
1010
1007
  pageIndex: 0
1011
1008
  });
1012
1009
  const [search, setSearch] = React__namespace.useState("");
@@ -1037,7 +1034,7 @@ const ProductsTable = ({ products }) => {
1037
1034
  );
1038
1035
  }, [products, search, sorting, pagination]);
1039
1036
  const table = ui.useDataTable({
1040
- columns: columns$1,
1037
+ columns: columns$2,
1041
1038
  data: shownProducts,
1042
1039
  getRowId: (product) => product.sku,
1043
1040
  rowCount: products.length,
@@ -1072,10 +1069,10 @@ const ProductsTable = ({ products }) => {
1072
1069
  }
1073
1070
  }
1074
1071
  ),
1075
- products.length > PAGE_SIZE && /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Pagination, {})
1072
+ products.length > PAGE_SIZE$1 && /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Pagination, {})
1076
1073
  ] });
1077
1074
  };
1078
- const BACKEND_URL$1 = window.location.origin;
1075
+ const BACKEND_URL$2 = __BACKEND_URL__ === "/" ? "" : __BACKEND_URL__;
1079
1076
  async function retrieveProductAnalytics(date) {
1080
1077
  if (!date || !date.from || !(date == null ? void 0 : date.to)) {
1081
1078
  return void 0;
@@ -1083,7 +1080,7 @@ async function retrieveProductAnalytics(date) {
1083
1080
  const dateFrom = dateFns.format(date.from, "yyyy-MM-dd");
1084
1081
  const dateTo = dateFns.format(date.to, "yyyy-MM-dd");
1085
1082
  const data = await fetch(
1086
- `${BACKEND_URL$1}/admin/agilo-analytics/products?date_from=${dateFrom}&date_to=${dateTo}`
1083
+ `${BACKEND_URL$2}/admin/agilo-analytics/products?date_from=${dateFrom}&date_to=${dateTo}`
1087
1084
  );
1088
1085
  const productAnalytics = await data.json();
1089
1086
  return productAnalytics;
@@ -1098,11 +1095,11 @@ const useProductAnalytics = (query, options) => {
1098
1095
  ...options
1099
1096
  });
1100
1097
  };
1101
- const BACKEND_URL = window.location.origin;
1098
+ const BACKEND_URL$1 = __BACKEND_URL__ === "/" ? "" : __BACKEND_URL__;
1102
1099
  async function retrieveOrderAnalytics(preset, date) {
1103
1100
  if (!date || !date.from || !(date == null ? void 0 : date.to)) {
1104
1101
  const data2 = await fetch(
1105
- `${BACKEND_URL}/admin/agilo-analytics/orders?preset=${preset}`
1102
+ `${BACKEND_URL$1}/admin/agilo-analytics/orders?preset=${preset}`
1106
1103
  );
1107
1104
  const orderAnalytics2 = await data2.json();
1108
1105
  return orderAnalytics2;
@@ -1110,7 +1107,7 @@ async function retrieveOrderAnalytics(preset, date) {
1110
1107
  const dateFrom = dateFns.format(date.from, "yyyy-MM-dd");
1111
1108
  const dateTo = dateFns.format(date.to, "yyyy-MM-dd");
1112
1109
  const data = await fetch(
1113
- `${BACKEND_URL}/admin/agilo-analytics/orders?date_from=${dateFrom}&date_to=${dateTo}&preset=${preset}`
1110
+ `${BACKEND_URL$1}/admin/agilo-analytics/orders?date_from=${dateFrom}&date_to=${dateTo}&preset=${preset}`
1114
1111
  );
1115
1112
  const orderAnalytics = await data.json();
1116
1113
  return orderAnalytics;
@@ -1151,7 +1148,7 @@ const BarChartSkeleton = () => {
1151
1148
  const PieChartSkeleton = () => {
1152
1149
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full aspect-square max-h-[400px]", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-full" }) });
1153
1150
  };
1154
- const dummyData = [
1151
+ const dummyData$1 = [
1155
1152
  {
1156
1153
  a: "a",
1157
1154
  b: "b",
@@ -1183,27 +1180,209 @@ const dummyData = [
1183
1180
  c: 0
1184
1181
  }
1185
1182
  ];
1186
- const columnHelper = ui.createDataTableColumnHelper();
1187
- const columns = [
1188
- columnHelper.accessor("a", {
1183
+ const columnHelper$2 = ui.createDataTableColumnHelper();
1184
+ const columns$1 = [
1185
+ columnHelper$2.accessor("a", {
1189
1186
  header: () => null,
1190
1187
  cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1191
1188
  }),
1192
- columnHelper.accessor("b", {
1189
+ columnHelper$2.accessor("b", {
1193
1190
  header: () => null,
1194
1191
  cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1195
1192
  }),
1196
- columnHelper.accessor("c", {
1193
+ columnHelper$2.accessor("c", {
1197
1194
  header: () => null,
1198
1195
  cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1199
1196
  })
1200
1197
  ];
1201
1198
  const ProductsTableSkeleton = () => {
1199
+ const [search, setSearch] = React__namespace.useState("");
1200
+ const table = ui.useDataTable({
1201
+ columns: columns$1,
1202
+ data: dummyData$1,
1203
+ getRowId: (product) => product.a,
1204
+ rowCount: dummyData$1.length,
1205
+ search: {
1206
+ state: search,
1207
+ onSearchChange: setSearch
1208
+ }
1209
+ });
1210
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.DataTable, { instance: table, children: [
1211
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Toolbar, { className: "px-0 pt-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Search, { placeholder: "Search..." }) }),
1212
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Table, {})
1213
+ ] });
1214
+ };
1215
+ const BACKEND_URL = __BACKEND_URL__ === "/" ? "" : __BACKEND_URL__;
1216
+ async function retrieveCustomersAnalytics(date) {
1217
+ if (!date || !date.from || !(date == null ? void 0 : date.to)) {
1218
+ return void 0;
1219
+ }
1220
+ const dateFrom = dateFns.format(date.from, "yyyy-MM-dd");
1221
+ const dateTo = dateFns.format(date.to, "yyyy-MM-dd");
1222
+ const data = await fetch(
1223
+ `${BACKEND_URL}/admin/agilo-analytics/customers?date_from=${dateFrom}&date_to=${dateTo}`
1224
+ );
1225
+ const customersAnalytics = await data.json();
1226
+ return customersAnalytics;
1227
+ }
1228
+ const useCustomerAnalytics = (query, options) => {
1229
+ return reactQuery.useQuery({
1230
+ queryKey: ["customer-analytics", query == null ? void 0 : query.from, query == null ? void 0 : query.to],
1231
+ queryFn: async () => {
1232
+ const data = await retrieveCustomersAnalytics(query);
1233
+ return data;
1234
+ },
1235
+ ...options
1236
+ });
1237
+ };
1238
+ const StackedBarChart = ({
1239
+ data,
1240
+ xAxisDataKey,
1241
+ yAxisTickFormatter,
1242
+ useStableColors = false,
1243
+ colorKeyField,
1244
+ dataKeys
1245
+ }) => {
1246
+ const isDark = useDarkMode();
1247
+ const colors = React__namespace.default.useMemo(() => {
1248
+ if (!useStableColors || !data || !colorKeyField) {
1249
+ return [];
1250
+ }
1251
+ return generateColorsForData(data, colorKeyField, 70, isDark ? 60 : 50);
1252
+ }, [data, useStableColors, colorKeyField, isDark]);
1253
+ return /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { aspect: 16 / 9, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data, margin: { left: 20 }, children: [
1254
+ /* @__PURE__ */ jsxRuntime.jsx(
1255
+ recharts.CartesianGrid,
1256
+ {
1257
+ strokeDasharray: "3 3",
1258
+ stroke: isDark ? "#374151" : "#E5E7EB"
1259
+ }
1260
+ ),
1261
+ /* @__PURE__ */ jsxRuntime.jsx(
1262
+ recharts.XAxis,
1263
+ {
1264
+ dataKey: String(xAxisDataKey),
1265
+ tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
1266
+ axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
1267
+ tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
1268
+ tickMargin: 10
1269
+ }
1270
+ ),
1271
+ /* @__PURE__ */ jsxRuntime.jsx(
1272
+ recharts.YAxis,
1273
+ {
1274
+ tickFormatter: yAxisTickFormatter,
1275
+ allowDecimals: false,
1276
+ tick: { fill: isDark ? "#D1D5DB" : "#6B7280" },
1277
+ axisLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" },
1278
+ tickLine: { stroke: isDark ? "#4B5563" : "#D1D5DB" }
1279
+ }
1280
+ ),
1281
+ /* @__PURE__ */ jsxRuntime.jsx(
1282
+ recharts.Tooltip,
1283
+ {
1284
+ cursor: {
1285
+ fill: isDark ? "rgba(55, 65, 81, 0.2)" : "rgba(243, 244, 246, 0.5)"
1286
+ },
1287
+ formatter: (value) => yAxisTickFormatter ? yAxisTickFormatter(value) : value,
1288
+ contentStyle: {
1289
+ backgroundColor: isDark ? "#1F2937" : "#FFFFFF",
1290
+ border: `1px solid ${isDark ? "#374151" : "#E5E7EB"}`,
1291
+ borderRadius: "0.5rem",
1292
+ color: isDark ? "#F9FAFB" : "#111827",
1293
+ boxShadow: isDark ? "0 4px 6px -1px rgba(0, 0, 0, 0.3)" : "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
1294
+ },
1295
+ labelStyle: {
1296
+ color: isDark ? "#F9FAFB" : "#111827",
1297
+ fontWeight: "500",
1298
+ marginBottom: "4px"
1299
+ }
1300
+ }
1301
+ ),
1302
+ dataKeys == null ? void 0 : dataKeys.map((key, index) => /* @__PURE__ */ jsxRuntime.jsx(
1303
+ recharts.Bar,
1304
+ {
1305
+ dataKey: String(key),
1306
+ stackId: "a",
1307
+ fill: useStableColors && colors.length > 0 ? colors[index] : "#3B82F6"
1308
+ },
1309
+ String(key)
1310
+ ))
1311
+ ] }) });
1312
+ };
1313
+ const dummyData = [
1314
+ {
1315
+ a: "a",
1316
+ b: "b",
1317
+ c: 0,
1318
+ d: 0,
1319
+ e: /* @__PURE__ */ new Date()
1320
+ },
1321
+ {
1322
+ a: "a",
1323
+ b: "b",
1324
+ c: 0,
1325
+ d: 0,
1326
+ e: /* @__PURE__ */ new Date()
1327
+ },
1328
+ {
1329
+ a: "a",
1330
+ b: "b",
1331
+ c: 0,
1332
+ d: 0,
1333
+ e: /* @__PURE__ */ new Date()
1334
+ },
1335
+ {
1336
+ a: "a",
1337
+ b: "b",
1338
+ c: 0,
1339
+ d: 0,
1340
+ e: /* @__PURE__ */ new Date()
1341
+ },
1342
+ {
1343
+ a: "a",
1344
+ b: "b",
1345
+ c: 0,
1346
+ d: 0,
1347
+ e: /* @__PURE__ */ new Date()
1348
+ },
1349
+ {
1350
+ a: "a",
1351
+ b: "b",
1352
+ c: 0,
1353
+ d: 0,
1354
+ e: /* @__PURE__ */ new Date()
1355
+ }
1356
+ ];
1357
+ const columnHelper$1 = ui.createDataTableColumnHelper();
1358
+ const columns = [
1359
+ columnHelper$1.accessor("a", {
1360
+ header: () => null,
1361
+ cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1362
+ }),
1363
+ columnHelper$1.accessor("b", {
1364
+ header: () => null,
1365
+ cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1366
+ }),
1367
+ columnHelper$1.accessor("c", {
1368
+ header: () => null,
1369
+ cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1370
+ }),
1371
+ columnHelper$1.accessor("d", {
1372
+ header: () => null,
1373
+ cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1374
+ }),
1375
+ columnHelper$1.accessor("e", {
1376
+ header: () => null,
1377
+ cell: () => /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "w-full h-5" })
1378
+ })
1379
+ ];
1380
+ const CustomersTableSkeleton = () => {
1202
1381
  const [search, setSearch] = React__namespace.useState("");
1203
1382
  const table = ui.useDataTable({
1204
1383
  columns,
1205
1384
  data: dummyData,
1206
- getRowId: (product) => product.a,
1385
+ getRowId: (customer) => customer.a,
1207
1386
  rowCount: dummyData.length,
1208
1387
  search: {
1209
1388
  state: search,
@@ -1215,6 +1394,140 @@ const ProductsTableSkeleton = () => {
1215
1394
  /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Table, {})
1216
1395
  ] });
1217
1396
  };
1397
+ const columnHelper = ui.createDataTableColumnHelper();
1398
+ const PAGE_SIZE = 10;
1399
+ const CustomersTable = ({
1400
+ customers,
1401
+ currencyCode
1402
+ }) => {
1403
+ const [pagination, setPagination] = React__namespace.useState({
1404
+ pageSize: PAGE_SIZE,
1405
+ pageIndex: 0
1406
+ });
1407
+ const [search, setSearch] = React__namespace.useState("");
1408
+ const [sorting, setSorting] = React__namespace.useState(
1409
+ null
1410
+ );
1411
+ const navigate = reactRouterDom.useNavigate();
1412
+ const shownCustomers = React__namespace.useMemo(() => {
1413
+ let filtered = customers.filter(
1414
+ (customer) => customer.name.toLowerCase().includes(search.toLowerCase()) || customer.email.toLowerCase().includes(search.toLowerCase())
1415
+ );
1416
+ if (sorting && sorting.id) {
1417
+ filtered = filtered.slice().sort((a, b) => {
1418
+ const aVal = a[sorting.id];
1419
+ const bVal = b[sorting.id];
1420
+ if (aVal < bVal) {
1421
+ return sorting.desc ? 1 : -1;
1422
+ }
1423
+ if (aVal > bVal) {
1424
+ return sorting.desc ? -1 : 1;
1425
+ }
1426
+ return 0;
1427
+ });
1428
+ }
1429
+ return filtered.slice(
1430
+ pagination.pageIndex * pagination.pageSize,
1431
+ (pagination.pageIndex + 1) * pagination.pageSize
1432
+ );
1433
+ }, [customers, search, sorting, pagination]);
1434
+ const columns2 = React__namespace.useMemo(
1435
+ () => [
1436
+ columnHelper.accessor("name", {
1437
+ header: "Name",
1438
+ enableSorting: true,
1439
+ sortLabel: "Name",
1440
+ sortAscLabel: "A-Z",
1441
+ sortDescLabel: "Z-A"
1442
+ }),
1443
+ columnHelper.accessor("email", {
1444
+ header: "Email",
1445
+ enableSorting: true,
1446
+ sortLabel: "Email",
1447
+ sortAscLabel: "A-Z",
1448
+ sortDescLabel: "Z-A"
1449
+ }),
1450
+ columnHelper.accessor("order_count", {
1451
+ header: "Order Count",
1452
+ enableSorting: true,
1453
+ sortLabel: "Order Count",
1454
+ sortAscLabel: "Low to High",
1455
+ sortDescLabel: "High to Low"
1456
+ }),
1457
+ columnHelper.accessor("sales", {
1458
+ header: "Total Sales",
1459
+ enableSorting: true,
1460
+ sortLabel: "Total Sales",
1461
+ sortAscLabel: "Low to High",
1462
+ sortDescLabel: "High to Low",
1463
+ cell: ({ getValue }) => {
1464
+ const sales = getValue();
1465
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { children: new Intl.NumberFormat("en-US", {
1466
+ style: "currency",
1467
+ currency: currencyCode || "EUR"
1468
+ }).format(sales || 0) });
1469
+ }
1470
+ }),
1471
+ columnHelper.accessor("groups", {
1472
+ header: "Groups",
1473
+ cell: ({ getValue }) => {
1474
+ const groups = getValue();
1475
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { children: groups.length ? groups.join(", ") : "No Group" });
1476
+ }
1477
+ }),
1478
+ columnHelper.accessor("last_order", {
1479
+ header: "Last Order",
1480
+ enableSorting: true,
1481
+ sortLabel: "Last Order",
1482
+ sortAscLabel: "Oldest to Newest",
1483
+ sortDescLabel: "Newest to Oldest",
1484
+ cell: ({ getValue }) => {
1485
+ const date = getValue();
1486
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { children: date ? dateFns.format(new Date(date), "MMM dd, yyyy") : "No orders yet" });
1487
+ }
1488
+ })
1489
+ ],
1490
+ [currencyCode]
1491
+ );
1492
+ const table = ui.useDataTable({
1493
+ columns: columns2,
1494
+ data: shownCustomers,
1495
+ getRowId: (customer) => customer.customer_id,
1496
+ rowCount: customers.length,
1497
+ search: {
1498
+ state: search,
1499
+ onSearchChange: setSearch
1500
+ },
1501
+ pagination: {
1502
+ state: pagination,
1503
+ onPaginationChange: setPagination
1504
+ },
1505
+ sorting: {
1506
+ state: sorting,
1507
+ onSortingChange: setSorting
1508
+ },
1509
+ onRowClick: (_, row) => {
1510
+ navigate(`/customers/${row.original.customer_id}`);
1511
+ }
1512
+ });
1513
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.DataTable, { instance: table, children: [
1514
+ /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Toolbar, { className: "px-0 pt-0", children: /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Search, { placeholder: "Search..." }) }),
1515
+ /* @__PURE__ */ jsxRuntime.jsx(
1516
+ ui.DataTable.Table,
1517
+ {
1518
+ emptyState: {
1519
+ filtered: {
1520
+ heading: "No customers found"
1521
+ },
1522
+ empty: {
1523
+ heading: "No customers available"
1524
+ }
1525
+ }
1526
+ }
1527
+ ),
1528
+ customers.length > PAGE_SIZE && /* @__PURE__ */ jsxRuntime.jsx(ui.DataTable.Pagination, {})
1529
+ ] });
1530
+ };
1218
1531
  function dateToCalendarDate(date) {
1219
1532
  return new $35ea8db9cb2ccb90$export$99faa760c7908e4f(
1220
1533
  date.getFullYear(),
@@ -1242,16 +1555,40 @@ function rangeValueToDateRange(rangeValue) {
1242
1555
  to: rangeValue.end ? calendarDateToDate(rangeValue.end) : void 0
1243
1556
  };
1244
1557
  }
1558
+ function presetToDateRange(preset) {
1559
+ const today = /* @__PURE__ */ new Date();
1560
+ if (preset === "this-month") return { from: dateFns.startOfMonth(today), to: today };
1561
+ if (preset === "last-month")
1562
+ return {
1563
+ from: dateFns.startOfMonth(dateFns.subMonths(today, 1)),
1564
+ to: dateFns.endOfMonth(dateFns.subMonths(today, 1))
1565
+ };
1566
+ return {
1567
+ from: dateFns.startOfMonth(dateFns.subMonths(today, 3)),
1568
+ to: dateFns.endOfMonth(dateFns.subMonths(today, 1))
1569
+ };
1570
+ }
1571
+ const DATE_RANGE_REGEX = /^(\d{4}-\d{2}-\d{2})-(\d{4}-\d{2}-\d{2})$/;
1245
1572
  const AnalyticsPage = () => {
1246
1573
  var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1247
- const [date, setDate] = React__namespace.useState({
1248
- from: dateFns.startOfMonth(/* @__PURE__ */ new Date()),
1249
- to: dateFns.endOfMonth(/* @__PURE__ */ new Date())
1250
- });
1251
- const [selectValue, setSelectValue] = React__namespace.useState("this-month");
1574
+ const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
1575
+ const rangeParam = searchParams.get("range") || "this-month";
1576
+ const date = React__namespace.useMemo(() => {
1577
+ if (rangeParam === "this-month" || rangeParam === "last-month" || rangeParam === "last-3-months") {
1578
+ return presetToDateRange(rangeParam);
1579
+ }
1580
+ const dates = rangeParam.match(DATE_RANGE_REGEX);
1581
+ if (dates) {
1582
+ const from = dateFns.parse(dates[1], "yyyy-MM-dd", /* @__PURE__ */ new Date());
1583
+ const to = dateFns.parse(dates[2], "yyyy-MM-dd", /* @__PURE__ */ new Date());
1584
+ return { from, to };
1585
+ }
1586
+ return void 0;
1587
+ }, [rangeParam]);
1252
1588
  const { data: products, isLoading: isLoadingProducts } = useProductAnalytics(date);
1589
+ const { data: customers, isLoading: isLoadingCustomers } = useCustomerAnalytics(date);
1253
1590
  const { data: orders, isLoading: isLoadingOrders } = useOrderAnalytics(
1254
- selectValue,
1591
+ ["this-month", "last-month", "last-3-months"].includes(rangeParam) ? rangeParam : "custom",
1255
1592
  date
1256
1593
  );
1257
1594
  const someOrderCountsGreaterThanZero = (_a = orders == null ? void 0 : orders.order_count) == null ? void 0 : _a.some(
@@ -1261,45 +1598,59 @@ const AnalyticsPage = () => {
1261
1598
  (item) => item.sales > 0
1262
1599
  );
1263
1600
  const someTopSellingProductsGreaterThanZero = (_c = products == null ? void 0 : products.variantQuantitySold) == null ? void 0 : _c.some((item) => item.quantity > 0);
1264
- const updateDatePreset = React__namespace.useCallback((preset) => {
1265
- const today = /* @__PURE__ */ new Date();
1266
- switch (preset) {
1267
- case "this-month":
1268
- setDate({
1269
- from: dateFns.startOfMonth(today),
1270
- to: today
1271
- });
1272
- setSelectValue("this-month");
1273
- break;
1274
- case "last-month":
1275
- setDate({
1276
- from: dateFns.startOfMonth(dateFns.subMonths(today, 1)),
1277
- to: dateFns.endOfMonth(dateFns.subMonths(today, 1))
1278
- });
1279
- setSelectValue("last-month");
1280
- break;
1281
- case "last-3-months":
1282
- setDate({
1283
- from: dateFns.startOfMonth(dateFns.subMonths(today, 3)),
1284
- to: dateFns.endOfMonth(dateFns.subMonths(today, 1))
1285
- });
1286
- setSelectValue("last-3-months");
1287
- break;
1288
- case "custom":
1289
- default:
1290
- setSelectValue("custom");
1291
- break;
1292
- }
1293
- }, []);
1601
+ const updateDatePreset = React__namespace.useCallback(
1602
+ (preset) => {
1603
+ const params = new URLSearchParams(searchParams.toString());
1604
+ switch (preset) {
1605
+ case "this-month":
1606
+ params.set("range", "this-month");
1607
+ break;
1608
+ case "last-month":
1609
+ params.set("range", "last-month");
1610
+ break;
1611
+ case "last-3-months":
1612
+ params.set("range", "last-3-months");
1613
+ break;
1614
+ case "custom":
1615
+ default:
1616
+ if (rangeParam === "this-month" || rangeParam === "last-month" || rangeParam === "last-3-months") {
1617
+ const currentDate = presetToDateRange(rangeParam);
1618
+ params.set(
1619
+ "range",
1620
+ `${dateFns.format(currentDate.from || /* @__PURE__ */ new Date(), "yyyy-MM-dd")}-${dateFns.format(
1621
+ currentDate.to || /* @__PURE__ */ new Date(),
1622
+ "yyyy-MM-dd"
1623
+ )}`
1624
+ );
1625
+ }
1626
+ break;
1627
+ }
1628
+ setSearchParams(params);
1629
+ },
1630
+ [searchParams, rangeParam, setSearchParams]
1631
+ );
1632
+ const updateUrlParams = React__namespace.useCallback(
1633
+ (value) => {
1634
+ const params = new URLSearchParams(searchParams.toString());
1635
+ if ((value == null ? void 0 : value.from) && (value == null ? void 0 : value.to)) {
1636
+ params.set(
1637
+ "range",
1638
+ `${dateFns.format(value.from, "yyyy-MM-dd")}-${dateFns.format(
1639
+ value.to,
1640
+ "yyyy-MM-dd"
1641
+ )}`
1642
+ );
1643
+ }
1644
+ setSearchParams(params);
1645
+ },
1646
+ [searchParams, setSearchParams]
1647
+ );
1294
1648
  const handleDateRangeChange = React__namespace.useCallback(
1295
1649
  (value) => {
1296
1650
  const newDateRange = rangeValueToDateRange(value);
1297
- setDate(newDateRange);
1298
- if (selectValue !== "custom") {
1299
- setSelectValue("custom");
1300
- }
1651
+ updateUrlParams(newDateRange);
1301
1652
  },
1302
- []
1653
+ [updateUrlParams]
1303
1654
  );
1304
1655
  return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
1305
1656
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-2 gap-y-4 items-center justify-between px-6 py-4", children: [
@@ -1310,7 +1661,9 @@ const AnalyticsPage = () => {
1310
1661
  {
1311
1662
  disabled: isLoadingOrders || isLoadingProducts,
1312
1663
  defaultValue: "this-month",
1313
- value: selectValue,
1664
+ value: ["this-month", "last-month", "last-3-months"].includes(
1665
+ rangeParam
1666
+ ) ? rangeParam : "custom",
1314
1667
  onValueChange: updateDatePreset,
1315
1668
  children: [
1316
1669
  /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, {}) }),
@@ -1406,193 +1759,306 @@ const AnalyticsPage = () => {
1406
1759
  )
1407
1760
  ] })
1408
1761
  ] }),
1409
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs, { defaultValue: "orders", children: [
1410
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.List, { children: [
1411
- /* @__PURE__ */ jsxRuntime.jsx(
1412
- ui.Tabs.Trigger,
1413
- {
1414
- value: "orders",
1415
- disabled: isLoadingOrders || isLoadingProducts,
1416
- children: "Orders"
1417
- }
1418
- ),
1419
- /* @__PURE__ */ jsxRuntime.jsx(
1420
- ui.Tabs.Trigger,
1421
- {
1422
- value: "products",
1423
- disabled: isLoadingOrders || isLoadingProducts,
1424
- children: "Products"
1425
- }
1426
- )
1427
- ] }),
1428
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8", children: [
1429
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.Content, { value: "orders", children: [
1430
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4 mb-4", children: [
1431
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1432
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1433
- /* @__PURE__ */ jsxRuntime.jsx(icons.ShoppingCart, { className: "absolute right-6 top-4 text-ui-fg-muted" }),
1434
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Total Orders" }),
1435
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1436
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: (orders == null ? void 0 : orders.total_orders) || 0 }),
1437
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
1438
- ((orders == null ? void 0 : orders.prev_orders_percent) || 0) > 0 && "+",
1439
- (orders == null ? void 0 : orders.prev_orders_percent) || 0,
1440
- "% from previous period"
1762
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs(
1763
+ ui.Tabs,
1764
+ {
1765
+ value: searchParams.get("tab") || "orders",
1766
+ onValueChange: (value) => {
1767
+ const params = new URLSearchParams(searchParams.toString());
1768
+ params.set("tab", value);
1769
+ setSearchParams(params);
1770
+ },
1771
+ children: [
1772
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.List, { children: [
1773
+ /* @__PURE__ */ jsxRuntime.jsx(
1774
+ ui.Tabs.Trigger,
1775
+ {
1776
+ value: "orders",
1777
+ disabled: isLoadingOrders || isLoadingProducts,
1778
+ children: "Orders"
1779
+ }
1780
+ ),
1781
+ /* @__PURE__ */ jsxRuntime.jsx(
1782
+ ui.Tabs.Trigger,
1783
+ {
1784
+ value: "products",
1785
+ disabled: isLoadingOrders || isLoadingProducts,
1786
+ children: "Products"
1787
+ }
1788
+ ),
1789
+ /* @__PURE__ */ jsxRuntime.jsx(
1790
+ ui.Tabs.Trigger,
1791
+ {
1792
+ value: "customers",
1793
+ disabled: isLoadingOrders || isLoadingProducts,
1794
+ children: "Customers"
1795
+ }
1796
+ )
1797
+ ] }),
1798
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8", children: [
1799
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.Content, { value: "orders", children: [
1800
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4 mb-4", children: [
1801
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1802
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1803
+ /* @__PURE__ */ jsxRuntime.jsx(icons.ShoppingCart, { className: "absolute right-6 top-4 text-ui-fg-muted" }),
1804
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Total Orders" }),
1805
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1806
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: (orders == null ? void 0 : orders.total_orders) || 0 }),
1807
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
1808
+ ((orders == null ? void 0 : orders.prev_orders_percent) || 0) > 0 && "+",
1809
+ (orders == null ? void 0 : orders.prev_orders_percent) || 0,
1810
+ "% from previous period"
1811
+ ] })
1812
+ ] })
1813
+ ] }),
1814
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1815
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Orders Over Time" }),
1816
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Total number of orders in the selected period" }),
1817
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(LineChartSkeleton, {}) : (orders == null ? void 0 : orders.order_count) && ((_d = orders == null ? void 0 : orders.order_count) == null ? void 0 : _d.length) > 0 && someOrderCountsGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1818
+ LineChart,
1819
+ {
1820
+ data: orders == null ? void 0 : orders.order_count,
1821
+ xAxisDataKey: "name",
1822
+ yAxisDataKey: "count"
1823
+ }
1824
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1825
+ ui.Text,
1826
+ {
1827
+ size: "small",
1828
+ className: "text-ui-fg-muted text-center",
1829
+ children: "No data available for the selected period."
1830
+ }
1831
+ )
1832
+ ] })
1833
+ ] }),
1834
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1835
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1836
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChartNoAxesCombined, { className: "absolute right-6 text-ui-fg-muted top-4 size-[15px]" }),
1837
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Total Sales" }),
1838
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1839
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: new Intl.NumberFormat("en-US", {
1840
+ style: "currency",
1841
+ currency: (orders == null ? void 0 : orders.currency_code) || "EUR"
1842
+ }).format((orders == null ? void 0 : orders.total_sales) || 0) }),
1843
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
1844
+ ((orders == null ? void 0 : orders.prev_sales_percent) || 0) > 0 && "+",
1845
+ (orders == null ? void 0 : orders.prev_sales_percent) || 0,
1846
+ "% from previous period"
1847
+ ] })
1848
+ ] })
1849
+ ] }),
1850
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1851
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Sales Over Time" }),
1852
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: [
1853
+ "Total sales in the selected period (",
1854
+ orders == null ? void 0 : orders.currency_code,
1855
+ ")"
1856
+ ] }),
1857
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(LineChartSkeleton, {}) : (orders == null ? void 0 : orders.order_sales) && ((_e = orders == null ? void 0 : orders.order_sales) == null ? void 0 : _e.length) > 0 && someOrderSalesGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1858
+ LineChart,
1859
+ {
1860
+ data: orders.order_sales,
1861
+ xAxisDataKey: "name",
1862
+ yAxisDataKey: "sales",
1863
+ lineColor: "#82ca9d",
1864
+ yAxisTickFormatter: (value) => new Intl.NumberFormat("en-US", {
1865
+ currency: orders.currency_code,
1866
+ maximumFractionDigits: 0
1867
+ }).format(value)
1868
+ }
1869
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1870
+ ui.Text,
1871
+ {
1872
+ size: "small",
1873
+ className: "text-ui-fg-muted text-center",
1874
+ children: "No data available for the selected period."
1875
+ }
1876
+ )
1441
1877
  ] })
1442
1878
  ] })
1443
1879
  ] }),
1444
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1445
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Orders Over Time" }),
1446
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Total number of orders in the selected period" }),
1447
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(LineChartSkeleton, {}) : (orders == null ? void 0 : orders.order_count) && ((_d = orders == null ? void 0 : orders.order_count) == null ? void 0 : _d.length) > 0 && someOrderCountsGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1448
- LineChart,
1449
- {
1450
- data: orders == null ? void 0 : orders.order_count,
1451
- xAxisDataKey: "name",
1452
- yAxisDataKey: "count"
1453
- }
1454
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1455
- ui.Text,
1880
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4", children: [
1881
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1882
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top Regions by Sales" }),
1883
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Sales breakdown by region in the selected period" }),
1884
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (orders == null ? void 0 : orders.regions) && ((_f = orders == null ? void 0 : orders.regions) == null ? void 0 : _f.length) > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1885
+ BarChart,
1886
+ {
1887
+ data: orders.regions,
1888
+ xAxisDataKey: "name",
1889
+ yAxisDataKey: "sales",
1890
+ lineColor: "#82ca9d",
1891
+ useStableColors: true,
1892
+ colorKeyField: "name",
1893
+ yAxisTickFormatter: (value) => new Intl.NumberFormat("en-US", {
1894
+ currency: orders.currency_code,
1895
+ maximumFractionDigits: 0
1896
+ }).format(value)
1897
+ }
1898
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1899
+ ui.Text,
1900
+ {
1901
+ size: "small",
1902
+ className: "text-ui-fg-muted text-center",
1903
+ children: "No data available for the selected period."
1904
+ }
1905
+ )
1906
+ ] }) }),
1907
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1908
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Order Status Breakdown" }),
1909
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Distribution of orders by status in the selected period" }),
1910
+ isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(PieChartSkeleton, {}) : (orders == null ? void 0 : orders.statuses) && ((_g = orders == null ? void 0 : orders.statuses) == null ? void 0 : _g.length) > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(PieChart, { data: orders == null ? void 0 : orders.statuses, dataKey: "count" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
1911
+ ui.Text,
1912
+ {
1913
+ size: "small",
1914
+ className: "text-ui-fg-muted text-center",
1915
+ children: "No data available for the selected period."
1916
+ }
1917
+ )
1918
+ ] }) })
1919
+ ] })
1920
+ ] }),
1921
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.Content, { value: "products", children: [
1922
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mb-4 min-h-[9.375rem]", children: [
1923
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top-Selling Products" }),
1924
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products by quantity sold in selected period" }),
1925
+ isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (products == null ? void 0 : products.variantQuantitySold) && someTopSellingProductsGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1926
+ BarChart,
1456
1927
  {
1457
- size: "small",
1458
- className: "text-ui-fg-muted text-center",
1459
- children: "No data available for the selected period."
1928
+ data: products.variantQuantitySold,
1929
+ xAxisDataKey: "title",
1930
+ yAxisDataKey: "quantity",
1931
+ lineColor: "#82ca9d",
1932
+ useStableColors: true,
1933
+ colorKeyField: "title"
1460
1934
  }
1461
- )
1935
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted text-center", children: "No data available for the selected period." })
1936
+ ] }),
1937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 max-xl:flex-col", children: [
1938
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
1939
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Out-of-Stock Variants" }),
1940
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products with zero inventory" }),
1941
+ isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(ProductsTableSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
1942
+ ProductsTable,
1943
+ {
1944
+ products: ((_h = products == null ? void 0 : products.lowStockVariants) == null ? void 0 : _h.filter(
1945
+ (product) => product.inventoryQuantity === 0
1946
+ )) || []
1947
+ }
1948
+ )
1949
+ ] }),
1950
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
1951
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Low Stock Variants" }),
1952
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products with inventory below threshold" }),
1953
+ isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(ProductsTableSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
1954
+ ProductsTable,
1955
+ {
1956
+ products: ((_i = products == null ? void 0 : products.lowStockVariants) == null ? void 0 : _i.filter(
1957
+ (product) => product.inventoryQuantity > 0
1958
+ )) || []
1959
+ }
1960
+ )
1961
+ ] })
1462
1962
  ] })
1463
1963
  ] }),
1464
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1465
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1466
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChartNoAxesCombined, { className: "absolute right-6 text-ui-fg-muted top-4 size-[15px]" }),
1467
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Total Sales" }),
1468
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1469
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: new Intl.NumberFormat("en-US", {
1470
- style: "currency",
1471
- currency: (orders == null ? void 0 : orders.currency_code) || "EUR"
1472
- }).format((orders == null ? void 0 : orders.total_sales) || 0) }),
1473
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "xsmall", className: "text-ui-fg-muted", children: [
1474
- ((orders == null ? void 0 : orders.prev_sales_percent) || 0) > 0 && "+",
1475
- (orders == null ? void 0 : orders.prev_sales_percent) || 0,
1476
- "% from previous period"
1964
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.Content, { value: "customers", children: [
1965
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4 mb-4", children: [
1966
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1967
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1968
+ /* @__PURE__ */ jsxRuntime.jsx(icons.User, { className: "absolute right-6 top-4 text-ui-fg-muted" }),
1969
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Total Customers" }),
1970
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: (customers == null ? void 0 : customers.total_customers) || 0 }) })
1971
+ ] }),
1972
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1973
+ /* @__PURE__ */ jsxRuntime.jsx(icons.User, { className: "absolute right-6 top-4 text-ui-fg-muted" }),
1974
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "New Customers" }),
1975
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: (customers == null ? void 0 : customers.new_customers) || 0 }) })
1976
+ ] })
1977
+ ] }),
1978
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 flex-1", children: [
1979
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1980
+ /* @__PURE__ */ jsxRuntime.jsx(icons.User, { className: "absolute right-6 text-ui-fg-muted top-4 size-[15px]" }),
1981
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Returning Customers" }),
1982
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: (customers == null ? void 0 : customers.returning_customers) || 0 }) })
1983
+ ] }),
1984
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "relative", children: [
1985
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChartNoAxesCombined, { className: "absolute right-6 top-4 text-ui-fg-muted" }),
1986
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", children: "Average Sales per Customer" }),
1987
+ isLoadingCustomers || isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(SmallCardSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: new Intl.NumberFormat("en-US", {
1988
+ currency: (customers == null ? void 0 : customers.currency_code) || "EUR",
1989
+ style: "currency"
1990
+ }).format(
1991
+ ((orders == null ? void 0 : orders.total_sales) || 0) / ((customers == null ? void 0 : customers.total_customers) || 0)
1992
+ ) }) })
1477
1993
  ] })
1478
1994
  ] })
1479
1995
  ] }),
1480
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1481
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Sales Over Time" }),
1482
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: [
1483
- "Total sales in the selected period (",
1484
- orders == null ? void 0 : orders.currency_code,
1485
- ")"
1486
- ] }),
1487
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(LineChartSkeleton, {}) : (orders == null ? void 0 : orders.order_sales) && ((_e = orders == null ? void 0 : orders.order_sales) == null ? void 0 : _e.length) > 0 && someOrderSalesGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1488
- LineChart,
1489
- {
1490
- data: orders.order_sales,
1491
- xAxisDataKey: "name",
1492
- yAxisDataKey: "sales",
1493
- lineColor: "#82ca9d",
1494
- yAxisTickFormatter: (value) => new Intl.NumberFormat("en-US", {
1495
- currency: orders.currency_code,
1496
- maximumFractionDigits: 0
1497
- }).format(value)
1498
- }
1499
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1500
- ui.Text,
1996
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4 mb-4", children: [
1997
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1998
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "New vs. Returning Customers" }),
1999
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Distribution of new and returning customers in the selected period" }),
2000
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (customers == null ? void 0 : customers.customer_count) && customers.customer_count.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2001
+ StackedBarChart,
2002
+ {
2003
+ data: customers.customer_count,
2004
+ xAxisDataKey: "name",
2005
+ lineColor: "#82ca9d",
2006
+ useStableColors: true,
2007
+ colorKeyField: "returning_customers",
2008
+ dataKeys: ["new_customers", "returning_customers"]
2009
+ }
2010
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
2011
+ ui.Text,
2012
+ {
2013
+ size: "small",
2014
+ className: "text-ui-fg-muted text-center",
2015
+ children: "No data available for the selected period."
2016
+ }
2017
+ )
2018
+ ] }) }),
2019
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
2020
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top Customer Groups by Sales" }),
2021
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Sales breakdown by customer group in the selected period" }),
2022
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (customers == null ? void 0 : customers.customer_group) && customers.customer_group.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
2023
+ BarChart,
2024
+ {
2025
+ data: customers.customer_group,
2026
+ xAxisDataKey: "name",
2027
+ lineColor: "#82ca9d",
2028
+ useStableColors: true,
2029
+ colorKeyField: "name",
2030
+ yAxisDataKey: "total",
2031
+ yAxisTickFormatter: (value) => new Intl.NumberFormat("en-US", {
2032
+ currency: customers.currency_code || "EUR",
2033
+ maximumFractionDigits: 0
2034
+ }).format(value)
2035
+ }
2036
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(
2037
+ ui.Text,
2038
+ {
2039
+ size: "small",
2040
+ className: "text-ui-fg-muted text-center",
2041
+ children: "No data available for the selected period."
2042
+ }
2043
+ )
2044
+ ] }) })
2045
+ ] }),
2046
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-4 max-xl:flex-col", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
2047
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top Customers by Sales" }),
2048
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Customers by sales in the selected period" }),
2049
+ isLoadingCustomers ? /* @__PURE__ */ jsxRuntime.jsx(CustomersTableSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
2050
+ CustomersTable,
1501
2051
  {
1502
- size: "small",
1503
- className: "text-ui-fg-muted text-center",
1504
- children: "No data available for the selected period."
2052
+ customers: (customers == null ? void 0 : customers.customer_sales) || [],
2053
+ currencyCode: (customers == null ? void 0 : customers.currency_code) || "EUR"
1505
2054
  }
1506
2055
  )
1507
- ] })
2056
+ ] }) })
1508
2057
  ] })
1509
- ] }),
1510
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex max-md:flex-col gap-4", children: [
1511
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1512
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top Regions by Sales" }),
1513
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Sales breakdown by region in the selected period" }),
1514
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (orders == null ? void 0 : orders.regions) && ((_f = orders == null ? void 0 : orders.regions) == null ? void 0 : _f.length) > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1515
- BarChart,
1516
- {
1517
- data: orders.regions,
1518
- xAxisDataKey: "name",
1519
- yAxisDataKey: "sales",
1520
- lineColor: "#82ca9d",
1521
- useStableColors: true,
1522
- colorKeyField: "name",
1523
- yAxisTickFormatter: (value) => new Intl.NumberFormat("en-US", {
1524
- currency: orders.currency_code,
1525
- maximumFractionDigits: 0
1526
- }).format(value)
1527
- }
1528
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(
1529
- ui.Text,
1530
- {
1531
- size: "small",
1532
- className: "text-ui-fg-muted text-center",
1533
- children: "No data available for the selected period."
1534
- }
1535
- )
1536
- ] }) }),
1537
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "min-h-[9.375rem]", children: [
1538
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Order Status Breakdown" }),
1539
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Distribution of orders by status in the selected period" }),
1540
- isLoadingOrders ? /* @__PURE__ */ jsxRuntime.jsx(PieChartSkeleton, {}) : (orders == null ? void 0 : orders.statuses) && ((_g = orders == null ? void 0 : orders.statuses) == null ? void 0 : _g.length) > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(PieChart, { data: orders == null ? void 0 : orders.statuses, dataKey: "count" }) }) : /* @__PURE__ */ jsxRuntime.jsx(
1541
- ui.Text,
1542
- {
1543
- size: "small",
1544
- className: "text-ui-fg-muted text-center",
1545
- children: "No data available for the selected period."
1546
- }
1547
- )
1548
- ] }) })
1549
2058
  ] })
1550
- ] }),
1551
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Tabs.Content, { value: "products", children: [
1552
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "mb-4 min-h-[9.375rem]", children: [
1553
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Top-Selling Products" }),
1554
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products by quantity sold in selected period" }),
1555
- isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(BarChartSkeleton, {}) : (products == null ? void 0 : products.variantQuantitySold) && someTopSellingProductsGreaterThanZero ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", style: { aspectRatio: "16/9" }, children: /* @__PURE__ */ jsxRuntime.jsx(
1556
- BarChart,
1557
- {
1558
- data: products.variantQuantitySold,
1559
- xAxisDataKey: "title",
1560
- yAxisDataKey: "quantity",
1561
- lineColor: "#82ca9d",
1562
- useStableColors: true,
1563
- colorKeyField: "title"
1564
- }
1565
- ) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-muted text-center", children: "No data available for the selected period." })
1566
- ] }),
1567
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4 max-xl:flex-col", children: [
1568
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
1569
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Out-of-Stock Variants" }),
1570
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products with zero inventory" }),
1571
- isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(ProductsTableSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
1572
- ProductsTable,
1573
- {
1574
- products: ((_h = products == null ? void 0 : products.lowStockVariants) == null ? void 0 : _h.filter(
1575
- (product) => product.inventoryQuantity === 0
1576
- )) || []
1577
- }
1578
- )
1579
- ] }),
1580
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { children: [
1581
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "xlarge", weight: "plus", children: "Low Stock Variants" }),
1582
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "mb-8 text-ui-fg-muted", children: "Products with inventory below threshold" }),
1583
- isLoadingProducts ? /* @__PURE__ */ jsxRuntime.jsx(ProductsTableSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
1584
- ProductsTable,
1585
- {
1586
- products: ((_i = products == null ? void 0 : products.lowStockVariants) == null ? void 0 : _i.filter(
1587
- (product) => product.inventoryQuantity > 0
1588
- )) || []
1589
- }
1590
- )
1591
- ] })
1592
- ] })
1593
- ] })
1594
- ] })
1595
- ] }) })
2059
+ ]
2060
+ }
2061
+ ) })
1596
2062
  ] });
1597
2063
  };
1598
2064
  const config = adminSdk.defineRouteConfig({