@elizaos/plugin-shopify-ui 2.0.3-beta.6 → 2.0.3-beta.7

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.
Files changed (79) hide show
  1. package/dist/CustomersPanel.d.ts +11 -0
  2. package/dist/CustomersPanel.d.ts.map +1 -0
  3. package/dist/CustomersPanel.js +86 -0
  4. package/dist/CustomersPanel.js.map +1 -0
  5. package/dist/InventoryLevelsPanel.d.ts +10 -0
  6. package/dist/InventoryLevelsPanel.d.ts.map +1 -0
  7. package/dist/InventoryLevelsPanel.js +190 -0
  8. package/dist/InventoryLevelsPanel.js.map +1 -0
  9. package/dist/OrdersPanel.d.ts +12 -0
  10. package/dist/OrdersPanel.d.ts.map +1 -0
  11. package/dist/OrdersPanel.js +170 -0
  12. package/dist/OrdersPanel.js.map +1 -0
  13. package/dist/ProductsPanel.d.ts +13 -0
  14. package/dist/ProductsPanel.d.ts.map +1 -0
  15. package/dist/ProductsPanel.js +419 -0
  16. package/dist/ProductsPanel.js.map +1 -0
  17. package/dist/ShopifyAppView.d.ts +3 -0
  18. package/dist/ShopifyAppView.d.ts.map +1 -0
  19. package/dist/ShopifyAppView.helpers.d.ts +11 -0
  20. package/dist/ShopifyAppView.helpers.d.ts.map +1 -0
  21. package/dist/ShopifyAppView.helpers.js +59 -0
  22. package/dist/ShopifyAppView.helpers.js.map +1 -0
  23. package/dist/ShopifyAppView.interact.d.ts +2 -0
  24. package/dist/ShopifyAppView.interact.d.ts.map +1 -0
  25. package/dist/ShopifyAppView.interact.js +93 -0
  26. package/dist/ShopifyAppView.interact.js.map +1 -0
  27. package/dist/ShopifyAppView.js +667 -0
  28. package/dist/ShopifyAppView.js.map +1 -0
  29. package/dist/ShopifyView.d.ts +18 -0
  30. package/dist/ShopifyView.d.ts.map +1 -0
  31. package/dist/ShopifyView.js +143 -0
  32. package/dist/ShopifyView.js.map +1 -0
  33. package/dist/StoreOverviewCard.d.ts +13 -0
  34. package/dist/StoreOverviewCard.d.ts.map +1 -0
  35. package/dist/StoreOverviewCard.js +23 -0
  36. package/dist/StoreOverviewCard.js.map +1 -0
  37. package/dist/components/ShopifySpatialView.d.ts +57 -0
  38. package/dist/components/ShopifySpatialView.d.ts.map +1 -0
  39. package/dist/components/ShopifySpatialView.js +419 -0
  40. package/dist/components/ShopifySpatialView.js.map +1 -0
  41. package/dist/index.d.ts +14 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +20 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/plugin.d.ts +14 -0
  46. package/dist/plugin.d.ts.map +1 -0
  47. package/dist/plugin.js +94 -0
  48. package/dist/plugin.js.map +1 -0
  49. package/dist/register-routes.d.ts +2 -0
  50. package/dist/register-routes.d.ts.map +1 -0
  51. package/dist/register-routes.js +6 -0
  52. package/dist/register-routes.js.map +1 -0
  53. package/dist/register-terminal-view.d.ts +15 -0
  54. package/dist/register-terminal-view.d.ts.map +1 -0
  55. package/dist/register-terminal-view.js +37 -0
  56. package/dist/register-terminal-view.js.map +1 -0
  57. package/dist/register.d.ts +2 -0
  58. package/dist/register.d.ts.map +1 -0
  59. package/dist/register.js +17 -0
  60. package/dist/register.js.map +1 -0
  61. package/dist/routes.d.ts +18 -0
  62. package/dist/routes.d.ts.map +1 -0
  63. package/dist/routes.js +518 -0
  64. package/dist/routes.js.map +1 -0
  65. package/dist/shopify-app.d.ts +11 -0
  66. package/dist/shopify-app.d.ts.map +1 -0
  67. package/dist/shopify-app.js +16 -0
  68. package/dist/shopify-app.js.map +1 -0
  69. package/dist/shopify-view-bundle.d.ts +3 -0
  70. package/dist/shopify-view-bundle.d.ts.map +1 -0
  71. package/dist/shopify-view-bundle.js +7 -0
  72. package/dist/shopify-view-bundle.js.map +1 -0
  73. package/dist/useShopifyDashboard.d.ts +118 -0
  74. package/dist/useShopifyDashboard.d.ts.map +1 -0
  75. package/dist/useShopifyDashboard.js +212 -0
  76. package/dist/useShopifyDashboard.js.map +1 -0
  77. package/dist/views/bundle.js +948 -0
  78. package/dist/views/bundle.js.map +1 -0
  79. package/package.json +5 -5
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ShopifyAppView.interact.ts"],"sourcesContent":["// View-bundle `interact` capability handler, split out of ShopifyAppView.tsx\n// so that file exports only React components and stays Fast-Refresh-compatible\n// (Vite would full-reload a component file that also exports a plain function).\n// The view bundle re-exports `interact` via ./shopify-view-bundle.ts.\nimport {\n fetchShopifyTuiJson,\n loadShopifyTuiState,\n postShopifyTuiJson,\n} from \"./ShopifyAppView.helpers\";\nimport type {\n ShopifyCustomersResponse,\n ShopifyInventoryResponse,\n ShopifyOrdersResponse,\n ShopifyProductsResponse,\n} from \"./useShopifyDashboard.js\";\n\nexport async function interact(\n capability: string,\n params?: Record<string, unknown>,\n): Promise<unknown> {\n if (capability === \"terminal-shopify-state\") {\n return { viewType: \"tui\", ...(await loadShopifyTuiState()) };\n }\n\n if (capability === \"terminal-shopify-products\") {\n const query = typeof params?.query === \"string\" ? params.query.trim() : \"\";\n const page = typeof params?.page === \"number\" ? params.page : 1;\n const limit = typeof params?.limit === \"number\" ? params.limit : 20;\n return {\n viewType: \"tui\",\n products: await fetchShopifyTuiJson<ShopifyProductsResponse>(\n `/api/shopify/products?${new URLSearchParams({\n page: String(page),\n limit: String(limit),\n q: query,\n })}`,\n ),\n };\n }\n\n if (capability === \"terminal-shopify-orders\") {\n const status =\n typeof params?.status === \"string\" ? params.status.trim() : \"any\";\n const limit = typeof params?.limit === \"number\" ? params.limit : 20;\n return {\n viewType: \"tui\",\n orders: await fetchShopifyTuiJson<ShopifyOrdersResponse>(\n `/api/shopify/orders?${new URLSearchParams({\n status,\n limit: String(limit),\n })}`,\n ),\n };\n }\n\n if (capability === \"terminal-shopify-inventory\") {\n return {\n viewType: \"tui\",\n inventory: await fetchShopifyTuiJson<ShopifyInventoryResponse>(\n \"/api/shopify/inventory\",\n ),\n };\n }\n\n if (capability === \"terminal-shopify-customers\") {\n const query = typeof params?.query === \"string\" ? params.query.trim() : \"\";\n const limit = typeof params?.limit === \"number\" ? params.limit : 20;\n return {\n viewType: \"tui\",\n customers: await fetchShopifyTuiJson<ShopifyCustomersResponse>(\n `/api/shopify/customers?${new URLSearchParams({\n q: query,\n limit: String(limit),\n })}`,\n ),\n };\n }\n\n if (capability === \"terminal-shopify-create-product\") {\n const title = typeof params?.title === \"string\" ? params.title.trim() : \"\";\n if (!title) throw new Error(\"title is required\");\n return {\n viewType: \"tui\",\n product: await postShopifyTuiJson(\"/api/shopify/products\", {\n title,\n vendor: typeof params?.vendor === \"string\" ? params.vendor : undefined,\n productType:\n typeof params?.productType === \"string\"\n ? params.productType\n : undefined,\n price:\n typeof params?.price === \"string\" || typeof params?.price === \"number\"\n ? params.price\n : undefined,\n }),\n };\n }\n\n if (capability === \"terminal-shopify-adjust-inventory\") {\n const itemId =\n typeof params?.itemId === \"string\" ? params.itemId.trim() : \"\";\n const delta = typeof params?.delta === \"number\" ? params.delta : null;\n if (!itemId) throw new Error(\"itemId is required\");\n if (delta === null) throw new Error(\"delta is required\");\n return {\n viewType: \"tui\",\n inventory: await postShopifyTuiJson(\n `/api/shopify/inventory/${encodeURIComponent(itemId)}/adjust`,\n {\n delta,\n locationId:\n typeof params?.locationId === \"string\"\n ? params.locationId\n : undefined,\n },\n ),\n };\n }\n\n throw new Error(`Unsupported capability \"${capability}\"`);\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,667 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import {
3
+ Badge,
4
+ Button,
5
+ Skeleton,
6
+ Tabs,
7
+ TabsContent,
8
+ TabsList,
9
+ TabsTrigger
10
+ } from "@elizaos/ui";
11
+ import { useAgentElement } from "@elizaos/ui/agent-surface";
12
+ import {
13
+ AlertTriangle,
14
+ BarChart3,
15
+ ChevronLeft,
16
+ Globe2,
17
+ KeyRound,
18
+ Package,
19
+ ShoppingBag,
20
+ ShoppingCart,
21
+ Store,
22
+ Users,
23
+ Wifi,
24
+ WifiOff
25
+ } from "lucide-react";
26
+ import { useState } from "react";
27
+ import { CustomersPanel } from "./CustomersPanel.js";
28
+ import { InventoryLevelsPanel } from "./InventoryLevelsPanel.js";
29
+ import { OrdersPanel } from "./OrdersPanel.js";
30
+ import { ProductsPanel } from "./ProductsPanel.js";
31
+ import { StoreOverviewCard } from "./StoreOverviewCard.js";
32
+ import { useShopifyDashboard } from "./useShopifyDashboard.js";
33
+ const SH_ACCENT = "var(--accent, #ff8a24)";
34
+ const SH_TXT = "var(--txt, #111)";
35
+ const SH_MUTED = "var(--muted, rgba(0,0,0,0.58))";
36
+ function SetupField({
37
+ icon: Icon,
38
+ label,
39
+ description,
40
+ envHint
41
+ }) {
42
+ return /* @__PURE__ */ jsxs(
43
+ "div",
44
+ {
45
+ style: {
46
+ display: "flex",
47
+ gap: 12,
48
+ padding: "10px 2px"
49
+ },
50
+ children: [
51
+ /* @__PURE__ */ jsx(
52
+ "span",
53
+ {
54
+ style: {
55
+ width: 34,
56
+ height: 34,
57
+ flexShrink: 0,
58
+ display: "flex",
59
+ alignItems: "center",
60
+ justifyContent: "center",
61
+ color: SH_ACCENT
62
+ },
63
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
64
+ }
65
+ ),
66
+ /* @__PURE__ */ jsxs(
67
+ "span",
68
+ {
69
+ style: {
70
+ minWidth: 0,
71
+ display: "flex",
72
+ flexDirection: "column",
73
+ gap: 2
74
+ },
75
+ children: [
76
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 13.5, fontWeight: 600, color: SH_TXT }, children: label }),
77
+ /* @__PURE__ */ jsx(
78
+ "span",
79
+ {
80
+ className: "sr-only",
81
+ style: { fontSize: 12, color: SH_MUTED, lineHeight: 1.4 },
82
+ children: description
83
+ }
84
+ ),
85
+ /* @__PURE__ */ jsx(
86
+ "code",
87
+ {
88
+ style: {
89
+ marginTop: 3,
90
+ fontSize: 10.5,
91
+ color: SH_MUTED,
92
+ opacity: 0.75,
93
+ fontFamily: "ui-monospace, monospace"
94
+ },
95
+ children: envHint
96
+ }
97
+ )
98
+ ]
99
+ }
100
+ )
101
+ ]
102
+ }
103
+ );
104
+ }
105
+ function ShopifySetupCard() {
106
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-md", children: [
107
+ /* @__PURE__ */ jsxs(
108
+ "div",
109
+ {
110
+ style: {
111
+ display: "flex",
112
+ flexDirection: "column",
113
+ alignItems: "center",
114
+ textAlign: "center",
115
+ gap: 6,
116
+ marginBottom: 18
117
+ },
118
+ children: [
119
+ /* @__PURE__ */ jsx(
120
+ "div",
121
+ {
122
+ style: {
123
+ width: 84,
124
+ height: 84,
125
+ display: "flex",
126
+ alignItems: "center",
127
+ justifyContent: "center"
128
+ },
129
+ children: /* @__PURE__ */ jsx(ShoppingBag, { style: { width: 38, height: 38, color: SH_ACCENT } })
130
+ }
131
+ ),
132
+ /* @__PURE__ */ jsx(
133
+ "h2",
134
+ {
135
+ style: {
136
+ margin: "12px 0 0",
137
+ fontSize: 20,
138
+ fontWeight: 700,
139
+ color: SH_TXT
140
+ },
141
+ children: "Connect your store"
142
+ }
143
+ ),
144
+ /* @__PURE__ */ jsx(
145
+ "p",
146
+ {
147
+ className: "sr-only",
148
+ style: {
149
+ margin: 0,
150
+ maxWidth: 320,
151
+ fontSize: 13.5,
152
+ color: SH_MUTED,
153
+ lineHeight: 1.5
154
+ },
155
+ children: "Link a Shopify store to manage products, orders, and inventory right here."
156
+ }
157
+ )
158
+ ]
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsxs(
162
+ "div",
163
+ {
164
+ style: {
165
+ padding: 4,
166
+ display: "flex",
167
+ flexDirection: "column",
168
+ gap: 10
169
+ },
170
+ children: [
171
+ /* @__PURE__ */ jsx(
172
+ SetupField,
173
+ {
174
+ icon: Globe2,
175
+ label: "Store domain",
176
+ description: "Your shop address, e.g. mystore.myshopify.com",
177
+ envHint: "SHOPIFY_STORE_DOMAIN"
178
+ }
179
+ ),
180
+ /* @__PURE__ */ jsx(
181
+ SetupField,
182
+ {
183
+ icon: KeyRound,
184
+ label: "Access token",
185
+ description: "Admin API token with product, order & inventory scopes",
186
+ envHint: "SHOPIFY_ACCESS_TOKEN"
187
+ }
188
+ ),
189
+ /* @__PURE__ */ jsx(
190
+ "div",
191
+ {
192
+ style: {
193
+ display: "flex",
194
+ flexWrap: "wrap",
195
+ gap: 6,
196
+ padding: "2px 2px 6px"
197
+ },
198
+ children: [
199
+ { label: "Products", icon: Package },
200
+ { label: "Orders", icon: ShoppingCart },
201
+ { label: "Stock", icon: BarChart3 }
202
+ ].map(({ label, icon: Icon }) => /* @__PURE__ */ jsxs(
203
+ "span",
204
+ {
205
+ style: {
206
+ display: "inline-flex",
207
+ alignItems: "center",
208
+ gap: 6,
209
+ padding: "3px 0",
210
+ fontSize: 12,
211
+ fontWeight: 600,
212
+ color: SH_TXT
213
+ },
214
+ children: [
215
+ /* @__PURE__ */ jsx(Icon, { style: { width: 13, height: 13, color: SH_MUTED } }),
216
+ label
217
+ ]
218
+ },
219
+ label
220
+ ))
221
+ }
222
+ ),
223
+ /* @__PURE__ */ jsxs(
224
+ "a",
225
+ {
226
+ href: "/settings",
227
+ style: {
228
+ display: "inline-flex",
229
+ alignItems: "center",
230
+ justifyContent: "center",
231
+ gap: 8,
232
+ height: 42,
233
+ background: SH_ACCENT,
234
+ color: "var(--accent-foreground, #fff)",
235
+ fontSize: 14,
236
+ fontWeight: 600,
237
+ textDecoration: "none"
238
+ },
239
+ children: [
240
+ /* @__PURE__ */ jsx(Store, { className: "h-4 w-4" }),
241
+ "Settings"
242
+ ]
243
+ }
244
+ )
245
+ ]
246
+ }
247
+ )
248
+ ] });
249
+ }
250
+ function ConnectionStatus({
251
+ connected,
252
+ loading,
253
+ domain
254
+ }) {
255
+ if (loading) {
256
+ return /* @__PURE__ */ jsx(Skeleton, { className: "h-6 w-24" });
257
+ }
258
+ if (connected && domain) {
259
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-1 py-1", children: [
260
+ /* @__PURE__ */ jsx(Wifi, { className: "h-3.5 w-3.5 text-ok" }),
261
+ /* @__PURE__ */ jsx("span", { className: "max-w-[10rem] truncate text-xs font-medium text-ok", children: domain })
262
+ ] });
263
+ }
264
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-1 py-1", children: [
265
+ /* @__PURE__ */ jsx(WifiOff, { className: "h-3.5 w-3.5 text-danger" }),
266
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-danger", children: "Offline" })
267
+ ] });
268
+ }
269
+ const DASHBOARD_TABS = [
270
+ { value: "overview", label: "Overview", icon: BarChart3 },
271
+ { value: "products", label: "Products", icon: Package },
272
+ { value: "orders", label: "Orders", icon: ShoppingCart },
273
+ { value: "inventory", label: "Inventory", icon: BarChart3 },
274
+ { value: "customers", label: "Customers", icon: Users }
275
+ ];
276
+ function ShopifyDashboardTabTrigger({
277
+ value,
278
+ label,
279
+ icon: Icon,
280
+ active
281
+ }) {
282
+ const { ref, agentProps } = useAgentElement({
283
+ id: `tab-${value}`,
284
+ role: "tab",
285
+ label,
286
+ group: "dashboard-tabs",
287
+ status: active ? "active" : "inactive",
288
+ description: `Show the ${label} tab`
289
+ });
290
+ return /* @__PURE__ */ jsxs(
291
+ TabsTrigger,
292
+ {
293
+ ref,
294
+ value,
295
+ className: "h-9 w-9 gap-0 px-0 sm:w-auto sm:gap-1.5 sm:px-3",
296
+ "aria-current": active ? "true" : void 0,
297
+ title: label,
298
+ ...agentProps,
299
+ children: [
300
+ /* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
301
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: label })
302
+ ]
303
+ }
304
+ );
305
+ }
306
+ function OverviewTile({
307
+ icon: Icon,
308
+ label,
309
+ value,
310
+ accent,
311
+ onClick
312
+ }) {
313
+ return /* @__PURE__ */ jsxs(
314
+ "button",
315
+ {
316
+ type: "button",
317
+ onClick,
318
+ className: "group flex min-h-20 items-start gap-3 px-2 py-2 text-left transition-colors hover:bg-bg-muted/20",
319
+ title: label,
320
+ children: [
321
+ /* @__PURE__ */ jsx(
322
+ "span",
323
+ {
324
+ className: `flex h-9 w-9 shrink-0 items-center justify-center ${accent}`,
325
+ children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" })
326
+ }
327
+ ),
328
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1", children: [
329
+ /* @__PURE__ */ jsx("span", { className: "block text-2xl font-semibold leading-none text-txt", children: value }),
330
+ /* @__PURE__ */ jsx("span", { className: "mt-2 block truncate text-xs font-medium text-muted", children: label })
331
+ ] })
332
+ ]
333
+ }
334
+ );
335
+ }
336
+ function ShopifyAppView({ exitToApps }) {
337
+ const [activeTab, setActiveTab] = useState("overview");
338
+ const {
339
+ status,
340
+ statusLoading,
341
+ statusError,
342
+ products,
343
+ productsTotal,
344
+ productsPage,
345
+ productsLoading,
346
+ productsError,
347
+ productSearch,
348
+ setProductsPage,
349
+ orders,
350
+ ordersTotal,
351
+ ordersLoading,
352
+ ordersError,
353
+ orderStatusFilter,
354
+ setOrderStatusFilter,
355
+ inventoryItems,
356
+ inventoryLocations,
357
+ inventoryLoading,
358
+ inventoryError,
359
+ customers,
360
+ customersTotal,
361
+ customersLoading,
362
+ customersError,
363
+ customerSearch,
364
+ counts
365
+ } = useShopifyDashboard();
366
+ const connected = status?.connected ?? false;
367
+ const shop = status?.shop ?? null;
368
+ const lowInventoryItems = inventoryItems.filter(
369
+ (item) => item.available <= 5
370
+ );
371
+ const urgentInventoryCount = lowInventoryItems.filter(
372
+ (item) => item.available === 0
373
+ ).length;
374
+ const backButton = useAgentElement({
375
+ id: "action-back",
376
+ role: "button",
377
+ label: "Back to apps",
378
+ group: "header",
379
+ description: "Exit the Shopify dashboard and return to the apps grid"
380
+ });
381
+ const viewAllOrdersButton = useAgentElement({
382
+ id: "overview-view-all-orders",
383
+ role: "button",
384
+ label: "View all orders",
385
+ group: "overview",
386
+ description: "Jump to the orders tab from the overview summary",
387
+ onActivate: () => setActiveTab("orders")
388
+ });
389
+ const viewAllInventoryButton = useAgentElement({
390
+ id: "overview-view-inventory",
391
+ role: "button",
392
+ label: "View inventory",
393
+ group: "overview",
394
+ description: "Jump to the inventory tab from the overview summary",
395
+ onActivate: () => setActiveTab("inventory")
396
+ });
397
+ return /* @__PURE__ */ jsxs(
398
+ "div",
399
+ {
400
+ "data-testid": "shopify-shell",
401
+ className: "fixed inset-0 z-50 flex flex-col overflow-hidden bg-bg pb-[var(--safe-area-bottom,0px)] pl-[var(--safe-area-left,0px)] pr-[var(--safe-area-right,0px)] pt-[var(--safe-area-top,0px)] supports-[height:100dvh]:h-[100dvh]",
402
+ children: [
403
+ /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-3 px-3 py-2", children: [
404
+ /* @__PURE__ */ jsx(
405
+ Button,
406
+ {
407
+ ref: backButton.ref,
408
+ type: "button",
409
+ variant: "ghost",
410
+ size: "icon",
411
+ onClick: exitToApps,
412
+ className: "h-8 w-8 shrink-0",
413
+ "aria-label": "Back to apps",
414
+ ...backButton.agentProps,
415
+ children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-4 w-4" })
416
+ }
417
+ ),
418
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
419
+ /* @__PURE__ */ jsx(
420
+ "span",
421
+ {
422
+ className: "flex h-8 w-8 shrink-0 items-center justify-center",
423
+ style: {
424
+ color: SH_ACCENT
425
+ },
426
+ children: /* @__PURE__ */ jsx(Store, { className: "h-4 w-4" })
427
+ }
428
+ ),
429
+ /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-txt", children: shop?.name ?? "Shopify" })
430
+ ] }),
431
+ /* @__PURE__ */ jsx("div", { className: "flex-1" }),
432
+ /* @__PURE__ */ jsx(
433
+ ConnectionStatus,
434
+ {
435
+ connected,
436
+ loading: statusLoading,
437
+ domain: shop?.domain
438
+ }
439
+ )
440
+ ] }),
441
+ /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto pb-[calc(7rem+var(--safe-area-bottom,0px))]", children: [
442
+ statusError ? /* @__PURE__ */ jsx("div", { className: "m-3 px-1 py-2 text-sm text-danger", children: statusError }) : null,
443
+ !statusLoading && !connected ? /* @__PURE__ */ jsx("div", { className: "flex min-h-full items-center justify-center px-4 py-10", children: /* @__PURE__ */ jsx(ShopifySetupCard, {}) }) : statusLoading && !connected ? /* @__PURE__ */ jsx("div", { className: "flex min-h-full items-center justify-center", children: /* @__PURE__ */ jsx(Skeleton, { className: "mx-4 h-80 w-full max-w-lg" }) }) : /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-3xl px-4 py-4", children: /* @__PURE__ */ jsxs(
444
+ Tabs,
445
+ {
446
+ value: activeTab,
447
+ onValueChange: (v) => setActiveTab(v),
448
+ children: [
449
+ /* @__PURE__ */ jsx(TabsList, { className: "sticky top-3 z-10 mb-3 h-auto w-full justify-between gap-1 bg-transparent p-0 sm:w-auto sm:justify-start", children: DASHBOARD_TABS.map((tab) => /* @__PURE__ */ jsx(
450
+ ShopifyDashboardTabTrigger,
451
+ {
452
+ value: tab.value,
453
+ label: tab.label,
454
+ icon: tab.icon,
455
+ active: activeTab === tab.value
456
+ },
457
+ tab.value
458
+ )) }),
459
+ /* @__PURE__ */ jsx(TabsContent, { value: "overview", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
460
+ shop ? /* @__PURE__ */ jsx(StoreOverviewCard, { shop }) : null,
461
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-2 sm:grid-cols-2", children: [
462
+ /* @__PURE__ */ jsx(
463
+ OverviewTile,
464
+ {
465
+ icon: Package,
466
+ label: "Products",
467
+ value: counts.productCount.toLocaleString(),
468
+ accent: "text-muted-strong",
469
+ onClick: () => setActiveTab("products")
470
+ }
471
+ ),
472
+ /* @__PURE__ */ jsx(
473
+ OverviewTile,
474
+ {
475
+ icon: ShoppingCart,
476
+ label: "Orders",
477
+ value: counts.orderCount.toLocaleString(),
478
+ accent: "text-muted-strong",
479
+ onClick: () => setActiveTab("orders")
480
+ }
481
+ ),
482
+ /* @__PURE__ */ jsx(
483
+ OverviewTile,
484
+ {
485
+ icon: AlertTriangle,
486
+ label: "Low stock",
487
+ value: lowInventoryItems.length.toLocaleString(),
488
+ accent: urgentInventoryCount > 0 ? "text-danger" : "text-warn",
489
+ onClick: () => setActiveTab("inventory")
490
+ }
491
+ ),
492
+ /* @__PURE__ */ jsx(
493
+ OverviewTile,
494
+ {
495
+ icon: Users,
496
+ label: "Customers",
497
+ value: counts.customerCount.toLocaleString(),
498
+ accent: "text-muted-strong",
499
+ onClick: () => setActiveTab("customers")
500
+ }
501
+ )
502
+ ] }),
503
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
504
+ /* @__PURE__ */ jsxs("div", { className: "px-2 py-2", children: [
505
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
506
+ /* @__PURE__ */ jsx(
507
+ "span",
508
+ {
509
+ className: "inline-flex h-8 w-8 items-center justify-center text-muted-strong",
510
+ title: "Recent orders",
511
+ children: /* @__PURE__ */ jsx(ShoppingCart, { className: "h-4 w-4", "aria-hidden": true })
512
+ }
513
+ ),
514
+ ordersTotal > 3 ? /* @__PURE__ */ jsxs(
515
+ Button,
516
+ {
517
+ ref: viewAllOrdersButton.ref,
518
+ type: "button",
519
+ variant: "ghost",
520
+ size: "sm",
521
+ className: "h-7 px-2 text-xs-tight",
522
+ onClick: () => setActiveTab("orders"),
523
+ title: `View all ${ordersTotal.toLocaleString()} orders`,
524
+ ...viewAllOrdersButton.agentProps,
525
+ children: [
526
+ "+",
527
+ (ordersTotal - 3).toLocaleString()
528
+ ]
529
+ }
530
+ ) : null
531
+ ] }),
532
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1.5", children: [
533
+ ordersLoading && orders.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
534
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }),
535
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }),
536
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" })
537
+ ] }) : orders.slice(0, 3).map((order) => /* @__PURE__ */ jsxs(
538
+ "div",
539
+ {
540
+ className: "grid grid-cols-[5rem_minmax(0,1fr)_auto] items-center gap-2 px-2 py-1.5",
541
+ children: [
542
+ /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-txt", children: order.name }),
543
+ /* @__PURE__ */ jsx("span", { className: "truncate text-xs-tight text-muted", children: order.email }),
544
+ /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-xs font-semibold text-txt", children: [
545
+ order.totalPrice,
546
+ " ",
547
+ order.currencyCode
548
+ ] })
549
+ ]
550
+ },
551
+ order.id
552
+ )),
553
+ orders.length === 0 && !ordersLoading ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted", children: "None" }) : null
554
+ ] })
555
+ ] }),
556
+ /* @__PURE__ */ jsxs("div", { className: "px-2 py-2", children: [
557
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
558
+ /* @__PURE__ */ jsx(
559
+ "span",
560
+ {
561
+ className: "inline-flex h-8 w-8 items-center justify-center text-muted-strong",
562
+ title: "Low inventory",
563
+ children: /* @__PURE__ */ jsx(Package, { className: "h-4 w-4", "aria-hidden": true })
564
+ }
565
+ ),
566
+ lowInventoryItems.length > 3 ? /* @__PURE__ */ jsxs(
567
+ Button,
568
+ {
569
+ ref: viewAllInventoryButton.ref,
570
+ type: "button",
571
+ variant: "ghost",
572
+ size: "sm",
573
+ className: "h-7 px-2 text-xs-tight",
574
+ onClick: () => setActiveTab("inventory"),
575
+ title: "View inventory",
576
+ ...viewAllInventoryButton.agentProps,
577
+ children: [
578
+ "+",
579
+ (lowInventoryItems.length - 3).toLocaleString()
580
+ ]
581
+ }
582
+ ) : null
583
+ ] }),
584
+ /* @__PURE__ */ jsxs("div", { className: "mt-2 space-y-1.5", children: [
585
+ inventoryLoading && inventoryItems.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
586
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }),
587
+ /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" })
588
+ ] }) : lowInventoryItems.slice(0, 3).map((item) => /* @__PURE__ */ jsxs(
589
+ "div",
590
+ {
591
+ className: "flex items-center justify-between gap-2 px-2 py-1.5",
592
+ children: [
593
+ /* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 truncate text-xs font-semibold text-txt", children: [
594
+ item.productTitle,
595
+ item.variantTitle ? ` \u2014 ${item.variantTitle}` : ""
596
+ ] }),
597
+ /* @__PURE__ */ jsx(
598
+ Badge,
599
+ {
600
+ variant: item.available === 0 ? "destructive" : "secondary",
601
+ className: "shrink-0 text-2xs",
602
+ children: item.available
603
+ }
604
+ )
605
+ ]
606
+ },
607
+ `${item.id}:${item.locationName}`
608
+ )),
609
+ lowInventoryItems.length === 0 && !inventoryLoading ? /* @__PURE__ */ jsx("p", { className: "text-xs text-muted", children: "Stock levels look good." }) : null
610
+ ] })
611
+ ] })
612
+ ] })
613
+ ] }) }),
614
+ /* @__PURE__ */ jsx(TabsContent, { value: "products", children: /* @__PURE__ */ jsx(
615
+ ProductsPanel,
616
+ {
617
+ products,
618
+ total: productsTotal,
619
+ page: productsPage,
620
+ loading: productsLoading,
621
+ error: productsError,
622
+ search: productSearch,
623
+ onPageChange: setProductsPage
624
+ }
625
+ ) }),
626
+ /* @__PURE__ */ jsx(TabsContent, { value: "orders", children: /* @__PURE__ */ jsx(
627
+ OrdersPanel,
628
+ {
629
+ orders,
630
+ total: ordersTotal,
631
+ loading: ordersLoading,
632
+ error: ordersError,
633
+ statusFilter: orderStatusFilter,
634
+ onStatusFilterChange: setOrderStatusFilter
635
+ }
636
+ ) }),
637
+ /* @__PURE__ */ jsx(TabsContent, { value: "inventory", children: /* @__PURE__ */ jsx(
638
+ InventoryLevelsPanel,
639
+ {
640
+ items: inventoryItems,
641
+ locations: inventoryLocations,
642
+ loading: inventoryLoading,
643
+ error: inventoryError
644
+ }
645
+ ) }),
646
+ /* @__PURE__ */ jsx(TabsContent, { value: "customers", children: /* @__PURE__ */ jsx(
647
+ CustomersPanel,
648
+ {
649
+ customers,
650
+ total: customersTotal,
651
+ loading: customersLoading,
652
+ error: customersError,
653
+ search: customerSearch
654
+ }
655
+ ) })
656
+ ]
657
+ }
658
+ ) })
659
+ ] })
660
+ ]
661
+ }
662
+ );
663
+ }
664
+ export {
665
+ ShopifyAppView
666
+ };
667
+ //# sourceMappingURL=ShopifyAppView.js.map