medusa-analytics 0.0.14 → 0.0.16

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.
@@ -5,6 +5,74 @@ const adminSdk = require("@medusajs/admin-sdk");
5
5
  const icons = require("@medusajs/icons");
6
6
  const ui = require("@medusajs/ui");
7
7
  const recharts = require("recharts");
8
+ function AnalyticsDashboardShell({ children }) {
9
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children });
10
+ }
11
+ function AnalyticsDashboardHeader({
12
+ title,
13
+ description,
14
+ actions
15
+ }) {
16
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "overflow-hidden rounded-2xl border border-ui-border-base bg-ui-bg-base p-0 shadow-sm", children: [
17
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 border-b border-ui-border-base px-5 py-4 lg:flex-row lg:items-end lg:justify-between", children: [
18
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
19
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "tracking-tight", children: title }),
20
+ description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: description }) : null
21
+ ] }),
22
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex self-start rounded-xl border border-ui-border-base bg-ui-bg-subtle p-2 lg:self-auto", children: actions }) : null
23
+ ] }),
24
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 bg-ui-bg-subtle" })
25
+ ] });
26
+ }
27
+ function AnalyticsStatCard({ label, value, helper }) {
28
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "h-full rounded-2xl border border-ui-border-base bg-ui-bg-base p-3 shadow-sm transition-shadow", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-[76px] flex-col justify-between gap-1.5", children: [
29
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs font-medium", children: label }),
30
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "text-2xl leading-none tracking-tight", children: value }),
31
+ helper ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-xs leading-4", children: helper }) : null
32
+ ] }) });
33
+ }
34
+ function AnalyticsSection({
35
+ title,
36
+ description,
37
+ actions,
38
+ children,
39
+ className
40
+ }) {
41
+ return /* @__PURE__ */ jsxRuntime.jsxs(
42
+ ui.Container,
43
+ {
44
+ className: `overflow-hidden rounded-2xl border border-ui-border-base bg-ui-bg-base p-0 shadow-sm ${className ?? ""}`.trim(),
45
+ children: [
46
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 border-b border-ui-border-base px-5 py-4 lg:flex-row lg:items-start lg:justify-between", children: [
47
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
48
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "tracking-tight", children: title }),
49
+ description ? /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: description }) : null
50
+ ] }),
51
+ actions ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2 rounded-xl border border-ui-border-base bg-ui-bg-subtle px-3 py-2", children: actions }) : null
52
+ ] }),
53
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4", children })
54
+ ]
55
+ }
56
+ );
57
+ }
58
+ function AnalyticsChartSurface({ children, className }) {
59
+ return /* @__PURE__ */ jsxRuntime.jsx(
60
+ "div",
61
+ {
62
+ className: `rounded-xl border border-ui-border-base bg-ui-bg-subtle p-3 shadow-inner ${className ?? ""}`.trim(),
63
+ children
64
+ }
65
+ );
66
+ }
67
+ function AnalyticsTableSurface({ children, className }) {
68
+ return /* @__PURE__ */ jsxRuntime.jsx(
69
+ "div",
70
+ {
71
+ className: `overflow-hidden rounded-xl border border-ui-border-base bg-ui-bg-base ${className ?? ""}`.trim(),
72
+ children
73
+ }
74
+ );
75
+ }
8
76
  function OrdersOverTimeTooltip({
9
77
  active,
10
78
  payload,
@@ -137,131 +205,167 @@ function OrdersDashboard() {
137
205
  { name: "Return orders", value: data.returnOrders, color: "#EF4444" },
138
206
  { name: "Exchange orders", value: data.exchangeOrders, color: "#F59E0B" }
139
207
  ].filter((d) => d.value > 0);
140
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
141
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
142
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Orders" }),
143
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
144
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
145
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "analytics-period", className: "text-ui-fg-muted text-sm", children: "Period" }),
146
- /* @__PURE__ */ jsxRuntime.jsx(
147
- "select",
208
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsDashboardShell, { children: [
209
+ /* @__PURE__ */ jsxRuntime.jsx(
210
+ AnalyticsDashboardHeader,
211
+ {
212
+ title: "Orders",
213
+ description: "Monitor revenue, operational health, and status distribution without leaving the analytics workspace.",
214
+ actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
215
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
216
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "analytics-period", className: "text-ui-fg-muted text-sm", children: "Period" }),
217
+ /* @__PURE__ */ jsxRuntime.jsx(
218
+ "select",
219
+ {
220
+ id: "analytics-period",
221
+ value: filter,
222
+ onChange: (e) => setFilter(e.target.value),
223
+ 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",
224
+ children: SUMMARY_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
225
+ }
226
+ )
227
+ ] }),
228
+ filter !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
229
+ "button",
148
230
  {
149
- id: "analytics-period",
150
- value: filter,
151
- onChange: (e) => setFilter(e.target.value),
152
- 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",
153
- children: SUMMARY_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
231
+ type: "button",
232
+ onClick: () => setFilter("all"),
233
+ className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
234
+ "aria-label": "Show all orders (clear filter)",
235
+ children: "Clear filter"
154
236
  }
155
237
  )
156
- ] }),
157
- filter !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
158
- "button",
238
+ ] })
239
+ }
240
+ ),
241
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4", children: [
242
+ /* @__PURE__ */ jsxRuntime.jsx(
243
+ AnalyticsStatCard,
244
+ {
245
+ label: "Total orders",
246
+ value: data.totalOrders.toLocaleString()
247
+ }
248
+ ),
249
+ /* @__PURE__ */ jsxRuntime.jsx(
250
+ AnalyticsStatCard,
251
+ {
252
+ label: "Total revenue",
253
+ value: formatCurrency$1(data.totalRevenue)
254
+ }
255
+ ),
256
+ /* @__PURE__ */ jsxRuntime.jsx(
257
+ AnalyticsStatCard,
258
+ {
259
+ label: "Average order value",
260
+ value: formatCurrency$1(data.aov)
261
+ }
262
+ ),
263
+ /* @__PURE__ */ jsxRuntime.jsx(
264
+ AnalyticsStatCard,
265
+ {
266
+ label: "Orders today",
267
+ value: data.ordersToday.toLocaleString()
268
+ }
269
+ ),
270
+ /* @__PURE__ */ jsxRuntime.jsx(
271
+ AnalyticsStatCard,
272
+ {
273
+ label: "Pending orders",
274
+ value: data.pendingOrders.toLocaleString()
275
+ }
276
+ ),
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ AnalyticsStatCard,
279
+ {
280
+ label: "Avg. fulfillment time",
281
+ value: data.avgFulfillmentTimeHours != null ? `${data.avgFulfillmentTimeHours}h` : "—",
282
+ helper: "Measured in hours"
283
+ }
284
+ ),
285
+ /* @__PURE__ */ jsxRuntime.jsx(
286
+ AnalyticsStatCard,
287
+ {
288
+ label: "Cancelled orders",
289
+ value: data.cancelledOrders.toLocaleString()
290
+ }
291
+ ),
292
+ /* @__PURE__ */ jsxRuntime.jsx(
293
+ AnalyticsStatCard,
294
+ {
295
+ label: "Delivered orders",
296
+ value: data.deliveredOrders.toLocaleString()
297
+ }
298
+ ),
299
+ /* @__PURE__ */ jsxRuntime.jsx(
300
+ AnalyticsStatCard,
301
+ {
302
+ label: "Exchange orders",
303
+ value: data.exchangeOrders.toLocaleString()
304
+ }
305
+ ),
306
+ /* @__PURE__ */ jsxRuntime.jsx(
307
+ AnalyticsStatCard,
308
+ {
309
+ label: "Return orders",
310
+ value: data.returnOrders.toLocaleString()
311
+ }
312
+ )
313
+ ] }),
314
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 xl:grid-cols-2", children: [
315
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsSection, { title: "Orders by status", children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[300px] items-center justify-center", children: pieData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { margin: { top: 8, right: 8, bottom: 8, left: 8 }, children: [
316
+ /* @__PURE__ */ jsxRuntime.jsx(
317
+ recharts.Pie,
159
318
  {
160
- type: "button",
161
- onClick: () => setFilter("all"),
162
- className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
163
- "aria-label": "Show all orders (clear filter)",
164
- children: "Clear filter"
319
+ data: pieData,
320
+ cx: "50%",
321
+ cy: "50%",
322
+ innerRadius: 52,
323
+ outerRadius: 78,
324
+ paddingAngle: 2,
325
+ dataKey: "value",
326
+ nameKey: "name",
327
+ isAnimationActive: true,
328
+ children: pieData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: entry.color }, `cell-${index}`))
165
329
  }
166
- )
167
- ] })
168
- ] }),
169
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4", children: [
170
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
171
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Total orders" }),
172
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.totalOrders.toLocaleString() })
173
- ] }),
174
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
175
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Total revenue" }),
176
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: formatCurrency$1(data.totalRevenue) })
177
- ] }),
178
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
179
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Average order value" }),
180
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: formatCurrency$1(data.aov) })
181
- ] }),
182
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
183
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Orders today" }),
184
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.ordersToday.toLocaleString() })
185
- ] })
186
- ] }),
187
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
188
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
189
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mb-2", children: "Pending orders" }),
190
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.pendingOrders.toLocaleString() })
191
- ] }),
192
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
193
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mb-2", children: "Avg. fulfillment time (hours)" }),
194
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.avgFulfillmentTimeHours != null ? `${data.avgFulfillmentTimeHours}h` : "" })
195
- ] })
196
- ] }),
197
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4", children: [
198
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
199
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Cancelled orders" }),
200
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.cancelledOrders.toLocaleString() })
201
- ] }),
202
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
203
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Delivered orders" }),
204
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.deliveredOrders.toLocaleString() })
205
- ] }),
206
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
207
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Exchange orders" }),
208
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.exchangeOrders.toLocaleString() })
209
- ] }),
210
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
211
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Return orders" }),
212
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: data.returnOrders.toLocaleString() })
213
- ] })
330
+ ),
331
+ /* @__PURE__ */ jsxRuntime.jsx(
332
+ recharts.Tooltip,
333
+ {
334
+ formatter: (value) => [value ?? 0, "Orders"]
335
+ }
336
+ ),
337
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { verticalAlign: "bottom", height: 36 })
338
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No orders in this period" }) }) }) }),
339
+ /* @__PURE__ */ jsxRuntime.jsx(AnalyticsSection, { title: "Returns & exchanges", children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex min-h-[300px] items-center justify-center", children: returnsExchangesData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { margin: { top: 8, right: 8, bottom: 8, left: 8 }, children: [
340
+ /* @__PURE__ */ jsxRuntime.jsx(
341
+ recharts.Pie,
342
+ {
343
+ data: returnsExchangesData,
344
+ cx: "50%",
345
+ cy: "50%",
346
+ innerRadius: 52,
347
+ outerRadius: 78,
348
+ paddingAngle: 2,
349
+ dataKey: "value",
350
+ nameKey: "name",
351
+ isAnimationActive: true,
352
+ children: returnsExchangesData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: entry.color }, `cell-re-${index}`))
353
+ }
354
+ ),
355
+ /* @__PURE__ */ jsxRuntime.jsx(
356
+ recharts.Tooltip,
357
+ {
358
+ formatter: (value) => [value ?? 0, "Count"]
359
+ }
360
+ ),
361
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { verticalAlign: "bottom", height: 36 })
362
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No returns or exchanges in this period" }) }) }) })
214
363
  ] }),
215
- /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col sm:flex-row flex-wrap gap-6 items-stretch", children: [
216
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex flex-col", style: { minWidth: "280px" }, children: [
217
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "mb-3", children: "Orders by status" }),
218
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-[280px] flex items-center justify-center", children: pieData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { margin: { top: 8, right: 8, bottom: 8, left: 8 }, children: [
219
- /* @__PURE__ */ jsxRuntime.jsx(
220
- recharts.Pie,
221
- {
222
- data: pieData,
223
- cx: "50%",
224
- cy: "50%",
225
- innerRadius: 52,
226
- outerRadius: 78,
227
- paddingAngle: 2,
228
- dataKey: "value",
229
- nameKey: "name",
230
- isAnimationActive: true,
231
- children: pieData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: entry.color }, `cell-${index}`))
232
- }
233
- ),
234
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { formatter: (value) => [value ?? 0, "Orders"] }),
235
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { verticalAlign: "bottom", height: 36 })
236
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No orders in this period" }) })
237
- ] }),
238
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex flex-col", style: { minWidth: "280px" }, children: [
239
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "mb-3", children: "Returns & exchanges" }),
240
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-[280px] flex items-center justify-center", children: returnsExchangesData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.PieChart, { margin: { top: 8, right: 8, bottom: 8, left: 8 }, children: [
241
- /* @__PURE__ */ jsxRuntime.jsx(
242
- recharts.Pie,
243
- {
244
- data: returnsExchangesData,
245
- cx: "50%",
246
- cy: "50%",
247
- innerRadius: 52,
248
- outerRadius: 78,
249
- paddingAngle: 2,
250
- dataKey: "value",
251
- nameKey: "name",
252
- isAnimationActive: true,
253
- children: returnsExchangesData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: entry.color }, `cell-re-${index}`))
254
- }
255
- ),
256
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { formatter: (value) => [value ?? 0, "Count"] }),
257
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { verticalAlign: "bottom", height: 36 })
258
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "No returns or exchanges in this period" }) })
259
- ] })
260
- ] }) }),
261
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
262
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 mb-4", children: [
263
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Orders over time" }),
264
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
364
+ /* @__PURE__ */ jsxRuntime.jsx(
365
+ AnalyticsSection,
366
+ {
367
+ title: "Orders over time",
368
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
265
369
  /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "over-time-period", className: "text-ui-fg-muted text-sm", children: "Range" }),
266
370
  /* @__PURE__ */ jsxRuntime.jsx(
267
371
  "select",
@@ -273,72 +377,72 @@ function OrdersDashboard() {
273
377
  children: OVER_TIME_PERIODS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
274
378
  }
275
379
  )
276
- ] })
277
- ] }),
278
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx(
279
- "div",
280
- {
281
- className: "flex items-center justify-center h-full",
282
- role: "status",
283
- "aria-label": "Loading orders over time",
284
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" })
285
- }
286
- ) : overTimeError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: overTimeError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
287
- recharts.LineChart,
288
- {
289
- data: dailyOrders,
290
- margin: { top: 8, right: 8, left: 8, bottom: 8 },
291
- children: [
292
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", className: "stroke-ui-border-base" }),
293
- /* @__PURE__ */ jsxRuntime.jsx(
294
- recharts.XAxis,
295
- {
296
- dataKey: "date",
297
- tick: { fontSize: 12 },
298
- tickFormatter: (v, index) => {
299
- const row = dailyOrders[index];
300
- if (row == null ? void 0 : row.label) return row.label;
301
- const d = new Date(v);
302
- return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;
380
+ ] }),
381
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx(
382
+ "div",
383
+ {
384
+ className: "flex items-center justify-center h-full",
385
+ role: "status",
386
+ "aria-label": "Loading orders over time",
387
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" })
388
+ }
389
+ ) : overTimeError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: overTimeError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
390
+ recharts.LineChart,
391
+ {
392
+ data: dailyOrders,
393
+ margin: { top: 8, right: 8, left: 8, bottom: 8 },
394
+ children: [
395
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", className: "stroke-ui-border-base" }),
396
+ /* @__PURE__ */ jsxRuntime.jsx(
397
+ recharts.XAxis,
398
+ {
399
+ dataKey: "date",
400
+ tick: { fontSize: 12 },
401
+ tickFormatter: (v, index) => {
402
+ const row = dailyOrders[index];
403
+ if (row == null ? void 0 : row.label) return row.label;
404
+ const d = new Date(v);
405
+ return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;
406
+ }
303
407
  }
304
- }
305
- ),
306
- /* @__PURE__ */ jsxRuntime.jsx(
307
- recharts.YAxis,
308
- {
309
- tick: { fontSize: 12 },
310
- allowDecimals: false,
311
- domain: [0, "auto"],
312
- ticks: (() => {
313
- const max = Math.max(
314
- 1,
315
- ...dailyOrders.map((d) => d.orders_count ?? 0)
316
- );
317
- const step = max <= 10 ? 1 : Math.ceil(max / 6);
318
- const arr = [];
319
- for (let i = 0; i <= max; i += step) arr.push(i);
320
- if (arr[arr.length - 1] !== max) arr.push(max);
321
- return arr;
322
- })(),
323
- tickFormatter: (v) => String(Math.floor(Number(v) || 0))
324
- }
325
- ),
326
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(OrdersOverTimeTooltip, {}) }),
327
- /* @__PURE__ */ jsxRuntime.jsx(
328
- recharts.Line,
329
- {
330
- type: "monotone",
331
- dataKey: "orders_count",
332
- name: "Orders",
333
- stroke: "var(--medusa-color-ui-fg-interactive)",
334
- strokeWidth: 2,
335
- dot: { r: 3 }
336
- }
337
- )
338
- ]
339
- }
340
- ) }) })
341
- ] })
408
+ ),
409
+ /* @__PURE__ */ jsxRuntime.jsx(
410
+ recharts.YAxis,
411
+ {
412
+ tick: { fontSize: 12 },
413
+ allowDecimals: false,
414
+ domain: [0, "auto"],
415
+ ticks: (() => {
416
+ const max = Math.max(
417
+ 1,
418
+ ...dailyOrders.map((d) => d.orders_count ?? 0)
419
+ );
420
+ const step = max <= 10 ? 1 : Math.ceil(max / 6);
421
+ const arr = [];
422
+ for (let i = 0; i <= max; i += step) arr.push(i);
423
+ if (arr[arr.length - 1] !== max) arr.push(max);
424
+ return arr;
425
+ })(),
426
+ tickFormatter: (v) => String(Math.floor(Number(v) || 0))
427
+ }
428
+ ),
429
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(OrdersOverTimeTooltip, {}) }),
430
+ /* @__PURE__ */ jsxRuntime.jsx(
431
+ recharts.Line,
432
+ {
433
+ type: "monotone",
434
+ dataKey: "orders_count",
435
+ name: "Orders",
436
+ stroke: "var(--medusa-color-ui-fg-interactive)",
437
+ strokeWidth: 2,
438
+ dot: { r: 3 }
439
+ }
440
+ )
441
+ ]
442
+ }
443
+ ) }) }) })
444
+ }
445
+ )
342
446
  ] });
343
447
  }
344
448
  function CustomersOverTimeTooltip({
@@ -454,64 +558,81 @@ function CustomersDashboard() {
454
558
  if (error || !data) {
455
559
  return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: error ?? "Failed to load analytics" }) });
456
560
  }
457
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
458
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
459
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Customers" }),
460
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
461
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
462
- /* @__PURE__ */ jsxRuntime.jsx(
463
- ui.Label,
464
- {
465
- htmlFor: "customers-count-period",
466
- className: "text-ui-fg-muted text-sm",
467
- children: "Period (counts)"
468
- }
469
- ),
470
- /* @__PURE__ */ jsxRuntime.jsx(
471
- "select",
561
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsDashboardShell, { children: [
562
+ /* @__PURE__ */ jsxRuntime.jsx(
563
+ AnalyticsDashboardHeader,
564
+ {
565
+ title: "Customers",
566
+ description: "Keep customer acquisition and account mix compact, readable, and aligned with the rest of analytics.",
567
+ actions: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
568
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
569
+ /* @__PURE__ */ jsxRuntime.jsx(
570
+ ui.Label,
571
+ {
572
+ htmlFor: "customers-count-period",
573
+ className: "text-ui-fg-muted text-sm",
574
+ children: "Period"
575
+ }
576
+ ),
577
+ /* @__PURE__ */ jsxRuntime.jsx(
578
+ "select",
579
+ {
580
+ id: "customers-count-period",
581
+ value: countDays,
582
+ onChange: (e) => setCountDays(e.target.value),
583
+ 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",
584
+ children: COUNT_DAY_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
585
+ }
586
+ )
587
+ ] }),
588
+ countDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
589
+ "button",
472
590
  {
473
- id: "customers-count-period",
474
- value: countDays,
475
- onChange: (e) => setCountDays(e.target.value),
476
- 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",
477
- children: COUNT_DAY_PRESETS.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
591
+ type: "button",
592
+ onClick: () => setCountDays("all"),
593
+ className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
594
+ "aria-label": "Show all customers (clear filter)",
595
+ children: "Clear filter"
478
596
  }
479
597
  )
480
- ] }),
481
- countDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
482
- "button",
483
- {
484
- type: "button",
485
- onClick: () => setCountDays("all"),
486
- className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
487
- "aria-label": "Show all customers (clear filter)",
488
- children: "Clear filter"
489
- }
490
- )
491
- ] })
492
- ] }),
493
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4", children: [
494
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
495
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Guest customers" }),
496
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: Math.floor(data.guestCount).toLocaleString() })
497
- ] }),
498
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
499
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Registered customers" }),
500
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: Math.floor(data.registeredCount).toLocaleString() })
501
- ] }),
502
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
503
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Overall customers" }),
504
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: Math.floor(data.totalCount).toLocaleString() })
505
- ] }),
506
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
507
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Deleted accounts" }),
508
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: (data.deletedAccountsCount ?? 0).toLocaleString() })
509
- ] })
598
+ ] })
599
+ }
600
+ ),
601
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4", children: [
602
+ /* @__PURE__ */ jsxRuntime.jsx(
603
+ AnalyticsStatCard,
604
+ {
605
+ label: "Guest customers",
606
+ value: Math.floor(data.guestCount).toLocaleString()
607
+ }
608
+ ),
609
+ /* @__PURE__ */ jsxRuntime.jsx(
610
+ AnalyticsStatCard,
611
+ {
612
+ label: "Registered customers",
613
+ value: Math.floor(data.registeredCount).toLocaleString()
614
+ }
615
+ ),
616
+ /* @__PURE__ */ jsxRuntime.jsx(
617
+ AnalyticsStatCard,
618
+ {
619
+ label: "Overall customers",
620
+ value: Math.floor(data.totalCount).toLocaleString()
621
+ }
622
+ ),
623
+ /* @__PURE__ */ jsxRuntime.jsx(
624
+ AnalyticsStatCard,
625
+ {
626
+ label: "Deleted accounts",
627
+ value: (data.deletedAccountsCount ?? 0).toLocaleString()
628
+ }
629
+ )
510
630
  ] }),
511
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
512
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 mb-4", children: [
513
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Customers over time" }),
514
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
631
+ /* @__PURE__ */ jsxRuntime.jsx(
632
+ AnalyticsSection,
633
+ {
634
+ title: "Customers over time",
635
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
515
636
  /* @__PURE__ */ jsxRuntime.jsx(
516
637
  ui.Label,
517
638
  {
@@ -530,78 +651,78 @@ function CustomersDashboard() {
530
651
  children: GRAPH_PERIODS$1.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p.value, children: p.label }, p.value))
531
652
  }
532
653
  )
533
- ] })
534
- ] }),
535
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: graphLoading ? /* @__PURE__ */ jsxRuntime.jsx(
536
- "div",
537
- {
538
- className: "flex items-center justify-center h-full",
539
- role: "status",
540
- "aria-label": "Loading customers over time",
541
- children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" })
542
- }
543
- ) : graphError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: graphError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
544
- recharts.LineChart,
545
- {
546
- data: series,
547
- margin: { top: 8, right: 8, left: 8, bottom: 8 },
548
- children: [
549
- /* @__PURE__ */ jsxRuntime.jsx(
550
- recharts.CartesianGrid,
551
- {
552
- strokeDasharray: "3 3",
553
- className: "stroke-ui-border-base"
554
- }
555
- ),
556
- /* @__PURE__ */ jsxRuntime.jsx(
557
- recharts.XAxis,
558
- {
559
- dataKey: "date",
560
- tick: { fontSize: 12 },
561
- tickFormatter: (v, index) => {
562
- const row = series[index];
563
- if (row == null ? void 0 : row.label) return row.label;
564
- const d = new Date(v);
565
- return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;
654
+ ] }),
655
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-72", children: graphLoading ? /* @__PURE__ */ jsxRuntime.jsx(
656
+ "div",
657
+ {
658
+ className: "flex items-center justify-center h-full",
659
+ role: "status",
660
+ "aria-label": "Loading customers over time",
661
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" })
662
+ }
663
+ ) : graphError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: graphError }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
664
+ recharts.LineChart,
665
+ {
666
+ data: series,
667
+ margin: { top: 8, right: 8, left: 8, bottom: 8 },
668
+ children: [
669
+ /* @__PURE__ */ jsxRuntime.jsx(
670
+ recharts.CartesianGrid,
671
+ {
672
+ strokeDasharray: "3 3",
673
+ className: "stroke-ui-border-base"
566
674
  }
567
- }
568
- ),
569
- /* @__PURE__ */ jsxRuntime.jsx(
570
- recharts.YAxis,
571
- {
572
- tick: { fontSize: 12 },
573
- tickFormatter: (v) => String(Math.floor(Number(v))),
574
- allowDecimals: false
575
- }
576
- ),
577
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomersOverTimeTooltip, {}) }),
578
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
579
- /* @__PURE__ */ jsxRuntime.jsx(
580
- recharts.Line,
581
- {
582
- type: "monotone",
583
- dataKey: "registered_count",
584
- name: "Registered",
585
- stroke: REGISTERED_COLOR,
586
- strokeWidth: 2,
587
- dot: { r: 3 }
588
- }
589
- ),
590
- /* @__PURE__ */ jsxRuntime.jsx(
591
- recharts.Line,
592
- {
593
- type: "monotone",
594
- dataKey: "guest_count",
595
- name: "Guest",
596
- stroke: GUEST_COLOR,
597
- strokeWidth: 2,
598
- dot: { r: 3 }
599
- }
600
- )
601
- ]
602
- }
603
- ) }) })
604
- ] })
675
+ ),
676
+ /* @__PURE__ */ jsxRuntime.jsx(
677
+ recharts.XAxis,
678
+ {
679
+ dataKey: "date",
680
+ tick: { fontSize: 12 },
681
+ tickFormatter: (v, index) => {
682
+ const row = series[index];
683
+ if (row == null ? void 0 : row.label) return row.label;
684
+ const d = new Date(v);
685
+ return `${d.getUTCMonth() + 1}/${d.getUTCDate()}`;
686
+ }
687
+ }
688
+ ),
689
+ /* @__PURE__ */ jsxRuntime.jsx(
690
+ recharts.YAxis,
691
+ {
692
+ tick: { fontSize: 12 },
693
+ tickFormatter: (v) => String(Math.floor(Number(v))),
694
+ allowDecimals: false
695
+ }
696
+ ),
697
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(CustomersOverTimeTooltip, {}) }),
698
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
699
+ /* @__PURE__ */ jsxRuntime.jsx(
700
+ recharts.Line,
701
+ {
702
+ type: "monotone",
703
+ dataKey: "registered_count",
704
+ name: "Registered",
705
+ stroke: REGISTERED_COLOR,
706
+ strokeWidth: 2,
707
+ dot: { r: 3 }
708
+ }
709
+ ),
710
+ /* @__PURE__ */ jsxRuntime.jsx(
711
+ recharts.Line,
712
+ {
713
+ type: "monotone",
714
+ dataKey: "guest_count",
715
+ name: "Guest",
716
+ stroke: GUEST_COLOR,
717
+ strokeWidth: 2,
718
+ dot: { r: 3 }
719
+ }
720
+ )
721
+ ]
722
+ }
723
+ ) }) }) })
724
+ }
725
+ )
605
726
  ] });
606
727
  }
607
728
  const SUMMARY_PERIODS = [
@@ -625,6 +746,7 @@ const TOP_SELLER_PERIODS = [
625
746
  const SALES_COLOR = "var(--medusa-color-ui-fg-interactive)";
626
747
  const VIEWS_COLOR = "#8B5CF6";
627
748
  const REVENUE_COLOR = "#F59E0B";
749
+ const REVENUE_MUTED_COLOR = "#FCD34D";
628
750
  function formatCurrency(value) {
629
751
  return new Intl.NumberFormat("en-IN", {
630
752
  style: "currency",
@@ -695,7 +817,8 @@ function TrendTooltip({
695
817
  }
696
818
  function ProductBarTooltip({
697
819
  active,
698
- payload
820
+ payload,
821
+ showViews = true
699
822
  }) {
700
823
  var _a;
701
824
  if (!active || !(payload == null ? void 0 : payload.length)) return null;
@@ -723,10 +846,10 @@ function ProductBarTooltip({
723
846
  "Units sold: ",
724
847
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(unitsSold).toLocaleString() })
725
848
  ] }),
726
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
849
+ showViews ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
727
850
  "Views: ",
728
851
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: Math.floor(totalViews).toLocaleString() })
729
- ] }),
852
+ ] }) : null,
730
853
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
731
854
  "Revenue: ",
732
855
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: formatCurrency(Number(revenue)) })
@@ -879,10 +1002,14 @@ function ProductsDashboard() {
879
1002
  };
880
1003
  }, [salesChannelId, summaryDays]);
881
1004
  const topSellerChartData = react.useMemo(
882
- () => ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 7).map((row) => ({
883
- ...row,
884
- product_title: truncateLabel(row.product_title, 24)
885
- })).reverse(),
1005
+ () => ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 7).map((row) => {
1006
+ var _a2, _b2;
1007
+ return {
1008
+ ...row,
1009
+ isBestSeller: row.product_id === (((_b2 = (_a2 = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _a2[0]) == null ? void 0 : _b2.product_id) ?? null),
1010
+ product_title: truncateLabel(row.product_title, 24)
1011
+ };
1012
+ }).reverse(),
886
1013
  [topSellers]
887
1014
  );
888
1015
  const topViewedChartData = react.useMemo(
@@ -908,105 +1035,125 @@ function ProductsDashboard() {
908
1035
  }
909
1036
  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;
910
1037
  const selectedChannelLabel = salesChannelId === "all" ? "All channels" : ((_a = salesChannels.find((channel) => channel.id === salesChannelId)) == null ? void 0 : _a.name) ?? "Selected channel";
911
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-8", children: [
912
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4", children: [
913
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
914
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: "Products" }),
915
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mt-1", children: "Track units sold, revenue, best sellers, and product visit behavior." })
916
- ] }),
917
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
918
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
919
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-channel-filter", className: "text-ui-fg-muted text-sm", children: "Channel" }),
920
- /* @__PURE__ */ jsxRuntime.jsxs(
921
- "select",
922
- {
923
- id: "products-channel-filter",
924
- value: salesChannelId,
925
- onChange: (event) => setSalesChannelId(event.target.value),
926
- disabled: filtersLoading,
927
- 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",
928
- children: [
929
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All channels" }),
930
- salesChannels.map((channel) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: channel.id, children: channel.name }, channel.id))
931
- ]
932
- }
933
- )
934
- ] }),
935
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
936
- /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-summary-period", className: "text-ui-fg-muted text-sm", children: "Period" }),
937
- /* @__PURE__ */ jsxRuntime.jsx(
938
- "select",
939
- {
940
- id: "products-summary-period",
941
- value: summaryDays,
942
- onChange: (event) => setSummaryDays(event.target.value),
943
- 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",
944
- children: SUMMARY_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
945
- }
946
- )
947
- ] }),
948
- summaryDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
949
- "button",
950
- {
951
- type: "button",
952
- onClick: () => setSummaryDays("all"),
953
- className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
954
- "aria-label": "Show all products analytics",
955
- children: "Clear filter"
956
- }
957
- ),
958
- salesChannelId !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
959
- "button",
960
- {
961
- type: "button",
962
- onClick: () => setSalesChannelId("all"),
963
- className: "text-xs text-ui-fg-muted hover:text-ui-fg-base transition-colors",
964
- "aria-label": "Show all sales channels",
965
- children: "Clear channel"
966
- }
967
- )
968
- ] })
969
- ] }),
970
- filtersError && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-sm", children: filtersError }) }),
971
- !viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Product views are unavailable until the `medusa-product-helper` tracking module is registered and storefront page views are being recorded." }) }),
972
- salesChannelId !== "all" && viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-sm", children: [
1038
+ return /* @__PURE__ */ jsxRuntime.jsxs(AnalyticsDashboardShell, { children: [
1039
+ /* @__PURE__ */ jsxRuntime.jsx(
1040
+ AnalyticsDashboardHeader,
1041
+ {
1042
+ title: "Products",
1043
+ description: "Track units sold, revenue, best sellers, and product visit behavior in a denser, easier-to-scan layout.",
1044
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-end gap-2.5", children: [
1045
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1046
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-channel-filter", className: "text-ui-fg-muted text-xs font-medium", children: "Channel" }),
1047
+ /* @__PURE__ */ jsxRuntime.jsxs(
1048
+ "select",
1049
+ {
1050
+ id: "products-channel-filter",
1051
+ value: salesChannelId,
1052
+ onChange: (event) => setSalesChannelId(event.target.value),
1053
+ disabled: filtersLoading,
1054
+ 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",
1055
+ children: [
1056
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All channels" }),
1057
+ salesChannels.map((channel) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: channel.id, children: channel.name }, channel.id))
1058
+ ]
1059
+ }
1060
+ )
1061
+ ] }),
1062
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
1063
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-summary-period", className: "text-ui-fg-muted text-xs font-medium", children: "Period" }),
1064
+ /* @__PURE__ */ jsxRuntime.jsx(
1065
+ "select",
1066
+ {
1067
+ id: "products-summary-period",
1068
+ value: summaryDays,
1069
+ onChange: (event) => setSummaryDays(event.target.value),
1070
+ 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",
1071
+ children: SUMMARY_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
1072
+ }
1073
+ )
1074
+ ] }),
1075
+ (summaryDays !== "all" || salesChannelId !== "all") && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 self-end pb-1", children: [
1076
+ summaryDays !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
1077
+ "button",
1078
+ {
1079
+ type: "button",
1080
+ onClick: () => setSummaryDays("all"),
1081
+ className: "text-xs text-ui-fg-muted transition-colors hover:text-ui-fg-base",
1082
+ "aria-label": "Show all products analytics",
1083
+ children: "Clear period"
1084
+ }
1085
+ ),
1086
+ salesChannelId !== "all" && /* @__PURE__ */ jsxRuntime.jsx(
1087
+ "button",
1088
+ {
1089
+ type: "button",
1090
+ onClick: () => setSalesChannelId("all"),
1091
+ className: "text-xs text-ui-fg-muted transition-colors hover:text-ui-fg-base",
1092
+ "aria-label": "Show all sales channels",
1093
+ children: "Clear channel"
1094
+ }
1095
+ )
1096
+ ] })
1097
+ ] })
1098
+ }
1099
+ ),
1100
+ filtersError && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger text-sm", children: filtersError }) }),
1101
+ !viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Product views are unavailable until the `medusa-product-helper` tracking module is registered and storefront page views are being recorded." }) }),
1102
+ salesChannelId !== "all" && viewsConnected && /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "rounded-2xl border border-ui-border-base bg-ui-bg-base p-4 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Text, { className: "text-ui-fg-muted text-sm", children: [
973
1103
  "Showing product analytics for ",
974
1104
  /* @__PURE__ */ jsxRuntime.jsx("strong", { children: selectedChannelLabel }),
975
1105
  ". Product views are scoped to products assigned to this sales channel."
976
1106
  ] }) }),
977
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-4", children: [
978
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
979
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Units sold" }),
980
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: summary.unitsSold.toLocaleString() })
981
- ] }),
982
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
983
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Product revenue" }),
984
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: formatCurrency(summary.productRevenue) })
985
- ] }),
986
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
987
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Orders with product sales" }),
988
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: summary.ordersWithProducts.toLocaleString() })
989
- ] }),
990
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
991
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Active products sold" }),
992
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: summary.activeProductsSold.toLocaleString() })
993
- ] }),
994
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
995
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Product views" }),
996
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: summary.totalProductViews.toLocaleString() })
997
- ] }),
998
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-4", children: [
999
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "View / order ratio" }),
1000
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", children: formatRatio(summary.viewToOrderRatio) })
1001
- ] })
1107
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3", children: [
1108
+ /* @__PURE__ */ jsxRuntime.jsx(
1109
+ AnalyticsStatCard,
1110
+ {
1111
+ label: "Units sold",
1112
+ value: summary.unitsSold.toLocaleString()
1113
+ }
1114
+ ),
1115
+ /* @__PURE__ */ jsxRuntime.jsx(
1116
+ AnalyticsStatCard,
1117
+ {
1118
+ label: "Product revenue",
1119
+ value: formatCurrency(summary.productRevenue)
1120
+ }
1121
+ ),
1122
+ /* @__PURE__ */ jsxRuntime.jsx(
1123
+ AnalyticsStatCard,
1124
+ {
1125
+ label: "Orders with product sales",
1126
+ value: summary.ordersWithProducts.toLocaleString()
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ jsxRuntime.jsx(
1130
+ AnalyticsStatCard,
1131
+ {
1132
+ label: "Active products sold",
1133
+ value: summary.activeProductsSold.toLocaleString()
1134
+ }
1135
+ ),
1136
+ /* @__PURE__ */ jsxRuntime.jsx(
1137
+ AnalyticsStatCard,
1138
+ {
1139
+ label: "Product views",
1140
+ value: summary.totalProductViews.toLocaleString()
1141
+ }
1142
+ ),
1143
+ /* @__PURE__ */ jsxRuntime.jsx(
1144
+ AnalyticsStatCard,
1145
+ {
1146
+ label: "View / order ratio",
1147
+ value: formatRatio(summary.viewToOrderRatio)
1148
+ }
1149
+ )
1002
1150
  ] }),
1003
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
1004
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 mb-4", children: [
1005
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1006
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Sales and views over time" }),
1007
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mt-1", children: "Units sold and revenue are always shown. Product views appear when tracking data is available." })
1008
- ] }),
1009
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1151
+ /* @__PURE__ */ jsxRuntime.jsx(
1152
+ AnalyticsSection,
1153
+ {
1154
+ title: "Sales and views over time",
1155
+ description: "Units sold and revenue are always shown. Product views appear when tracking data is available.",
1156
+ actions: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1010
1157
  /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "products-graph-period", className: "text-ui-fg-muted text-sm", children: "Range" }),
1011
1158
  /* @__PURE__ */ jsxRuntime.jsx(
1012
1159
  "select",
@@ -1018,172 +1165,205 @@ function ProductsDashboard() {
1018
1165
  children: GRAPH_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: period.value, children: period.label }, period.value))
1019
1166
  }
1020
1167
  )
1021
- ] })
1022
- ] }),
1023
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" }) }) : overTimeError || !overTime ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: overTimeError ?? "Failed to load product trend" }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: overTime.series, children: [
1024
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
1025
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "label" }),
1026
- /* @__PURE__ */ jsxRuntime.jsx(
1027
- recharts.YAxis,
1028
- {
1029
- yAxisId: "counts",
1030
- allowDecimals: false,
1031
- tickFormatter: (value) => Math.floor(Number(value)).toLocaleString()
1032
- }
1033
- ),
1034
- /* @__PURE__ */ jsxRuntime.jsx(
1035
- recharts.YAxis,
1036
- {
1037
- yAxisId: "revenue",
1038
- orientation: "right",
1039
- tickFormatter: (value) => formatCurrency(Number(value))
1040
- }
1041
- ),
1042
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(TrendTooltip, {}) }),
1043
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
1044
- /* @__PURE__ */ jsxRuntime.jsx(
1045
- recharts.Line,
1046
- {
1047
- yAxisId: "counts",
1048
- type: "monotone",
1049
- dataKey: "units_sold",
1050
- name: "Units sold",
1051
- stroke: SALES_COLOR,
1052
- strokeWidth: 2,
1053
- dot: false
1054
- }
1055
- ),
1056
- /* @__PURE__ */ jsxRuntime.jsx(
1057
- recharts.Line,
1058
- {
1059
- yAxisId: "counts",
1060
- type: "monotone",
1061
- dataKey: "views",
1062
- name: "Views",
1063
- stroke: VIEWS_COLOR,
1064
- strokeWidth: 2,
1065
- dot: false
1066
- }
1067
- ),
1068
- /* @__PURE__ */ jsxRuntime.jsx(
1069
- recharts.Line,
1070
- {
1071
- yAxisId: "revenue",
1072
- type: "monotone",
1073
- dataKey: "revenue",
1074
- name: "Revenue",
1075
- stroke: REVENUE_COLOR,
1076
- strokeWidth: 2,
1077
- dot: false
1078
- }
1079
- )
1080
- ] }) }) })
1081
- ] }),
1082
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 xl:grid-cols-2 gap-4", children: [
1083
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
1084
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-4 mb-4", children: [
1085
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1086
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", children: "Best sellers" }),
1087
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mt-1", children: "Ranked by units sold." })
1088
- ] }),
1089
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", children: TOP_SELLER_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx(
1090
- ui.Button,
1091
- {
1092
- variant: topSellerPeriod === period.value ? "secondary" : "transparent",
1093
- size: "small",
1094
- onClick: () => setTopSellerPeriod(period.value),
1095
- children: period.label
1096
- },
1097
- period.value
1098
- )) })
1099
1168
  ] }),
1100
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: topSellersLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading best sellers…" }) }) : topSellersError || !topSellers ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: topSellersError ?? "Failed to load best sellers" }) }) : topSellerChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product sales found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topSellerChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
1101
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
1102
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", allowDecimals: false }),
1169
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: overTimeLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading chart…" }) }) : overTimeError || !overTime ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: overTimeError ?? "Failed to load product trend" }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data: overTime.series, children: [
1170
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
1171
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { dataKey: "label" }),
1103
1172
  /* @__PURE__ */ jsxRuntime.jsx(
1104
1173
  recharts.YAxis,
1105
1174
  {
1106
- type: "category",
1107
- dataKey: "product_title",
1108
- width: 160,
1109
- tickLine: false
1175
+ yAxisId: "counts",
1176
+ allowDecimals: false,
1177
+ tickFormatter: (value) => Math.floor(Number(value)).toLocaleString()
1110
1178
  }
1111
1179
  ),
1112
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {}) }),
1113
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "units_sold", fill: SALES_COLOR, radius: [0, 6, 6, 0] })
1114
- ] }) }) })
1115
- ] }),
1116
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
1117
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "mb-4", children: "Top seller breakdown" }),
1118
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1119
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1120
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
1121
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
1122
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Orders" }),
1123
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Revenue" })
1124
- ] }) }),
1125
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
1126
- ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 8).map((product) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1127
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
1128
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
1129
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.order_count.toLocaleString() }),
1130
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatCurrency(product.revenue) })
1131
- ] }, product.product_id)),
1132
- !topSellersLoading && (((_b = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _b.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1133
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No best seller data yet." }),
1134
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1135
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1136
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
1137
- ] })
1138
- ] })
1139
- ] })
1140
- ] })
1141
- ] }),
1142
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 xl:grid-cols-2 gap-4", children: [
1143
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
1144
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "mb-1", children: "Most viewed products" }),
1145
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm mb-4", children: "View activity is sourced from the existing product-helper tracking module." }),
1146
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading product views…" }) }) : performanceError || !performance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: performanceError ?? "Failed to load product performance" }) }) : !performance.productViewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Product view tracking is not available in this environment." }) }) : topViewedChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product views found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topViewedChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
1147
- /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
1148
- /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", allowDecimals: false }),
1149
1180
  /* @__PURE__ */ jsxRuntime.jsx(
1150
1181
  recharts.YAxis,
1151
1182
  {
1152
- type: "category",
1153
- dataKey: "product_title",
1154
- width: 160,
1155
- tickLine: false
1183
+ yAxisId: "revenue",
1184
+ orientation: "right",
1185
+ tickFormatter: (value) => formatCurrency(Number(value))
1156
1186
  }
1157
1187
  ),
1158
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {}) }),
1159
- /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "total_views", fill: VIEWS_COLOR, radius: [0, 6, 6, 0] })
1160
- ] }) }) })
1161
- ] }),
1162
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "p-6", children: [
1163
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h3", className: "mb-4", children: "View-to-sales opportunities" }),
1164
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1165
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1166
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
1167
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views" }),
1168
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
1169
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views / unit" })
1170
- ] }) }),
1171
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
1172
- ((performance == null ? void 0 : performance.viewOpportunities) ?? []).slice(0, 8).map((product) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1173
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
1174
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.total_views.toLocaleString() }),
1175
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
1176
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatRatio(product.views_per_unit) })
1177
- ] }, product.product_id)),
1178
- !performanceLoading && !performanceError && (((_c = performance == null ? void 0 : performance.viewOpportunities) == null ? void 0 : _c.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1179
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No product view opportunities yet." }),
1180
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1181
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1182
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
1188
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(TrendTooltip, {}) }),
1189
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, {}),
1190
+ /* @__PURE__ */ jsxRuntime.jsx(
1191
+ recharts.Line,
1192
+ {
1193
+ yAxisId: "counts",
1194
+ type: "monotone",
1195
+ dataKey: "units_sold",
1196
+ name: "Units sold",
1197
+ stroke: SALES_COLOR,
1198
+ strokeWidth: 2,
1199
+ dot: false
1200
+ }
1201
+ ),
1202
+ /* @__PURE__ */ jsxRuntime.jsx(
1203
+ recharts.Line,
1204
+ {
1205
+ yAxisId: "counts",
1206
+ type: "monotone",
1207
+ dataKey: "views",
1208
+ name: "Views",
1209
+ stroke: VIEWS_COLOR,
1210
+ strokeWidth: 2,
1211
+ dot: false
1212
+ }
1213
+ ),
1214
+ /* @__PURE__ */ jsxRuntime.jsx(
1215
+ recharts.Line,
1216
+ {
1217
+ yAxisId: "revenue",
1218
+ type: "monotone",
1219
+ dataKey: "revenue",
1220
+ name: "Revenue",
1221
+ stroke: REVENUE_COLOR,
1222
+ strokeWidth: 2,
1223
+ dot: false
1224
+ }
1225
+ )
1226
+ ] }) }) }) })
1227
+ }
1228
+ ),
1229
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 xl:grid-cols-2", children: [
1230
+ /* @__PURE__ */ jsxRuntime.jsx(
1231
+ AnalyticsSection,
1232
+ {
1233
+ title: "Best sellers",
1234
+ description: "Top products by revenue.",
1235
+ actions: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2", children: TOP_SELLER_PERIODS.map((period) => /* @__PURE__ */ jsxRuntime.jsx(
1236
+ ui.Button,
1237
+ {
1238
+ variant: topSellerPeriod === period.value ? "secondary" : "transparent",
1239
+ size: "small",
1240
+ onClick: () => setTopSellerPeriod(period.value),
1241
+ children: period.label
1242
+ },
1243
+ period.value
1244
+ )) }),
1245
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: topSellersLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading best sellers…" }) }) : topSellersError || !topSellers ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: topSellersError ?? "Failed to load best sellers" }) }) : topSellerChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product sales found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topSellerChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
1246
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
1247
+ /* @__PURE__ */ jsxRuntime.jsx(
1248
+ recharts.XAxis,
1249
+ {
1250
+ type: "number",
1251
+ allowDecimals: false,
1252
+ tickFormatter: (value) => formatCurrency(Number(value))
1253
+ }
1254
+ ),
1255
+ /* @__PURE__ */ jsxRuntime.jsx(
1256
+ recharts.YAxis,
1257
+ {
1258
+ type: "category",
1259
+ dataKey: "product_title",
1260
+ width: 160,
1261
+ tickLine: false
1262
+ }
1263
+ ),
1264
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, { showViews: false }) }),
1265
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "revenue", radius: [0, 6, 6, 0], children: topSellerChartData.map((entry) => /* @__PURE__ */ jsxRuntime.jsx(
1266
+ recharts.Cell,
1267
+ {
1268
+ fill: entry.isBestSeller ? REVENUE_COLOR : REVENUE_MUTED_COLOR
1269
+ },
1270
+ entry.product_id
1271
+ )) })
1272
+ ] }) }) }) })
1273
+ }
1274
+ ),
1275
+ /* @__PURE__ */ jsxRuntime.jsx(
1276
+ AnalyticsSection,
1277
+ {
1278
+ title: "Top seller breakdown",
1279
+ description: "Products ranked by revenue.",
1280
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTableSurface, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1281
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1282
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
1283
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
1284
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Orders" }),
1285
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Revenue" })
1286
+ ] }) }),
1287
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
1288
+ ((topSellers == null ? void 0 : topSellers.products) ?? []).slice(0, 8).map((product) => {
1289
+ var _a2, _b2;
1290
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1291
+ ui.Table.Row,
1292
+ {
1293
+ 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,
1294
+ children: [
1295
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
1296
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
1297
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.order_count.toLocaleString() }),
1298
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatCurrency(product.revenue) })
1299
+ ]
1300
+ },
1301
+ product.product_id
1302
+ );
1303
+ }),
1304
+ !topSellersLoading && (((_b = topSellers == null ? void 0 : topSellers.products) == null ? void 0 : _b.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1305
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No best seller data yet." }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1307
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1308
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
1309
+ ] })
1183
1310
  ] })
1184
- ] })
1185
- ] })
1186
- ] })
1311
+ ] }) })
1312
+ }
1313
+ )
1314
+ ] }),
1315
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 xl:grid-cols-2", children: [
1316
+ /* @__PURE__ */ jsxRuntime.jsx(
1317
+ AnalyticsSection,
1318
+ {
1319
+ title: "Most viewed products",
1320
+ description: "View activity is sourced from the existing product-helper tracking module.",
1321
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsChartSurface, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-80", children: performanceLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Loading product views…" }) }) : performanceError || !performance ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-danger", children: performanceError ?? "Failed to load product performance" }) }) : !performance.productViewsConnected ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "Product view tracking is not available in this environment." }) }) : topViewedChartData.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted", children: "No product views found for this range." }) }) : /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.BarChart, { data: topViewedChartData, layout: "vertical", margin: { left: 8, right: 8 }, children: [
1322
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false }),
1323
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.XAxis, { type: "number", allowDecimals: false }),
1324
+ /* @__PURE__ */ jsxRuntime.jsx(
1325
+ recharts.YAxis,
1326
+ {
1327
+ type: "category",
1328
+ dataKey: "product_title",
1329
+ width: 160,
1330
+ tickLine: false
1331
+ }
1332
+ ),
1333
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(ProductBarTooltip, {}) }),
1334
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Bar, { dataKey: "total_views", fill: VIEWS_COLOR, radius: [0, 6, 6, 0] })
1335
+ ] }) }) }) })
1336
+ }
1337
+ ),
1338
+ /* @__PURE__ */ jsxRuntime.jsx(
1339
+ AnalyticsSection,
1340
+ {
1341
+ title: "View-to-sales opportunities",
1342
+ description: "Highlight products that attract attention but convert less efficiently.",
1343
+ children: /* @__PURE__ */ jsxRuntime.jsx(AnalyticsTableSurface, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1344
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1345
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Product" }),
1346
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views" }),
1347
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Units" }),
1348
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Views / unit" })
1349
+ ] }) }),
1350
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Body, { children: [
1351
+ ((performance == null ? void 0 : performance.viewOpportunities) ?? []).slice(0, 8).map((product) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1352
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.product_title }),
1353
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.total_views.toLocaleString() }),
1354
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: product.units_sold.toLocaleString() }),
1355
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatRatio(product.views_per_unit) })
1356
+ ] }, product.product_id)),
1357
+ !performanceLoading && !performanceError && (((_c = performance == null ? void 0 : performance.viewOpportunities) == null ? void 0 : _c.length) ?? 0) === 0 && /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1358
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: "No product view opportunities yet." }),
1359
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1360
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {}),
1361
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {})
1362
+ ] })
1363
+ ] })
1364
+ ] }) })
1365
+ }
1366
+ )
1187
1367
  ] })
1188
1368
  ] });
1189
1369
  }
@@ -1194,22 +1374,32 @@ const ANALYTICS_MODULES = [
1194
1374
  ];
1195
1375
  const AnalyticsPage = () => {
1196
1376
  const [activeModule, setActiveModule] = react.useState("orders");
1197
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full bg-ui-bg-base", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { className: "divide-y p-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-6 px-6", children: [
1198
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", className: "mb-4", children: "Analytics" }),
1199
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2 mb-6", children: ANALYTICS_MODULES.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
1200
- ui.Button,
1201
- {
1202
- variant: activeModule === m.id ? "secondary" : "transparent",
1203
- size: "small",
1204
- onClick: () => setActiveModule(m.id),
1205
- children: m.label
1206
- },
1207
- m.id
1208
- )) }),
1209
- activeModule === "orders" && /* @__PURE__ */ jsxRuntime.jsx(OrdersDashboard, {}),
1210
- activeModule === "customers" && /* @__PURE__ */ jsxRuntime.jsx(CustomersDashboard, {}),
1211
- activeModule === "products" && /* @__PURE__ */ jsxRuntime.jsx(ProductsDashboard, {})
1212
- ] }) }) }) });
1377
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full bg-ui-bg-subtle", children: /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-auto flex w-full max-w-[1600px] flex-col gap-4 p-4", children: [
1378
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "overflow-hidden rounded-2xl border border-ui-border-base bg-ui-bg-base p-0 shadow-sm", children: [
1379
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-5 px-5 py-5 xl:flex-row xl:items-end xl:justify-between", children: [
1380
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5", children: [
1381
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", className: "tracking-tight", children: "Analytics" }),
1382
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { className: "text-ui-fg-muted text-sm", children: "Review orders, customers, and products in one organized workspace." })
1383
+ ] }),
1384
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap items-center gap-2 rounded-2xl border border-ui-border-base bg-ui-bg-subtle p-1.5", children: ANALYTICS_MODULES.map((m) => /* @__PURE__ */ jsxRuntime.jsx(
1385
+ ui.Button,
1386
+ {
1387
+ variant: activeModule === m.id ? "secondary" : "transparent",
1388
+ size: "small",
1389
+ onClick: () => setActiveModule(m.id),
1390
+ children: m.label
1391
+ },
1392
+ m.id
1393
+ )) })
1394
+ ] }),
1395
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 bg-ui-bg-subtle" })
1396
+ ] }),
1397
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1398
+ activeModule === "orders" && /* @__PURE__ */ jsxRuntime.jsx(OrdersDashboard, {}),
1399
+ activeModule === "customers" && /* @__PURE__ */ jsxRuntime.jsx(CustomersDashboard, {}),
1400
+ activeModule === "products" && /* @__PURE__ */ jsxRuntime.jsx(ProductsDashboard, {})
1401
+ ] })
1402
+ ] }) }) });
1213
1403
  };
1214
1404
  const config = adminSdk.defineRouteConfig({
1215
1405
  label: "Analytics",