medusa-analytics 0.0.18 → 0.0.20

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.
@@ -40,8 +40,8 @@ const ACCENT_STYLES = {
40
40
  function getAccentStyle(accent) {
41
41
  return ACCENT_STYLES[accent];
42
42
  }
43
- function AnalyticsDashboardShell({ children }) {
44
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2.5 md:space-y-3", children });
43
+ function AnalyticsDashboardShell({ children, className }) {
44
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: ["space-y-2.5 md:space-y-3", className].filter(Boolean).join(" "), children });
45
45
  }
46
46
  function AnalyticsDashboardHeader({
47
47
  title,
@@ -49,20 +49,30 @@ function AnalyticsDashboardHeader({
49
49
  actions,
50
50
  variant = "default",
51
51
  actionsBare = false,
52
- appearance = "card"
52
+ appearance = "card",
53
+ actionsClassName
53
54
  }) {
54
55
  const isPremium = variant === "premium";
55
56
  const isInset = appearance === "inset";
56
57
  const headerRow = /* @__PURE__ */ jsxRuntime.jsxs(
57
58
  "div",
58
59
  {
59
- className: `flex flex-col gap-2 px-4 py-2.5 lg:flex-row lg:items-center lg:justify-between ${isPremium ? "border-b border-ui-border-base/80" : "border-b border-ui-border-base"}`.trim(),
60
+ className: `flex flex-col gap-2 px-4 py-2.5 lg:flex-row lg:items-center lg:justify-between lg:gap-4 ${isPremium ? "border-b border-ui-border-base/80" : "border-b border-ui-border-base"}`.trim(),
60
61
  children: [
61
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
62
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 flex-1 space-y-0.5", children: [
62
63
  /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: isPremium ? "text-lg font-semibold tracking-tight" : "tracking-tight", children: title }),
63
64
  description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: `text-ui-fg-muted ${isPremium ? "max-w-2xl text-xs leading-snug" : "text-sm"}`.trim(), children: description }) : null
64
65
  ] }),
65
- actions ? actionsBare ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-3 self-start lg:self-auto", children: actions }) : /* @__PURE__ */ jsxRuntime.jsx(
66
+ actions ? actionsBare ? /* @__PURE__ */ jsxRuntime.jsx(
67
+ "div",
68
+ {
69
+ className: [
70
+ "flex flex-wrap items-center gap-3 self-start lg:shrink-0 lg:self-auto",
71
+ actionsClassName ?? ""
72
+ ].join(" ").trim(),
73
+ children: actions
74
+ }
75
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
66
76
  "div",
67
77
  {
68
78
  className: `flex self-start rounded-xl border px-2 py-1.5 lg:self-auto ${isPremium ? "border-ui-border-strong bg-ui-bg-subtle shadow-[inset_0_1px_0_rgba(255,255,255,0.35)]" : "border-ui-border-base bg-ui-bg-subtle"}`.trim(),
@@ -156,7 +166,7 @@ function AnalyticsSection({
156
166
  }) {
157
167
  const isAtlas = variant === "atlas";
158
168
  const isPremium = variant !== "default" && !isAtlas;
159
- const shellClass = isAtlas ? "overflow-hidden rounded-lg border border-ui-border-base bg-ui-bg-base shadow-sm" : `overflow-hidden rounded-2xl border bg-ui-bg-base p-0 ${isPremium ? "border-ui-border-strong shadow-sm" : "border-ui-border-base shadow-sm"}`.trim();
169
+ const shellClass = isAtlas ? "min-w-0 overflow-x-clip overflow-y-visible rounded-lg border border-ui-border-base bg-ui-bg-base shadow-sm" : `overflow-hidden rounded-2xl border bg-ui-bg-base p-0 ${isPremium ? "border-ui-border-strong shadow-sm" : "border-ui-border-base shadow-sm"}`.trim();
160
170
  const headerClass = isAtlas ? "flex flex-col gap-1 border-b border-ui-border-base bg-ui-bg-subtle/40 px-3 py-2 lg:flex-row lg:items-center lg:justify-between" : `flex flex-col gap-2 px-4 py-2.5 lg:flex-row lg:items-center lg:justify-between ${isPremium ? "border-b border-ui-border-base/80" : "border-b border-ui-border-base"}`.trim();
161
171
  const titleClass = isAtlas ? "text-sm font-semibold tracking-tight text-ui-fg-base" : isPremium ? "text-base font-semibold tracking-tight" : "tracking-tight";
162
172
  const descClass = isAtlas ? "max-w-2xl text-[11px] leading-snug text-ui-fg-muted" : isPremium ? "max-w-2xl text-xs leading-snug" : "text-sm";
@@ -191,11 +201,55 @@ function AnalyticsTableSurface({ children, className }) {
191
201
  return /* @__PURE__ */ jsxRuntime.jsx(
192
202
  "div",
193
203
  {
194
- className: `overflow-hidden rounded-xl border border-ui-border-base bg-ui-bg-base ${className ?? ""}`.trim(),
204
+ className: [
205
+ "min-w-0 overflow-x-auto overflow-y-visible rounded-xl border border-ui-border-base bg-ui-bg-base",
206
+ "[scrollbar-width:thin]",
207
+ className ?? ""
208
+ ].join(" ").trim(),
195
209
  children
196
210
  }
197
211
  );
198
212
  }
213
+ function AnalyticsTooltipCard({
214
+ title,
215
+ children,
216
+ variant = "default"
217
+ }) {
218
+ const compact = variant === "compact";
219
+ return /* @__PURE__ */ jsxRuntime.jsxs(
220
+ "div",
221
+ {
222
+ style: {
223
+ background: "linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(248,250,252,0.96) 100%)",
224
+ color: "#111827",
225
+ border: "1px solid rgba(148, 163, 184, 0.18)",
226
+ borderRadius: compact ? "8px" : "14px",
227
+ padding: compact ? "5px 8px" : "12px 14px",
228
+ boxShadow: compact ? "0 6px 16px rgba(15, 23, 42, 0.1)" : "0 16px 40px rgba(15, 23, 42, 0.12)",
229
+ fontSize: compact ? "11px" : "13px",
230
+ lineHeight: compact ? 1.35 : 1.5,
231
+ minWidth: compact ? 0 : 176,
232
+ maxWidth: compact ? "min(92vw, 200px)" : "min(96vw, 380px)"
233
+ },
234
+ children: [
235
+ /* @__PURE__ */ jsxRuntime.jsx(
236
+ "div",
237
+ {
238
+ style: {
239
+ fontWeight: 600,
240
+ marginBottom: compact ? "2px" : "6px",
241
+ fontSize: compact ? "10px" : "inherit",
242
+ lineHeight: compact ? 1.25 : 1.35,
243
+ wordBreak: "break-word"
244
+ },
245
+ children: title
246
+ }
247
+ ),
248
+ children
249
+ ]
250
+ }
251
+ );
252
+ }
199
253
  function isDailyOrderRow(value) {
200
254
  if (typeof value !== "object" || value === null) return false;
201
255
  const v = value;
@@ -225,7 +279,7 @@ function formatCurrency$1(value) {
225
279
  maximumFractionDigits: 0
226
280
  }).format(value);
227
281
  }
228
- function formatCompactCurrency(value) {
282
+ function formatCompactCurrency$1(value) {
229
283
  return new Intl.NumberFormat("en-IN", {
230
284
  style: "currency",
231
285
  currency: "INR",
@@ -233,7 +287,7 @@ function formatCompactCurrency(value) {
233
287
  maximumFractionDigits: 1
234
288
  }).format(value);
235
289
  }
236
- function formatChartLabel(value) {
290
+ function formatChartLabel$2(value) {
237
291
  if (!value) return "";
238
292
  const parsed = new Date(value);
239
293
  if (Number.isNaN(parsed.getTime())) return value;
@@ -248,37 +302,12 @@ function ordersCountFromPiePayload(payload) {
248
302
  const c = payload.orders_count;
249
303
  return Math.floor(Number(c) || 0);
250
304
  }
251
- function formatShortNumber(value) {
305
+ function formatShortNumber$1(value) {
252
306
  return new Intl.NumberFormat("en-IN", {
253
307
  notation: "compact",
254
308
  maximumFractionDigits: value < 10 ? 1 : 0
255
309
  }).format(value);
256
310
  }
257
- function TooltipCard({
258
- title,
259
- children
260
- }) {
261
- return /* @__PURE__ */ jsxRuntime.jsxs(
262
- "div",
263
- {
264
- style: {
265
- background: "linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(248,250,252,0.96) 100%)",
266
- color: "#111827",
267
- border: "1px solid rgba(148, 163, 184, 0.18)",
268
- borderRadius: "14px",
269
- padding: "12px 14px",
270
- boxShadow: "0 16px 40px rgba(15, 23, 42, 0.12)",
271
- fontSize: "13px",
272
- lineHeight: 1.5,
273
- minWidth: "176px"
274
- },
275
- children: [
276
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, marginBottom: "6px" }, children: title }),
277
- children
278
- ]
279
- }
280
- );
281
- }
282
311
  function OrdersTrendTooltip({
283
312
  active,
284
313
  payload,
@@ -290,7 +319,7 @@ function OrdersTrendTooltip({
290
319
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
291
320
  const orders = ((_c = payload.find((entry) => entry.name === "Orders")) == null ? void 0 : _c.value) ?? 0;
292
321
  const revenue = ((_d = payload.find((entry) => entry.name === "Revenue")) == null ? void 0 : _d.value) ?? 0;
293
- return /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: displayLabel, children: [
322
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { title: displayLabel, children: [
294
323
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
295
324
  "Orders: ",
296
325
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(orders).toLocaleString() })
@@ -311,7 +340,7 @@ function OrdersTodayTooltip({
311
340
  const row = isOrdersTodayPoint((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
312
341
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
313
342
  const orders = ((_c = payload[0]) == null ? void 0 : _c.value) ?? 0;
314
- return /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: displayLabel, children: [
343
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: displayLabel, children: [
315
344
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
316
345
  "Orders: ",
317
346
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(orders).toLocaleString() })
@@ -329,7 +358,7 @@ function OrdersSparklineTooltip({
329
358
  const row = isDailyOrderRow((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
330
359
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
331
360
  const orders = Number((_c = payload[0]) == null ? void 0 : _c.value) || 0;
332
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipCard, { title: displayLabel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
361
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: displayLabel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
333
362
  "Orders: ",
334
363
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(orders).toLocaleString() })
335
364
  ] }) });
@@ -343,33 +372,28 @@ function OutcomesTrendTooltip({
343
372
  if (!active || !(payload == null ? void 0 : payload.length)) return null;
344
373
  const row = isDailyOrderRow((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
345
374
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
346
- return /* @__PURE__ */ jsxRuntime.jsx(TooltipCard, { title: displayLabel, children: payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
375
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: displayLabel, children: payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
347
376
  entry.name,
348
377
  ":",
349
378
  " ",
350
379
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(entry.value) || 0).toLocaleString() })
351
380
  ] }, String(entry.name))) });
352
381
  }
353
- const KPI_ICON_BG = {
382
+ const KPI_ICON_BG$2 = {
354
383
  green: "bg-emerald-500/20",
355
384
  blue: "bg-sky-500/20",
356
385
  purple: "bg-violet-500/20",
357
386
  amber: "bg-amber-500/20"
358
387
  };
359
- const KPI_ICONS = {
388
+ const KPI_ICONS$2 = {
360
389
  green: icons.CurrencyDollar,
361
390
  blue: icons.ShoppingCart,
362
391
  purple: icons.TruckFast,
363
392
  amber: icons.Cash
364
393
  };
365
394
  const PIE_PALETTE = ["#6366F1", "#94A3B8", "#10B981", "#F59E0B"];
366
- function TrafficRevenueDonut({
367
- traffic,
368
- compact = false
369
- }) {
370
- const innerRadius = compact ? 28 : 34;
371
- const outerRadius = compact ? 44 : 54;
372
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: compact ? "h-[118px] w-full" : "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: [
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: [
373
397
  /* @__PURE__ */ jsxRuntime.jsx(
374
398
  recharts.Pie,
375
399
  {
@@ -378,8 +402,8 @@ function TrafficRevenueDonut({
378
402
  nameKey: "label",
379
403
  cx: "50%",
380
404
  cy: "48%",
381
- innerRadius,
382
- outerRadius,
405
+ innerRadius: 34,
406
+ outerRadius: 54,
383
407
  paddingAngle: 2,
384
408
  children: traffic.map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: PIE_PALETTE[i % PIE_PALETTE.length] }, `traffic-slice-${i}`))
385
409
  }
@@ -389,7 +413,7 @@ function TrafficRevenueDonut({
389
413
  {
390
414
  content: ({ active, payload }) => {
391
415
  var _a, _b, _c;
392
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: String(((_a = payload[0]) == null ? void 0 : _a.name) ?? ""), children: [
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: [
393
417
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
394
418
  "Revenue:",
395
419
  " ",
@@ -407,44 +431,28 @@ function TrafficRevenueDonut({
407
431
  /* @__PURE__ */ jsxRuntime.jsx(
408
432
  recharts.Legend,
409
433
  {
410
- wrapperStyle: { fontSize: compact ? 8 : 9, paddingTop: 0 },
434
+ wrapperStyle: { fontSize: 9, paddingTop: 0 },
411
435
  verticalAlign: "bottom",
412
- height: compact ? 18 : 22,
436
+ height: 22,
413
437
  iconType: "circle"
414
438
  }
415
439
  )
416
440
  ] }) }) });
417
441
  }
418
- function TrafficSourcesOverviewCard({
419
- traffic,
420
- loading,
421
- error,
422
- totalRevenue,
423
- windowLabel
424
- }) {
425
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[132px] flex-col rounded-2xl border border-ui-border-base p-3 shadow-sm", children: [
426
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-xs font-medium text-ui-fg-base", children: "Traffic sources" }),
427
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "mb-1 text-[10px] leading-snug text-ui-fg-muted", children: [
428
- "Revenue share · ",
429
- windowLabel
430
- ] }),
431
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[104px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) : error ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[104px] items-center justify-center px-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-[10px] text-ui-fg-danger", children: error }) }) : traffic.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[104px] items-center justify-center px-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-[10px] leading-snug text-ui-fg-muted", children: "No traffic breakdown for this window." }) }) : totalRevenue <= 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[104px] items-center justify-center px-1", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-[10px] leading-snug text-ui-fg-muted", children: "No recorded revenue in this window." }) }) : /* @__PURE__ */ jsxRuntime.jsx(TrafficRevenueDonut, { traffic, compact: true }) })
432
- ] });
433
- }
434
- function AtlasKpiCard({
442
+ function AtlasKpiCard$2({
435
443
  label,
436
444
  value,
437
445
  helper,
438
446
  accent
439
447
  }) {
440
- const Icon = KPI_ICONS[accent];
448
+ const Icon = KPI_ICONS$2[accent];
441
449
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-[112px] min-w-0 flex-col rounded-xl border border-ui-border-base/80 bg-ui-bg-subtle/25 p-4 shadow-sm", children: [
442
450
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
443
451
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "min-w-0 flex-1 text-left text-xs font-medium leading-snug text-ui-fg-base", children: label }),
444
452
  /* @__PURE__ */ jsxRuntime.jsx(
445
453
  "div",
446
454
  {
447
- className: `flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${KPI_ICON_BG[accent]}`,
455
+ className: `flex h-8 w-8 shrink-0 items-center justify-center rounded-lg ${KPI_ICON_BG$2[accent]}`,
448
456
  "aria-hidden": true,
449
457
  children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-4 w-4 text-ui-fg-base" })
450
458
  }
@@ -476,11 +484,11 @@ const STATUS_BAR_COLORS = {
476
484
  orders: "#38BDF8",
477
485
  revenue: "#D946EF"
478
486
  };
479
- const CHART_AXIS_TICK = { fontSize: 10, fill: "#e5e7eb" };
480
- const CHART_AXIS_TICK_SM = { fontSize: 9, fill: "#e5e7eb" };
481
- const CHART_AXIS_LINE = "#94a3b8";
482
- const SELECT_CLASS_NAME = "h-9 min-w-[132px] cursor-pointer appearance-none rounded-full border border-ui-border-base bg-ui-bg-base py-1.5 pl-3 pr-8 text-xs text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive";
483
- function EmptyAnalyticsPanel({
487
+ const CHART_AXIS_TICK$2 = { fontSize: 10, fill: "#e5e7eb" };
488
+ const CHART_AXIS_TICK_SM$1 = { fontSize: 9, fill: "#e5e7eb" };
489
+ const CHART_AXIS_LINE$2 = "#94a3b8";
490
+ const SELECT_CLASS_NAME$2 = "h-9 min-w-[132px] cursor-pointer appearance-none rounded border border-ui-border-base bg-ui-bg-base py-1.5 pl-3 pr-8 text-xs text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive";
491
+ function EmptyAnalyticsPanel$1({
484
492
  title,
485
493
  description
486
494
  }) {
@@ -490,7 +498,7 @@ function EmptyAnalyticsPanel({
490
498
  ] });
491
499
  }
492
500
  function OrdersDashboard() {
493
- var _a, _b, _c, _d;
501
+ var _a, _b, _c;
494
502
  const [data, setData] = react.useState(null);
495
503
  const [loading, setLoading] = react.useState(true);
496
504
  const [error, setError] = react.useState(null);
@@ -734,7 +742,7 @@ function OrdersDashboard() {
734
742
  const pctDeliveredOfShipped = shipped > 0 ? delivered / shipped * 100 : 0;
735
743
  return {
736
744
  date: d.date,
737
- label: d.label ?? formatChartLabel(d.date),
745
+ label: d.label ?? formatChartLabel$2(d.date),
738
746
  placed,
739
747
  not_cancelled: notCancelled,
740
748
  shipped,
@@ -749,17 +757,16 @@ function OrdersDashboard() {
749
757
  () => (ordersInsights == null ? void 0 : ordersInsights.traffic.reduce((sum, t) => sum + (t.revenue || 0), 0)) ?? 0,
750
758
  [ordersInsights]
751
759
  );
752
- const insightsRangeLabel = ((_b = OVER_TIME_PERIODS.find((p) => p.value === overTimePeriod)) == null ? void 0 : _b.label) ?? "One week";
753
760
  const quickPulseMetrics = [
754
761
  {
755
762
  label: "Range revenue",
756
- value: formatCompactCurrency(trendRevenueTotal),
763
+ value: formatCompactCurrency$1(trendRevenueTotal),
757
764
  helper: selectedSummaryPeriod,
758
765
  accentClassName: "border-emerald-400/25 bg-emerald-500/5"
759
766
  },
760
767
  {
761
768
  label: "Range orders",
762
- value: formatShortNumber(trendOrdersTotal),
769
+ value: formatShortNumber$1(trendOrdersTotal),
763
770
  helper: "Current trend window",
764
771
  accentClassName: "border-sky-400/25 bg-sky-500/5"
765
772
  },
@@ -771,8 +778,8 @@ function OrdersDashboard() {
771
778
  },
772
779
  {
773
780
  label: "Peak revenue day",
774
- value: peakRevenuePoint ? formatCompactCurrency(peakRevenuePoint.total_revenue) : "—",
775
- helper: (peakRevenuePoint == null ? void 0 : peakRevenuePoint.label) ?? formatChartLabel(peakRevenuePoint == null ? void 0 : peakRevenuePoint.date),
781
+ value: peakRevenuePoint ? formatCompactCurrency$1(peakRevenuePoint.total_revenue) : "—",
782
+ helper: (peakRevenuePoint == null ? void 0 : peakRevenuePoint.label) ?? formatChartLabel$2(peakRevenuePoint == null ? void 0 : peakRevenuePoint.date),
776
783
  accentClassName: "border-amber-400/25 bg-amber-500/5"
777
784
  }
778
785
  ];
@@ -815,7 +822,7 @@ function OrdersDashboard() {
815
822
  id: "analytics-period",
816
823
  value: filter,
817
824
  onChange: (e) => setFilter(e.target.value),
818
- className: SELECT_CLASS_NAME,
825
+ className: SELECT_CLASS_NAME$2,
819
826
  children: SUMMARY_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
820
827
  }
821
828
  )
@@ -836,28 +843,16 @@ function OrdersDashboard() {
836
843
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 p-3 pt-0 md:p-4 md:pt-0", children: [
837
844
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
838
845
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Order overview" }) }),
839
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3", children: [
840
- /* @__PURE__ */ jsxRuntime.jsx(
841
- TrafficSourcesOverviewCard,
842
- {
843
- traffic: (ordersInsights == null ? void 0 : ordersInsights.traffic) ?? [],
844
- loading: insightsLoading,
845
- error: insightsError,
846
- totalRevenue: trafficTotalRevenue,
847
- windowLabel: insightsRangeLabel
848
- }
849
- ),
850
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: primaryStats.map((stat) => /* @__PURE__ */ jsxRuntime.jsx(
851
- AtlasKpiCard,
852
- {
853
- label: stat.label,
854
- value: stat.value,
855
- helper: stat.helper,
856
- accent: stat.accent
857
- },
858
- stat.label
859
- )) })
860
- ] })
846
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-3 lg:grid-cols-4", children: primaryStats.map((stat) => /* @__PURE__ */ jsxRuntime.jsx(
847
+ AtlasKpiCard$2,
848
+ {
849
+ label: stat.label,
850
+ value: stat.value,
851
+ helper: stat.helper,
852
+ accent: stat.accent
853
+ },
854
+ stat.label
855
+ )) })
861
856
  ] }),
862
857
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 grid grid-cols-12 gap-2 xl:items-start", children: [
863
858
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 xl:col-span-6", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -882,7 +877,7 @@ function OrdersDashboard() {
882
877
  id: "over-time-period",
883
878
  value: overTimePeriod,
884
879
  onChange: (e) => setOverTimePeriod(e.target.value),
885
- className: SELECT_CLASS_NAME,
880
+ className: SELECT_CLASS_NAME$2,
886
881
  children: OVER_TIME_PERIODS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
887
882
  }
888
883
  )
@@ -891,10 +886,10 @@ function OrdersDashboard() {
891
886
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-1.5 sm:grid-cols-3", children: [
892
887
  /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
893
888
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window revenue" }),
894
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatCompactCurrency(trendRevenueTotal) }),
889
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatCompactCurrency$1(trendRevenueTotal) }),
895
890
  /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
896
891
  "Avg/day ",
897
- formatCompactCurrency(trendAverageRevenue)
892
+ formatCompactCurrency$1(trendAverageRevenue)
898
893
  ] })
899
894
  ] }) }),
900
895
  /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
@@ -938,26 +933,27 @@ function OrdersDashboard() {
938
933
  recharts.YAxis,
939
934
  {
940
935
  width: 36,
941
- tick: CHART_AXIS_TICK_SM,
942
- tickFormatter: (v) => formatCompactCurrency(Number(v))
936
+ tick: CHART_AXIS_TICK_SM$1,
937
+ tickFormatter: (v) => formatCompactCurrency$1(Number(v))
943
938
  }
944
939
  ),
945
940
  /* @__PURE__ */ jsxRuntime.jsx(
946
941
  recharts.Tooltip,
947
942
  {
948
943
  content: ({ active, payload, label }) => {
949
- var _a2, _b2, _c2, _d2;
944
+ var _a2, _b2, _c2, _d;
950
945
  return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(
951
- TooltipCard,
946
+ AnalyticsTooltipCard,
952
947
  {
948
+ variant: "compact",
953
949
  title: String(
954
- isDailyOrderRow((_a2 = payload[0]) == null ? void 0 : _a2.payload) ? ((_b2 = payload[0]) == null ? void 0 : _b2.payload.label) ?? formatChartLabel(String(label)) : label
950
+ isDailyOrderRow((_a2 = payload[0]) == null ? void 0 : _a2.payload) ? ((_b2 = payload[0]) == null ? void 0 : _b2.payload.label) ?? formatChartLabel$2(String(label)) : label
955
951
  ),
956
952
  children: [
957
953
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
958
954
  "This:",
959
955
  " ",
960
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency(
956
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency$1(
961
957
  Number(
962
958
  (_c2 = payload.find((p) => p.dataKey === "total_revenue")) == null ? void 0 : _c2.value
963
959
  ) || 0
@@ -966,9 +962,9 @@ function OrdersDashboard() {
966
962
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
967
963
  "Previous:",
968
964
  " ",
969
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency(
965
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCompactCurrency$1(
970
966
  Number(
971
- (_d2 = payload.find((p) => p.dataKey === "prev_revenue")) == null ? void 0 : _d2.value
967
+ (_d = payload.find((p) => p.dataKey === "prev_revenue")) == null ? void 0 : _d.value
972
968
  ) || 0
973
969
  ) })
974
970
  ] })
@@ -1026,7 +1022,7 @@ function OrdersDashboard() {
1026
1022
  recharts.YAxis,
1027
1023
  {
1028
1024
  width: 28,
1029
- tick: CHART_AXIS_TICK_SM,
1025
+ tick: CHART_AXIS_TICK_SM$1,
1030
1026
  allowDecimals: false
1031
1027
  }
1032
1028
  ),
@@ -1035,7 +1031,7 @@ function OrdersDashboard() {
1035
1031
  {
1036
1032
  content: ({ active, payload, label }) => {
1037
1033
  var _a2, _b2;
1038
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: String(label), children: [
1034
+ return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
1039
1035
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1040
1036
  "This:",
1041
1037
  " ",
@@ -1106,8 +1102,8 @@ function OrdersDashboard() {
1106
1102
  recharts.YAxis,
1107
1103
  {
1108
1104
  width: 36,
1109
- tick: CHART_AXIS_TICK_SM,
1110
- tickFormatter: (v) => formatCompactCurrency(Number(v))
1105
+ tick: CHART_AXIS_TICK_SM$1,
1106
+ tickFormatter: (v) => formatCompactCurrency$1(Number(v))
1111
1107
  }
1112
1108
  ),
1113
1109
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1115,7 +1111,7 @@ function OrdersDashboard() {
1115
1111
  {
1116
1112
  content: ({ active, payload, label }) => {
1117
1113
  var _a2, _b2;
1118
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: String(label), children: [
1114
+ return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
1119
1115
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1120
1116
  "This:",
1121
1117
  " ",
@@ -1186,26 +1182,26 @@ function OrdersDashboard() {
1186
1182
  recharts.XAxis,
1187
1183
  {
1188
1184
  dataKey: "date",
1189
- tick: CHART_AXIS_TICK,
1185
+ tick: CHART_AXIS_TICK$2,
1190
1186
  tickLine: false,
1191
1187
  axisLine: false,
1192
1188
  tickFormatter: (value, index) => {
1193
1189
  const row = dailyOrders[index];
1194
- return (row == null ? void 0 : row.label) ?? formatChartLabel(value);
1190
+ return (row == null ? void 0 : row.label) ?? formatChartLabel$2(value);
1195
1191
  }
1196
1192
  }
1197
1193
  ),
1198
1194
  /* @__PURE__ */ jsxRuntime.jsx(
1199
1195
  recharts.YAxis,
1200
1196
  {
1201
- tick: CHART_AXIS_TICK,
1202
- tickFormatter: (v) => formatCompactCurrency(Number(v))
1197
+ tick: CHART_AXIS_TICK$2,
1198
+ tickFormatter: (v) => formatCompactCurrency$1(Number(v))
1203
1199
  }
1204
1200
  ),
1205
1201
  /* @__PURE__ */ jsxRuntime.jsx(
1206
1202
  recharts.Tooltip,
1207
1203
  {
1208
- content: ({ active, payload, label }) => active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(TooltipCard, { title: String(label), children: payload.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1204
+ 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: [
1209
1205
  p.name,
1210
1206
  ":",
1211
1207
  " ",
@@ -1261,7 +1257,7 @@ function OrdersDashboard() {
1261
1257
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-1.5", children: [
1262
1258
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
1263
1259
  /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Trend overview" }),
1264
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-sm font-semibold", children: ((_c = OVER_TIME_PERIODS.find((period) => period.value === overTimePeriod)) == null ? void 0 : _c.label) ?? "One week" })
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" })
1265
1261
  ] }),
1266
1262
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap justify-end gap-2 text-[10px] text-ui-fg-muted", children: [
1267
1263
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
@@ -1318,12 +1314,12 @@ function OrdersDashboard() {
1318
1314
  recharts.XAxis,
1319
1315
  {
1320
1316
  dataKey: "date",
1321
- tick: CHART_AXIS_TICK,
1317
+ tick: CHART_AXIS_TICK$2,
1322
1318
  tickLine: false,
1323
1319
  axisLine: false,
1324
1320
  tickFormatter: (value, index) => {
1325
1321
  const row = dailyOrders[index];
1326
- return (row == null ? void 0 : row.label) ?? formatChartLabel(value);
1322
+ return (row == null ? void 0 : row.label) ?? formatChartLabel$2(value);
1327
1323
  }
1328
1324
  }
1329
1325
  ),
@@ -1332,7 +1328,7 @@ function OrdersDashboard() {
1332
1328
  {
1333
1329
  yAxisId: "orders",
1334
1330
  width: 32,
1335
- tick: CHART_AXIS_TICK,
1331
+ tick: CHART_AXIS_TICK$2,
1336
1332
  tickLine: false,
1337
1333
  axisLine: false,
1338
1334
  allowDecimals: false,
@@ -1345,10 +1341,10 @@ function OrdersDashboard() {
1345
1341
  yAxisId: "revenue",
1346
1342
  orientation: "right",
1347
1343
  width: 40,
1348
- tick: CHART_AXIS_TICK,
1344
+ tick: CHART_AXIS_TICK$2,
1349
1345
  tickLine: false,
1350
1346
  axisLine: false,
1351
- tickFormatter: (value) => formatCompactCurrency(Number(value) || 0)
1347
+ tickFormatter: (value) => formatCompactCurrency$1(Number(value) || 0)
1352
1348
  }
1353
1349
  ),
1354
1350
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -1487,7 +1483,7 @@ function OrdersDashboard() {
1487
1483
  {
1488
1484
  variant: "atlas",
1489
1485
  title: "Order → fulfillment funnel",
1490
- description: `Stages by order created date (UTC), same range as Revenue & orders (${((_d = OVER_TIME_PERIODS.find((p) => p.value === overTimePeriod)) == null ? void 0 : _d.label) ?? "period"}). Not storefront visitors.`,
1486
+ description: `Stages by order created date (UTC), same range as Revenue & orders (${((_c = OVER_TIME_PERIODS.find((p) => p.value === overTimePeriod)) == null ? void 0 : _c.label) ?? "period"}). Not storefront visitors.`,
1491
1487
  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: [
1492
1488
  /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", children: [
1493
1489
  /* @__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)" }),
@@ -1508,21 +1504,21 @@ function OrdersDashboard() {
1508
1504
  recharts.XAxis,
1509
1505
  {
1510
1506
  dataKey: "date",
1511
- tick: CHART_AXIS_TICK_SM,
1512
- stroke: CHART_AXIS_LINE,
1513
- tickLine: { stroke: CHART_AXIS_LINE },
1507
+ tick: CHART_AXIS_TICK_SM$1,
1508
+ stroke: CHART_AXIS_LINE$2,
1509
+ tickLine: { stroke: CHART_AXIS_LINE$2 },
1514
1510
  tickFormatter: (value) => {
1515
1511
  const row = dailyOrders.find((r) => r.date === value);
1516
- return (row == null ? void 0 : row.label) ?? formatChartLabel(String(value));
1512
+ return (row == null ? void 0 : row.label) ?? formatChartLabel$2(String(value));
1517
1513
  }
1518
1514
  }
1519
1515
  ),
1520
1516
  /* @__PURE__ */ jsxRuntime.jsx(
1521
1517
  recharts.YAxis,
1522
1518
  {
1523
- tick: CHART_AXIS_TICK_SM,
1524
- stroke: CHART_AXIS_LINE,
1525
- tickLine: { stroke: CHART_AXIS_LINE },
1519
+ tick: CHART_AXIS_TICK_SM$1,
1520
+ stroke: CHART_AXIS_LINE$2,
1521
+ tickLine: { stroke: CHART_AXIS_LINE$2 },
1526
1522
  width: 28,
1527
1523
  allowDecimals: false,
1528
1524
  tickFormatter: (v) => Math.floor(Number(v) || 0).toLocaleString()
@@ -1534,9 +1530,10 @@ function OrdersDashboard() {
1534
1530
  content: ({ active, payload, label }) => {
1535
1531
  var _a2;
1536
1532
  return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(
1537
- TooltipCard,
1533
+ AnalyticsTooltipCard,
1538
1534
  {
1539
- title: typeof label === "string" ? ((_a2 = dailyOrders.find((r) => r.date === label)) == null ? void 0 : _a2.label) ?? formatChartLabel(label) : String(label),
1535
+ variant: "compact",
1536
+ title: typeof label === "string" ? ((_a2 = dailyOrders.find((r) => r.date === label)) == null ? void 0 : _a2.label) ?? formatChartLabel$2(label) : String(label),
1540
1537
  children: payload.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1541
1538
  String(p.name),
1542
1539
  ":",
@@ -1623,12 +1620,12 @@ function OrdersDashboard() {
1623
1620
  recharts.XAxis,
1624
1621
  {
1625
1622
  dataKey: "date",
1626
- tick: CHART_AXIS_TICK_SM,
1627
- stroke: CHART_AXIS_LINE,
1628
- tickLine: { stroke: CHART_AXIS_LINE },
1623
+ tick: CHART_AXIS_TICK_SM$1,
1624
+ stroke: CHART_AXIS_LINE$2,
1625
+ tickLine: { stroke: CHART_AXIS_LINE$2 },
1629
1626
  tickFormatter: (value) => {
1630
1627
  const row = dailyOrders.find((r) => r.date === value);
1631
- return (row == null ? void 0 : row.label) ?? formatChartLabel(String(value));
1628
+ return (row == null ? void 0 : row.label) ?? formatChartLabel$2(String(value));
1632
1629
  }
1633
1630
  }
1634
1631
  ),
@@ -1636,9 +1633,9 @@ function OrdersDashboard() {
1636
1633
  recharts.YAxis,
1637
1634
  {
1638
1635
  domain: [0, 100],
1639
- tick: CHART_AXIS_TICK_SM,
1640
- stroke: CHART_AXIS_LINE,
1641
- tickLine: { stroke: CHART_AXIS_LINE },
1636
+ tick: CHART_AXIS_TICK_SM$1,
1637
+ stroke: CHART_AXIS_LINE$2,
1638
+ tickLine: { stroke: CHART_AXIS_LINE$2 },
1642
1639
  width: 36,
1643
1640
  tickFormatter: (v) => `${Math.round(Number(v) || 0)}%`
1644
1641
  }
@@ -1649,9 +1646,10 @@ function OrdersDashboard() {
1649
1646
  content: ({ active, payload, label }) => {
1650
1647
  var _a2;
1651
1648
  return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(
1652
- TooltipCard,
1649
+ AnalyticsTooltipCard,
1653
1650
  {
1654
- title: typeof label === "string" ? ((_a2 = dailyOrders.find((r) => r.date === label)) == null ? void 0 : _a2.label) ?? formatChartLabel(label) : String(label),
1651
+ variant: "compact",
1652
+ title: typeof label === "string" ? ((_a2 = dailyOrders.find((r) => r.date === label)) == null ? void 0 : _a2.label) ?? formatChartLabel$2(label) : String(label),
1655
1653
  children: payload.map((p) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1656
1654
  String(p.name),
1657
1655
  ":",
@@ -1709,7 +1707,7 @@ function OrdersDashboard() {
1709
1707
  ) }) })
1710
1708
  ] })
1711
1709
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(
1712
- EmptyAnalyticsPanel,
1710
+ EmptyAnalyticsPanel$1,
1713
1711
  {
1714
1712
  title: "No funnel data",
1715
1713
  description: "No orders in this range to chart."
@@ -1724,7 +1722,7 @@ function OrdersDashboard() {
1724
1722
  title: "Order revenue (attribution)",
1725
1723
  description: "All revenue is from captured Medusa orders until storefront channel data exists.",
1726
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(
1727
- EmptyAnalyticsPanel,
1725
+ EmptyAnalyticsPanel$1,
1728
1726
  {
1729
1727
  title: "No order revenue",
1730
1728
  description: "No orders in this window."
@@ -1773,13 +1771,13 @@ function OrdersDashboard() {
1773
1771
  recharts.XAxis,
1774
1772
  {
1775
1773
  dataKey: "date",
1776
- tick: CHART_AXIS_TICK,
1774
+ tick: CHART_AXIS_TICK$2,
1777
1775
  tickLine: false,
1778
1776
  axisLine: false,
1779
1777
  tickFormatter: (value) => {
1780
1778
  const dateStr = typeof value === "string" ? value : String(value);
1781
1779
  const row = dailyOrders.find((d) => d.date === dateStr);
1782
- return (row == null ? void 0 : row.label) ?? formatChartLabel(dateStr);
1780
+ return (row == null ? void 0 : row.label) ?? formatChartLabel$2(dateStr);
1783
1781
  }
1784
1782
  }
1785
1783
  ),
@@ -1787,7 +1785,7 @@ function OrdersDashboard() {
1787
1785
  recharts.YAxis,
1788
1786
  {
1789
1787
  width: 28,
1790
- tick: CHART_AXIS_TICK,
1788
+ tick: CHART_AXIS_TICK$2,
1791
1789
  tickLine: false,
1792
1790
  axisLine: false,
1793
1791
  allowDecimals: false,
@@ -1898,17 +1896,17 @@ function OrdersDashboard() {
1898
1896
  recharts.XAxis,
1899
1897
  {
1900
1898
  dataKey: "date",
1901
- tick: CHART_AXIS_TICK,
1899
+ tick: CHART_AXIS_TICK$2,
1902
1900
  tickLine: false,
1903
1901
  axisLine: false,
1904
- tickFormatter: formatChartLabel
1902
+ tickFormatter: formatChartLabel$2
1905
1903
  }
1906
1904
  ),
1907
1905
  /* @__PURE__ */ jsxRuntime.jsx(
1908
1906
  recharts.YAxis,
1909
1907
  {
1910
1908
  width: 28,
1911
- tick: CHART_AXIS_TICK,
1909
+ tick: CHART_AXIS_TICK$2,
1912
1910
  tickLine: false,
1913
1911
  axisLine: false,
1914
1912
  allowDecimals: false,
@@ -1997,15 +1995,15 @@ function OrdersDashboard() {
1997
1995
  recharts.XAxis,
1998
1996
  {
1999
1997
  dataKey: "label",
2000
- tick: CHART_AXIS_TICK
1998
+ tick: CHART_AXIS_TICK$2
2001
1999
  }
2002
2000
  ),
2003
2001
  /* @__PURE__ */ jsxRuntime.jsx(
2004
2002
  recharts.YAxis,
2005
2003
  {
2006
2004
  width: 40,
2007
- tick: CHART_AXIS_TICK_SM,
2008
- tickFormatter: (v) => formatCompactCurrency(Number(v))
2005
+ tick: CHART_AXIS_TICK_SM$1,
2006
+ tickFormatter: (v) => formatCompactCurrency$1(Number(v))
2009
2007
  }
2010
2008
  ),
2011
2009
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2013,7 +2011,7 @@ function OrdersDashboard() {
2013
2011
  {
2014
2012
  content: ({ active, payload, label }) => {
2015
2013
  var _a2, _b2;
2016
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: String(label), children: [
2014
+ return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
2017
2015
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2018
2016
  "Revenue:",
2019
2017
  " ",
@@ -2040,7 +2038,7 @@ function OrdersDashboard() {
2040
2038
  ]
2041
2039
  }
2042
2040
  ) }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(
2043
- EmptyAnalyticsPanel,
2041
+ EmptyAnalyticsPanel$1,
2044
2042
  {
2045
2043
  title: "No weekday data",
2046
2044
  description: "No orders in this window."
@@ -2081,7 +2079,7 @@ function OrdersDashboard() {
2081
2079
  {
2082
2080
  content: ({ active, payload }) => {
2083
2081
  var _a2, _b2;
2084
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(TooltipCard, { title: String(((_a2 = payload[0]) == null ? void 0 : _a2.name) ?? ""), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2082
+ return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: String(((_a2 = payload[0]) == null ? void 0 : _a2.name) ?? ""), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2085
2083
  "Count:",
2086
2084
  " ",
2087
2085
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(
@@ -2103,7 +2101,7 @@ function OrdersDashboard() {
2103
2101
  ] }) }) }),
2104
2102
  (ordersInsights == null ? void 0 : ordersInsights.drafts.available) === false ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted mt-0.5 px-0.5 text-[10px] leading-snug", children: "Draft totals need draft_order remote query access." }) : null
2105
2103
  ] }) : /* @__PURE__ */ jsxRuntime.jsx(
2106
- EmptyAnalyticsPanel,
2104
+ EmptyAnalyticsPanel$1,
2107
2105
  {
2108
2106
  title: "Nothing to compare",
2109
2107
  description: "No placed orders and no draft rows in this snapshot."
@@ -2136,14 +2134,14 @@ function OrdersDashboard() {
2136
2134
  {
2137
2135
  dataKey: "label",
2138
2136
  interval: 3,
2139
- tick: CHART_AXIS_TICK_SM
2137
+ tick: CHART_AXIS_TICK_SM$1
2140
2138
  }
2141
2139
  ),
2142
2140
  /* @__PURE__ */ jsxRuntime.jsx(
2143
2141
  recharts.YAxis,
2144
2142
  {
2145
2143
  width: 28,
2146
- tick: CHART_AXIS_TICK,
2144
+ tick: CHART_AXIS_TICK$2,
2147
2145
  allowDecimals: false
2148
2146
  }
2149
2147
  ),
@@ -2152,7 +2150,7 @@ function OrdersDashboard() {
2152
2150
  {
2153
2151
  content: ({ active, payload, label }) => {
2154
2152
  var _a2, _b2;
2155
- return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(TooltipCard, { title: String(label), children: [
2153
+ return active && (payload == null ? void 0 : payload.length) ? /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: String(label), children: [
2156
2154
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2157
2155
  "Orders:",
2158
2156
  " ",
@@ -2179,7 +2177,7 @@ function OrdersDashboard() {
2179
2177
  ]
2180
2178
  }
2181
2179
  ) }) }) }) : /* @__PURE__ */ jsxRuntime.jsx(
2182
- EmptyAnalyticsPanel,
2180
+ EmptyAnalyticsPanel$1,
2183
2181
  {
2184
2182
  title: "No hourly data",
2185
2183
  description: "No orders in this window."
@@ -2191,6 +2189,41 @@ function OrdersDashboard() {
2191
2189
  ] })
2192
2190
  ] }) });
2193
2191
  }
2192
+ const KPI_ICON_BG$1 = {
2193
+ green: "bg-emerald-500/20",
2194
+ blue: "bg-sky-500/20",
2195
+ purple: "bg-violet-500/20",
2196
+ amber: "bg-amber-500/20"
2197
+ };
2198
+ const KPI_ICONS$1 = {
2199
+ green: icons.UsersSolid,
2200
+ blue: icons.User,
2201
+ purple: icons.UserGroup,
2202
+ amber: icons.Trash
2203
+ };
2204
+ function AtlasKpiCard$1({
2205
+ label,
2206
+ value,
2207
+ helper,
2208
+ accent
2209
+ }) {
2210
+ const Icon = KPI_ICONS$1[accent];
2211
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-[88px] min-w-0 flex-col rounded-xl border border-ui-border-base/80 bg-ui-bg-subtle/25 p-3 shadow-sm", children: [
2212
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
2213
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "min-w-0 flex-1 text-left text-xs font-medium leading-snug text-ui-fg-base", children: label }),
2214
+ /* @__PURE__ */ jsxRuntime.jsx(
2215
+ "div",
2216
+ {
2217
+ className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-lg ${KPI_ICON_BG$1[accent]}`,
2218
+ "aria-hidden": true,
2219
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3.5 w-3.5 text-ui-fg-base" })
2220
+ }
2221
+ )
2222
+ ] }),
2223
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-lg font-semibold tabular-nums tracking-tight text-ui-fg-base sm:text-xl", children: value }),
2224
+ helper ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-[11px] leading-snug text-ui-fg-muted", children: helper }) : null
2225
+ ] });
2226
+ }
2194
2227
  function CustomersOverTimeTooltip({
2195
2228
  active,
2196
2229
  payload,
@@ -2202,32 +2235,16 @@ function CustomersOverTimeTooltip({
2202
2235
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : label);
2203
2236
  const registered = Math.floor(((_b = payload.find((p) => p.name === "Registered")) == null ? void 0 : _b.value) ?? 0);
2204
2237
  const guest = Math.floor(((_c = payload.find((p) => p.name === "Guest")) == null ? void 0 : _c.value) ?? 0);
2205
- return /* @__PURE__ */ jsxRuntime.jsxs(
2206
- "div",
2207
- {
2208
- style: {
2209
- backgroundColor: "rgb(254, 254, 254)",
2210
- color: "#111827",
2211
- border: "1px solid rgb(229, 231, 235)",
2212
- borderRadius: "8px",
2213
- padding: "12px 16px",
2214
- boxShadow: "0 4px 14px rgba(0, 0, 0, 0.08)",
2215
- fontSize: "14px",
2216
- lineHeight: 1.5
2217
- },
2218
- children: [
2219
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, marginBottom: "6px", color: "#111827" }, children: displayLabel }),
2220
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: "#374151" }, children: [
2221
- "Registered: ",
2222
- /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: "#1f2937" }, children: registered })
2223
- ] }),
2224
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { color: "#374151" }, children: [
2225
- "Guest: ",
2226
- /* @__PURE__ */ jsxRuntime.jsx("strong", { style: { color: "#1f2937" }, children: guest })
2227
- ] })
2228
- ]
2229
- }
2230
- );
2238
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { title: String(displayLabel ?? ""), children: [
2239
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2240
+ "Registered: ",
2241
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: registered.toLocaleString() })
2242
+ ] }),
2243
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2244
+ "Guest: ",
2245
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: guest.toLocaleString() })
2246
+ ] })
2247
+ ] });
2231
2248
  }
2232
2249
  function MixPieTooltip({
2233
2250
  active,
@@ -2235,10 +2252,10 @@ function MixPieTooltip({
2235
2252
  }) {
2236
2253
  if (!active || !(payload == null ? void 0 : payload.length)) return null;
2237
2254
  const row = payload[0];
2238
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-base px-3 py-2 text-sm shadow-md", children: [
2239
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "font-medium text-ui-fg-base", children: row.name }),
2240
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: Math.floor(Number(row.value) || 0).toLocaleString() })
2241
- ] });
2255
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTooltipCard, { variant: "compact", title: String(row.name ?? ""), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2256
+ "Count: ",
2257
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(row.value) || 0).toLocaleString() })
2258
+ ] }) });
2242
2259
  }
2243
2260
  const COUNT_DAY_PRESETS = [
2244
2261
  { value: "all", label: "All time" },
@@ -2254,7 +2271,17 @@ const GRAPH_PERIODS$1 = [
2254
2271
  ];
2255
2272
  const REGISTERED_COLOR = "var(--medusa-color-ui-fg-interactive)";
2256
2273
  const GUEST_COLOR = "#6B7280";
2274
+ const CHART_AXIS_TICK$1 = { fontSize: 10, fill: "#e5e7eb" };
2275
+ const CHART_AXIS_LINE$1 = "#94a3b8";
2276
+ const SELECT_CLASS_NAME$1 = "h-9 w-full min-w-[8rem] max-w-full cursor-pointer appearance-none rounded border border-ui-border-base bg-ui-bg-base py-1.5 pl-3 pr-8 text-xs text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive sm:w-auto sm:min-w-[132px] sm:max-w-[220px]";
2277
+ function formatChartLabel$1(value) {
2278
+ if (!value) return "";
2279
+ const parsed = new Date(value);
2280
+ if (Number.isNaN(parsed.getTime())) return value;
2281
+ return `${parsed.getUTCMonth() + 1}/${parsed.getUTCDate()}`;
2282
+ }
2257
2283
  function CustomersDashboard() {
2284
+ var _a, _b;
2258
2285
  const [data, setData] = react.useState(null);
2259
2286
  const [loading, setLoading] = react.useState(true);
2260
2287
  const [error, setError] = react.useState(null);
@@ -2324,6 +2351,7 @@ function CustomersDashboard() {
2324
2351
  cancelled = true;
2325
2352
  };
2326
2353
  }, [countDays]);
2354
+ const selectedCountPeriodLabel = ((_a = COUNT_DAY_PRESETS.find((p) => p.value === countDays)) == null ? void 0 : _a.label) ?? "All time";
2327
2355
  const guestRegisteredPieData = react.useMemo(() => {
2328
2356
  const g = Math.max(0, Math.floor((data == null ? void 0 : data.guestCount) ?? 0));
2329
2357
  const r = Math.max(0, Math.floor((data == null ? void 0 : data.registeredCount) ?? 0));
@@ -2332,11 +2360,50 @@ function CustomersDashboard() {
2332
2360
  { name: "Registered", value: r, key: "registered" }
2333
2361
  ].filter((s) => s.value > 0);
2334
2362
  }, [data]);
2363
+ const seriesWindowTotals = react.useMemo(() => {
2364
+ let registered = 0;
2365
+ let guest = 0;
2366
+ for (const row of series) {
2367
+ registered += Math.max(0, Math.floor(row.registered_count));
2368
+ guest += Math.max(0, Math.floor(row.guest_count));
2369
+ }
2370
+ return {
2371
+ registered,
2372
+ guest,
2373
+ points: series.length
2374
+ };
2375
+ }, [series]);
2376
+ const primaryStats = data ? [
2377
+ {
2378
+ label: "Guest customers",
2379
+ value: Math.floor(data.guestCount).toLocaleString(),
2380
+ helper: selectedCountPeriodLabel,
2381
+ accent: "blue"
2382
+ },
2383
+ {
2384
+ label: "Registered customers",
2385
+ value: Math.floor(data.registeredCount).toLocaleString(),
2386
+ helper: selectedCountPeriodLabel,
2387
+ accent: "purple"
2388
+ },
2389
+ {
2390
+ label: "Overall customers",
2391
+ value: Math.floor(data.totalCount).toLocaleString(),
2392
+ helper: "Guest + registered",
2393
+ accent: "green"
2394
+ },
2395
+ {
2396
+ label: "Deleted accounts",
2397
+ value: (data.deletedAccountsCount ?? 0).toLocaleString(),
2398
+ helper: "Removed profiles",
2399
+ accent: "amber"
2400
+ }
2401
+ ] : [];
2335
2402
  if (loading) {
2336
2403
  return /* @__PURE__ */ jsxRuntime.jsx(
2337
2404
  "div",
2338
2405
  {
2339
- className: "flex items-center justify-center min-h-[320px]",
2406
+ className: "flex min-h-[200px] items-center justify-center",
2340
2407
  role: "status",
2341
2408
  "aria-label": "Loading analytics",
2342
2409
  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading…" })
@@ -2346,19 +2413,22 @@ function CustomersDashboard() {
2346
2413
  if (error || !data) {
2347
2414
  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" }) });
2348
2415
  }
2349
- return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsDashboardShell, { children: [
2416
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsDashboardShell, { className: "w-full min-w-0 max-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full min-w-0 max-w-full overflow-hidden rounded-2xl border border-ui-border-base/80 bg-ui-bg-base shadow-sm", children: [
2350
2417
  /* @__PURE__ */ jsxRuntime.jsx(
2351
2418
  AnalyticsDashboardHeader,
2352
2419
  {
2420
+ variant: "premium",
2421
+ appearance: "inset",
2422
+ actionsBare: true,
2353
2423
  title: "Customers",
2354
- description: "Keep customer acquisition and account mix compact, readable, and aligned with the rest of analytics.",
2424
+ description: "Acquisition mix, repeat behavior, and signups over time aligned with Orders and Products analytics.",
2355
2425
  actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2356
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2426
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
2357
2427
  /* @__PURE__ */ jsxRuntime.jsx(
2358
2428
  ui.Label,
2359
2429
  {
2360
2430
  htmlFor: "customers-count-period",
2361
- className: "text-ui-fg-muted text-sm",
2431
+ className: "shrink-0 text-ui-fg-muted text-xs font-medium",
2362
2432
  children: "Period"
2363
2433
  }
2364
2434
  ),
@@ -2368,214 +2438,245 @@ function CustomersDashboard() {
2368
2438
  id: "customers-count-period",
2369
2439
  value: countDays,
2370
2440
  onChange: (e) => setCountDays(e.target.value),
2371
- className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
2441
+ className: SELECT_CLASS_NAME$1,
2372
2442
  children: COUNT_DAY_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
2373
2443
  }
2374
2444
  )
2375
2445
  ] }),
2376
- countDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
2446
+ countDays !== "all" ? /* @__PURE__ */ jsxRuntime.jsx(
2377
2447
  "button",
2378
2448
  {
2379
2449
  type: "button",
2380
2450
  onClick: () => setCountDays("all"),
2381
- className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
2451
+ className: "text-xs text-ui-fg-muted transition-colors hover:text-ui-fg-base",
2382
2452
  "aria-label": "Show all customers (clear filter)",
2383
- children: "Clear filter"
2453
+ children: "Clear period"
2384
2454
  }
2385
- )
2455
+ ) : null
2386
2456
  ] })
2387
2457
  }
2388
2458
  ),
2389
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4", children: [
2390
- /* @__PURE__ */ jsxRuntime.jsx(
2391
- AnalyticsStatCard,
2392
- {
2393
- label: "Guest customers",
2394
- value: Math.floor(data.guestCount).toLocaleString()
2395
- }
2396
- ),
2397
- /* @__PURE__ */ jsxRuntime.jsx(
2398
- AnalyticsStatCard,
2399
- {
2400
- label: "Registered customers",
2401
- value: Math.floor(data.registeredCount).toLocaleString()
2402
- }
2403
- ),
2404
- /* @__PURE__ */ jsxRuntime.jsx(
2405
- AnalyticsStatCard,
2406
- {
2407
- label: "Overall customers",
2408
- value: Math.floor(data.totalCount).toLocaleString()
2409
- }
2410
- ),
2411
- /* @__PURE__ */ jsxRuntime.jsx(
2412
- AnalyticsStatCard,
2413
- {
2414
- label: "Deleted accounts",
2415
- value: (data.deletedAccountsCount ?? 0).toLocaleString()
2416
- }
2417
- )
2418
- ] }),
2419
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 lg:grid-cols-2", children: [
2459
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 p-2 pt-0 sm:p-3 sm:pt-0 md:p-4 md:pt-0", children: [
2460
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2461
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Customer overview" }) }),
2462
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 lg:grid-cols-4", children: primaryStats.map((stat) => /* @__PURE__ */ jsxRuntime.jsx(
2463
+ AtlasKpiCard$1,
2464
+ {
2465
+ label: stat.label,
2466
+ value: stat.value,
2467
+ helper: stat.helper,
2468
+ accent: stat.accent
2469
+ },
2470
+ stat.label
2471
+ )) })
2472
+ ] }),
2473
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 grid grid-cols-12 gap-2 lg:items-stretch", children: [
2474
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 flex min-h-0 min-w-0 lg:col-span-5", children: /* @__PURE__ */ jsxRuntime.jsx(
2475
+ AnalyticsSection,
2476
+ {
2477
+ variant: "atlas",
2478
+ className: "flex min-h-0 w-full flex-col",
2479
+ title: "Guest vs registered",
2480
+ description: "Mix for the selected period (same filter as overview).",
2481
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(168px,22vh)] min-h-[140px] w-full sm:h-[min(176px,24vh)]", children: guestRegisteredPieData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-ui-fg-muted text-[11px] leading-snug", children: "No guest or registered customers in this range." }) }) : /* @__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: [
2482
+ /* @__PURE__ */ jsxRuntime.jsx(
2483
+ recharts.Pie,
2484
+ {
2485
+ data: guestRegisteredPieData,
2486
+ dataKey: "value",
2487
+ nameKey: "name",
2488
+ cx: "50%",
2489
+ cy: "48%",
2490
+ innerRadius: 34,
2491
+ outerRadius: 54,
2492
+ paddingAngle: 2,
2493
+ children: guestRegisteredPieData.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
2494
+ recharts.Cell,
2495
+ {
2496
+ fill: entry.key === "guest" ? GUEST_COLOR : REGISTERED_COLOR
2497
+ },
2498
+ entry.key
2499
+ ))
2500
+ }
2501
+ ),
2502
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MixPieTooltip, {}) }),
2503
+ /* @__PURE__ */ jsxRuntime.jsx(
2504
+ recharts.Legend,
2505
+ {
2506
+ wrapperStyle: { fontSize: 9, paddingTop: 0 },
2507
+ verticalAlign: "bottom",
2508
+ height: 22,
2509
+ iconType: "circle"
2510
+ }
2511
+ )
2512
+ ] }) }) }) })
2513
+ }
2514
+ ) }),
2515
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 flex min-h-0 min-w-0 lg:col-span-7", children: /* @__PURE__ */ jsxRuntime.jsx(
2516
+ AnalyticsSection,
2517
+ {
2518
+ variant: "atlas",
2519
+ className: "flex min-h-0 w-full flex-col",
2520
+ title: "Repeat purchases",
2521
+ description: "Orders with a customer_id in the same window (guest checkouts excluded from rate).",
2522
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-1.5", children: repeatLoading ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "flex flex-1 items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) : repeatError ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "flex flex-1 items-center justify-center px-2 py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-ui-fg-danger text-xs", children: repeatError }) }) : repeatStats ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-1.5 sm:grid-cols-3", children: [
2523
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2524
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Repeat rate" }),
2525
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: `${repeatStats.repeat_rate_percent.toFixed(1)}%` }),
2526
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] leading-snug", children: repeatStats.window_days >= 365 ? "Approx. 12-month window" : `Last ${repeatStats.window_days} days` })
2527
+ ] }) }),
2528
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2529
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "With orders" }),
2530
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: repeatStats.customers_with_orders.toLocaleString() }),
2531
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] leading-snug", children: "Customers in window" })
2532
+ ] }) }),
2533
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2534
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Repeat (2+ orders)" }),
2535
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: repeatStats.repeat_customers.toLocaleString() }),
2536
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] leading-snug", children: "Multi-order customers" })
2537
+ ] }) })
2538
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "flex flex-1 items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No data." }) }) })
2539
+ }
2540
+ ) })
2541
+ ] }),
2420
2542
  /* @__PURE__ */ jsxRuntime.jsx(
2421
2543
  AnalyticsSection,
2422
2544
  {
2423
- title: "Guest vs registered",
2424
- description: "Customer mix for the selected count period (same filter as the summary cards).",
2425
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: guestRegisteredPieData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No guest or registered customers in this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { children: [
2545
+ variant: "atlas",
2546
+ actionsBare: true,
2547
+ title: "Customers over time",
2548
+ description: "New registered vs guest activity for the chart range below.",
2549
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
2426
2550
  /* @__PURE__ */ jsxRuntime.jsx(
2427
- recharts.Pie,
2551
+ ui.Label,
2428
2552
  {
2429
- data: guestRegisteredPieData,
2430
- dataKey: "value",
2431
- nameKey: "name",
2432
- cx: "50%",
2433
- cy: "50%",
2434
- innerRadius: 52,
2435
- outerRadius: 88,
2436
- paddingAngle: 2,
2437
- children: guestRegisteredPieData.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
2438
- recharts.Cell,
2439
- {
2440
- fill: entry.key === "guest" ? GUEST_COLOR : REGISTERED_COLOR
2441
- },
2442
- entry.key
2443
- ))
2553
+ htmlFor: "customers-graph-period",
2554
+ className: "shrink-0 text-ui-fg-muted text-xs font-medium",
2555
+ children: "Range"
2444
2556
  }
2445
2557
  ),
2446
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MixPieTooltip, {}) }),
2447
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { wrapperStyle: { fontSize: 12 }, iconType: "circle" })
2448
- ] }) }) }) })
2449
- }
2450
- ),
2451
- /* @__PURE__ */ jsxRuntime.jsx(
2452
- AnalyticsSection,
2453
- {
2454
- title: "Repeat purchases",
2455
- description: "Orders with a customer_id in the same window as the period filter (guest checkouts excluded from rate).",
2456
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: repeatLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[200px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Loading…" }) }) : repeatError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[200px] items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-sm", children: repeatError }) }) : repeatStats ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3", children: [
2457
2558
  /* @__PURE__ */ jsxRuntime.jsx(
2458
- AnalyticsStatCard,
2559
+ "select",
2459
2560
  {
2460
- label: "Repeat rate",
2461
- value: `${repeatStats.repeat_rate_percent.toFixed(1)}%`,
2462
- helper: repeatStats.window_days >= 365 ? "Approx. 12-month window" : `Last ${repeatStats.window_days} days`
2561
+ id: "customers-graph-period",
2562
+ value: graphPeriod,
2563
+ onChange: (e) => setGraphPeriod(e.target.value),
2564
+ className: SELECT_CLASS_NAME$1,
2565
+ children: GRAPH_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
2463
2566
  }
2464
- ),
2465
- /* @__PURE__ */ jsxRuntime.jsx(
2466
- AnalyticsStatCard,
2567
+ )
2568
+ ] }),
2569
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
2570
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-1.5 sm:grid-cols-3", children: [
2571
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2572
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window registered (sum)" }),
2573
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: seriesWindowTotals.registered.toLocaleString() }),
2574
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
2575
+ "Across ",
2576
+ seriesWindowTotals.points,
2577
+ " buckets"
2578
+ ] })
2579
+ ] }) }),
2580
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2581
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window guest (sum)" }),
2582
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: seriesWindowTotals.guest.toLocaleString() }),
2583
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: "Same range as chart" })
2584
+ ] }) }),
2585
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
2586
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Chart period" }),
2587
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: ((_b = GRAPH_PERIODS$1.find((p) => p.value === graphPeriod)) == null ? void 0 : _b.label) ?? graphPeriod }),
2588
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] leading-snug", children: "Independent of summary period filter" })
2589
+ ] }) })
2590
+ ] }),
2591
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[212px] w-full sm:h-[228px]", children: graphLoading ? /* @__PURE__ */ jsxRuntime.jsx(
2592
+ "div",
2467
2593
  {
2468
- label: "Customers with orders",
2469
- value: repeatStats.customers_with_orders.toLocaleString()
2594
+ className: "flex h-full items-center justify-center",
2595
+ role: "status",
2596
+ "aria-label": "Loading customers over time",
2597
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" })
2470
2598
  }
2471
- ),
2472
- /* @__PURE__ */ jsxRuntime.jsx(
2473
- AnalyticsStatCard,
2599
+ ) : graphError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-center text-ui-fg-danger text-xs", children: graphError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
2600
+ recharts.LineChart,
2474
2601
  {
2475
- label: "Repeat customers (2+)",
2476
- value: repeatStats.repeat_customers.toLocaleString()
2477
- }
2478
- )
2479
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[200px] items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No data." }) }) })
2480
- }
2481
- )
2482
- ] }),
2483
- /* @__PURE__ */ jsxRuntime.jsx(
2484
- AnalyticsSection,
2485
- {
2486
- title: "Customers over time",
2487
- actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2488
- /* @__PURE__ */ jsxRuntime.jsx(
2489
- ui.Label,
2490
- {
2491
- htmlFor: "customers-graph-period",
2492
- className: "text-ui-fg-muted text-sm",
2493
- children: "Range"
2494
- }
2495
- ),
2496
- /* @__PURE__ */ jsxRuntime.jsx(
2497
- "select",
2498
- {
2499
- id: "customers-graph-period",
2500
- value: graphPeriod,
2501
- onChange: (e) => setGraphPeriod(e.target.value),
2502
- className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
2503
- children: GRAPH_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
2504
- }
2505
- )
2506
- ] }),
2507
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: graphLoading ? /* @__PURE__ */ jsxRuntime.jsx(
2508
- "div",
2509
- {
2510
- className: "flex items-center justify-center h-full",
2511
- role: "status",
2512
- "aria-label": "Loading customers over time",
2513
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" })
2514
- }
2515
- ) : graphError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: graphError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
2516
- recharts.LineChart,
2517
- {
2518
- data: series,
2519
- margin: { top: 8, right: 8, left: 8, bottom: 8 },
2520
- children: [
2521
- /* @__PURE__ */ jsxRuntime.jsx(
2522
- recharts.CartesianGrid,
2523
- {
2524
- strokeDasharray: "3 3",
2525
- className: "stroke-ui-border-base"
2526
- }
2527
- ),
2528
- /* @__PURE__ */ jsxRuntime.jsx(
2529
- recharts.XAxis,
2530
- {
2531
- dataKey: "date",
2532
- tick: { fontSize: 12 },
2533
- tickFormatter: (v, index) => {
2534
- const row = series[index];
2535
- if (row == null ? void 0 : row.label) return row.label;
2536
- const d = new Date(v);
2537
- return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;
2538
- }
2539
- }
2540
- ),
2541
- /* @__PURE__ */ jsxRuntime.jsx(
2542
- recharts.YAxis,
2543
- {
2544
- tick: { fontSize: 12 },
2545
- tickFormatter: (v) => String(Math.floor(Number(v))),
2546
- allowDecimals: false
2547
- }
2548
- ),
2549
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomersOverTimeTooltip, {}) }),
2550
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
2551
- /* @__PURE__ */ jsxRuntime.jsx(
2552
- recharts.Line,
2553
- {
2554
- type: "monotone",
2555
- dataKey: "registered_count",
2556
- name: "Registered",
2557
- stroke: REGISTERED_COLOR,
2558
- strokeWidth: 2,
2559
- dot: { r: 3 }
2560
- }
2561
- ),
2562
- /* @__PURE__ */ jsxRuntime.jsx(
2563
- recharts.Line,
2564
- {
2565
- type: "monotone",
2566
- dataKey: "guest_count",
2567
- name: "Guest",
2568
- stroke: GUEST_COLOR,
2569
- strokeWidth: 2,
2570
- dot: { r: 3 }
2571
- }
2572
- )
2573
- ]
2574
- }
2575
- ) }) }) })
2576
- }
2577
- )
2578
- ] });
2602
+ data: series,
2603
+ margin: { top: 6, right: 8, left: 0, bottom: 4 },
2604
+ children: [
2605
+ /* @__PURE__ */ jsxRuntime.jsx(
2606
+ recharts.CartesianGrid,
2607
+ {
2608
+ strokeDasharray: "3 3",
2609
+ vertical: false,
2610
+ stroke: "rgba(148,163,184,0.12)"
2611
+ }
2612
+ ),
2613
+ /* @__PURE__ */ jsxRuntime.jsx(
2614
+ recharts.XAxis,
2615
+ {
2616
+ dataKey: "date",
2617
+ tick: CHART_AXIS_TICK$1,
2618
+ stroke: CHART_AXIS_LINE$1,
2619
+ tickLine: false,
2620
+ axisLine: { stroke: CHART_AXIS_LINE$1 },
2621
+ tickFormatter: (_v, index) => {
2622
+ var _a2;
2623
+ const row = series[index];
2624
+ if (row == null ? void 0 : row.label) return row.label;
2625
+ const d = (_a2 = series[index]) == null ? void 0 : _a2.date;
2626
+ return formatChartLabel$1(d);
2627
+ }
2628
+ }
2629
+ ),
2630
+ /* @__PURE__ */ jsxRuntime.jsx(
2631
+ recharts.YAxis,
2632
+ {
2633
+ width: 36,
2634
+ tick: CHART_AXIS_TICK$1,
2635
+ stroke: CHART_AXIS_LINE$1,
2636
+ tickLine: false,
2637
+ axisLine: { stroke: CHART_AXIS_LINE$1 },
2638
+ tickFormatter: (v) => String(Math.floor(Number(v))),
2639
+ allowDecimals: false
2640
+ }
2641
+ ),
2642
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomersOverTimeTooltip, {}) }),
2643
+ /* @__PURE__ */ jsxRuntime.jsx(
2644
+ recharts.Legend,
2645
+ {
2646
+ wrapperStyle: { fontSize: 10, paddingTop: 4 },
2647
+ iconType: "circle"
2648
+ }
2649
+ ),
2650
+ /* @__PURE__ */ jsxRuntime.jsx(
2651
+ recharts.Line,
2652
+ {
2653
+ type: "monotone",
2654
+ dataKey: "registered_count",
2655
+ name: "Registered",
2656
+ stroke: REGISTERED_COLOR,
2657
+ strokeWidth: 2,
2658
+ dot: { r: 2 }
2659
+ }
2660
+ ),
2661
+ /* @__PURE__ */ jsxRuntime.jsx(
2662
+ recharts.Line,
2663
+ {
2664
+ type: "monotone",
2665
+ dataKey: "guest_count",
2666
+ name: "Guest",
2667
+ stroke: GUEST_COLOR,
2668
+ strokeWidth: 2,
2669
+ dot: { r: 2 }
2670
+ }
2671
+ )
2672
+ ]
2673
+ }
2674
+ ) }) }) })
2675
+ ] })
2676
+ }
2677
+ )
2678
+ ] })
2679
+ ] }) });
2579
2680
  }
2580
2681
  const SUMMARY_PERIODS = [
2581
2682
  { value: "all", label: "All time" },
@@ -2595,10 +2696,32 @@ const TOP_SELLER_PERIODS = [
2595
2696
  { value: "year", label: "Year" },
2596
2697
  { value: "all", label: "All time" }
2597
2698
  ];
2598
- const SALES_COLOR = "var(--medusa-color-ui-fg-interactive)";
2599
- const VIEWS_COLOR = "#8B5CF6";
2600
- const REVENUE_COLOR = "#F59E0B";
2601
- const REVENUE_MUTED_COLOR = "#FCD34D";
2699
+ const PRODUCT_CHART_COLORS = {
2700
+ units: "#38BDF8",
2701
+ views: "#C084FC",
2702
+ revenue: "#D946EF",
2703
+ revenueMuted: "#94A3B8",
2704
+ scatter: "#A855F7"
2705
+ };
2706
+ const KPI_ICON_BG = {
2707
+ green: "bg-emerald-500/20",
2708
+ blue: "bg-sky-500/20",
2709
+ purple: "bg-violet-500/20",
2710
+ amber: "bg-amber-500/20"
2711
+ };
2712
+ const KPI_ICONS = {
2713
+ green: icons.CurrencyDollar,
2714
+ blue: icons.ShoppingCart,
2715
+ purple: icons.Tag,
2716
+ amber: icons.CubeSolid
2717
+ };
2718
+ const CHART_AXIS_TICK = { fontSize: 10, fill: "#e5e7eb" };
2719
+ const CHART_AXIS_TICK_SM = { fontSize: 9, fill: "#e5e7eb" };
2720
+ const CHART_AXIS_LINE = "#94a3b8";
2721
+ const SELECT_CLASS_NAME = "h-9 w-full min-w-[8rem] max-w-full cursor-pointer appearance-none rounded border border-ui-border-base bg-ui-bg-base py-1.5 pl-3 pr-8 text-xs text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive sm:w-auto sm:min-w-[132px] sm:max-w-[220px]";
2722
+ const LEADERBOARD_TABLE_CLASS = "min-w-[32rem] sm:min-w-[36rem] max-w-none";
2723
+ const OPPORTUNITIES_TABLE_CLASS = "min-w-[30rem] sm:min-w-[34rem] max-w-none";
2724
+ const TABLE_HEAD_CELL_NOWRAP = "whitespace-nowrap";
2602
2725
  function formatCurrency(value) {
2603
2726
  return new Intl.NumberFormat("en-IN", {
2604
2727
  style: "currency",
@@ -2607,12 +2730,39 @@ function formatCurrency(value) {
2607
2730
  maximumFractionDigits: 0
2608
2731
  }).format(value);
2609
2732
  }
2733
+ function formatCompactCurrency(value) {
2734
+ return new Intl.NumberFormat("en-IN", {
2735
+ style: "currency",
2736
+ currency: "INR",
2737
+ notation: "compact",
2738
+ maximumFractionDigits: 1
2739
+ }).format(value);
2740
+ }
2741
+ function formatChartLabel(value) {
2742
+ if (!value) return "";
2743
+ const parsed = new Date(value);
2744
+ if (Number.isNaN(parsed.getTime())) return value;
2745
+ return `${parsed.getUTCMonth() + 1}/${parsed.getUTCDate()}`;
2746
+ }
2610
2747
  function formatRatio(value) {
2611
2748
  if (value === null || Number.isNaN(value)) return "N/A";
2612
2749
  return `${value.toFixed(2)}x`;
2613
2750
  }
2614
- function truncateLabel(value, maxLength = 22) {
2615
- return value.length > maxLength ? `${value.slice(0, maxLength - 1)}…` : value;
2751
+ function formatShortNumber(value) {
2752
+ return new Intl.NumberFormat("en-IN", {
2753
+ notation: "compact",
2754
+ maximumFractionDigits: value < 10 ? 1 : 0
2755
+ }).format(value);
2756
+ }
2757
+ function topSellerPeriodToGraphPeriod(period) {
2758
+ if (period === "month") return "one_month";
2759
+ if (period === "year" || period === "all") return "one_year";
2760
+ return "one_week";
2761
+ }
2762
+ function summaryDaysToGraphPeriod(days) {
2763
+ if (days === "30") return "one_month";
2764
+ if (days === "all" || days === "90") return "one_year";
2765
+ return "one_week";
2616
2766
  }
2617
2767
  function buildAnalyticsUrl(path, params) {
2618
2768
  const search = new URLSearchParams();
@@ -2624,48 +2774,71 @@ function buildAnalyticsUrl(path, params) {
2624
2774
  const query = search.toString();
2625
2775
  return query ? `${path}?${query}` : path;
2626
2776
  }
2777
+ function isProductOverTimePoint(value) {
2778
+ if (typeof value !== "object" || value === null) return false;
2779
+ const v = value;
2780
+ return typeof v.date === "string" && typeof v.units_sold === "number" && typeof v.revenue === "number" && typeof v.views === "number";
2781
+ }
2627
2782
  function TrendTooltip({
2628
2783
  active,
2629
2784
  payload,
2630
2785
  label
2631
2786
  }) {
2632
- var _a, _b, _c, _d;
2787
+ var _a, _b, _c, _d, _e;
2633
2788
  if (!active || !(payload == null ? void 0 : payload.length)) return null;
2634
- const row = (_a = payload[0]) == null ? void 0 : _a.payload;
2789
+ const row = isProductOverTimePoint((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
2635
2790
  const displayLabel = (row == null ? void 0 : row.label) ?? (label ? new Date(label).toLocaleDateString() : "");
2636
- const unitsSold = ((_b = payload.find((entry) => entry.name === "Units sold")) == null ? void 0 : _b.value) ?? 0;
2637
- const views = ((_c = payload.find((entry) => entry.name === "Views")) == null ? void 0 : _c.value) ?? 0;
2638
- const revenue = ((_d = payload.find((entry) => entry.name === "Revenue")) == null ? void 0 : _d.value) ?? 0;
2639
- return /* @__PURE__ */ jsxRuntime.jsxs(
2640
- "div",
2641
- {
2642
- style: {
2643
- backgroundColor: "rgb(255, 255, 255)",
2644
- color: "#111827",
2645
- border: "1px solid rgb(229, 231, 235)",
2646
- borderRadius: "8px",
2647
- padding: "12px 16px",
2648
- boxShadow: "0 4px 14px rgba(0, 0, 0, 0.08)",
2649
- fontSize: "14px",
2650
- lineHeight: 1.5
2651
- },
2652
- children: [
2653
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, marginBottom: "6px" }, children: displayLabel }),
2654
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2655
- "Units sold: ",
2656
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(unitsSold).toLocaleString() })
2657
- ] }),
2658
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2659
- "Views: ",
2660
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(views).toLocaleString() })
2661
- ] }),
2662
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2663
- "Revenue: ",
2664
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
2665
- ] })
2666
- ]
2667
- }
2668
- );
2791
+ const unitsSold = ((_c = payload.find((entry) => entry.name === "Units sold")) == null ? void 0 : _c.value) ?? 0;
2792
+ const views = ((_d = payload.find((entry) => entry.name === "Views")) == null ? void 0 : _d.value) ?? 0;
2793
+ const revenue = ((_e = payload.find((entry) => entry.name === "Revenue")) == null ? void 0 : _e.value) ?? 0;
2794
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { title: displayLabel, children: [
2795
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2796
+ "Units sold: ",
2797
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(unitsSold)).toLocaleString() })
2798
+ ] }),
2799
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2800
+ "Views: ",
2801
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(views)).toLocaleString() })
2802
+ ] }),
2803
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2804
+ "Revenue: ",
2805
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
2806
+ ] })
2807
+ ] });
2808
+ }
2809
+ function MiniTrendTooltip({
2810
+ active,
2811
+ payload,
2812
+ label,
2813
+ productHeadline,
2814
+ hideViewsRow,
2815
+ hideUnitsRow,
2816
+ hideRevenueRow
2817
+ }) {
2818
+ var _a, _b, _c, _d, _e;
2819
+ if (!active || !(payload == null ? void 0 : payload.length)) return null;
2820
+ const row = isProductOverTimePoint((_a = payload[0]) == null ? void 0 : _a.payload) ? (_b = payload[0]) == null ? void 0 : _b.payload : void 0;
2821
+ const labelKey = label !== void 0 && label !== null ? String(label) : "";
2822
+ const displayLabel = (row == null ? void 0 : row.label) ?? (labelKey ? new Date(labelKey).toLocaleDateString() : "");
2823
+ const unitsSold = ((_c = payload.find((entry) => entry.name === "Units sold")) == null ? void 0 : _c.value) ?? 0;
2824
+ const views = ((_d = payload.find((entry) => entry.name === "Views")) == null ? void 0 : _d.value) ?? 0;
2825
+ const revenue = ((_e = payload.find((entry) => entry.name === "Revenue")) == null ? void 0 : _e.value) ?? 0;
2826
+ const title = productHeadline ?? displayLabel;
2827
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title, children: [
2828
+ productHeadline ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-1 text-[10px] leading-tight opacity-80", children: displayLabel }) : null,
2829
+ !hideUnitsRow ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2830
+ "Units sold: ",
2831
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(unitsSold)).toLocaleString() })
2832
+ ] }) : null,
2833
+ !hideViewsRow ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2834
+ "Views: ",
2835
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(Number(views)).toLocaleString() })
2836
+ ] }) : null,
2837
+ !hideRevenueRow ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2838
+ "Revenue: ",
2839
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
2840
+ ] }) : null
2841
+ ] });
2669
2842
  }
2670
2843
  function ProductBarTooltip({
2671
2844
  active,
@@ -2679,39 +2852,52 @@ function ProductBarTooltip({
2679
2852
  const unitsSold = "units_sold" in row ? row.units_sold : 0;
2680
2853
  const totalViews = "total_views" in row ? row.total_views : 0;
2681
2854
  const revenue = "revenue" in row ? row.revenue : 0;
2682
- return /* @__PURE__ */ jsxRuntime.jsxs(
2683
- "div",
2684
- {
2685
- style: {
2686
- backgroundColor: "rgb(255, 255, 255)",
2687
- color: "#111827",
2688
- border: "1px solid rgb(229, 231, 235)",
2689
- borderRadius: "8px",
2690
- padding: "12px 16px",
2691
- boxShadow: "0 4px 14px rgba(0, 0, 0, 0.08)",
2692
- fontSize: "14px",
2693
- lineHeight: 1.5
2694
- },
2695
- children: [
2696
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontWeight: 600, marginBottom: "6px" }, children: row.product_title }),
2697
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2698
- "Units sold: ",
2699
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(unitsSold).toLocaleString() })
2700
- ] }),
2701
- showViews ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2702
- "Views: ",
2703
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(totalViews).toLocaleString() })
2704
- ] }) : null,
2705
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2706
- "Revenue: ",
2707
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
2708
- ] })
2709
- ]
2710
- }
2711
- );
2855
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsTooltipCard, { variant: "compact", title: row.product_title, children: [
2856
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2857
+ "Units sold: ",
2858
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(unitsSold).toLocaleString() })
2859
+ ] }),
2860
+ showViews ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2861
+ "Views: ",
2862
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(totalViews).toLocaleString() })
2863
+ ] }) : null,
2864
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2865
+ "Revenue: ",
2866
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
2867
+ ] })
2868
+ ] });
2869
+ }
2870
+ function AtlasKpiCard({
2871
+ label,
2872
+ value,
2873
+ helper,
2874
+ accent
2875
+ }) {
2876
+ const Icon = KPI_ICONS[accent];
2877
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-[88px] min-w-0 flex-col rounded-xl border border-ui-border-base/80 bg-ui-bg-subtle/25 p-3 shadow-sm", children: [
2878
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
2879
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "min-w-0 flex-1 text-left text-xs font-medium leading-snug text-ui-fg-base", children: label }),
2880
+ /* @__PURE__ */ jsxRuntime.jsx(
2881
+ "div",
2882
+ {
2883
+ className: `flex h-7 w-7 shrink-0 items-center justify-center rounded-lg ${KPI_ICON_BG[accent]}`,
2884
+ "aria-hidden": true,
2885
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-3.5 w-3.5 text-ui-fg-base" })
2886
+ }
2887
+ )
2888
+ ] }),
2889
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 text-lg font-semibold tabular-nums tracking-tight text-ui-fg-base sm:text-xl", children: value }),
2890
+ helper ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "mt-2 text-[11px] leading-snug text-ui-fg-muted", children: helper }) : null
2891
+ ] });
2892
+ }
2893
+ function EmptyAnalyticsPanel({ title, description }) {
2894
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[88px] flex-col gap-1.5 rounded-lg border border-dashed border-ui-border-base px-3 py-3", children: [
2895
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-xs font-semibold", children: title }),
2896
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[11px] leading-snug", children: description })
2897
+ ] });
2712
2898
  }
2713
2899
  function ProductsDashboard() {
2714
- var _a, _b, _c;
2900
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2715
2901
  const [summaryDays, setSummaryDays] = react.useState("all");
2716
2902
  const [graphPeriod, setGraphPeriod] = react.useState("one_week");
2717
2903
  const [topSellerPeriod, setTopSellerPeriod] = react.useState("week");
@@ -2731,11 +2917,17 @@ function ProductsDashboard() {
2731
2917
  const [performance, setPerformance] = react.useState(null);
2732
2918
  const [performanceLoading, setPerformanceLoading] = react.useState(true);
2733
2919
  const [performanceError, setPerformanceError] = react.useState(null);
2920
+ const [bestSellersTrend, setBestSellersTrend] = react.useState(null);
2921
+ const [bestSellersTrendLoading, setBestSellersTrendLoading] = react.useState(true);
2922
+ const [bestSellersTrendError, setBestSellersTrendError] = react.useState(null);
2923
+ const [mostViewedTrend, setMostViewedTrend] = react.useState(null);
2924
+ const [mostViewedTrendLoading, setMostViewedTrendLoading] = react.useState(true);
2925
+ const [mostViewedTrendError, setMostViewedTrendError] = react.useState(null);
2734
2926
  react.useEffect(() => {
2735
2927
  let cancelled = false;
2736
2928
  setFiltersLoading(true);
2737
2929
  setFiltersError(null);
2738
- fetch("/admin/analytics/products-filters").then((res) => {
2930
+ fetch("/admin/analytics/products-filters", { credentials: "include" }).then((res) => {
2739
2931
  if (!res.ok) throw new Error(res.statusText);
2740
2932
  return res.json();
2741
2933
  }).then((body) => {
@@ -2761,7 +2953,8 @@ function ProductsDashboard() {
2761
2953
  buildAnalyticsUrl("/admin/analytics/products-summary", {
2762
2954
  days: summaryDays,
2763
2955
  sales_channel_id: salesChannelId !== "all" ? salesChannelId : null
2764
- })
2956
+ }),
2957
+ { credentials: "include" }
2765
2958
  ).then((res) => {
2766
2959
  if (!res.ok) throw new Error(res.statusText);
2767
2960
  return res.json();
@@ -2786,7 +2979,8 @@ function ProductsDashboard() {
2786
2979
  buildAnalyticsUrl("/admin/analytics/products-over-time", {
2787
2980
  period: graphPeriod,
2788
2981
  sales_channel_id: salesChannelId !== "all" ? salesChannelId : null
2789
- })
2982
+ }),
2983
+ { credentials: "include" }
2790
2984
  ).then((res) => {
2791
2985
  if (!res.ok) throw new Error(res.statusText);
2792
2986
  return res.json();
@@ -2811,7 +3005,8 @@ function ProductsDashboard() {
2811
3005
  buildAnalyticsUrl("/admin/analytics/products-top-sellers", {
2812
3006
  period: topSellerPeriod,
2813
3007
  sales_channel_id: salesChannelId !== "all" ? salesChannelId : null
2814
- })
3008
+ }),
3009
+ { credentials: "include" }
2815
3010
  ).then((res) => {
2816
3011
  if (!res.ok) throw new Error(res.statusText);
2817
3012
  return res.json();
@@ -2828,6 +3023,126 @@ function ProductsDashboard() {
2828
3023
  cancelled = true;
2829
3024
  };
2830
3025
  }, [salesChannelId, topSellerPeriod]);
3026
+ react.useEffect(() => {
3027
+ var _a2, _b2;
3028
+ let cancelled = false;
3029
+ if (topSellersLoading) {
3030
+ setBestSellersTrendLoading(true);
3031
+ return () => {
3032
+ cancelled = true;
3033
+ };
3034
+ }
3035
+ if (topSellersError) {
3036
+ setBestSellersTrendLoading(false);
3037
+ setBestSellersTrendError(topSellersError);
3038
+ setBestSellersTrend(null);
3039
+ return () => {
3040
+ cancelled = true;
3041
+ };
3042
+ }
3043
+ const topProductId = (_b2 = (_a2 = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id;
3044
+ if (!topProductId) {
3045
+ setBestSellersTrendLoading(false);
3046
+ setBestSellersTrendError(null);
3047
+ setBestSellersTrend({
3048
+ series: [],
3049
+ productViewsConnected: (topSellers == null ? void 0 : topSellers.productViewsConnected) ?? false,
3050
+ product: null
3051
+ });
3052
+ return () => {
3053
+ cancelled = true;
3054
+ };
3055
+ }
3056
+ setBestSellersTrendLoading(true);
3057
+ setBestSellersTrendError(null);
3058
+ const period = topSellerPeriodToGraphPeriod(topSellerPeriod);
3059
+ fetch(
3060
+ buildAnalyticsUrl("/admin/analytics/products-over-time", {
3061
+ period,
3062
+ sales_channel_id: salesChannelId !== "all" ? salesChannelId : null,
3063
+ product_id: topProductId
3064
+ }),
3065
+ { credentials: "include" }
3066
+ ).then((res) => {
3067
+ if (!res.ok) throw new Error(res.statusText);
3068
+ return res.json();
3069
+ }).then((body) => {
3070
+ if (!cancelled) setBestSellersTrend(body);
3071
+ }).catch((error) => {
3072
+ if (!cancelled) {
3073
+ setBestSellersTrendError(error instanceof Error ? error.message : String(error));
3074
+ }
3075
+ }).finally(() => {
3076
+ if (!cancelled) setBestSellersTrendLoading(false);
3077
+ });
3078
+ return () => {
3079
+ cancelled = true;
3080
+ };
3081
+ }, [salesChannelId, topSellerPeriod, topSellersLoading, topSellersError, topSellers]);
3082
+ react.useEffect(() => {
3083
+ var _a2, _b2;
3084
+ let cancelled = false;
3085
+ if (performanceLoading) {
3086
+ setMostViewedTrendLoading(true);
3087
+ return () => {
3088
+ cancelled = true;
3089
+ };
3090
+ }
3091
+ if (performanceError) {
3092
+ setMostViewedTrendLoading(false);
3093
+ setMostViewedTrendError(performanceError);
3094
+ setMostViewedTrend(null);
3095
+ return () => {
3096
+ cancelled = true;
3097
+ };
3098
+ }
3099
+ if (!(performance == null ? void 0 : performance.productViewsConnected)) {
3100
+ setMostViewedTrendLoading(false);
3101
+ setMostViewedTrendError(null);
3102
+ setMostViewedTrend(null);
3103
+ return () => {
3104
+ cancelled = true;
3105
+ };
3106
+ }
3107
+ const topViewedId = (_b2 = (_a2 = performance.topViewedProducts) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id;
3108
+ if (!topViewedId) {
3109
+ setMostViewedTrendLoading(false);
3110
+ setMostViewedTrendError(null);
3111
+ setMostViewedTrend({
3112
+ series: [],
3113
+ productViewsConnected: true,
3114
+ product: null
3115
+ });
3116
+ return () => {
3117
+ cancelled = true;
3118
+ };
3119
+ }
3120
+ setMostViewedTrendLoading(true);
3121
+ setMostViewedTrendError(null);
3122
+ const period = summaryDaysToGraphPeriod(summaryDays);
3123
+ fetch(
3124
+ buildAnalyticsUrl("/admin/analytics/products-over-time", {
3125
+ period,
3126
+ sales_channel_id: salesChannelId !== "all" ? salesChannelId : null,
3127
+ product_id: topViewedId
3128
+ }),
3129
+ { credentials: "include" }
3130
+ ).then((res) => {
3131
+ if (!res.ok) throw new Error(res.statusText);
3132
+ return res.json();
3133
+ }).then((body) => {
3134
+ if (!cancelled) setMostViewedTrend(body);
3135
+ }).catch((error) => {
3136
+ if (!cancelled) {
3137
+ setMostViewedTrendError(error instanceof Error ? error.message : String(error));
3138
+ }
3139
+ }).finally(() => {
3140
+ if (!cancelled) setMostViewedTrendLoading(false);
3141
+ });
3142
+ return () => {
3143
+ cancelled = true;
3144
+ };
3145
+ }, [salesChannelId, summaryDays, performanceLoading, performanceError, performance]);
2831
3146
  react.useEffect(() => {
2832
3147
  let cancelled = false;
2833
3148
  setPerformanceLoading(true);
@@ -2836,7 +3151,8 @@ function ProductsDashboard() {
2836
3151
  buildAnalyticsUrl("/admin/analytics/products-performance", {
2837
3152
  days: summaryDays,
2838
3153
  sales_channel_id: salesChannelId !== "all" ? salesChannelId : null
2839
- })
3154
+ }),
3155
+ { credentials: "include" }
2840
3156
  ).then((res) => {
2841
3157
  if (!res.ok) throw new Error(res.statusText);
2842
3158
  return res.json();
@@ -2853,33 +3169,64 @@ function ProductsDashboard() {
2853
3169
  cancelled = true;
2854
3170
  };
2855
3171
  }, [salesChannelId, summaryDays]);
2856
- const topSellerChartData = react.useMemo(
2857
- () => ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 7).map((row) => {
2858
- var _a2, _b2;
2859
- return {
2860
- ...row,
2861
- isBestSeller: row.product_id === (((_b2 = (_a2 = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id) ?? null),
2862
- product_title: truncateLabel(row.product_title, 24)
2863
- };
2864
- }).reverse(),
2865
- [topSellers]
2866
- );
2867
- const topViewedChartData = react.useMemo(
2868
- () => ((performance == null ? void 0 : performance.topViewedProducts) ?? []).slice(0, 7).map((row) => ({
2869
- ...row,
2870
- product_title: truncateLabel(row.product_title, 24)
2871
- })).reverse(),
2872
- [performance]
2873
- );
3172
+ const series = (overTime == null ? void 0 : overTime.series) ?? [];
3173
+ const trendTotals = react.useMemo(() => {
3174
+ const totalUnits = series.reduce((s, p) => s + p.units_sold, 0);
3175
+ const totalRevenue = series.reduce((s, p) => s + p.revenue, 0);
3176
+ const totalViews = series.reduce((s, p) => s + p.views, 0);
3177
+ const n = series.length || 1;
3178
+ return {
3179
+ totalUnits,
3180
+ totalRevenue,
3181
+ totalViews,
3182
+ avgUnitsPerDay: totalUnits / n,
3183
+ avgRevenuePerDay: totalRevenue / n,
3184
+ avgViewsPerDay: totalViews / n
3185
+ };
3186
+ }, [series]);
3187
+ const peakRevenuePoint = series.length > 0 ? series.reduce((peak, point) => point.revenue > peak.revenue ? point : peak) : null;
3188
+ 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;
3189
+ const bestSellersTrendSeries = (bestSellersTrend == null ? void 0 : bestSellersTrend.series) ?? [];
3190
+ const mostViewedTrendSeries = (mostViewedTrend == null ? void 0 : mostViewedTrend.series) ?? [];
3191
+ const bestSellerTrendProductTitle = ((_a = bestSellersTrend == null ? void 0 : bestSellersTrend.product) == null ? void 0 : _a.product_title) ?? ((_c = (_b = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _b[0]) == null ? void 0 : _c.product_title) ?? null;
3192
+ const mostViewedTrendProductTitle = ((_d = mostViewedTrend == null ? void 0 : mostViewedTrend.product) == null ? void 0 : _d.product_title) ?? ((_f = (_e = performance == null ? void 0 : performance.topViewedProducts) == null ? void 0 : _e[0]) == null ? void 0 : _f.product_title) ?? null;
2874
3193
  const viewsVsUnitsScatterData = react.useMemo(
2875
3194
  () => ((performance == null ? void 0 : performance.topViewedProducts) ?? []).slice(0, 48).filter((row) => row.total_views > 0 || row.units_sold > 0),
2876
3195
  [performance]
2877
3196
  );
3197
+ const selectedSummaryPeriod = ((_g = SUMMARY_PERIODS.find((p) => p.value === summaryDays)) == null ? void 0 : _g.label) ?? "All time";
3198
+ const selectedGraphPeriodLabel = ((_h = GRAPH_PERIODS.find((p) => p.value === graphPeriod)) == null ? void 0 : _h.label) ?? "One week";
3199
+ const quickPulseMetrics = [
3200
+ {
3201
+ label: "Range units",
3202
+ value: formatShortNumber(trendTotals.totalUnits),
3203
+ helper: selectedGraphPeriodLabel,
3204
+ accentClassName: "border-sky-400/25 bg-sky-500/5"
3205
+ },
3206
+ {
3207
+ label: "Range revenue",
3208
+ value: formatCompactCurrency(trendTotals.totalRevenue),
3209
+ helper: "Current chart window",
3210
+ accentClassName: "border-fuchsia-400/25 bg-fuchsia-500/5"
3211
+ },
3212
+ {
3213
+ label: "Avg/day views",
3214
+ value: trendTotals.avgViewsPerDay.toFixed(0),
3215
+ helper: viewsConnectedForPulse ? "Across chart range" : "Views need tracking",
3216
+ accentClassName: "border-violet-400/25 bg-violet-500/5"
3217
+ },
3218
+ {
3219
+ label: "Peak revenue day",
3220
+ value: peakRevenuePoint ? formatCompactCurrency(peakRevenuePoint.revenue) : "—",
3221
+ helper: (peakRevenuePoint == null ? void 0 : peakRevenuePoint.label) ?? formatChartLabel(peakRevenuePoint == null ? void 0 : peakRevenuePoint.date),
3222
+ accentClassName: "border-amber-400/25 bg-amber-500/5"
3223
+ }
3224
+ ];
2878
3225
  if (summaryLoading) {
2879
3226
  return /* @__PURE__ */ jsxRuntime.jsx(
2880
3227
  "div",
2881
3228
  {
2882
- className: "flex items-center justify-center min-h-[320px]",
3229
+ className: "flex min-h-[200px] items-center justify-center",
2883
3230
  role: "status",
2884
3231
  "aria-label": "Loading product analytics",
2885
3232
  children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading…" })
@@ -2890,16 +3237,65 @@ function ProductsDashboard() {
2890
3237
  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" }) });
2891
3238
  }
2892
3239
  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;
2893
- const selectedChannelLabel = salesChannelId === "all" ? "All channels" : ((_a = salesChannels.find((channel) => channel.id === salesChannelId)) == null ? void 0 : _a.name) ?? "Selected channel";
2894
- return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsDashboardShell, { children: [
2895
- /* @__PURE__ */ jsxRuntime.jsx(
2896
- AnalyticsDashboardHeader,
2897
- {
3240
+ const selectedChannelLabel = salesChannelId === "all" ? "All channels" : ((_i = salesChannels.find((channel) => channel.id === salesChannelId)) == null ? void 0 : _i.name) ?? "Selected channel";
3241
+ const primaryStats = [
3242
+ {
3243
+ label: "Units sold",
3244
+ value: summary.unitsSold.toLocaleString(),
3245
+ helper: selectedSummaryPeriod,
3246
+ accent: "amber"
3247
+ },
3248
+ {
3249
+ label: "Product revenue",
3250
+ value: formatCurrency(summary.productRevenue),
3251
+ helper: selectedSummaryPeriod,
3252
+ accent: "green"
3253
+ },
3254
+ {
3255
+ label: "Orders with products",
3256
+ value: summary.ordersWithProducts.toLocaleString(),
3257
+ helper: "Distinct orders",
3258
+ accent: "blue"
3259
+ },
3260
+ {
3261
+ label: "Active products sold",
3262
+ value: summary.activeProductsSold.toLocaleString(),
3263
+ helper: "Unique SKUs with sales",
3264
+ accent: "purple"
3265
+ },
3266
+ {
3267
+ label: "Product views",
3268
+ value: summary.totalProductViews.toLocaleString(),
3269
+ helper: viewsConnected ? "Tracked views" : "Tracking unavailable",
3270
+ accent: "green"
3271
+ },
3272
+ {
3273
+ label: "View / order ratio",
3274
+ value: formatRatio(summary.viewToOrderRatio),
3275
+ helper: viewsConnected ? "Views per product order" : "N/A without views",
3276
+ accent: "blue"
3277
+ }
3278
+ ];
3279
+ return /* @__PURE__ */ jsxRuntime.jsx(AnalyticsDashboardShell, { className: "w-full min-w-0 max-w-full", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full min-w-0 max-w-full overflow-hidden rounded-2xl border border-ui-border-base/80 bg-ui-bg-base shadow-sm", children: [
3280
+ /* @__PURE__ */ jsxRuntime.jsx(
3281
+ AnalyticsDashboardHeader,
3282
+ {
3283
+ variant: "premium",
3284
+ appearance: "inset",
3285
+ actionsBare: true,
3286
+ actionsClassName: "w-full justify-start lg:w-auto lg:justify-end",
2898
3287
  title: "Products",
2899
- description: "Track units sold, revenue, best sellers, and product visit behavior in a denser, easier-to-scan layout.",
2900
- actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-end gap-2.5", children: [
2901
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2902
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-channel-filter", className: "text-ui-fg-muted text-xs font-medium", children: "Channel" }),
3288
+ description: "Units, revenue, best sellers, and visit behavior in a compact layout aligned with Orders analytics.",
3289
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full min-w-0 flex-wrap items-center gap-x-3 gap-y-2 sm:flex-nowrap lg:gap-x-4", children: [
3290
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 sm:flex-initial sm:flex-none", children: [
3291
+ /* @__PURE__ */ jsxRuntime.jsx(
3292
+ ui.Label,
3293
+ {
3294
+ htmlFor: "products-channel-filter",
3295
+ className: "shrink-0 whitespace-nowrap text-ui-fg-muted text-xs font-medium",
3296
+ children: "Channel"
3297
+ }
3298
+ ),
2903
3299
  /* @__PURE__ */ jsxRuntime.jsxs(
2904
3300
  "select",
2905
3301
  {
@@ -2907,7 +3303,8 @@ function ProductsDashboard() {
2907
3303
  value: salesChannelId,
2908
3304
  onChange: (event) => setSalesChannelId(event.target.value),
2909
3305
  disabled: filtersLoading,
2910
- className: "h-8 min-w-[150px] rounded-md border border-ui-border-base bg-ui-bg-base px-2.5 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
3306
+ className: SELECT_CLASS_NAME,
3307
+ "aria-busy": filtersLoading,
2911
3308
  children: [
2912
3309
  /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All channels" }),
2913
3310
  salesChannels.map((channel) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: channel.id, children: channel.name }, channel.id))
@@ -2915,419 +3312,966 @@ function ProductsDashboard() {
2915
3312
  }
2916
3313
  )
2917
3314
  ] }),
2918
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
2919
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-summary-period", className: "text-ui-fg-muted text-xs font-medium", children: "Period" }),
3315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2 sm:flex-initial sm:flex-none", children: [
3316
+ /* @__PURE__ */ jsxRuntime.jsx(
3317
+ ui.Label,
3318
+ {
3319
+ htmlFor: "products-summary-period",
3320
+ className: "shrink-0 whitespace-nowrap text-ui-fg-muted text-xs font-medium",
3321
+ children: "Period"
3322
+ }
3323
+ ),
2920
3324
  /* @__PURE__ */ jsxRuntime.jsx(
2921
3325
  "select",
2922
3326
  {
2923
3327
  id: "products-summary-period",
2924
3328
  value: summaryDays,
2925
3329
  onChange: (event) => setSummaryDays(event.target.value),
2926
- className: "h-8 min-w-[132px] rounded-md border border-ui-border-base bg-ui-bg-base px-2.5 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
3330
+ className: SELECT_CLASS_NAME,
2927
3331
  children: SUMMARY_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
2928
3332
  }
2929
3333
  )
2930
3334
  ] }),
2931
- (summaryDays !== "all" || salesChannelId !== "all") && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 self-end pb-1", children: [
2932
- summaryDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
3335
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full shrink-0 flex-wrap items-center gap-x-3 gap-y-1 sm:w-auto sm:pl-1", children: [
3336
+ summaryDays !== "all" ? /* @__PURE__ */ jsxRuntime.jsx(
2933
3337
  "button",
2934
3338
  {
2935
3339
  type: "button",
2936
3340
  onClick: () => setSummaryDays("all"),
2937
3341
  className: "text-xs text-ui-fg-muted transition-colors hover:text-ui-fg-base",
2938
- "aria-label": "Show all products analytics",
3342
+ "aria-label": "Clear summary period filter",
2939
3343
  children: "Clear period"
2940
3344
  }
2941
- ),
2942
- salesChannelId !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
3345
+ ) : null,
3346
+ salesChannelId !== "all" ? /* @__PURE__ */ jsxRuntime.jsx(
2943
3347
  "button",
2944
3348
  {
2945
3349
  type: "button",
2946
3350
  onClick: () => setSalesChannelId("all"),
2947
3351
  className: "text-xs text-ui-fg-muted transition-colors hover:text-ui-fg-base",
2948
- "aria-label": "Show all sales channels",
3352
+ "aria-label": "Clear sales channel filter",
2949
3353
  children: "Clear channel"
2950
3354
  }
2951
- )
3355
+ ) : null
2952
3356
  ] })
2953
3357
  ] })
2954
3358
  }
2955
3359
  ),
2956
- filtersError && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-sm", children: filtersError }) }),
2957
- !viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Product views are unavailable until the `medusa-product-helper` tracking module is registered and storefront page views are being recorded." }) }),
2958
- salesChannelId !== "all" && viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-sm", children: [
2959
- "Showing product analytics for ",
2960
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: selectedChannelLabel }),
2961
- ". Product views are scoped to products assigned to this sales channel."
2962
- ] }) }),
2963
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3", children: [
2964
- /* @__PURE__ */ jsxRuntime.jsx(
2965
- AnalyticsStatCard,
2966
- {
2967
- label: "Units sold",
2968
- value: summary.unitsSold.toLocaleString()
2969
- }
2970
- ),
2971
- /* @__PURE__ */ jsxRuntime.jsx(
2972
- AnalyticsStatCard,
2973
- {
2974
- label: "Product revenue",
2975
- value: formatCurrency(summary.productRevenue)
2976
- }
2977
- ),
2978
- /* @__PURE__ */ jsxRuntime.jsx(
2979
- AnalyticsStatCard,
2980
- {
2981
- label: "Orders with product sales",
2982
- value: summary.ordersWithProducts.toLocaleString()
2983
- }
2984
- ),
2985
- /* @__PURE__ */ jsxRuntime.jsx(
2986
- AnalyticsStatCard,
2987
- {
2988
- label: "Active products sold",
2989
- value: summary.activeProductsSold.toLocaleString()
2990
- }
2991
- ),
2992
- /* @__PURE__ */ jsxRuntime.jsx(
2993
- AnalyticsStatCard,
2994
- {
2995
- label: "Product views",
2996
- value: summary.totalProductViews.toLocaleString()
2997
- }
2998
- ),
2999
- /* @__PURE__ */ jsxRuntime.jsx(
3000
- AnalyticsStatCard,
3001
- {
3002
- label: "View / order ratio",
3003
- value: formatRatio(summary.viewToOrderRatio)
3004
- }
3005
- )
3006
- ] }),
3007
- /* @__PURE__ */ jsxRuntime.jsx(
3008
- AnalyticsSection,
3009
- {
3010
- title: "Sales and views over time",
3011
- description: "Units sold and revenue are always shown. Product views appear when tracking data is available.",
3012
- actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
3013
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-graph-period", className: "text-ui-fg-muted text-sm", children: "Range" }),
3014
- /* @__PURE__ */ jsxRuntime.jsx(
3015
- "select",
3016
- {
3017
- id: "products-graph-period",
3018
- value: graphPeriod,
3019
- onChange: (event) => setGraphPeriod(event.target.value),
3020
- className: "h-9 rounded-md border border-ui-border-base bg-transparent px-3 text-sm text-ui-fg-base outline-none transition focus:ring-2 focus:ring-ui-fg-interactive",
3021
- children: GRAPH_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
3022
- }
3023
- )
3024
- ] }),
3025
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" }) }) : overTimeError || !overTime ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: overTimeError ?? "Failed to load product trend" }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: overTime.series, children: [
3026
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
3027
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "label" }),
3028
- /* @__PURE__ */ jsxRuntime.jsx(
3029
- recharts.YAxis,
3030
- {
3031
- yAxisId: "counts",
3032
- allowDecimals: false,
3033
- tickFormatter: (value) => Math.floor(Number(value)).toLocaleString()
3034
- }
3035
- ),
3036
- /* @__PURE__ */ jsxRuntime.jsx(
3037
- recharts.YAxis,
3038
- {
3039
- yAxisId: "revenue",
3040
- orientation: "right",
3041
- tickFormatter: (value) => formatCurrency(Number(value))
3042
- }
3043
- ),
3044
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(TrendTooltip, {}) }),
3045
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
3046
- /* @__PURE__ */ jsxRuntime.jsx(
3047
- recharts.Line,
3048
- {
3049
- yAxisId: "counts",
3050
- type: "monotone",
3051
- dataKey: "units_sold",
3052
- name: "Units sold",
3053
- stroke: SALES_COLOR,
3054
- strokeWidth: 2,
3055
- dot: false
3056
- }
3057
- ),
3058
- /* @__PURE__ */ jsxRuntime.jsx(
3059
- recharts.Line,
3060
- {
3061
- yAxisId: "counts",
3062
- type: "monotone",
3063
- dataKey: "views",
3064
- name: "Views",
3065
- stroke: VIEWS_COLOR,
3066
- strokeWidth: 2,
3067
- dot: false
3068
- }
3069
- ),
3070
- /* @__PURE__ */ jsxRuntime.jsx(
3071
- recharts.Line,
3072
- {
3073
- yAxisId: "revenue",
3074
- type: "monotone",
3075
- dataKey: "revenue",
3076
- name: "Revenue",
3077
- stroke: REVENUE_COLOR,
3078
- strokeWidth: 2,
3079
- dot: false
3080
- }
3081
- )
3082
- ] }) }) }) })
3083
- }
3084
- ),
3085
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 xl:grid-cols-2", children: [
3086
- /* @__PURE__ */ jsxRuntime.jsx(
3087
- AnalyticsSection,
3088
- {
3089
- title: "Best sellers",
3090
- description: "Top products by revenue.",
3091
- actions: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", children: TOP_SELLER_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx(
3092
- ui.Button,
3093
- {
3094
- variant: topSellerPeriod === period.value ? "secondary" : "transparent",
3095
- size: "small",
3096
- onClick: () => setTopSellerPeriod(period.value),
3097
- children: period.label
3098
- },
3099
- period.value
3100
- )) }),
3101
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: topSellersLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading best sellers…" }) }) : topSellersError || !topSellers ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: topSellersError ?? "Failed to load best sellers" }) }) : topSellerChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product sales found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topSellerChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
3102
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
3103
- /* @__PURE__ */ jsxRuntime.jsx(
3104
- recharts.XAxis,
3105
- {
3106
- type: "number",
3107
- allowDecimals: false,
3108
- tickFormatter: (value) => formatCurrency(Number(value))
3109
- }
3110
- ),
3111
- /* @__PURE__ */ jsxRuntime.jsx(
3112
- recharts.YAxis,
3113
- {
3114
- type: "category",
3115
- dataKey: "product_title",
3116
- width: 160,
3117
- tickLine: false
3118
- }
3119
- ),
3120
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, { showViews: false }) }),
3121
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "revenue", radius: [0, 6, 6, 0], children: topSellerChartData.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
3122
- recharts.Cell,
3123
- {
3124
- fill: entry.isBestSeller ? REVENUE_COLOR : REVENUE_MUTED_COLOR
3125
- },
3126
- entry.product_id
3127
- )) })
3128
- ] }) }) }) })
3129
- }
3130
- ),
3131
- /* @__PURE__ */ jsxRuntime.jsx(
3132
- AnalyticsSection,
3133
- {
3134
- title: "Top seller breakdown",
3135
- description: "Products ranked by revenue.",
3136
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTableSurface, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
3137
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3138
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
3139
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
3140
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Orders" }),
3141
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Revenue" })
3142
- ] }) }),
3143
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
3144
- ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 8).map((product) => {
3145
- var _a2, _b2;
3146
- return /* @__PURE__ */ jsxRuntime.jsxs(
3147
- ui.Table.Row,
3148
- {
3149
- className: product.product_id === ((_b2 = (_a2 = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id) ? "bg-ui-bg-subtle" : void 0,
3150
- children: [
3151
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
3152
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
3153
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.order_count.toLocaleString() }),
3154
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatCurrency(product.revenue) })
3155
- ]
3156
- },
3157
- product.product_id
3158
- );
3159
- }),
3160
- !topSellersLoading && (((_b = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _b.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3161
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No best seller data yet." }),
3162
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3163
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3164
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
3165
- ] })
3166
- ] })
3167
- ] }) })
3168
- }
3169
- )
3170
- ] }),
3171
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 xl:grid-cols-2", children: [
3172
- /* @__PURE__ */ jsxRuntime.jsx(
3173
- AnalyticsSection,
3174
- {
3175
- title: "Most viewed products",
3176
- description: "View activity is sourced from the existing product-helper tracking module.",
3177
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading product views…" }) }) : performanceError || !performance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: performanceError ?? "Failed to load product performance" }) }) : !performance.productViewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Product view tracking is not available in this environment." }) }) : topViewedChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product views found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topViewedChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
3178
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
3179
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", allowDecimals: false }),
3180
- /* @__PURE__ */ jsxRuntime.jsx(
3181
- recharts.YAxis,
3182
- {
3183
- type: "category",
3184
- dataKey: "product_title",
3185
- width: 160,
3186
- tickLine: false
3187
- }
3188
- ),
3189
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {}) }),
3190
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "total_views", fill: VIEWS_COLOR, radius: [0, 6, 6, 0] })
3191
- ] }) }) }) })
3192
- }
3193
- ),
3194
- /* @__PURE__ */ jsxRuntime.jsx(
3195
- AnalyticsSection,
3196
- {
3197
- title: "View-to-sales opportunities",
3198
- description: "Highlight products that attract attention but convert less efficiently.",
3199
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTableSurface, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
3200
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3201
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
3202
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views" }),
3203
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
3204
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views / unit" })
3205
- ] }) }),
3206
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
3207
- ((performance == null ? void 0 : performance.viewOpportunities) ?? []).slice(0, 8).map((product) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3208
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
3209
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.total_views.toLocaleString() }),
3210
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
3211
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatRatio(product.views_per_unit) })
3212
- ] }, product.product_id)),
3213
- !performanceLoading && !performanceError && (((_c = performance == null ? void 0 : performance.viewOpportunities) == null ? void 0 : _c.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3214
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No product view opportunities yet." }),
3215
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3216
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3217
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
3218
- ] })
3219
- ] })
3220
- ] }) })
3221
- }
3222
- )
3223
- ] }),
3224
- /* @__PURE__ */ jsxRuntime.jsx(
3225
- AnalyticsSection,
3226
- {
3227
- title: "Views vs units sold",
3228
- description: "Each point is a product (top viewed in this period). Requires product view tracking.",
3229
- children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading scatter…" }) }) : performanceError || !performance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: performanceError ?? "Failed to load product performance" }) }) : !performance.productViewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Product view tracking is not available in this environment." }) }) : viewsVsUnitsScatterData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No products with views or sales in this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ScatterChart, { margin: { top: 12, right: 16, bottom: 8, left: 8 }, children: [
3230
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", stroke: "rgba(148,163,184,0.2)" }),
3231
- /* @__PURE__ */ jsxRuntime.jsx(
3232
- recharts.XAxis,
3233
- {
3234
- type: "number",
3235
- dataKey: "total_views",
3236
- name: "Views",
3237
- tick: { fontSize: 11 },
3238
- allowDecimals: false,
3239
- label: {
3240
- value: "Views",
3241
- position: "insideBottom",
3242
- offset: -4,
3243
- fontSize: 11,
3244
- fill: "#6b7280"
3245
- }
3246
- }
3247
- ),
3248
- /* @__PURE__ */ jsxRuntime.jsx(
3249
- recharts.YAxis,
3250
- {
3251
- type: "number",
3252
- dataKey: "units_sold",
3253
- name: "Units sold",
3254
- tick: { fontSize: 11 },
3255
- allowDecimals: false,
3256
- label: {
3257
- value: "Units sold",
3258
- angle: -90,
3259
- position: "insideLeft",
3260
- fontSize: 11,
3261
- fill: "#6b7280"
3262
- }
3263
- }
3264
- ),
3265
- /* @__PURE__ */ jsxRuntime.jsx(
3266
- recharts.Tooltip,
3267
- {
3268
- cursor: { strokeDasharray: "4 4" },
3269
- content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {})
3270
- }
3271
- ),
3272
- /* @__PURE__ */ jsxRuntime.jsx(
3273
- recharts.Scatter,
3274
- {
3275
- name: "Products",
3276
- data: viewsVsUnitsScatterData,
3277
- fill: VIEWS_COLOR
3278
- }
3279
- )
3280
- ] }) }) }) })
3281
- }
3282
- )
3283
- ] });
3284
- }
3285
- const ANALYTICS_MODULES = [
3286
- { id: "orders", label: "Orders" },
3287
- { id: "customers", label: "Customers" },
3288
- { id: "products", label: "Products" }
3289
- ];
3290
- const AnalyticsPage = () => {
3291
- const [activeModule, setActiveModule] = react.useState("orders");
3292
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[1600px] flex-col gap-4 p-4", children: [
3293
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "overflow-hidden rounded-2xl border border-ui-border-base bg-ui-bg-base p-0 shadow-sm", children: [
3294
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 px-5 py-5 xl:flex-row xl:items-end xl:justify-between", children: [
3295
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
3296
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", className: "tracking-tight", children: "Analytics" }),
3297
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Review orders, customers, and products in one organized workspace." })
3298
- ] }),
3299
- /* @__PURE__ */ jsxRuntime.jsx(
3300
- "div",
3360
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 p-2 pt-0 sm:p-3 sm:pt-0 md:p-4 md:pt-0", children: [
3361
+ filtersError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-ui-border-base bg-ui-bg-subtle/30 px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-xs", children: filtersError }) }) : null,
3362
+ !viewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-dashed border-ui-border-base bg-ui-bg-subtle/30 px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[11px] leading-snug", children: "Product views are unavailable until the `medusa-product-helper` tracking module is registered and storefront page views are being recorded." }) }) : null,
3363
+ salesChannelId !== "all" && viewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border border-ui-border-base/80 bg-ui-bg-subtle/25 px-3 py-2 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[11px] leading-snug", children: [
3364
+ "Showing analytics for ",
3365
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-ui-fg-base", children: selectedChannelLabel }),
3366
+ ". Views are scoped to products assigned to this sales channel."
3367
+ ] }) }) : null,
3368
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
3369
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-0.5", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Product overview" }) }),
3370
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2 sm:grid-cols-3 lg:grid-cols-6", children: primaryStats.map((stat) => /* @__PURE__ */ jsxRuntime.jsx(
3371
+ AtlasKpiCard,
3301
3372
  {
3302
- className: "flex flex-wrap items-center gap-1 rounded-2xl border border-ui-border-base bg-ui-bg-subtle p-1",
3303
- role: "tablist",
3304
- "aria-label": "Analytics modules",
3305
- children: ANALYTICS_MODULES.map((m) => {
3306
- const active = activeModule === m.id;
3307
- return /* @__PURE__ */ jsxRuntime.jsx(
3308
- "button",
3309
- {
3310
- type: "button",
3311
- role: "tab",
3312
- "aria-selected": active,
3313
- onClick: () => setActiveModule(m.id),
3314
- className: `rounded-xl px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ui-fg-interactive focus-visible:ring-offset-2 focus-visible:ring-offset-ui-bg-base ${active ? "bg-ui-bg-base text-ui-fg-base shadow-sm" : "text-ui-fg-muted hover:bg-ui-bg-base/60 hover:text-ui-fg-base"}`.trim(),
3315
- children: m.label
3316
- },
3317
- m.id
3318
- );
3319
- })
3320
- }
3321
- )
3373
+ label: stat.label,
3374
+ value: stat.value,
3375
+ helper: stat.helper,
3376
+ accent: stat.accent
3377
+ },
3378
+ stat.label
3379
+ )) })
3322
3380
  ] }),
3323
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 bg-ui-bg-subtle" })
3324
- ] }),
3325
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
3326
- activeModule === "orders" && /* @__PURE__ */ jsxRuntime.jsx(OrdersDashboard, {}),
3327
- activeModule === "customers" && /* @__PURE__ */ jsxRuntime.jsx(CustomersDashboard, {}),
3328
- activeModule === "products" && /* @__PURE__ */ jsxRuntime.jsx(ProductsDashboard, {})
3329
- ] })
3330
- ] }) }) });
3381
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 grid grid-cols-12 gap-2 lg:items-start", children: [
3382
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "col-span-12 lg:col-span-6", children: /* @__PURE__ */ jsxRuntime.jsx(
3383
+ AnalyticsSection,
3384
+ {
3385
+ variant: "atlas",
3386
+ actionsBare: true,
3387
+ title: "Sales & views over time",
3388
+ description: "Units and views share the left axis; revenue uses the right. Window totals match this range.",
3389
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
3390
+ /* @__PURE__ */ jsxRuntime.jsx(
3391
+ ui.Label,
3392
+ {
3393
+ htmlFor: "products-graph-period",
3394
+ className: "shrink-0 text-ui-fg-muted text-xs font-medium",
3395
+ children: "Range"
3396
+ }
3397
+ ),
3398
+ /* @__PURE__ */ jsxRuntime.jsx(
3399
+ "select",
3400
+ {
3401
+ id: "products-graph-period",
3402
+ value: graphPeriod,
3403
+ onChange: (event) => setGraphPeriod(event.target.value),
3404
+ className: SELECT_CLASS_NAME,
3405
+ children: GRAPH_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
3406
+ }
3407
+ )
3408
+ ] }),
3409
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
3410
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-1.5 sm:grid-cols-3", children: [
3411
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
3412
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window units" }),
3413
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatShortNumber(trendTotals.totalUnits) }),
3414
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
3415
+ "Avg/day ",
3416
+ trendTotals.avgUnitsPerDay.toFixed(1)
3417
+ ] })
3418
+ ] }) }),
3419
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
3420
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window revenue" }),
3421
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatCompactCurrency(trendTotals.totalRevenue) }),
3422
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
3423
+ "Avg/day ",
3424
+ formatCompactCurrency(trendTotals.avgRevenuePerDay)
3425
+ ] })
3426
+ ] }) }),
3427
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0.5", children: [
3428
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: "Window views" }),
3429
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-lg font-semibold tracking-tight", children: formatShortNumber(trendTotals.totalViews) }),
3430
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-[10px]", children: [
3431
+ "Avg/day ",
3432
+ trendTotals.avgViewsPerDay.toFixed(0)
3433
+ ] })
3434
+ ] }) })
3435
+ ] }),
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
+ /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsChartSurface, { variant: "atlas", className: "relative overflow-hidden", children: [
3562
+ /* @__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
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative space-y-1", children: [
3564
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-1.5", children: [
3565
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-0", children: [
3566
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.16em]", children: "Trend overview" }),
3567
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base text-sm font-semibold", children: selectedGraphPeriodLabel })
3568
+ ] }),
3569
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap justify-end gap-2 text-[10px] text-ui-fg-muted", children: [
3570
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
3571
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-sky-400" }),
3572
+ "Units"
3573
+ ] }),
3574
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
3575
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-violet-400" }),
3576
+ "Views"
3577
+ ] }),
3578
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1", children: [
3579
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-fuchsia-400" }),
3580
+ "Revenue"
3581
+ ] })
3582
+ ] })
3583
+ ] }),
3584
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[min(168px,24vh)] min-h-[140px] sm:h-[min(184px,26vh)]", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx(
3585
+ "div",
3586
+ {
3587
+ className: "flex h-full items-center justify-center",
3588
+ role: "status",
3589
+ "aria-label": "Loading product trend chart",
3590
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" })
3591
+ }
3592
+ ) : overTimeError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: overTimeError }) }) : series.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No data in this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
3593
+ recharts.ComposedChart,
3594
+ {
3595
+ data: series,
3596
+ margin: { top: 4, right: 6, left: -6, bottom: 0 },
3597
+ children: [
3598
+ /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
3599
+ /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "productUnitsGradient", x1: "0", y1: "0", x2: "1", y2: "0", children: [
3600
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#67E8F9" }),
3601
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#3B82F6" })
3602
+ ] }),
3603
+ /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "productRevenueGradient", x1: "0", y1: "0", x2: "1", y2: "0", children: [
3604
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#F472B6" }),
3605
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#C084FC" })
3606
+ ] }),
3607
+ /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "productUnitsAreaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
3608
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#38BDF8", stopOpacity: 0.22 }),
3609
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#38BDF8", stopOpacity: 0 })
3610
+ ] }),
3611
+ /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "productRevenueAreaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
3612
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#E879F9", stopOpacity: 0.2 }),
3613
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#E879F9", stopOpacity: 0 })
3614
+ ] }),
3615
+ /* @__PURE__ */ jsxRuntime.jsxs("linearGradient", { id: "productViewsAreaFill", x1: "0", y1: "0", x2: "0", y2: "1", children: [
3616
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#C084FC", stopOpacity: 0.18 }),
3617
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#C084FC", stopOpacity: 0 })
3618
+ ] })
3619
+ ] }),
3620
+ /* @__PURE__ */ jsxRuntime.jsx(
3621
+ recharts.CartesianGrid,
3622
+ {
3623
+ stroke: "rgba(148,163,184,0.14)",
3624
+ strokeDasharray: "3 3",
3625
+ vertical: false
3626
+ }
3627
+ ),
3628
+ /* @__PURE__ */ jsxRuntime.jsx(
3629
+ recharts.XAxis,
3630
+ {
3631
+ dataKey: "date",
3632
+ tick: CHART_AXIS_TICK,
3633
+ tickLine: false,
3634
+ axisLine: false,
3635
+ tickFormatter: (value, index) => {
3636
+ const row = series[index];
3637
+ return (row == null ? void 0 : row.label) ?? formatChartLabel(String(value));
3638
+ }
3639
+ }
3640
+ ),
3641
+ /* @__PURE__ */ jsxRuntime.jsx(
3642
+ recharts.YAxis,
3643
+ {
3644
+ yAxisId: "counts",
3645
+ width: 32,
3646
+ tick: CHART_AXIS_TICK,
3647
+ tickLine: false,
3648
+ axisLine: false,
3649
+ allowDecimals: false,
3650
+ tickFormatter: (value) => Math.floor(Number(value) || 0).toLocaleString()
3651
+ }
3652
+ ),
3653
+ /* @__PURE__ */ jsxRuntime.jsx(
3654
+ recharts.YAxis,
3655
+ {
3656
+ yAxisId: "revenue",
3657
+ orientation: "right",
3658
+ width: 40,
3659
+ tick: CHART_AXIS_TICK,
3660
+ tickLine: false,
3661
+ axisLine: false,
3662
+ tickFormatter: (value) => formatCompactCurrency(Number(value) || 0)
3663
+ }
3664
+ ),
3665
+ /* @__PURE__ */ jsxRuntime.jsx(
3666
+ recharts.Tooltip,
3667
+ {
3668
+ content: /* @__PURE__ */ jsxRuntime.jsx(TrendTooltip, {}),
3669
+ cursor: {
3670
+ stroke: "rgba(248, 250, 252, 0.35)",
3671
+ strokeWidth: 1
3672
+ }
3673
+ }
3674
+ ),
3675
+ /* @__PURE__ */ jsxRuntime.jsx(
3676
+ recharts.Area,
3677
+ {
3678
+ yAxisId: "counts",
3679
+ type: "natural",
3680
+ dataKey: "units_sold",
3681
+ stroke: "none",
3682
+ fill: "url(#productUnitsAreaFill)",
3683
+ isAnimationActive: false,
3684
+ legendType: "none"
3685
+ }
3686
+ ),
3687
+ /* @__PURE__ */ jsxRuntime.jsx(
3688
+ recharts.Area,
3689
+ {
3690
+ yAxisId: "counts",
3691
+ type: "natural",
3692
+ dataKey: "views",
3693
+ stroke: "none",
3694
+ fill: "url(#productViewsAreaFill)",
3695
+ isAnimationActive: false,
3696
+ legendType: "none"
3697
+ }
3698
+ ),
3699
+ /* @__PURE__ */ jsxRuntime.jsx(
3700
+ recharts.Area,
3701
+ {
3702
+ yAxisId: "revenue",
3703
+ type: "natural",
3704
+ dataKey: "revenue",
3705
+ stroke: "none",
3706
+ fill: "url(#productRevenueAreaFill)",
3707
+ isAnimationActive: false,
3708
+ legendType: "none"
3709
+ }
3710
+ ),
3711
+ /* @__PURE__ */ jsxRuntime.jsx(
3712
+ recharts.Line,
3713
+ {
3714
+ yAxisId: "counts",
3715
+ type: "natural",
3716
+ dataKey: "units_sold",
3717
+ name: "Units sold",
3718
+ stroke: "url(#productUnitsGradient)",
3719
+ strokeWidth: 2,
3720
+ dot: false,
3721
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.units }
3722
+ }
3723
+ ),
3724
+ /* @__PURE__ */ jsxRuntime.jsx(
3725
+ recharts.Line,
3726
+ {
3727
+ yAxisId: "counts",
3728
+ type: "natural",
3729
+ dataKey: "views",
3730
+ name: "Views",
3731
+ stroke: PRODUCT_CHART_COLORS.views,
3732
+ strokeWidth: 1.5,
3733
+ strokeDasharray: "4 3",
3734
+ dot: false,
3735
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.views }
3736
+ }
3737
+ ),
3738
+ /* @__PURE__ */ jsxRuntime.jsx(
3739
+ recharts.Line,
3740
+ {
3741
+ yAxisId: "revenue",
3742
+ type: "natural",
3743
+ dataKey: "revenue",
3744
+ name: "Revenue",
3745
+ stroke: "url(#productRevenueGradient)",
3746
+ strokeWidth: 2,
3747
+ dot: false,
3748
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.revenue }
3749
+ }
3750
+ )
3751
+ ]
3752
+ }
3753
+ ) }) })
3754
+ ] })
3755
+ ] })
3756
+ ] })
3757
+ }
3758
+ ) }),
3759
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "col-span-12 flex flex-col gap-2 lg:col-span-6", children: [
3760
+ /* @__PURE__ */ jsxRuntime.jsx(
3761
+ AnalyticsSection,
3762
+ {
3763
+ variant: "atlas",
3764
+ title: "Pulse & range",
3765
+ description: "Totals for the chart window above — independent of the summary period filter.",
3766
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-2", children: quickPulseMetrics.map((metric) => /* @__PURE__ */ jsxRuntime.jsxs(
3767
+ "div",
3768
+ {
3769
+ className: `rounded-lg border border-ui-border-base bg-ui-bg-base px-2 py-2 shadow-sm ${metric.accentClassName}`.trim(),
3770
+ children: [
3771
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-[10px] font-medium uppercase tracking-[0.14em]", children: metric.label }),
3772
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-base mt-0.5 text-sm font-semibold tracking-tight", children: metric.value }),
3773
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted mt-0.5 text-[9px] leading-snug", children: metric.helper })
3774
+ ]
3775
+ },
3776
+ metric.label
3777
+ )) })
3778
+ }
3779
+ ),
3780
+ /* @__PURE__ */ jsxRuntime.jsx(
3781
+ AnalyticsSection,
3782
+ {
3783
+ variant: "atlas",
3784
+ actionsBare: true,
3785
+ title: "Best sellers",
3786
+ description: bestSellerTrendProductTitle ? `Revenue and units over time for “${bestSellerTrendProductTitle}” (#1 by revenue in this window; all-time uses a 12‑month chart).` : "Revenue and units over time for the top product by revenue in this window (all-time leaderboard uses a 12‑month chart).",
3787
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
3788
+ /* @__PURE__ */ jsxRuntime.jsx(
3789
+ ui.Label,
3790
+ {
3791
+ htmlFor: "products-top-seller-period",
3792
+ className: "shrink-0 text-ui-fg-muted text-xs font-medium",
3793
+ children: "Window"
3794
+ }
3795
+ ),
3796
+ /* @__PURE__ */ jsxRuntime.jsx(
3797
+ "select",
3798
+ {
3799
+ id: "products-top-seller-period",
3800
+ value: topSellerPeriod,
3801
+ onChange: (event) => setTopSellerPeriod(event.target.value),
3802
+ className: SELECT_CLASS_NAME,
3803
+ children: TOP_SELLER_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
3804
+ }
3805
+ )
3806
+ ] }),
3807
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-w-0 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[212px] min-w-[280px] w-full sm:h-[228px]", children: bestSellersTrendLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) : bestSellersTrendError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: bestSellersTrendError }) }) : bestSellersTrendSeries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No product sales for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", minWidth: 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
3808
+ recharts.ComposedChart,
3809
+ {
3810
+ data: bestSellersTrendSeries,
3811
+ margin: { left: 0, right: 8, top: 6, bottom: 2 },
3812
+ children: [
3813
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
3814
+ "linearGradient",
3815
+ {
3816
+ id: "bestSellersRevenueArea",
3817
+ x1: "0",
3818
+ y1: "0",
3819
+ x2: "0",
3820
+ y2: "1",
3821
+ children: [
3822
+ /* @__PURE__ */ jsxRuntime.jsx(
3823
+ "stop",
3824
+ {
3825
+ offset: "0%",
3826
+ stopColor: PRODUCT_CHART_COLORS.revenue,
3827
+ stopOpacity: 0.22
3828
+ }
3829
+ ),
3830
+ /* @__PURE__ */ jsxRuntime.jsx(
3831
+ "stop",
3832
+ {
3833
+ offset: "100%",
3834
+ stopColor: PRODUCT_CHART_COLORS.revenue,
3835
+ stopOpacity: 0
3836
+ }
3837
+ )
3838
+ ]
3839
+ }
3840
+ ) }),
3841
+ /* @__PURE__ */ jsxRuntime.jsx(
3842
+ recharts.CartesianGrid,
3843
+ {
3844
+ strokeDasharray: "3 3",
3845
+ vertical: false,
3846
+ stroke: "rgba(148,163,184,0.12)"
3847
+ }
3848
+ ),
3849
+ /* @__PURE__ */ jsxRuntime.jsx(
3850
+ recharts.XAxis,
3851
+ {
3852
+ dataKey: "date",
3853
+ tick: CHART_AXIS_TICK_SM,
3854
+ tickFormatter: (value) => formatChartLabel(String(value)),
3855
+ tickLine: false,
3856
+ axisLine: { stroke: CHART_AXIS_LINE }
3857
+ }
3858
+ ),
3859
+ /* @__PURE__ */ jsxRuntime.jsx(
3860
+ recharts.YAxis,
3861
+ {
3862
+ yAxisId: "units",
3863
+ tick: CHART_AXIS_TICK_SM,
3864
+ tickFormatter: (value) => formatShortNumber(Number(value)),
3865
+ width: 36,
3866
+ tickLine: false,
3867
+ axisLine: { stroke: CHART_AXIS_LINE },
3868
+ allowDecimals: false
3869
+ }
3870
+ ),
3871
+ /* @__PURE__ */ jsxRuntime.jsx(
3872
+ recharts.YAxis,
3873
+ {
3874
+ yAxisId: "revenue",
3875
+ orientation: "right",
3876
+ tick: CHART_AXIS_TICK_SM,
3877
+ tickFormatter: (value) => formatCompactCurrency(Number(value)),
3878
+ width: 44,
3879
+ tickLine: false,
3880
+ axisLine: { stroke: CHART_AXIS_LINE }
3881
+ }
3882
+ ),
3883
+ /* @__PURE__ */ jsxRuntime.jsx(
3884
+ recharts.Tooltip,
3885
+ {
3886
+ content: (tooltipProps) => /* @__PURE__ */ jsxRuntime.jsx(
3887
+ MiniTrendTooltip,
3888
+ {
3889
+ ...tooltipProps,
3890
+ productHeadline: bestSellerTrendProductTitle,
3891
+ hideViewsRow: true
3892
+ }
3893
+ )
3894
+ }
3895
+ ),
3896
+ /* @__PURE__ */ jsxRuntime.jsx(
3897
+ recharts.Area,
3898
+ {
3899
+ yAxisId: "revenue",
3900
+ type: "natural",
3901
+ dataKey: "revenue",
3902
+ name: "Revenue",
3903
+ stroke: "transparent",
3904
+ fill: "url(#bestSellersRevenueArea)",
3905
+ isAnimationActive: false
3906
+ }
3907
+ ),
3908
+ /* @__PURE__ */ jsxRuntime.jsx(
3909
+ recharts.Line,
3910
+ {
3911
+ yAxisId: "revenue",
3912
+ type: "natural",
3913
+ dataKey: "revenue",
3914
+ name: "Revenue",
3915
+ stroke: PRODUCT_CHART_COLORS.revenue,
3916
+ strokeWidth: 2,
3917
+ dot: false,
3918
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.revenue },
3919
+ isAnimationActive: false
3920
+ }
3921
+ ),
3922
+ /* @__PURE__ */ jsxRuntime.jsx(
3923
+ recharts.Line,
3924
+ {
3925
+ yAxisId: "units",
3926
+ type: "natural",
3927
+ dataKey: "units_sold",
3928
+ name: "Units sold",
3929
+ stroke: PRODUCT_CHART_COLORS.units,
3930
+ strokeWidth: 2,
3931
+ dot: false,
3932
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.units },
3933
+ isAnimationActive: false
3934
+ }
3935
+ )
3936
+ ]
3937
+ }
3938
+ ) }) }) })
3939
+ }
3940
+ )
3941
+ ] })
3942
+ ] }),
3943
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 grid grid-cols-1 gap-2 md:grid-cols-2 md:items-stretch xl:grid-cols-3 xl:gap-3", children: [
3944
+ /* @__PURE__ */ jsxRuntime.jsx(
3945
+ AnalyticsSection,
3946
+ {
3947
+ variant: "atlas",
3948
+ className: "min-w-0 md:col-span-1 xl:col-span-1",
3949
+ title: "Leaderboard table",
3950
+ description: "Products ranked by revenue — same window as Best sellers.",
3951
+ 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
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3953
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Product" }),
3954
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Units" }),
3955
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Orders" }),
3956
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Revenue" })
3957
+ ] }) }),
3958
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
3959
+ topSellersError ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3960
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-xs", children: topSellersError }) }),
3961
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3962
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3963
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
3964
+ ] }) : null,
3965
+ !topSellersError ? ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 8).map((product) => {
3966
+ var _a2, _b2;
3967
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3968
+ ui.Table.Row,
3969
+ {
3970
+ className: product.product_id === ((_b2 = (_a2 = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id) ? "bg-emerald-500/5" : void 0,
3971
+ children: [
3972
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
3973
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
3974
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.order_count.toLocaleString() }),
3975
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatCurrency(product.revenue) })
3976
+ ]
3977
+ },
3978
+ product.product_id
3979
+ );
3980
+ }) : null,
3981
+ !topSellersLoading && !topSellersError && (((_j = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _j.length) ?? 0) === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
3982
+ /* @__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
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3984
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
3985
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
3986
+ ] }) : null
3987
+ ] })
3988
+ ] }) }) })
3989
+ }
3990
+ ),
3991
+ /* @__PURE__ */ jsxRuntime.jsx(
3992
+ AnalyticsSection,
3993
+ {
3994
+ variant: "atlas",
3995
+ className: "min-w-0 md:col-span-1 xl:col-span-1",
3996
+ title: "Most viewed products",
3997
+ description: mostViewedTrendProductTitle ? `Views over time for “${mostViewedTrendProductTitle}” (top of the list for your summary period; buckets follow period: today / 7d → week, 30d → month, 90d / all → year).` : "Views over time for the most-viewed product in your summary period (buckets: today / 7d → week, 30d → month, 90d / all → year).",
3998
+ children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[212px] items-center justify-center sm:h-[228px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading…" }) }) }) : performanceError ? /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-[212px] items-center justify-center px-2 sm:h-[228px]", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: performanceError }) }) }) : !(performance == null ? void 0 : performance.productViewsConnected) ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-[212px] sm:min-h-[228px]", children: /* @__PURE__ */ jsxRuntime.jsx(
3999
+ EmptyAnalyticsPanel,
4000
+ {
4001
+ title: "Views unavailable",
4002
+ description: "Product view tracking is not available in this environment."
4003
+ }
4004
+ ) }) : ((performance == null ? void 0 : performance.topViewedProducts) ?? []).length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-[212px] sm:min-h-[228px]", children: /* @__PURE__ */ jsxRuntime.jsx(
4005
+ EmptyAnalyticsPanel,
4006
+ {
4007
+ title: "No views",
4008
+ description: "No product views found for this summary period."
4009
+ }
4010
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", className: "min-w-0 overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[212px] min-w-[280px] w-full sm:h-[228px]", children: mostViewedTrendLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading chart…" }) }) : mostViewedTrendError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: mostViewedTrendError }) }) : mostViewedTrendSeries.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No view data in this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", minWidth: 0, children: /* @__PURE__ */ jsxRuntime.jsxs(
4011
+ recharts.ComposedChart,
4012
+ {
4013
+ data: mostViewedTrendSeries,
4014
+ margin: { left: 0, right: 8, top: 6, bottom: 2 },
4015
+ children: [
4016
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs(
4017
+ "linearGradient",
4018
+ {
4019
+ id: "mostViewedViewsArea",
4020
+ x1: "0",
4021
+ y1: "0",
4022
+ x2: "0",
4023
+ y2: "1",
4024
+ children: [
4025
+ /* @__PURE__ */ jsxRuntime.jsx(
4026
+ "stop",
4027
+ {
4028
+ offset: "0%",
4029
+ stopColor: PRODUCT_CHART_COLORS.views,
4030
+ stopOpacity: 0.22
4031
+ }
4032
+ ),
4033
+ /* @__PURE__ */ jsxRuntime.jsx(
4034
+ "stop",
4035
+ {
4036
+ offset: "100%",
4037
+ stopColor: PRODUCT_CHART_COLORS.views,
4038
+ stopOpacity: 0
4039
+ }
4040
+ )
4041
+ ]
4042
+ }
4043
+ ) }),
4044
+ /* @__PURE__ */ jsxRuntime.jsx(
4045
+ recharts.CartesianGrid,
4046
+ {
4047
+ strokeDasharray: "3 3",
4048
+ vertical: false,
4049
+ stroke: "rgba(148,163,184,0.12)"
4050
+ }
4051
+ ),
4052
+ /* @__PURE__ */ jsxRuntime.jsx(
4053
+ recharts.XAxis,
4054
+ {
4055
+ dataKey: "date",
4056
+ tick: CHART_AXIS_TICK_SM,
4057
+ tickFormatter: (value) => formatChartLabel(String(value)),
4058
+ tickLine: false,
4059
+ axisLine: { stroke: CHART_AXIS_LINE }
4060
+ }
4061
+ ),
4062
+ /* @__PURE__ */ jsxRuntime.jsx(
4063
+ recharts.YAxis,
4064
+ {
4065
+ tick: CHART_AXIS_TICK_SM,
4066
+ tickFormatter: (value) => formatShortNumber(Number(value)),
4067
+ width: 36,
4068
+ tickLine: false,
4069
+ axisLine: { stroke: CHART_AXIS_LINE },
4070
+ allowDecimals: false
4071
+ }
4072
+ ),
4073
+ /* @__PURE__ */ jsxRuntime.jsx(
4074
+ recharts.Tooltip,
4075
+ {
4076
+ content: (tooltipProps) => /* @__PURE__ */ jsxRuntime.jsx(
4077
+ MiniTrendTooltip,
4078
+ {
4079
+ ...tooltipProps,
4080
+ productHeadline: mostViewedTrendProductTitle,
4081
+ hideUnitsRow: true,
4082
+ hideRevenueRow: true
4083
+ }
4084
+ )
4085
+ }
4086
+ ),
4087
+ /* @__PURE__ */ jsxRuntime.jsx(
4088
+ recharts.Area,
4089
+ {
4090
+ type: "natural",
4091
+ dataKey: "views",
4092
+ name: "Views",
4093
+ stroke: "transparent",
4094
+ fill: "url(#mostViewedViewsArea)",
4095
+ isAnimationActive: false
4096
+ }
4097
+ ),
4098
+ /* @__PURE__ */ jsxRuntime.jsx(
4099
+ recharts.Line,
4100
+ {
4101
+ type: "natural",
4102
+ dataKey: "views",
4103
+ name: "Views",
4104
+ stroke: PRODUCT_CHART_COLORS.views,
4105
+ strokeWidth: 2,
4106
+ dot: false,
4107
+ activeDot: { r: 4, fill: PRODUCT_CHART_COLORS.views },
4108
+ isAnimationActive: false
4109
+ }
4110
+ )
4111
+ ]
4112
+ }
4113
+ ) }) }) })
4114
+ }
4115
+ ),
4116
+ /* @__PURE__ */ jsxRuntime.jsx(
4117
+ AnalyticsSection,
4118
+ {
4119
+ variant: "atlas",
4120
+ className: "min-w-0 md:col-span-2 xl:col-span-1",
4121
+ title: "View-to-sales opportunities",
4122
+ description: "Products with attention but weaker unit conversion.",
4123
+ 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: OPPORTUNITIES_TABLE_CLASS, children: [
4124
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
4125
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Product" }),
4126
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Views" }),
4127
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Units" }),
4128
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: TABLE_HEAD_CELL_NOWRAP, children: "Views / unit" })
4129
+ ] }) }),
4130
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
4131
+ ((performance == null ? void 0 : performance.viewOpportunities) ?? []).slice(0, 8).map((product) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
4132
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
4133
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.total_views.toLocaleString() }),
4134
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
4135
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatRatio(product.views_per_unit) })
4136
+ ] }, product.product_id)),
4137
+ !performanceLoading && !performanceError && (((_k = performance == null ? void 0 : performance.viewOpportunities) == null ? void 0 : _k.length) ?? 0) === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
4138
+ /* @__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
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
4140
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
4141
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
4142
+ ] }) : null
4143
+ ] })
4144
+ ] }) }) })
4145
+ }
4146
+ )
4147
+ ] }),
4148
+ /* @__PURE__ */ jsxRuntime.jsx(
4149
+ AnalyticsSection,
4150
+ {
4151
+ variant: "atlas",
4152
+ className: "mt-2",
4153
+ title: "Views vs units sold",
4154
+ description: "Each point is a product (top viewed in this period). Requires product view tracking.",
4155
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { variant: "atlas", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[220px] w-full sm:h-[248px]", children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Loading scatter…" }) }) : performanceError || !performance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center px-2", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-center text-xs", children: performanceError ?? "Failed to load product performance" }) }) : !performance.productViewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "Product view tracking is not available in this environment." }) }) : viewsVsUnitsScatterData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs", children: "No products with views or sales in this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.ScatterChart, { margin: { top: 12, right: 16, bottom: 8, left: 8 }, children: [
4156
+ /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("radialGradient", { id: "productScatterGlow", cx: "50%", cy: "50%", r: "50%", children: [
4157
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "0%", stopColor: "#E879F9", stopOpacity: 0.95 }),
4158
+ /* @__PURE__ */ jsxRuntime.jsx("stop", { offset: "100%", stopColor: "#6366F1", stopOpacity: 0.65 })
4159
+ ] }) }),
4160
+ /* @__PURE__ */ jsxRuntime.jsx(
4161
+ recharts.CartesianGrid,
4162
+ {
4163
+ strokeDasharray: "3 3",
4164
+ stroke: "rgba(148,163,184,0.14)"
4165
+ }
4166
+ ),
4167
+ /* @__PURE__ */ jsxRuntime.jsx(
4168
+ recharts.XAxis,
4169
+ {
4170
+ type: "number",
4171
+ dataKey: "total_views",
4172
+ name: "Views",
4173
+ tick: CHART_AXIS_TICK_SM,
4174
+ stroke: CHART_AXIS_LINE,
4175
+ tickLine: { stroke: CHART_AXIS_LINE },
4176
+ allowDecimals: false,
4177
+ label: {
4178
+ value: "Views",
4179
+ position: "insideBottom",
4180
+ offset: -4,
4181
+ fontSize: 10,
4182
+ fill: "#9ca3af"
4183
+ }
4184
+ }
4185
+ ),
4186
+ /* @__PURE__ */ jsxRuntime.jsx(
4187
+ recharts.YAxis,
4188
+ {
4189
+ type: "number",
4190
+ dataKey: "units_sold",
4191
+ name: "Units sold",
4192
+ tick: CHART_AXIS_TICK_SM,
4193
+ stroke: CHART_AXIS_LINE,
4194
+ tickLine: { stroke: CHART_AXIS_LINE },
4195
+ allowDecimals: false,
4196
+ label: {
4197
+ value: "Units sold",
4198
+ angle: -90,
4199
+ position: "insideLeft",
4200
+ fontSize: 10,
4201
+ fill: "#9ca3af"
4202
+ }
4203
+ }
4204
+ ),
4205
+ /* @__PURE__ */ jsxRuntime.jsx(
4206
+ recharts.Tooltip,
4207
+ {
4208
+ cursor: { strokeDasharray: "4 4", stroke: "rgba(148,163,184,0.45)" },
4209
+ content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {})
4210
+ }
4211
+ ),
4212
+ /* @__PURE__ */ jsxRuntime.jsx(
4213
+ recharts.Scatter,
4214
+ {
4215
+ name: "Products",
4216
+ data: viewsVsUnitsScatterData,
4217
+ fill: "url(#productScatterGlow)"
4218
+ }
4219
+ )
4220
+ ] }) }) }) })
4221
+ }
4222
+ )
4223
+ ] })
4224
+ ] }) });
4225
+ }
4226
+ const ANALYTICS_MODULES = [
4227
+ { id: "orders", label: "Orders" },
4228
+ { id: "customers", label: "Customers" },
4229
+ { id: "products", label: "Products" }
4230
+ ];
4231
+ const AnalyticsPage = () => {
4232
+ const [activeModule, setActiveModule] = react.useState("orders");
4233
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(
4234
+ "div",
4235
+ {
4236
+ className: `mx-auto flex w-full min-w-0 flex-col ${activeModule === "products" ? "max-w-full gap-2 px-3 py-3 sm:px-4 sm:py-3" : "max-w-[1600px] gap-4 p-4"}`.trim(),
4237
+ children: [
4238
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "overflow-hidden rounded-xl border border-ui-border-base bg-ui-bg-base p-0 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 px-4 py-4 sm:gap-5 sm:px-5 sm:py-5 xl:flex-row xl:items-end xl:justify-between", children: [
4239
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 space-y-1.5", children: [
4240
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", className: "tracking-tight", children: "Analytics" }),
4241
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Review orders, customers, and products in one organized workspace." })
4242
+ ] }),
4243
+ /* @__PURE__ */ jsxRuntime.jsx(
4244
+ "div",
4245
+ {
4246
+ className: "flex shrink-0 flex-wrap items-center gap-1",
4247
+ role: "tablist",
4248
+ "aria-label": "Analytics modules",
4249
+ children: ANALYTICS_MODULES.map((m) => {
4250
+ const active = activeModule === m.id;
4251
+ return /* @__PURE__ */ jsxRuntime.jsx(
4252
+ "button",
4253
+ {
4254
+ type: "button",
4255
+ role: "tab",
4256
+ "aria-selected": active,
4257
+ onClick: () => setActiveModule(m.id),
4258
+ className: `rounded-md px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ui-fg-interactive focus-visible:ring-offset-2 focus-visible:ring-offset-ui-bg-base ${active ? "bg-ui-bg-base text-ui-fg-base shadow-sm" : "text-ui-fg-muted hover:bg-ui-bg-base/60 hover:text-ui-fg-base"}`.trim(),
4259
+ children: m.label
4260
+ },
4261
+ m.id
4262
+ );
4263
+ })
4264
+ }
4265
+ )
4266
+ ] }) }),
4267
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0 w-full", children: [
4268
+ activeModule === "orders" && /* @__PURE__ */ jsxRuntime.jsx(OrdersDashboard, {}),
4269
+ activeModule === "customers" && /* @__PURE__ */ jsxRuntime.jsx(CustomersDashboard, {}),
4270
+ activeModule === "products" && /* @__PURE__ */ jsxRuntime.jsx(ProductsDashboard, {})
4271
+ ] })
4272
+ ]
4273
+ }
4274
+ ) }) });
3331
4275
  };
3332
4276
  const config = adminSdk.defineRouteConfig({
3333
4277
  label: "Analytics",