medusa-analytics 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.medusa/server/src/admin/index.js +476 -848
- package/.medusa/server/src/admin/index.mjs +477 -849
- package/package.json +1 -1
|
@@ -296,37 +296,72 @@ function formatChartLabel$2(value) {
|
|
|
296
296
|
function formatPercent(value) {
|
|
297
297
|
return `${value.toFixed(1)}%`;
|
|
298
298
|
}
|
|
299
|
-
function ordersCountFromPiePayload(payload) {
|
|
300
|
-
if (typeof payload !== "object" || payload === null) return 0;
|
|
301
|
-
if (!("orders_count" in payload)) return 0;
|
|
302
|
-
const c = payload.orders_count;
|
|
303
|
-
return Math.floor(Number(c) || 0);
|
|
304
|
-
}
|
|
305
299
|
function formatShortNumber$1(value) {
|
|
306
300
|
return new Intl.NumberFormat("en-IN", {
|
|
307
301
|
notation: "compact",
|
|
308
302
|
maximumFractionDigits: value < 10 ? 1 : 0
|
|
309
303
|
}).format(value);
|
|
310
304
|
}
|
|
311
|
-
|
|
305
|
+
const SALES_GRANULARITY_TABS = [
|
|
306
|
+
{ value: "day", label: "Day" },
|
|
307
|
+
{ value: "hour", label: "Hour" },
|
|
308
|
+
{ value: "week", label: "Week" },
|
|
309
|
+
{ value: "month", label: "Month" }
|
|
310
|
+
];
|
|
311
|
+
function monthKeyFromDateStr(dateStr) {
|
|
312
|
+
if (dateStr.length >= 7) return dateStr.slice(0, 7);
|
|
313
|
+
return dateStr;
|
|
314
|
+
}
|
|
315
|
+
function formatMonthBucketLabel(ymKey) {
|
|
316
|
+
const [ys, ms] = ymKey.split("-");
|
|
317
|
+
const y = Number(ys);
|
|
318
|
+
const m = Number(ms);
|
|
319
|
+
if (!Number.isFinite(y) || !Number.isFinite(m)) return ymKey;
|
|
320
|
+
return new Intl.DateTimeFormat("en-IN", {
|
|
321
|
+
month: "short",
|
|
322
|
+
year: "numeric",
|
|
323
|
+
timeZone: "UTC"
|
|
324
|
+
}).format(new Date(Date.UTC(y, m - 1, 1)));
|
|
325
|
+
}
|
|
326
|
+
function aggregateDailyOrdersForBreakdown(rows, keyFn, labelFn) {
|
|
327
|
+
const map = /* @__PURE__ */ new Map();
|
|
328
|
+
for (const d of rows) {
|
|
329
|
+
const key = keyFn(d);
|
|
330
|
+
const cur = map.get(key) ?? { orders: 0, revenue: 0, bucketRows: [] };
|
|
331
|
+
cur.orders += d.orders_count;
|
|
332
|
+
cur.revenue += d.total_revenue;
|
|
333
|
+
cur.bucketRows.push(d);
|
|
334
|
+
map.set(key, cur);
|
|
335
|
+
}
|
|
336
|
+
return Array.from(map.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([key, v]) => ({
|
|
337
|
+
key,
|
|
338
|
+
label: labelFn(key, v.bucketRows),
|
|
339
|
+
orders_count: v.orders,
|
|
340
|
+
revenue: v.revenue
|
|
341
|
+
}));
|
|
342
|
+
}
|
|
343
|
+
function isSalesBreakdownBarRow(value) {
|
|
344
|
+
if (typeof value !== "object" || value === null) return false;
|
|
345
|
+
const v = value;
|
|
346
|
+
return typeof v.key === "string" && typeof v.label === "string" && typeof v.orders_count === "number" && typeof v.revenue === "number";
|
|
347
|
+
}
|
|
348
|
+
function SalesBreakdownTooltip({
|
|
312
349
|
active,
|
|
313
|
-
payload
|
|
314
|
-
label
|
|
350
|
+
payload
|
|
315
351
|
}) {
|
|
316
|
-
var _a, _b
|
|
352
|
+
var _a, _b;
|
|
317
353
|
if (!active || !(payload == null ? void 0 : payload.length)) return null;
|
|
318
|
-
const row =
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const revenue = ((_d = payload.find((entry) => entry.name === "Revenue")) == null ? void 0 : _d.value) ?? 0;
|
|
322
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { title: displayLabel, children: [
|
|
354
|
+
const row = isSalesBreakdownBarRow((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
|
|
355
|
+
if (!row) return null;
|
|
356
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: row.label, children: [
|
|
323
357
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
324
|
-
"
|
|
325
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children:
|
|
358
|
+
"Revenue: ",
|
|
359
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(row.revenue) })
|
|
326
360
|
] }),
|
|
327
361
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
328
|
-
"
|
|
329
|
-
|
|
362
|
+
"Orders:",
|
|
363
|
+
" ",
|
|
364
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(row.orders_count).toLocaleString() })
|
|
330
365
|
] })
|
|
331
366
|
] });
|
|
332
367
|
}
|
|
@@ -348,21 +383,6 @@ function OrdersTodayTooltip({
|
|
|
348
383
|
(row == null ? void 0 : row.isToday) ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#6B7280" }, children: "Current day" }) : null
|
|
349
384
|
] });
|
|
350
385
|
}
|
|
351
|
-
function OrdersSparklineTooltip({
|
|
352
|
-
active,
|
|
353
|
-
payload,
|
|
354
|
-
label
|
|
355
|
-
}) {
|
|
356
|
-
var _a, _b, _c;
|
|
357
|
-
if (!active || !(payload == null ? void 0 : payload.length)) return null;
|
|
358
|
-
const row = isDailyOrderRow((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
|
|
359
|
-
const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
|
|
360
|
-
const orders = Number((_c = payload[0]) == null ? void 0 : _c.value) || 0;
|
|
361
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: displayLabel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
362
|
-
"Orders: ",
|
|
363
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(orders).toLocaleString() })
|
|
364
|
-
] }) });
|
|
365
|
-
}
|
|
366
386
|
function OutcomesTrendTooltip({
|
|
367
387
|
active,
|
|
368
388
|
payload,
|
|
@@ -379,6 +399,53 @@ function OutcomesTrendTooltip({
|
|
|
379
399
|
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(entry.value) || 0).toLocaleString() })
|
|
380
400
|
] }, String(entry.name))) });
|
|
381
401
|
}
|
|
402
|
+
function isTrendRowDetailed(value) {
|
|
403
|
+
if (!isDailyOrderRow(value)) return false;
|
|
404
|
+
const v = value;
|
|
405
|
+
return typeof v.aov === "number" && typeof v.prev_revenue === "number" && typeof v.prev_orders === "number" && typeof v.prev_aov === "number";
|
|
406
|
+
}
|
|
407
|
+
function CombinedMetricsTooltip({
|
|
408
|
+
active,
|
|
409
|
+
payload
|
|
410
|
+
}) {
|
|
411
|
+
var _a, _b;
|
|
412
|
+
if (!active || !(payload == null ? void 0 : payload.length)) return null;
|
|
413
|
+
const row = isTrendRowDetailed((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
|
|
414
|
+
if (!row) return null;
|
|
415
|
+
const title = row.label ?? formatChartLabel$2(row.date);
|
|
416
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title, children: [
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
418
|
+
"Revenue:",
|
|
419
|
+
" ",
|
|
420
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency$1(row.total_revenue) }),
|
|
421
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-muted", children: [
|
|
422
|
+
" ",
|
|
423
|
+
"· prev ",
|
|
424
|
+
formatCompactCurrency$1(row.prev_revenue)
|
|
425
|
+
] })
|
|
426
|
+
] }),
|
|
427
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
428
|
+
"Orders:",
|
|
429
|
+
" ",
|
|
430
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(row.orders_count).toLocaleString() }),
|
|
431
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-muted", children: [
|
|
432
|
+
" ",
|
|
433
|
+
"· prev ",
|
|
434
|
+
Math.floor(row.prev_orders).toLocaleString()
|
|
435
|
+
] })
|
|
436
|
+
] }),
|
|
437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
438
|
+
"AOV (non-canc.):",
|
|
439
|
+
" ",
|
|
440
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(row.aov) }),
|
|
441
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-fg-muted", children: [
|
|
442
|
+
" ",
|
|
443
|
+
"· prev ",
|
|
444
|
+
formatCurrency$1(row.prev_aov)
|
|
445
|
+
] })
|
|
446
|
+
] })
|
|
447
|
+
] });
|
|
448
|
+
}
|
|
382
449
|
const KPI_ICON_BG$2 = {
|
|
383
450
|
green: "bg-emerald-500/20",
|
|
384
451
|
blue: "bg-sky-500/20",
|
|
@@ -392,53 +459,6 @@ const KPI_ICONS$2 = {
|
|
|
392
459
|
amber: icons.Cash
|
|
393
460
|
};
|
|
394
461
|
const PIE_PALETTE = ["#6366F1", "#94A3B8", "#10B981", "#F59E0B"];
|
|
395
|
-
function TrafficRevenueDonut({ traffic }) {
|
|
396
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[152px] w-full shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { margin: { top: 2, right: 2, left: 2, bottom: 2 }, children: [
|
|
397
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
398
|
-
recharts.Pie,
|
|
399
|
-
{
|
|
400
|
-
data: traffic,
|
|
401
|
-
dataKey: "revenue",
|
|
402
|
-
nameKey: "label",
|
|
403
|
-
cx: "50%",
|
|
404
|
-
cy: "48%",
|
|
405
|
-
innerRadius: 34,
|
|
406
|
-
outerRadius: 54,
|
|
407
|
-
paddingAngle: 2,
|
|
408
|
-
children: traffic.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: PIE_PALETTE[i % PIE_PALETTE.length] }, `traffic-slice-${i}`))
|
|
409
|
-
}
|
|
410
|
-
),
|
|
411
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
412
|
-
recharts.Tooltip,
|
|
413
|
-
{
|
|
414
|
-
content: ({ active, payload }) => {
|
|
415
|
-
var _a, _b, _c;
|
|
416
|
-
return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(((_a = payload[0]) == null ? void 0 : _a.name) ?? ""), children: [
|
|
417
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
418
|
-
"Revenue:",
|
|
419
|
-
" ",
|
|
420
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(Number((_b = payload[0]) == null ? void 0 : _b.value) || 0) })
|
|
421
|
-
] }),
|
|
422
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
423
|
-
"Orders:",
|
|
424
|
-
" ",
|
|
425
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: ordersCountFromPiePayload((_c = payload[0]) == null ? void 0 : _c.payload).toLocaleString() })
|
|
426
|
-
] })
|
|
427
|
-
] }) : null;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
),
|
|
431
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
432
|
-
recharts.Legend,
|
|
433
|
-
{
|
|
434
|
-
wrapperStyle: { fontSize: 9, paddingTop: 0 },
|
|
435
|
-
verticalAlign: "bottom",
|
|
436
|
-
height: 22,
|
|
437
|
-
iconType: "circle"
|
|
438
|
-
}
|
|
439
|
-
)
|
|
440
|
-
] }) }) });
|
|
441
|
-
}
|
|
442
462
|
function AtlasKpiCard$2({
|
|
443
463
|
label,
|
|
444
464
|
value,
|
|
@@ -498,7 +518,7 @@ function EmptyAnalyticsPanel$1({
|
|
|
498
518
|
] });
|
|
499
519
|
}
|
|
500
520
|
function OrdersDashboard() {
|
|
501
|
-
var _a, _b
|
|
521
|
+
var _a, _b;
|
|
502
522
|
const [data, setData] = react.useState(null);
|
|
503
523
|
const [loading, setLoading] = react.useState(true);
|
|
504
524
|
const [error, setError] = react.useState(null);
|
|
@@ -514,6 +534,7 @@ function OrdersDashboard() {
|
|
|
514
534
|
const [todayContext, setTodayContext] = react.useState([]);
|
|
515
535
|
const [todayContextLoading, setTodayContextLoading] = react.useState(true);
|
|
516
536
|
const [todayContextError, setTodayContextError] = react.useState(null);
|
|
537
|
+
const [salesGranularity, setSalesGranularity] = react.useState("day");
|
|
517
538
|
react.useEffect(() => {
|
|
518
539
|
let cancelled = false;
|
|
519
540
|
setLoading(true);
|
|
@@ -709,14 +730,61 @@ function OrdersDashboard() {
|
|
|
709
730
|
revenue: h.revenue
|
|
710
731
|
}));
|
|
711
732
|
}, [ordersInsights]);
|
|
712
|
-
const
|
|
713
|
-
if (
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
733
|
+
const salesBreakdownChartRows = react.useMemo(() => {
|
|
734
|
+
if (salesGranularity === "hour") {
|
|
735
|
+
return hourlyChartRows.map((h) => ({
|
|
736
|
+
key: `hour-${h.hour}`,
|
|
737
|
+
label: h.label,
|
|
738
|
+
orders_count: h.orders_count,
|
|
739
|
+
revenue: h.revenue
|
|
740
|
+
}));
|
|
741
|
+
}
|
|
742
|
+
if (salesGranularity === "week") {
|
|
743
|
+
if (!ordersInsights) return [];
|
|
744
|
+
return ordersInsights.byWeekday.map((w) => ({
|
|
745
|
+
key: `weekday-${w.weekday}`,
|
|
746
|
+
label: w.label,
|
|
747
|
+
orders_count: w.orders_count,
|
|
748
|
+
revenue: w.revenue
|
|
749
|
+
}));
|
|
750
|
+
}
|
|
751
|
+
if (salesGranularity === "month") {
|
|
752
|
+
return aggregateDailyOrdersForBreakdown(
|
|
753
|
+
dailyOrders,
|
|
754
|
+
(d) => monthKeyFromDateStr(d.date),
|
|
755
|
+
(ymKey) => formatMonthBucketLabel(ymKey)
|
|
756
|
+
);
|
|
757
|
+
}
|
|
758
|
+
return dailyOrders.map((d) => ({
|
|
759
|
+
key: d.date,
|
|
760
|
+
label: d.label ?? formatChartLabel$2(d.date),
|
|
761
|
+
orders_count: d.orders_count,
|
|
762
|
+
revenue: d.total_revenue
|
|
718
763
|
}));
|
|
719
|
-
}, [ordersInsights]);
|
|
764
|
+
}, [salesGranularity, dailyOrders, hourlyChartRows, ordersInsights]);
|
|
765
|
+
const salesBreakdownDescription = react.useMemo(() => {
|
|
766
|
+
var _a2;
|
|
767
|
+
const rangeLabel = ((_a2 = OVER_TIME_PERIODS.find((p) => p.value === overTimePeriod)) == null ? void 0 : _a2.label) ?? "selected range";
|
|
768
|
+
const insightsHint = `Order-time breakdown uses last ${insightsWindowDays} days (UTC).`;
|
|
769
|
+
switch (salesGranularity) {
|
|
770
|
+
case "day":
|
|
771
|
+
return `Revenue by calendar day for ${rangeLabel} (aligned with Revenue & orders).`;
|
|
772
|
+
case "hour":
|
|
773
|
+
return `${insightsHint} Bars show revenue by hour of day.`;
|
|
774
|
+
case "week":
|
|
775
|
+
return `Revenue by UTC weekday — last ${insightsWindowDays} days.`;
|
|
776
|
+
case "month":
|
|
777
|
+
return `Revenue summed by calendar month (UTC) across ${rangeLabel}.`;
|
|
778
|
+
default:
|
|
779
|
+
return "";
|
|
780
|
+
}
|
|
781
|
+
}, [salesGranularity, overTimePeriod, insightsWindowDays]);
|
|
782
|
+
const salesBreakdownXAxisInterval = react.useMemo(() => {
|
|
783
|
+
const n = salesBreakdownChartRows.length;
|
|
784
|
+
if (salesGranularity === "hour") return 3;
|
|
785
|
+
if (salesGranularity === "day" && n > 24) return Math.max(0, Math.ceil(n / 10) - 1);
|
|
786
|
+
return 0;
|
|
787
|
+
}, [salesGranularity, salesBreakdownChartRows.length]);
|
|
720
788
|
const ordersVsDraftsPie = react.useMemo(() => {
|
|
721
789
|
var _a2;
|
|
722
790
|
if (!ordersInsights) return [];
|
|
@@ -753,10 +821,6 @@ function OrdersDashboard() {
|
|
|
753
821
|
};
|
|
754
822
|
});
|
|
755
823
|
}, [dailyOrders]);
|
|
756
|
-
const trafficTotalRevenue = react.useMemo(
|
|
757
|
-
() => (ordersInsights == null ? void 0 : ordersInsights.traffic.reduce((sum, t) => sum + (t.revenue || 0), 0)) ?? 0,
|
|
758
|
-
[ordersInsights]
|
|
759
|
-
);
|
|
760
824
|
const quickPulseMetrics = [
|
|
761
825
|
{
|
|
762
826
|
label: "Range revenue",
|
|
@@ -797,6 +861,84 @@ function OrdersDashboard() {
|
|
|
797
861
|
if (error || !data) {
|
|
798
862
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: error ?? "Failed to load analytics" }) });
|
|
799
863
|
}
|
|
864
|
+
const needsSalesOverTime = salesGranularity === "day" || salesGranularity === "month";
|
|
865
|
+
const needsSalesInsights = salesGranularity === "hour" || salesGranularity === "week";
|
|
866
|
+
const salesBreakdownBody = (() => {
|
|
867
|
+
if (needsSalesOverTime && overTimeLoading) {
|
|
868
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[min(176px,28vh)] items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" }) }) });
|
|
869
|
+
}
|
|
870
|
+
if (needsSalesOverTime && overTimeError) {
|
|
871
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[min(176px,28vh)] items-center justify-center px-2 py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: overTimeError }) }) });
|
|
872
|
+
}
|
|
873
|
+
if (needsSalesInsights && insightsLoading) {
|
|
874
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[min(176px,28vh)] items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" }) }) });
|
|
875
|
+
}
|
|
876
|
+
if (needsSalesInsights && insightsError) {
|
|
877
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[min(176px,28vh)] items-center justify-center px-2 py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: insightsError }) }) });
|
|
878
|
+
}
|
|
879
|
+
if (salesBreakdownChartRows.length === 0) {
|
|
880
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
881
|
+
EmptyAnalyticsPanel$1,
|
|
882
|
+
{
|
|
883
|
+
title: "No sales data",
|
|
884
|
+
description: "Nothing to show for this view and range."
|
|
885
|
+
}
|
|
886
|
+
);
|
|
887
|
+
}
|
|
888
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(200px,30vh)] min-h-[160px] w-full sm:h-[min(220px,32vh)]", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
889
|
+
recharts.BarChart,
|
|
890
|
+
{
|
|
891
|
+
data: salesBreakdownChartRows,
|
|
892
|
+
margin: { top: 4, right: 8, left: 4, bottom: 4 },
|
|
893
|
+
children: [
|
|
894
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
895
|
+
recharts.CartesianGrid,
|
|
896
|
+
{
|
|
897
|
+
strokeDasharray: "3 3",
|
|
898
|
+
vertical: false,
|
|
899
|
+
stroke: "rgba(148,163,184,0.12)"
|
|
900
|
+
}
|
|
901
|
+
),
|
|
902
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
903
|
+
recharts.XAxis,
|
|
904
|
+
{
|
|
905
|
+
dataKey: "label",
|
|
906
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
907
|
+
tickLine: false,
|
|
908
|
+
axisLine: false,
|
|
909
|
+
interval: salesBreakdownXAxisInterval
|
|
910
|
+
}
|
|
911
|
+
),
|
|
912
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
913
|
+
recharts.YAxis,
|
|
914
|
+
{
|
|
915
|
+
width: 44,
|
|
916
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
917
|
+
tickLine: false,
|
|
918
|
+
axisLine: false,
|
|
919
|
+
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
920
|
+
}
|
|
921
|
+
),
|
|
922
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
923
|
+
recharts.Tooltip,
|
|
924
|
+
{
|
|
925
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(SalesBreakdownTooltip, {}),
|
|
926
|
+
cursor: { fill: "rgba(148,163,184,0.08)" }
|
|
927
|
+
}
|
|
928
|
+
),
|
|
929
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
930
|
+
recharts.Bar,
|
|
931
|
+
{
|
|
932
|
+
dataKey: "revenue",
|
|
933
|
+
name: "Revenue",
|
|
934
|
+
fill: "#D946EF",
|
|
935
|
+
radius: [6, 6, 0, 0]
|
|
936
|
+
}
|
|
937
|
+
)
|
|
938
|
+
]
|
|
939
|
+
}
|
|
940
|
+
) }) }) });
|
|
941
|
+
})();
|
|
800
942
|
return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsDashboardShell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-hidden rounded-2xl border border-ui-border-base/80 bg-ui-bg-base shadow-sm", children: [
|
|
801
943
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
802
944
|
AnalyticsDashboardHeader,
|
|
@@ -911,397 +1053,197 @@ function OrdersDashboard() {
|
|
|
911
1053
|
] }) })
|
|
912
1054
|
] }),
|
|
913
1055
|
!overTimeLoading && !overTimeError && dailyOrders.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
914
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
915
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
916
|
-
/* @__PURE__ */ jsxRuntime.
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
var _a2, _b2, _c2, _d;
|
|
945
|
-
return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
946
|
-
AnalyticsTooltipCard,
|
|
947
|
-
{
|
|
948
|
-
variant: "compact",
|
|
949
|
-
title: String(
|
|
950
|
-
isDailyOrderRow((_a2 = payload[0]) == null ? void 0 : _a2.payload) ? ((_b2 = payload[0]) == null ? void 0 : _b2.payload.label) ?? formatChartLabel$2(String(label)) : label
|
|
951
|
-
),
|
|
952
|
-
children: [
|
|
953
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
954
|
-
"This:",
|
|
955
|
-
" ",
|
|
956
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency$1(
|
|
957
|
-
Number(
|
|
958
|
-
(_c2 = payload.find((p) => p.dataKey === "total_revenue")) == null ? void 0 : _c2.value
|
|
959
|
-
) || 0
|
|
960
|
-
) })
|
|
961
|
-
] }),
|
|
962
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
963
|
-
"Previous:",
|
|
964
|
-
" ",
|
|
965
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency$1(
|
|
966
|
-
Number(
|
|
967
|
-
(_d = payload.find((p) => p.dataKey === "prev_revenue")) == null ? void 0 : _d.value
|
|
968
|
-
) || 0
|
|
969
|
-
) })
|
|
970
|
-
] })
|
|
971
|
-
]
|
|
972
|
-
}
|
|
973
|
-
) : null;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
),
|
|
977
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
978
|
-
recharts.Line,
|
|
979
|
-
{
|
|
980
|
-
type: "natural",
|
|
981
|
-
dataKey: "total_revenue",
|
|
982
|
-
name: "This period",
|
|
983
|
-
stroke: "#D946EF",
|
|
984
|
-
strokeWidth: 2,
|
|
985
|
-
dot: false
|
|
986
|
-
}
|
|
987
|
-
),
|
|
988
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
989
|
-
recharts.Line,
|
|
990
|
-
{
|
|
991
|
-
type: "natural",
|
|
992
|
-
dataKey: "prev_revenue",
|
|
993
|
-
name: "Previous",
|
|
994
|
-
stroke: "#94a3b8",
|
|
995
|
-
strokeWidth: 1.5,
|
|
996
|
-
strokeDasharray: "5 4",
|
|
997
|
-
dot: false
|
|
998
|
-
}
|
|
999
|
-
)
|
|
1000
|
-
]
|
|
1001
|
-
}
|
|
1002
|
-
) }) })
|
|
1003
|
-
] }),
|
|
1004
|
-
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
1005
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Orders count" }),
|
|
1006
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[118px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1007
|
-
recharts.LineChart,
|
|
1008
|
-
{
|
|
1009
|
-
data: trendRowsDetailed,
|
|
1010
|
-
margin: { top: 4, right: 4, left: 0, bottom: 0 },
|
|
1011
|
-
children: [
|
|
1012
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1013
|
-
recharts.CartesianGrid,
|
|
1014
|
-
{
|
|
1015
|
-
strokeDasharray: "3 3",
|
|
1016
|
-
vertical: false,
|
|
1017
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
1018
|
-
}
|
|
1019
|
-
),
|
|
1020
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
1021
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1022
|
-
recharts.YAxis,
|
|
1023
|
-
{
|
|
1024
|
-
width: 28,
|
|
1025
|
-
tick: CHART_AXIS_TICK_SM$1,
|
|
1026
|
-
allowDecimals: false
|
|
1027
|
-
}
|
|
1028
|
-
),
|
|
1029
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1030
|
-
recharts.Tooltip,
|
|
1031
|
-
{
|
|
1032
|
-
content: ({ active, payload, label }) => {
|
|
1033
|
-
var _a2, _b2;
|
|
1034
|
-
return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
|
|
1035
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1036
|
-
"This:",
|
|
1037
|
-
" ",
|
|
1038
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(
|
|
1039
|
-
Number(
|
|
1040
|
-
(_a2 = payload.find((p) => p.dataKey === "orders_count")) == null ? void 0 : _a2.value
|
|
1041
|
-
) || 0
|
|
1042
|
-
).toLocaleString() })
|
|
1043
|
-
] }),
|
|
1044
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1045
|
-
"Previous:",
|
|
1046
|
-
" ",
|
|
1047
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(
|
|
1048
|
-
Number(
|
|
1049
|
-
(_b2 = payload.find((p) => p.dataKey === "prev_orders")) == null ? void 0 : _b2.value
|
|
1050
|
-
) || 0
|
|
1051
|
-
).toLocaleString() })
|
|
1052
|
-
] })
|
|
1053
|
-
] }) : null;
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
),
|
|
1057
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1058
|
-
recharts.Line,
|
|
1059
|
-
{
|
|
1060
|
-
type: "natural",
|
|
1061
|
-
dataKey: "orders_count",
|
|
1062
|
-
name: "This period",
|
|
1063
|
-
stroke: "#38BDF8",
|
|
1064
|
-
strokeWidth: 2,
|
|
1065
|
-
dot: false
|
|
1066
|
-
}
|
|
1067
|
-
),
|
|
1068
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1069
|
-
recharts.Line,
|
|
1070
|
-
{
|
|
1071
|
-
type: "natural",
|
|
1072
|
-
dataKey: "prev_orders",
|
|
1073
|
-
name: "Previous",
|
|
1074
|
-
stroke: "#94a3b8",
|
|
1075
|
-
strokeWidth: 1.5,
|
|
1076
|
-
strokeDasharray: "5 4",
|
|
1077
|
-
dot: false
|
|
1078
|
-
}
|
|
1079
|
-
)
|
|
1080
|
-
]
|
|
1081
|
-
}
|
|
1082
|
-
) }) })
|
|
1056
|
+
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
1057
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1 flex flex-col gap-0.5 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
1058
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1059
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Revenue, orders & AOV" }),
|
|
1060
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[9px] leading-snug", children: "One timeline · solid = this range, dashed = previous period (same length)" })
|
|
1061
|
+
] }),
|
|
1062
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-x-3 gap-y-0.5 text-[9px] text-ui-fg-muted sm:justify-end", children: [
|
|
1063
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1064
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 shrink-0 rounded-full bg-fuchsia-500" }),
|
|
1065
|
+
"Revenue"
|
|
1066
|
+
] }),
|
|
1067
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1068
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 shrink-0 rounded-full bg-sky-400" }),
|
|
1069
|
+
"Orders"
|
|
1070
|
+
] }),
|
|
1071
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1072
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2 w-2 shrink-0 rounded-full bg-amber-500" }),
|
|
1073
|
+
"AOV"
|
|
1074
|
+
] }),
|
|
1075
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1076
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1077
|
+
"span",
|
|
1078
|
+
{
|
|
1079
|
+
className: "h-0 w-4 shrink-0 border-t border-dashed border-slate-400",
|
|
1080
|
+
"aria-hidden": true
|
|
1081
|
+
}
|
|
1082
|
+
),
|
|
1083
|
+
"Previous"
|
|
1084
|
+
] })
|
|
1085
|
+
] })
|
|
1083
1086
|
] }),
|
|
1084
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1085
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "AOV (non-cancelled)" }),
|
|
1086
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[118px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1087
|
-
recharts.LineChart,
|
|
1088
|
-
{
|
|
1089
|
-
data: trendRowsDetailed,
|
|
1090
|
-
margin: { top: 4, right: 4, left: 0, bottom: 0 },
|
|
1091
|
-
children: [
|
|
1092
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1093
|
-
recharts.CartesianGrid,
|
|
1094
|
-
{
|
|
1095
|
-
strokeDasharray: "3 3",
|
|
1096
|
-
vertical: false,
|
|
1097
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
1098
|
-
}
|
|
1099
|
-
),
|
|
1100
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
1101
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1102
|
-
recharts.YAxis,
|
|
1103
|
-
{
|
|
1104
|
-
width: 36,
|
|
1105
|
-
tick: CHART_AXIS_TICK_SM$1,
|
|
1106
|
-
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
1107
|
-
}
|
|
1108
|
-
),
|
|
1109
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1110
|
-
recharts.Tooltip,
|
|
1111
|
-
{
|
|
1112
|
-
content: ({ active, payload, label }) => {
|
|
1113
|
-
var _a2, _b2;
|
|
1114
|
-
return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
|
|
1115
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1116
|
-
"This:",
|
|
1117
|
-
" ",
|
|
1118
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(
|
|
1119
|
-
Number(
|
|
1120
|
-
(_a2 = payload.find((p) => p.dataKey === "aov")) == null ? void 0 : _a2.value
|
|
1121
|
-
) || 0
|
|
1122
|
-
) })
|
|
1123
|
-
] }),
|
|
1124
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1125
|
-
"Previous:",
|
|
1126
|
-
" ",
|
|
1127
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(
|
|
1128
|
-
Number(
|
|
1129
|
-
(_b2 = payload.find((p) => p.dataKey === "prev_aov")) == null ? void 0 : _b2.value
|
|
1130
|
-
) || 0
|
|
1131
|
-
) })
|
|
1132
|
-
] })
|
|
1133
|
-
] }) : null;
|
|
1134
|
-
}
|
|
1135
|
-
}
|
|
1136
|
-
),
|
|
1137
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1138
|
-
recharts.Line,
|
|
1139
|
-
{
|
|
1140
|
-
type: "natural",
|
|
1141
|
-
dataKey: "aov",
|
|
1142
|
-
name: "This period",
|
|
1143
|
-
stroke: "#D97706",
|
|
1144
|
-
strokeWidth: 2,
|
|
1145
|
-
dot: false
|
|
1146
|
-
}
|
|
1147
|
-
),
|
|
1148
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1149
|
-
recharts.Line,
|
|
1150
|
-
{
|
|
1151
|
-
type: "natural",
|
|
1152
|
-
dataKey: "prev_aov",
|
|
1153
|
-
name: "Previous",
|
|
1154
|
-
stroke: "#94a3b8",
|
|
1155
|
-
strokeWidth: 1.5,
|
|
1156
|
-
strokeDasharray: "5 4",
|
|
1157
|
-
dot: false
|
|
1158
|
-
}
|
|
1159
|
-
)
|
|
1160
|
-
]
|
|
1161
|
-
}
|
|
1162
|
-
) }) })
|
|
1163
|
-
] })
|
|
1164
|
-
] }),
|
|
1165
|
-
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", className: "mt-1.5", children: [
|
|
1166
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Revenue breakdown (stacked — by order status)" }),
|
|
1167
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(168px,26vh)] min-h-[140px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1087
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(220px,32vh)] min-h-[156px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1168
1088
|
recharts.ComposedChart,
|
|
1169
1089
|
{
|
|
1170
|
-
data:
|
|
1171
|
-
margin: { top:
|
|
1090
|
+
data: trendRowsDetailed,
|
|
1091
|
+
margin: { top: 6, right: 8, left: 2, bottom: 4 },
|
|
1172
1092
|
children: [
|
|
1173
1093
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1174
1094
|
recharts.CartesianGrid,
|
|
1175
1095
|
{
|
|
1176
|
-
stroke: "rgba(148,163,184,0.14)",
|
|
1177
1096
|
strokeDasharray: "3 3",
|
|
1178
|
-
vertical: false
|
|
1097
|
+
vertical: false,
|
|
1098
|
+
stroke: "rgba(148,163,184,0.12)"
|
|
1179
1099
|
}
|
|
1180
1100
|
),
|
|
1181
1101
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1182
1102
|
recharts.XAxis,
|
|
1183
1103
|
{
|
|
1184
1104
|
dataKey: "date",
|
|
1185
|
-
tick:
|
|
1105
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
1186
1106
|
tickLine: false,
|
|
1187
1107
|
axisLine: false,
|
|
1188
1108
|
tickFormatter: (value, index) => {
|
|
1189
|
-
const row =
|
|
1190
|
-
return (row == null ? void 0 : row.label) ?? formatChartLabel$2(value);
|
|
1109
|
+
const row = trendRowsDetailed[index];
|
|
1110
|
+
return (row == null ? void 0 : row.label) ?? formatChartLabel$2(String(value));
|
|
1191
1111
|
}
|
|
1192
1112
|
}
|
|
1193
1113
|
),
|
|
1194
1114
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1195
1115
|
recharts.YAxis,
|
|
1196
1116
|
{
|
|
1197
|
-
|
|
1117
|
+
yAxisId: "orders",
|
|
1118
|
+
width: 30,
|
|
1119
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
1120
|
+
tickLine: false,
|
|
1121
|
+
axisLine: false,
|
|
1122
|
+
allowDecimals: false,
|
|
1123
|
+
tickFormatter: (v) => Math.floor(Number(v) || 0).toLocaleString()
|
|
1124
|
+
}
|
|
1125
|
+
),
|
|
1126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1127
|
+
recharts.YAxis,
|
|
1128
|
+
{
|
|
1129
|
+
yAxisId: "revenue",
|
|
1130
|
+
orientation: "right",
|
|
1131
|
+
width: 42,
|
|
1132
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
1133
|
+
tickLine: false,
|
|
1134
|
+
axisLine: false,
|
|
1135
|
+
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
1136
|
+
}
|
|
1137
|
+
),
|
|
1138
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1139
|
+
recharts.YAxis,
|
|
1140
|
+
{
|
|
1141
|
+
yAxisId: "aov",
|
|
1142
|
+
orientation: "right",
|
|
1143
|
+
width: 40,
|
|
1144
|
+
tick: CHART_AXIS_TICK_SM$1,
|
|
1145
|
+
tickLine: false,
|
|
1146
|
+
axisLine: false,
|
|
1198
1147
|
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
1199
1148
|
}
|
|
1200
1149
|
),
|
|
1201
1150
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1202
1151
|
recharts.Tooltip,
|
|
1203
1152
|
{
|
|
1204
|
-
content:
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
] }, String(p.name))) }) : null
|
|
1153
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(CombinedMetricsTooltip, {}),
|
|
1154
|
+
cursor: {
|
|
1155
|
+
stroke: "rgba(248, 250, 252, 0.35)",
|
|
1156
|
+
strokeWidth: 1
|
|
1157
|
+
}
|
|
1210
1158
|
}
|
|
1211
1159
|
),
|
|
1212
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { wrapperStyle: { fontSize: 10 }, iconType: "circle" }),
|
|
1213
1160
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1214
|
-
recharts.
|
|
1161
|
+
recharts.Line,
|
|
1215
1162
|
{
|
|
1163
|
+
yAxisId: "orders",
|
|
1216
1164
|
type: "natural",
|
|
1217
|
-
dataKey: "
|
|
1218
|
-
name: "
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
fillOpacity: 0.85
|
|
1165
|
+
dataKey: "orders_count",
|
|
1166
|
+
name: "Orders",
|
|
1167
|
+
stroke: "#38BDF8",
|
|
1168
|
+
strokeWidth: 2,
|
|
1169
|
+
dot: false
|
|
1223
1170
|
}
|
|
1224
1171
|
),
|
|
1225
1172
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1226
|
-
recharts.
|
|
1173
|
+
recharts.Line,
|
|
1227
1174
|
{
|
|
1175
|
+
yAxisId: "orders",
|
|
1228
1176
|
type: "natural",
|
|
1229
|
-
dataKey: "
|
|
1230
|
-
name: "
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1177
|
+
dataKey: "prev_orders",
|
|
1178
|
+
name: "Orders (prev)",
|
|
1179
|
+
stroke: "#64748b",
|
|
1180
|
+
strokeWidth: 1.5,
|
|
1181
|
+
strokeDasharray: "5 4",
|
|
1182
|
+
dot: false
|
|
1235
1183
|
}
|
|
1236
1184
|
),
|
|
1237
1185
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1238
|
-
recharts.
|
|
1186
|
+
recharts.Line,
|
|
1239
1187
|
{
|
|
1188
|
+
yAxisId: "revenue",
|
|
1240
1189
|
type: "natural",
|
|
1241
|
-
dataKey: "
|
|
1242
|
-
name: "
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1190
|
+
dataKey: "total_revenue",
|
|
1191
|
+
name: "Revenue",
|
|
1192
|
+
stroke: "#D946EF",
|
|
1193
|
+
strokeWidth: 2,
|
|
1194
|
+
dot: false
|
|
1195
|
+
}
|
|
1196
|
+
),
|
|
1197
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1198
|
+
recharts.Line,
|
|
1199
|
+
{
|
|
1200
|
+
yAxisId: "revenue",
|
|
1201
|
+
type: "natural",
|
|
1202
|
+
dataKey: "prev_revenue",
|
|
1203
|
+
name: "Revenue (prev)",
|
|
1204
|
+
stroke: "#64748b",
|
|
1205
|
+
strokeWidth: 1.5,
|
|
1206
|
+
strokeDasharray: "5 4",
|
|
1207
|
+
dot: false
|
|
1208
|
+
}
|
|
1209
|
+
),
|
|
1210
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1211
|
+
recharts.Line,
|
|
1212
|
+
{
|
|
1213
|
+
yAxisId: "aov",
|
|
1214
|
+
type: "natural",
|
|
1215
|
+
dataKey: "aov",
|
|
1216
|
+
name: "AOV",
|
|
1217
|
+
stroke: "#D97706",
|
|
1218
|
+
strokeWidth: 2,
|
|
1219
|
+
dot: false
|
|
1220
|
+
}
|
|
1221
|
+
),
|
|
1222
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1223
|
+
recharts.Line,
|
|
1224
|
+
{
|
|
1225
|
+
yAxisId: "aov",
|
|
1226
|
+
type: "natural",
|
|
1227
|
+
dataKey: "prev_aov",
|
|
1228
|
+
name: "AOV (prev)",
|
|
1229
|
+
stroke: "#64748b",
|
|
1230
|
+
strokeWidth: 1.5,
|
|
1231
|
+
strokeDasharray: "5 4",
|
|
1232
|
+
dot: false
|
|
1247
1233
|
}
|
|
1248
1234
|
)
|
|
1249
1235
|
]
|
|
1250
1236
|
}
|
|
1251
1237
|
) }) })
|
|
1252
|
-
] })
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative space-y-1", children: [
|
|
1257
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-1.5", children: [
|
|
1258
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
|
|
1259
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Trend overview" }),
|
|
1260
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-sm font-semibold", children: ((_b = OVER_TIME_PERIODS.find((period) => period.value === overTimePeriod)) == null ? void 0 : _b.label) ?? "One week" })
|
|
1261
|
-
] }),
|
|
1262
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap justify-end gap-2 text-[10px] text-ui-fg-muted", children: [
|
|
1263
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1264
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-sky-400" }),
|
|
1265
|
-
"Orders"
|
|
1266
|
-
] }),
|
|
1267
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
|
|
1268
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-fuchsia-400" }),
|
|
1269
|
-
"Revenue"
|
|
1270
|
-
] })
|
|
1271
|
-
] })
|
|
1272
|
-
] }),
|
|
1273
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(200px,30vh)] min-h-[160px] sm:h-[min(216px,32vh)]", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
1274
|
-
"div",
|
|
1275
|
-
{
|
|
1276
|
-
className: "flex h-full items-center justify-center",
|
|
1277
|
-
role: "status",
|
|
1278
|
-
"aria-label": "Loading orders over time",
|
|
1279
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" })
|
|
1280
|
-
}
|
|
1281
|
-
) : overTimeError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-xs", children: overTimeError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1238
|
+
] }),
|
|
1239
|
+
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", className: "mt-1.5", children: [
|
|
1240
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Revenue breakdown (stacked — by order status)" }),
|
|
1241
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(168px,26vh)] min-h-[140px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1282
1242
|
recharts.ComposedChart,
|
|
1283
1243
|
{
|
|
1284
1244
|
data: dailyOrders,
|
|
1285
|
-
margin: { top: 4, right:
|
|
1245
|
+
margin: { top: 4, right: 8, left: -4, bottom: 0 },
|
|
1286
1246
|
children: [
|
|
1287
|
-
/* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
|
|
1288
|
-
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "ordersGradient", x1: "0", y1: "0", x2: "1", y2: "0", children: [
|
|
1289
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#67E8F9" }),
|
|
1290
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#3B82F6" })
|
|
1291
|
-
] }),
|
|
1292
|
-
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "revenueGradient", x1: "0", y1: "0", x2: "1", y2: "0", children: [
|
|
1293
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#F472B6" }),
|
|
1294
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#C084FC" })
|
|
1295
|
-
] }),
|
|
1296
|
-
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "ordersAreaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
1297
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#38BDF8", stopOpacity: 0.22 }),
|
|
1298
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#38BDF8", stopOpacity: 0 })
|
|
1299
|
-
] }),
|
|
1300
|
-
/* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "revenueAreaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
|
1301
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#E879F9", stopOpacity: 0.2 }),
|
|
1302
|
-
/* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#E879F9", stopOpacity: 0 })
|
|
1303
|
-
] })
|
|
1304
|
-
] }),
|
|
1305
1247
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1306
1248
|
recharts.CartesianGrid,
|
|
1307
1249
|
{
|
|
@@ -1326,156 +1268,85 @@ function OrdersDashboard() {
|
|
|
1326
1268
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1327
1269
|
recharts.YAxis,
|
|
1328
1270
|
{
|
|
1329
|
-
yAxisId: "orders",
|
|
1330
|
-
width: 32,
|
|
1331
|
-
tick: CHART_AXIS_TICK$2,
|
|
1332
|
-
tickLine: false,
|
|
1333
|
-
axisLine: false,
|
|
1334
|
-
allowDecimals: false,
|
|
1335
|
-
tickFormatter: (value) => Math.floor(Number(value) || 0).toLocaleString()
|
|
1336
|
-
}
|
|
1337
|
-
),
|
|
1338
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1339
|
-
recharts.YAxis,
|
|
1340
|
-
{
|
|
1341
|
-
yAxisId: "revenue",
|
|
1342
|
-
orientation: "right",
|
|
1343
|
-
width: 40,
|
|
1344
1271
|
tick: CHART_AXIS_TICK$2,
|
|
1345
|
-
|
|
1346
|
-
axisLine: false,
|
|
1347
|
-
tickFormatter: (value) => formatCompactCurrency$1(Number(value) || 0)
|
|
1272
|
+
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
1348
1273
|
}
|
|
1349
1274
|
),
|
|
1350
1275
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1351
1276
|
recharts.Tooltip,
|
|
1352
1277
|
{
|
|
1353
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1278
|
+
content: ({ active, payload, label }) => active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: payload.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1279
|
+
p.name,
|
|
1280
|
+
":",
|
|
1281
|
+
" ",
|
|
1282
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(Number(p.value) || 0) })
|
|
1283
|
+
] }, String(p.name))) }) : null
|
|
1358
1284
|
}
|
|
1359
1285
|
),
|
|
1286
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { wrapperStyle: { fontSize: 10 }, iconType: "circle" }),
|
|
1360
1287
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1361
1288
|
recharts.Area,
|
|
1362
1289
|
{
|
|
1363
|
-
yAxisId: "orders",
|
|
1364
1290
|
type: "natural",
|
|
1365
|
-
dataKey: "
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1291
|
+
dataKey: "revenue_delivered",
|
|
1292
|
+
name: "Delivered",
|
|
1293
|
+
stackId: "r",
|
|
1294
|
+
fill: "#10B981",
|
|
1295
|
+
stroke: "#059669",
|
|
1296
|
+
fillOpacity: 0.85
|
|
1370
1297
|
}
|
|
1371
1298
|
),
|
|
1372
1299
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1373
1300
|
recharts.Area,
|
|
1374
1301
|
{
|
|
1375
|
-
yAxisId: "revenue",
|
|
1376
|
-
type: "natural",
|
|
1377
|
-
dataKey: "total_revenue",
|
|
1378
|
-
stroke: "none",
|
|
1379
|
-
fill: "url(#revenueAreaFill)",
|
|
1380
|
-
isAnimationActive: false,
|
|
1381
|
-
legendType: "none"
|
|
1382
|
-
}
|
|
1383
|
-
),
|
|
1384
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1385
|
-
recharts.Line,
|
|
1386
|
-
{
|
|
1387
|
-
yAxisId: "orders",
|
|
1388
1302
|
type: "natural",
|
|
1389
|
-
dataKey: "
|
|
1390
|
-
name: "
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1303
|
+
dataKey: "revenue_open",
|
|
1304
|
+
name: "Open / pending",
|
|
1305
|
+
stackId: "r",
|
|
1306
|
+
fill: "#3B82F6",
|
|
1307
|
+
stroke: "#2563eb",
|
|
1308
|
+
fillOpacity: 0.85
|
|
1395
1309
|
}
|
|
1396
1310
|
),
|
|
1397
1311
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1398
|
-
recharts.
|
|
1312
|
+
recharts.Area,
|
|
1399
1313
|
{
|
|
1400
|
-
yAxisId: "revenue",
|
|
1401
1314
|
type: "natural",
|
|
1402
|
-
dataKey: "
|
|
1403
|
-
name: "
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1315
|
+
dataKey: "revenue_cancelled",
|
|
1316
|
+
name: "Cancelled",
|
|
1317
|
+
stackId: "r",
|
|
1318
|
+
fill: "#F87171",
|
|
1319
|
+
stroke: "#EF4444",
|
|
1320
|
+
fillOpacity: 0.75
|
|
1408
1321
|
}
|
|
1409
1322
|
)
|
|
1410
1323
|
]
|
|
1411
1324
|
}
|
|
1412
1325
|
) }) })
|
|
1413
1326
|
] })
|
|
1414
|
-
] })
|
|
1327
|
+
] }) : null
|
|
1415
1328
|
] })
|
|
1416
1329
|
}
|
|
1417
1330
|
) }),
|
|
1418
1331
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 flex flex-col gap-2 xl:col-span-6", children: [
|
|
1419
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1332
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1420
1333
|
AnalyticsSection,
|
|
1421
1334
|
{
|
|
1422
1335
|
variant: "atlas",
|
|
1423
1336
|
title: "Pulse & range",
|
|
1424
|
-
description: "Window totals
|
|
1425
|
-
children:
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
{
|
|
1429
|
-
|
|
1430
|
-
children:
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
)) }),
|
|
1438
|
-
!overTimeLoading && !overTimeError && dailyOrders.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", className: "mt-1.5", children: [
|
|
1439
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Orders (time series)" }),
|
|
1440
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[76px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1441
|
-
recharts.LineChart,
|
|
1442
|
-
{
|
|
1443
|
-
data: dailyOrders,
|
|
1444
|
-
margin: { top: 2, right: 4, left: -18, bottom: 2 },
|
|
1445
|
-
children: [
|
|
1446
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1447
|
-
recharts.CartesianGrid,
|
|
1448
|
-
{
|
|
1449
|
-
strokeDasharray: "3 3",
|
|
1450
|
-
vertical: false,
|
|
1451
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
1452
|
-
}
|
|
1453
|
-
),
|
|
1454
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
1455
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.YAxis, { hide: true, domain: ["auto", "auto"] }),
|
|
1456
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1457
|
-
recharts.Tooltip,
|
|
1458
|
-
{
|
|
1459
|
-
content: /* @__PURE__ */ jsxRuntime.jsx(OrdersSparklineTooltip, {}),
|
|
1460
|
-
cursor: { stroke: "rgba(148,163,184,0.35)", strokeWidth: 1 }
|
|
1461
|
-
}
|
|
1462
|
-
),
|
|
1463
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1464
|
-
recharts.Line,
|
|
1465
|
-
{
|
|
1466
|
-
type: "natural",
|
|
1467
|
-
dataKey: "orders_count",
|
|
1468
|
-
stroke: "#3b82f6",
|
|
1469
|
-
strokeWidth: 2,
|
|
1470
|
-
dot: { r: 2, fill: "#3b82f6" },
|
|
1471
|
-
activeDot: { r: 3 }
|
|
1472
|
-
}
|
|
1473
|
-
)
|
|
1474
|
-
]
|
|
1475
|
-
}
|
|
1476
|
-
) }) })
|
|
1477
|
-
] }) : null
|
|
1478
|
-
]
|
|
1337
|
+
description: "Window totals for the selected range.",
|
|
1338
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: quickPulseMetrics.map((metric) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1339
|
+
"div",
|
|
1340
|
+
{
|
|
1341
|
+
className: `rounded-lg border border-ui-border-base bg-ui-bg-base px-2 py-2 shadow-sm ${metric.accentClassName}`.trim(),
|
|
1342
|
+
children: [
|
|
1343
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: metric.label }),
|
|
1344
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base mt-0.5 text-sm font-semibold tracking-tight", children: metric.value }),
|
|
1345
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted mt-0.5 text-[9px] leading-snug", children: metric.helper })
|
|
1346
|
+
]
|
|
1347
|
+
},
|
|
1348
|
+
metric.label
|
|
1349
|
+
)) })
|
|
1479
1350
|
}
|
|
1480
1351
|
),
|
|
1481
1352
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1483,7 +1354,7 @@ function OrdersDashboard() {
|
|
|
1483
1354
|
{
|
|
1484
1355
|
variant: "atlas",
|
|
1485
1356
|
title: "Order → fulfillment funnel",
|
|
1486
|
-
description: `Stages by order created date (UTC), same range as Revenue & orders (${((
|
|
1357
|
+
description: `Stages by order created date (UTC), same range as Revenue & orders (${((_b = OVER_TIME_PERIODS.find((p) => p.value === overTimePeriod)) == null ? void 0 : _b.label) ?? "period"}). Not storefront visitors.`,
|
|
1487
1358
|
children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[120px] items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) }) : overTimeError ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[120px] items-center justify-center px-2 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: overTimeError }) }) }) : funnelTimeSeriesRows.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1488
1359
|
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
1489
1360
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Stage counts (time series)" }),
|
|
@@ -1714,21 +1585,6 @@ function OrdersDashboard() {
|
|
|
1714
1585
|
}
|
|
1715
1586
|
)
|
|
1716
1587
|
}
|
|
1717
|
-
),
|
|
1718
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1719
|
-
AnalyticsSection,
|
|
1720
|
-
{
|
|
1721
|
-
variant: "atlas",
|
|
1722
|
-
title: "Order revenue (attribution)",
|
|
1723
|
-
description: "All revenue is from captured Medusa orders until storefront channel data exists.",
|
|
1724
|
-
children: insightsLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) : insightsError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center px-2 py-3", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: insightsError }) }) : ordersInsights && ordersInsights.traffic.length > 0 ? trafficTotalRevenue <= 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted px-0.5 text-center text-[11px] leading-snug", children: "No recorded revenue in this window (totals may be zero until orders are paid or finalized)." }) : /* @__PURE__ */ jsxRuntime.jsx(TrafficRevenueDonut, { traffic: ordersInsights.traffic }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1725
|
-
EmptyAnalyticsPanel$1,
|
|
1726
|
-
{
|
|
1727
|
-
title: "No order revenue",
|
|
1728
|
-
description: "No orders in this window."
|
|
1729
|
-
}
|
|
1730
|
-
)
|
|
1731
|
-
}
|
|
1732
1588
|
)
|
|
1733
1589
|
] })
|
|
1734
1590
|
] }),
|
|
@@ -1970,86 +1826,46 @@ function OrdersDashboard() {
|
|
|
1970
1826
|
}
|
|
1971
1827
|
)
|
|
1972
1828
|
] }),
|
|
1973
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 grid grid-cols-1 items-start gap-
|
|
1829
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 grid grid-cols-1 items-start gap-3 xl:grid-cols-12", children: [
|
|
1974
1830
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1975
1831
|
AnalyticsSection,
|
|
1976
1832
|
{
|
|
1977
1833
|
variant: "atlas",
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1834
|
+
className: "xl:col-span-8",
|
|
1835
|
+
title: "Sales breakdown",
|
|
1836
|
+
description: salesBreakdownDescription,
|
|
1837
|
+
actionsBare: true,
|
|
1838
|
+
actions: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1839
|
+
"div",
|
|
1982
1840
|
{
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
vertical: false,
|
|
1991
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
1992
|
-
}
|
|
1993
|
-
),
|
|
1994
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1995
|
-
recharts.XAxis,
|
|
1996
|
-
{
|
|
1997
|
-
dataKey: "label",
|
|
1998
|
-
tick: CHART_AXIS_TICK$2
|
|
1999
|
-
}
|
|
2000
|
-
),
|
|
2001
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2002
|
-
recharts.YAxis,
|
|
2003
|
-
{
|
|
2004
|
-
width: 40,
|
|
2005
|
-
tick: CHART_AXIS_TICK_SM$1,
|
|
2006
|
-
tickFormatter: (v) => formatCompactCurrency$1(Number(v))
|
|
2007
|
-
}
|
|
2008
|
-
),
|
|
2009
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2010
|
-
recharts.Tooltip,
|
|
1841
|
+
className: "flex flex-wrap items-center gap-1 rounded-lg border border-ui-border-base bg-ui-bg-subtle/40 p-0.5",
|
|
1842
|
+
role: "tablist",
|
|
1843
|
+
"aria-label": "Sales breakdown granularity",
|
|
1844
|
+
children: SALES_GRANULARITY_TABS.map((tab) => {
|
|
1845
|
+
const selected = salesGranularity === tab.value;
|
|
1846
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1847
|
+
"button",
|
|
2011
1848
|
{
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
) })
|
|
2023
|
-
] }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2025
|
-
"Orders:",
|
|
2026
|
-
" ",
|
|
2027
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(
|
|
2028
|
-
Number(
|
|
2029
|
-
(_b2 = payload.find((p) => p.dataKey === "orders_count")) == null ? void 0 : _b2.value
|
|
2030
|
-
) || 0
|
|
2031
|
-
).toLocaleString() })
|
|
2032
|
-
] })
|
|
2033
|
-
] }) : null;
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
),
|
|
2037
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "revenue", name: "Revenue", fill: "#D946EF", radius: [4, 4, 0, 0] })
|
|
2038
|
-
]
|
|
2039
|
-
}
|
|
2040
|
-
) }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2041
|
-
EmptyAnalyticsPanel$1,
|
|
2042
|
-
{
|
|
2043
|
-
title: "No weekday data",
|
|
2044
|
-
description: "No orders in this window."
|
|
1849
|
+
type: "button",
|
|
1850
|
+
role: "tab",
|
|
1851
|
+
"aria-selected": selected,
|
|
1852
|
+
onClick: () => setSalesGranularity(tab.value),
|
|
1853
|
+
className: `rounded-md px-2.5 py-1.5 text-xs font-medium transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ui-fg-interactive ${selected ? "bg-ui-bg-base text-ui-fg-base shadow-sm" : "text-ui-fg-muted hover:text-ui-fg-base"}`,
|
|
1854
|
+
children: tab.label
|
|
1855
|
+
},
|
|
1856
|
+
tab.value
|
|
1857
|
+
);
|
|
1858
|
+
})
|
|
2045
1859
|
}
|
|
2046
|
-
)
|
|
1860
|
+
),
|
|
1861
|
+
children: salesBreakdownBody
|
|
2047
1862
|
}
|
|
2048
1863
|
),
|
|
2049
1864
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2050
1865
|
AnalyticsSection,
|
|
2051
1866
|
{
|
|
2052
1867
|
variant: "atlas",
|
|
1868
|
+
className: "xl:col-span-4",
|
|
2053
1869
|
title: "Placed orders vs drafts",
|
|
2054
1870
|
description: "Window order count vs current open draft orders (admin). Not storefront cart abandonment.",
|
|
2055
1871
|
children: insightsLoading ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) }) : insightsError ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center px-2 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: insightsError }) }) }) : ordersVsDraftsPie.some((s) => s.value > 0) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
@@ -2108,82 +1924,6 @@ function OrdersDashboard() {
|
|
|
2108
1924
|
}
|
|
2109
1925
|
)
|
|
2110
1926
|
}
|
|
2111
|
-
),
|
|
2112
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2113
|
-
AnalyticsSection,
|
|
2114
|
-
{
|
|
2115
|
-
variant: "atlas",
|
|
2116
|
-
title: "Sales by hour (UTC)",
|
|
2117
|
-
description: `Orders created by hour — last ${insightsWindowDays} days.`,
|
|
2118
|
-
children: insightsLoading ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) }) : insightsError ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[100px] items-center justify-center px-2 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: insightsError }) }) }) : hourlyChartRows.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(176px,28vh)] min-h-[148px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2119
|
-
recharts.BarChart,
|
|
2120
|
-
{
|
|
2121
|
-
data: hourlyChartRows,
|
|
2122
|
-
margin: { top: 2, right: 4, left: -8, bottom: 2 },
|
|
2123
|
-
children: [
|
|
2124
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2125
|
-
recharts.CartesianGrid,
|
|
2126
|
-
{
|
|
2127
|
-
strokeDasharray: "3 3",
|
|
2128
|
-
vertical: false,
|
|
2129
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
2130
|
-
}
|
|
2131
|
-
),
|
|
2132
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2133
|
-
recharts.XAxis,
|
|
2134
|
-
{
|
|
2135
|
-
dataKey: "label",
|
|
2136
|
-
interval: 3,
|
|
2137
|
-
tick: CHART_AXIS_TICK_SM$1
|
|
2138
|
-
}
|
|
2139
|
-
),
|
|
2140
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2141
|
-
recharts.YAxis,
|
|
2142
|
-
{
|
|
2143
|
-
width: 28,
|
|
2144
|
-
tick: CHART_AXIS_TICK$2,
|
|
2145
|
-
allowDecimals: false
|
|
2146
|
-
}
|
|
2147
|
-
),
|
|
2148
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2149
|
-
recharts.Tooltip,
|
|
2150
|
-
{
|
|
2151
|
-
content: ({ active, payload, label }) => {
|
|
2152
|
-
var _a2, _b2;
|
|
2153
|
-
return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
|
|
2154
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2155
|
-
"Orders:",
|
|
2156
|
-
" ",
|
|
2157
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(
|
|
2158
|
-
Number(
|
|
2159
|
-
(_a2 = payload.find((p) => p.dataKey === "orders_count")) == null ? void 0 : _a2.value
|
|
2160
|
-
) || 0
|
|
2161
|
-
).toLocaleString() })
|
|
2162
|
-
] }),
|
|
2163
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2164
|
-
"Revenue:",
|
|
2165
|
-
" ",
|
|
2166
|
-
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency$1(
|
|
2167
|
-
Number(
|
|
2168
|
-
(_b2 = payload.find((p) => p.dataKey === "revenue")) == null ? void 0 : _b2.value
|
|
2169
|
-
) || 0
|
|
2170
|
-
) })
|
|
2171
|
-
] })
|
|
2172
|
-
] }) : null;
|
|
2173
|
-
}
|
|
2174
|
-
}
|
|
2175
|
-
),
|
|
2176
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "orders_count", name: "Orders", fill: "#38BDF8", radius: [4, 4, 0, 0] })
|
|
2177
|
-
]
|
|
2178
|
-
}
|
|
2179
|
-
) }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2180
|
-
EmptyAnalyticsPanel$1,
|
|
2181
|
-
{
|
|
2182
|
-
title: "No hourly data",
|
|
2183
|
-
description: "No orders in this window."
|
|
2184
|
-
}
|
|
2185
|
-
)
|
|
2186
|
-
}
|
|
2187
1927
|
)
|
|
2188
1928
|
] })
|
|
2189
1929
|
] })
|
|
@@ -2897,7 +2637,7 @@ function EmptyAnalyticsPanel({ title, description }) {
|
|
|
2897
2637
|
] });
|
|
2898
2638
|
}
|
|
2899
2639
|
function ProductsDashboard() {
|
|
2900
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j
|
|
2640
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
2901
2641
|
const [summaryDays, setSummaryDays] = react.useState("all");
|
|
2902
2642
|
const [graphPeriod, setGraphPeriod] = react.useState("one_week");
|
|
2903
2643
|
const [topSellerPeriod, setTopSellerPeriod] = react.useState("week");
|
|
@@ -3024,7 +2764,7 @@ function ProductsDashboard() {
|
|
|
3024
2764
|
};
|
|
3025
2765
|
}, [salesChannelId, topSellerPeriod]);
|
|
3026
2766
|
react.useEffect(() => {
|
|
3027
|
-
var _a2
|
|
2767
|
+
var _a2;
|
|
3028
2768
|
let cancelled = false;
|
|
3029
2769
|
if (topSellersLoading) {
|
|
3030
2770
|
setBestSellersTrendLoading(true);
|
|
@@ -3040,7 +2780,12 @@ function ProductsDashboard() {
|
|
|
3040
2780
|
cancelled = true;
|
|
3041
2781
|
};
|
|
3042
2782
|
}
|
|
3043
|
-
const
|
|
2783
|
+
const topSellersByUnits2 = [...(topSellers == null ? void 0 : topSellers.products) ?? []].sort((a, b) => {
|
|
2784
|
+
if (b.units_sold !== a.units_sold) return b.units_sold - a.units_sold;
|
|
2785
|
+
if (b.order_count !== a.order_count) return b.order_count - a.order_count;
|
|
2786
|
+
return b.revenue - a.revenue;
|
|
2787
|
+
});
|
|
2788
|
+
const topProductId = (_a2 = topSellersByUnits2[0]) == null ? void 0 : _a2.product_id;
|
|
3044
2789
|
if (!topProductId) {
|
|
3045
2790
|
setBestSellersTrendLoading(false);
|
|
3046
2791
|
setBestSellersTrendError(null);
|
|
@@ -3186,16 +2931,24 @@ function ProductsDashboard() {
|
|
|
3186
2931
|
}, [series]);
|
|
3187
2932
|
const peakRevenuePoint = series.length > 0 ? series.reduce((peak, point) => point.revenue > peak.revenue ? point : peak) : null;
|
|
3188
2933
|
const viewsConnectedForPulse = ((summary == null ? void 0 : summary.productViewsConnected) ?? false) || (overTime == null ? void 0 : overTime.productViewsConnected) === true || (topSellers == null ? void 0 : topSellers.productViewsConnected) === true || (performance == null ? void 0 : performance.productViewsConnected) === true;
|
|
2934
|
+
const topSellersByUnits = react.useMemo(
|
|
2935
|
+
() => [...(topSellers == null ? void 0 : topSellers.products) ?? []].sort((a, b) => {
|
|
2936
|
+
if (b.units_sold !== a.units_sold) return b.units_sold - a.units_sold;
|
|
2937
|
+
if (b.order_count !== a.order_count) return b.order_count - a.order_count;
|
|
2938
|
+
return b.revenue - a.revenue;
|
|
2939
|
+
}),
|
|
2940
|
+
[topSellers]
|
|
2941
|
+
);
|
|
3189
2942
|
const bestSellersTrendSeries = (bestSellersTrend == null ? void 0 : bestSellersTrend.series) ?? [];
|
|
3190
2943
|
const mostViewedTrendSeries = (mostViewedTrend == null ? void 0 : mostViewedTrend.series) ?? [];
|
|
3191
|
-
const bestSellerTrendProductTitle = ((_a = bestSellersTrend == null ? void 0 : bestSellersTrend.product) == null ? void 0 : _a.product_title) ?? ((
|
|
3192
|
-
const mostViewedTrendProductTitle = ((
|
|
2944
|
+
const bestSellerTrendProductTitle = ((_a = bestSellersTrend == null ? void 0 : bestSellersTrend.product) == null ? void 0 : _a.product_title) ?? ((_b = topSellersByUnits[0]) == null ? void 0 : _b.product_title) ?? null;
|
|
2945
|
+
const mostViewedTrendProductTitle = ((_c = mostViewedTrend == null ? void 0 : mostViewedTrend.product) == null ? void 0 : _c.product_title) ?? ((_e = (_d = performance == null ? void 0 : performance.topViewedProducts) == null ? void 0 : _d[0]) == null ? void 0 : _e.product_title) ?? null;
|
|
3193
2946
|
const viewsVsUnitsScatterData = react.useMemo(
|
|
3194
2947
|
() => ((performance == null ? void 0 : performance.topViewedProducts) ?? []).slice(0, 48).filter((row) => row.total_views > 0 || row.units_sold > 0),
|
|
3195
2948
|
[performance]
|
|
3196
2949
|
);
|
|
3197
|
-
const selectedSummaryPeriod = ((
|
|
3198
|
-
const selectedGraphPeriodLabel = ((
|
|
2950
|
+
const selectedSummaryPeriod = ((_f = SUMMARY_PERIODS.find((p) => p.value === summaryDays)) == null ? void 0 : _f.label) ?? "All time";
|
|
2951
|
+
const selectedGraphPeriodLabel = ((_g = GRAPH_PERIODS.find((p) => p.value === graphPeriod)) == null ? void 0 : _g.label) ?? "One week";
|
|
3199
2952
|
const quickPulseMetrics = [
|
|
3200
2953
|
{
|
|
3201
2954
|
label: "Range units",
|
|
@@ -3237,7 +2990,7 @@ function ProductsDashboard() {
|
|
|
3237
2990
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: summaryError ?? "Failed to load product analytics" }) });
|
|
3238
2991
|
}
|
|
3239
2992
|
const viewsConnected = summary.productViewsConnected || (overTime == null ? void 0 : overTime.productViewsConnected) === true || (topSellers == null ? void 0 : topSellers.productViewsConnected) === true || (performance == null ? void 0 : performance.productViewsConnected) === true;
|
|
3240
|
-
const selectedChannelLabel = salesChannelId === "all" ? "All channels" : ((
|
|
2993
|
+
const selectedChannelLabel = salesChannelId === "all" ? "All channels" : ((_h = salesChannels.find((channel) => channel.id === salesChannelId)) == null ? void 0 : _h.name) ?? "Selected channel";
|
|
3241
2994
|
const primaryStats = [
|
|
3242
2995
|
{
|
|
3243
2996
|
label: "Units sold",
|
|
@@ -3406,9 +3159,9 @@ function ProductsDashboard() {
|
|
|
3406
3159
|
}
|
|
3407
3160
|
)
|
|
3408
3161
|
] }),
|
|
3409
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
3410
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-
|
|
3411
|
-
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3162
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3163
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-2 sm:grid-cols-3 sm:gap-1.5", children: [
|
|
3164
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3412
3165
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window units" }),
|
|
3413
3166
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatShortNumber(trendTotals.totalUnits) }),
|
|
3414
3167
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
|
|
@@ -3416,7 +3169,7 @@ function ProductsDashboard() {
|
|
|
3416
3169
|
trendTotals.avgUnitsPerDay.toFixed(1)
|
|
3417
3170
|
] })
|
|
3418
3171
|
] }) }),
|
|
3419
|
-
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3172
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3420
3173
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window revenue" }),
|
|
3421
3174
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatCompactCurrency(trendTotals.totalRevenue) }),
|
|
3422
3175
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
|
|
@@ -3424,7 +3177,7 @@ function ProductsDashboard() {
|
|
|
3424
3177
|
formatCompactCurrency(trendTotals.avgRevenuePerDay)
|
|
3425
3178
|
] })
|
|
3426
3179
|
] }) }),
|
|
3427
|
-
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3180
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
|
|
3428
3181
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window views" }),
|
|
3429
3182
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatShortNumber(trendTotals.totalViews) }),
|
|
3430
3183
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
|
|
@@ -3433,131 +3186,6 @@ function ProductsDashboard() {
|
|
|
3433
3186
|
] })
|
|
3434
3187
|
] }) })
|
|
3435
3188
|
] }),
|
|
3436
|
-
!overTimeLoading && !overTimeError && series.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-1.5 md:grid-cols-3", children: [
|
|
3437
|
-
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
3438
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Units sold" }),
|
|
3439
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[96px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3440
|
-
recharts.LineChart,
|
|
3441
|
-
{
|
|
3442
|
-
data: series,
|
|
3443
|
-
margin: { top: 4, right: 4, left: 0, bottom: 0 },
|
|
3444
|
-
children: [
|
|
3445
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3446
|
-
recharts.CartesianGrid,
|
|
3447
|
-
{
|
|
3448
|
-
strokeDasharray: "3 3",
|
|
3449
|
-
vertical: false,
|
|
3450
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
3451
|
-
}
|
|
3452
|
-
),
|
|
3453
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
3454
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3455
|
-
recharts.YAxis,
|
|
3456
|
-
{
|
|
3457
|
-
width: 28,
|
|
3458
|
-
tick: CHART_AXIS_TICK_SM,
|
|
3459
|
-
allowDecimals: false
|
|
3460
|
-
}
|
|
3461
|
-
),
|
|
3462
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MiniTrendTooltip, {}) }),
|
|
3463
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3464
|
-
recharts.Line,
|
|
3465
|
-
{
|
|
3466
|
-
type: "natural",
|
|
3467
|
-
dataKey: "units_sold",
|
|
3468
|
-
name: "Units sold",
|
|
3469
|
-
stroke: PRODUCT_CHART_COLORS.units,
|
|
3470
|
-
strokeWidth: 2,
|
|
3471
|
-
dot: false
|
|
3472
|
-
}
|
|
3473
|
-
)
|
|
3474
|
-
]
|
|
3475
|
-
}
|
|
3476
|
-
) }) })
|
|
3477
|
-
] }),
|
|
3478
|
-
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
3479
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Views" }),
|
|
3480
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[96px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3481
|
-
recharts.LineChart,
|
|
3482
|
-
{
|
|
3483
|
-
data: series,
|
|
3484
|
-
margin: { top: 4, right: 4, left: 0, bottom: 0 },
|
|
3485
|
-
children: [
|
|
3486
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3487
|
-
recharts.CartesianGrid,
|
|
3488
|
-
{
|
|
3489
|
-
strokeDasharray: "3 3",
|
|
3490
|
-
vertical: false,
|
|
3491
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
3492
|
-
}
|
|
3493
|
-
),
|
|
3494
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
3495
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3496
|
-
recharts.YAxis,
|
|
3497
|
-
{
|
|
3498
|
-
width: 28,
|
|
3499
|
-
tick: CHART_AXIS_TICK_SM,
|
|
3500
|
-
allowDecimals: false
|
|
3501
|
-
}
|
|
3502
|
-
),
|
|
3503
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MiniTrendTooltip, {}) }),
|
|
3504
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3505
|
-
recharts.Line,
|
|
3506
|
-
{
|
|
3507
|
-
type: "natural",
|
|
3508
|
-
dataKey: "views",
|
|
3509
|
-
name: "Views",
|
|
3510
|
-
stroke: PRODUCT_CHART_COLORS.views,
|
|
3511
|
-
strokeWidth: 2,
|
|
3512
|
-
dot: false
|
|
3513
|
-
}
|
|
3514
|
-
)
|
|
3515
|
-
]
|
|
3516
|
-
}
|
|
3517
|
-
) }) })
|
|
3518
|
-
] }),
|
|
3519
|
-
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
|
|
3520
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mb-0.5 text-[10px] font-medium uppercase tracking-[0.14em] text-ui-fg-muted", children: "Revenue" }),
|
|
3521
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[96px] w-full", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3522
|
-
recharts.LineChart,
|
|
3523
|
-
{
|
|
3524
|
-
data: series,
|
|
3525
|
-
margin: { top: 4, right: 4, left: 0, bottom: 0 },
|
|
3526
|
-
children: [
|
|
3527
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3528
|
-
recharts.CartesianGrid,
|
|
3529
|
-
{
|
|
3530
|
-
strokeDasharray: "3 3",
|
|
3531
|
-
vertical: false,
|
|
3532
|
-
stroke: "rgba(148,163,184,0.12)"
|
|
3533
|
-
}
|
|
3534
|
-
),
|
|
3535
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "date", hide: true }),
|
|
3536
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3537
|
-
recharts.YAxis,
|
|
3538
|
-
{
|
|
3539
|
-
width: 36,
|
|
3540
|
-
tick: CHART_AXIS_TICK_SM,
|
|
3541
|
-
tickFormatter: (v) => formatCompactCurrency(Number(v))
|
|
3542
|
-
}
|
|
3543
|
-
),
|
|
3544
|
-
/* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MiniTrendTooltip, {}) }),
|
|
3545
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3546
|
-
recharts.Line,
|
|
3547
|
-
{
|
|
3548
|
-
type: "natural",
|
|
3549
|
-
dataKey: "revenue",
|
|
3550
|
-
name: "Revenue",
|
|
3551
|
-
stroke: PRODUCT_CHART_COLORS.revenue,
|
|
3552
|
-
strokeWidth: 2,
|
|
3553
|
-
dot: false
|
|
3554
|
-
}
|
|
3555
|
-
)
|
|
3556
|
-
]
|
|
3557
|
-
}
|
|
3558
|
-
) }) })
|
|
3559
|
-
] })
|
|
3560
|
-
] }) : null,
|
|
3561
3189
|
/* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", className: "relative overflow-hidden", children: [
|
|
3562
3190
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute inset-x-6 top-0 h-12 rounded-b-full bg-gradient-to-r from-sky-400/10 via-fuchsia-400/10 to-transparent blur-xl" }),
|
|
3563
3191
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative space-y-1", children: [
|
|
@@ -3783,7 +3411,7 @@ function ProductsDashboard() {
|
|
|
3783
3411
|
variant: "atlas",
|
|
3784
3412
|
actionsBare: true,
|
|
3785
3413
|
title: "Best sellers",
|
|
3786
|
-
description: bestSellerTrendProductTitle ? `Revenue and units over time for “${bestSellerTrendProductTitle}” (#1 by
|
|
3414
|
+
description: bestSellerTrendProductTitle ? `Revenue and units over time for “${bestSellerTrendProductTitle}” (#1 by units sold in this window; all-time uses a 12‑month chart).` : "Revenue and units over time for the top product by units sold in this window (all-time leaderboard uses a 12‑month chart).",
|
|
3787
3415
|
actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
3788
3416
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3789
3417
|
ui.Label,
|
|
@@ -3947,7 +3575,7 @@ function ProductsDashboard() {
|
|
|
3947
3575
|
variant: "atlas",
|
|
3948
3576
|
className: "min-w-0 md:col-span-1 xl:col-span-1",
|
|
3949
3577
|
title: "Leaderboard table",
|
|
3950
|
-
description: "Products ranked by
|
|
3578
|
+
description: "Products ranked by units sold — same window as Best sellers.",
|
|
3951
3579
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-[212px] min-w-0 sm:min-h-[228px]", children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTableSurface, { className: "shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { className: LEADERBOARD_TABLE_CLASS, children: [
|
|
3952
3580
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
3953
3581
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Product" }),
|
|
@@ -3962,12 +3590,12 @@ function ProductsDashboard() {
|
|
|
3962
3590
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
|
|
3963
3591
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
|
|
3964
3592
|
] }) : null,
|
|
3965
|
-
!topSellersError ?
|
|
3966
|
-
var _a2
|
|
3593
|
+
!topSellersError ? topSellersByUnits.slice(0, 8).map((product) => {
|
|
3594
|
+
var _a2;
|
|
3967
3595
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3968
3596
|
ui.Table.Row,
|
|
3969
3597
|
{
|
|
3970
|
-
className: product.product_id === ((
|
|
3598
|
+
className: product.product_id === ((_a2 = topSellersByUnits[0]) == null ? void 0 : _a2.product_id) ? "bg-emerald-500/5" : void 0,
|
|
3971
3599
|
children: [
|
|
3972
3600
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
|
|
3973
3601
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
|
|
@@ -3978,7 +3606,7 @@ function ProductsDashboard() {
|
|
|
3978
3606
|
product.product_id
|
|
3979
3607
|
);
|
|
3980
3608
|
}) : null,
|
|
3981
|
-
!topSellersLoading && !topSellersError && (((
|
|
3609
|
+
!topSellersLoading && !topSellersError && (((_i = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _i.length) ?? 0) === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
3982
3610
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No best seller data yet." }) }),
|
|
3983
3611
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
|
|
3984
3612
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
|
|
@@ -4134,7 +3762,7 @@ function ProductsDashboard() {
|
|
|
4134
3762
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
|
|
4135
3763
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatRatio(product.views_per_unit) })
|
|
4136
3764
|
] }, product.product_id)),
|
|
4137
|
-
!performanceLoading && !performanceError && (((
|
|
3765
|
+
!performanceLoading && !performanceError && (((_j = performance == null ? void 0 : performance.viewOpportunities) == null ? void 0 : _j.length) ?? 0) === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
4138
3766
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No product view opportunities yet." }) }),
|
|
4139
3767
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
|
|
4140
3768
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
|