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