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