@burdenoff/microfe-store 2026.530.1 → 2026.601.1

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.
@@ -7,8 +7,8 @@ import { FeatureGate as s } from "@burdenoff/fe-libs/shared/feature-flags";
7
7
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
8
  import { Navigate as u, Route as d, Routes as f } from "react-router-dom";
9
9
  //#region src/StoreRoutes.tsx
10
- var p = o(() => import("./pages/MarketplaceHomePage.js").then((e) => ({ default: e.MarketplaceHomePage }))), m = o(() => import("./pages/InstalledAppsPage.js").then((e) => ({ default: e.InstalledAppsPage }))), h = o(() => import("./pages/ProductDetailPage.js").then((e) => ({ default: e.ProductDetailPage }))), g = o(() => import("./pages/CartPage.js").then((e) => ({ default: e.CartPage }))), _ = o(() => import("./pages/OrdersPage.js").then((e) => ({ default: e.OrdersPage }))), v = o(() => import("./pages/PublisherSubmitPage.js").then((e) => ({ default: e.PublisherSubmitPage }))), y = o(() => import("./pages/MyLicensesPage.js").then((e) => ({ default: e.MyLicensesPage }))), b = o(() => import("./pages/OrderConfirmationPage.js").then((e) => ({ default: e.OrderConfirmationPage }))), x = o(() => import("./pages/PublisherDashboardPage.js").then((e) => ({ default: e.PublisherDashboardPage }))), S = o(() => import("./pages/PublisherSubmissionsPage.js").then((e) => ({ default: e.PublisherSubmissionsPage }))), C = o(() => import("./pages/PublisherRevenuePage.js").then((e) => ({ default: e.PublisherRevenuePage }))), w = o(() => import("./pages/ProductCategoryPage.js").then((e) => ({ default: e.ProductCategoryPage }))), T = o(() => import("./pages/SearchResultsPage.js").then((e) => ({ default: e.SearchResultsPage }))), E = o(() => import("./pages/AppDetailPage.js").then((e) => ({ default: e.AppDetailPage }))), D = o(() => import("./pages/AppSettingsPage.js").then((e) => ({ default: e.AppSettingsPage }))), O = o(() => import("./pages/ProductReviewsPage.js").then((e) => ({ default: e.ProductReviewsPage }))), k = o(() => import("./pages/StoresPage.js").then((e) => ({ default: e.StoresPage })));
11
- function A({ title: e, featureFlag: t }) {
10
+ var p = o(() => import("./pages/MarketplaceHomePage.js").then((e) => ({ default: e.MarketplaceHomePage }))), m = o(() => import("./pages/InstalledAppsPage.js").then((e) => ({ default: e.InstalledAppsPage }))), h = o(() => import("./pages/ProductDetailPage.js").then((e) => ({ default: e.ProductDetailPage }))), g = o(() => import("./pages/CartPage.js").then((e) => ({ default: e.CartPage }))), _ = o(() => import("./pages/OrdersPage.js").then((e) => ({ default: e.OrdersPage }))), v = o(() => import("./pages/PublisherSubmitPage.js").then((e) => ({ default: e.PublisherSubmitPage }))), y = o(() => import("./pages/MyLicensesPage.js").then((e) => ({ default: e.MyLicensesPage }))), b = o(() => import("./pages/OrderConfirmationPage.js").then((e) => ({ default: e.OrderConfirmationPage }))), x = o(() => import("./pages/PublisherDashboardPage.js").then((e) => ({ default: e.PublisherDashboardPage }))), S = o(() => import("./pages/PublisherSubmissionsPage.js").then((e) => ({ default: e.PublisherSubmissionsPage }))), C = o(() => import("./pages/PublisherRevenuePage.js").then((e) => ({ default: e.PublisherRevenuePage }))), w = o(() => import("./pages/AppDetailPage.js").then((e) => ({ default: e.AppDetailPage }))), T = o(() => import("./pages/AppSettingsPage.js").then((e) => ({ default: e.AppSettingsPage }))), E = o(() => import("./pages/ProductReviewsPage.js").then((e) => ({ default: e.ProductReviewsPage })));
11
+ function D({ title: e, featureFlag: t }) {
12
12
  return /* @__PURE__ */ c("div", {
13
13
  className: "flex min-h-[400px] items-center justify-center p-6",
14
14
  children: /* @__PURE__ */ l("div", {
@@ -31,19 +31,19 @@ function A({ title: e, featureFlag: t }) {
31
31
  })
32
32
  });
33
33
  }
34
- function j({ title: e, featureFlag: t, allowed: n, isLoading: a, children: o }) {
34
+ function O({ title: e, featureFlag: t, allowed: n, isLoading: a, children: o }) {
35
35
  return a ? /* @__PURE__ */ c(i, {}) : /* @__PURE__ */ c(s, {
36
36
  flag: t,
37
37
  defaultValue: !0,
38
- fallback: /* @__PURE__ */ c(A, {
38
+ fallback: /* @__PURE__ */ c(D, {
39
39
  title: e,
40
40
  featureFlag: t
41
41
  }),
42
42
  children: n ? o : /* @__PURE__ */ c(r, {})
43
43
  });
44
44
  }
45
- var M = () => {
46
- let { basePath: r } = e(), { permissions: o, hasPermission: s, isLoading: A } = n();
45
+ var k = () => {
46
+ let { basePath: r } = e(), { permissions: o, hasPermission: s, isLoading: D } = n();
47
47
  return /* @__PURE__ */ l(f, { children: [
48
48
  /* @__PURE__ */ c(d, {
49
49
  index: !0,
@@ -54,50 +54,24 @@ var M = () => {
54
54
  }),
55
55
  /* @__PURE__ */ c(d, {
56
56
  path: "marketplace",
57
- element: /* @__PURE__ */ c(j, {
57
+ element: /* @__PURE__ */ c(O, {
58
58
  title: "Marketplace",
59
59
  featureFlag: "store.marketplace",
60
60
  allowed: o.canBrowse,
61
- isLoading: A,
61
+ isLoading: D,
62
62
  children: /* @__PURE__ */ c(a, {
63
63
  fallback: /* @__PURE__ */ c(i, {}),
64
64
  children: /* @__PURE__ */ c(p, {})
65
65
  })
66
66
  })
67
67
  }),
68
- /* @__PURE__ */ c(d, {
69
- path: "marketplace/category/:categorySlug",
70
- element: /* @__PURE__ */ c(j, {
71
- title: "Marketplace",
72
- featureFlag: "store.marketplace",
73
- allowed: o.canBrowse,
74
- isLoading: A,
75
- children: /* @__PURE__ */ c(a, {
76
- fallback: /* @__PURE__ */ c(i, {}),
77
- children: /* @__PURE__ */ c(w, {})
78
- })
79
- })
80
- }),
81
- /* @__PURE__ */ c(d, {
82
- path: "marketplace/search",
83
- element: /* @__PURE__ */ c(j, {
84
- title: "Marketplace",
85
- featureFlag: "store.marketplace",
86
- allowed: o.canBrowse,
87
- isLoading: A,
88
- children: /* @__PURE__ */ c(a, {
89
- fallback: /* @__PURE__ */ c(i, {}),
90
- children: /* @__PURE__ */ c(T, {})
91
- })
92
- })
93
- }),
94
68
  /* @__PURE__ */ c(d, {
95
69
  path: "marketplace/product/:productId",
96
- element: /* @__PURE__ */ c(j, {
70
+ element: /* @__PURE__ */ c(O, {
97
71
  title: "Marketplace",
98
72
  featureFlag: "store.marketplace",
99
73
  allowed: o.canBrowse,
100
- isLoading: A,
74
+ isLoading: D,
101
75
  children: /* @__PURE__ */ c(a, {
102
76
  fallback: /* @__PURE__ */ c(i, {}),
103
77
  children: /* @__PURE__ */ c(h, {})
@@ -106,11 +80,11 @@ var M = () => {
106
80
  }),
107
81
  /* @__PURE__ */ c(d, {
108
82
  path: "cart",
109
- element: /* @__PURE__ */ c(j, {
83
+ element: /* @__PURE__ */ c(O, {
110
84
  title: "Cart",
111
85
  featureFlag: "store.cart",
112
86
  allowed: o.canPurchase,
113
- isLoading: A,
87
+ isLoading: D,
114
88
  children: /* @__PURE__ */ c(a, {
115
89
  fallback: /* @__PURE__ */ c(i, {}),
116
90
  children: /* @__PURE__ */ c(g, {})
@@ -119,11 +93,11 @@ var M = () => {
119
93
  }),
120
94
  /* @__PURE__ */ c(d, {
121
95
  path: "orders/:orderId/confirmation",
122
- element: /* @__PURE__ */ c(j, {
96
+ element: /* @__PURE__ */ c(O, {
123
97
  title: "Order confirmation",
124
98
  featureFlag: "store.orders",
125
99
  allowed: o.canPurchase,
126
- isLoading: A,
100
+ isLoading: D,
127
101
  children: /* @__PURE__ */ c(a, {
128
102
  fallback: /* @__PURE__ */ c(i, {}),
129
103
  children: /* @__PURE__ */ c(b, {})
@@ -132,11 +106,11 @@ var M = () => {
132
106
  }),
133
107
  /* @__PURE__ */ c(d, {
134
108
  path: "orders",
135
- element: /* @__PURE__ */ c(j, {
109
+ element: /* @__PURE__ */ c(O, {
136
110
  title: "Orders",
137
111
  featureFlag: "store.orders",
138
112
  allowed: o.canPurchase,
139
- isLoading: A,
113
+ isLoading: D,
140
114
  children: /* @__PURE__ */ c(a, {
141
115
  fallback: /* @__PURE__ */ c(i, {}),
142
116
  children: /* @__PURE__ */ c(_, {})
@@ -145,11 +119,11 @@ var M = () => {
145
119
  }),
146
120
  /* @__PURE__ */ c(d, {
147
121
  path: "installed",
148
- element: /* @__PURE__ */ c(j, {
122
+ element: /* @__PURE__ */ c(O, {
149
123
  title: "Installed apps",
150
124
  featureFlag: "store.installed",
151
125
  allowed: o.canInstall,
152
- isLoading: A,
126
+ isLoading: D,
153
127
  children: /* @__PURE__ */ c(a, {
154
128
  fallback: /* @__PURE__ */ c(i, {}),
155
129
  children: /* @__PURE__ */ c(m, {})
@@ -158,63 +132,50 @@ var M = () => {
158
132
  }),
159
133
  /* @__PURE__ */ c(d, {
160
134
  path: "installed/:installationId",
161
- element: /* @__PURE__ */ c(j, {
135
+ element: /* @__PURE__ */ c(O, {
162
136
  title: "Installed apps",
163
137
  featureFlag: "store.installed",
164
138
  allowed: o.canInstall,
165
- isLoading: A,
139
+ isLoading: D,
166
140
  children: /* @__PURE__ */ c(a, {
167
141
  fallback: /* @__PURE__ */ c(i, {}),
168
- children: /* @__PURE__ */ c(E, {})
142
+ children: /* @__PURE__ */ c(w, {})
169
143
  })
170
144
  })
171
145
  }),
172
146
  /* @__PURE__ */ c(d, {
173
147
  path: "installed/:installationId/settings",
174
- element: /* @__PURE__ */ c(j, {
148
+ element: /* @__PURE__ */ c(O, {
175
149
  title: "Installed apps",
176
150
  featureFlag: "store.installed",
177
151
  allowed: o.canInstall,
178
- isLoading: A,
152
+ isLoading: D,
179
153
  children: /* @__PURE__ */ c(a, {
180
154
  fallback: /* @__PURE__ */ c(i, {}),
181
- children: /* @__PURE__ */ c(D, {})
155
+ children: /* @__PURE__ */ c(T, {})
182
156
  })
183
157
  })
184
158
  }),
185
159
  /* @__PURE__ */ c(d, {
186
160
  path: "licenses",
187
- element: /* @__PURE__ */ c(j, {
161
+ element: /* @__PURE__ */ c(O, {
188
162
  title: "Licenses",
189
163
  featureFlag: "store.licenses",
190
164
  allowed: o.canManageLicenses,
191
- isLoading: A,
165
+ isLoading: D,
192
166
  children: /* @__PURE__ */ c(a, {
193
167
  fallback: /* @__PURE__ */ c(i, {}),
194
168
  children: /* @__PURE__ */ c(y, {})
195
169
  })
196
170
  })
197
171
  }),
198
- /* @__PURE__ */ c(d, {
199
- path: "stores",
200
- element: /* @__PURE__ */ c(j, {
201
- title: "Stores",
202
- featureFlag: "store.stores",
203
- allowed: o.canBrowse,
204
- isLoading: A,
205
- children: /* @__PURE__ */ c(a, {
206
- fallback: /* @__PURE__ */ c(i, {}),
207
- children: /* @__PURE__ */ c(k, {})
208
- })
209
- })
210
- }),
211
172
  /* @__PURE__ */ c(d, {
212
173
  path: "publisher",
213
- element: /* @__PURE__ */ c(j, {
174
+ element: /* @__PURE__ */ c(O, {
214
175
  title: "Publisher portal",
215
176
  featureFlag: "store.publisher-portal",
216
177
  allowed: o.canPublish,
217
- isLoading: A,
178
+ isLoading: D,
218
179
  children: /* @__PURE__ */ c(a, {
219
180
  fallback: /* @__PURE__ */ c(i, {}),
220
181
  children: /* @__PURE__ */ c(x, {})
@@ -223,11 +184,11 @@ var M = () => {
223
184
  }),
224
185
  /* @__PURE__ */ c(d, {
225
186
  path: "publisher/submit",
226
- element: /* @__PURE__ */ c(j, {
187
+ element: /* @__PURE__ */ c(O, {
227
188
  title: "Publisher portal",
228
189
  featureFlag: "store.publisher-portal",
229
190
  allowed: o.canPublish,
230
- isLoading: A,
191
+ isLoading: D,
231
192
  children: /* @__PURE__ */ c(a, {
232
193
  fallback: /* @__PURE__ */ c(i, {}),
233
194
  children: /* @__PURE__ */ c(v, {})
@@ -236,11 +197,11 @@ var M = () => {
236
197
  }),
237
198
  /* @__PURE__ */ c(d, {
238
199
  path: "publisher/submissions",
239
- element: /* @__PURE__ */ c(j, {
200
+ element: /* @__PURE__ */ c(O, {
240
201
  title: "Publisher portal",
241
202
  featureFlag: "store.publisher-portal",
242
203
  allowed: o.canPublish,
243
- isLoading: A,
204
+ isLoading: D,
244
205
  children: /* @__PURE__ */ c(a, {
245
206
  fallback: /* @__PURE__ */ c(i, {}),
246
207
  children: /* @__PURE__ */ c(S, {})
@@ -249,11 +210,11 @@ var M = () => {
249
210
  }),
250
211
  /* @__PURE__ */ c(d, {
251
212
  path: "publisher/revenue",
252
- element: /* @__PURE__ */ c(j, {
213
+ element: /* @__PURE__ */ c(O, {
253
214
  title: "Publisher revenue",
254
215
  featureFlag: "store.publisher-portal.revenue",
255
216
  allowed: s(t.EARNINGS_READ),
256
- isLoading: A,
217
+ isLoading: D,
257
218
  children: /* @__PURE__ */ c(a, {
258
219
  fallback: /* @__PURE__ */ c(i, {}),
259
220
  children: /* @__PURE__ */ c(C, {})
@@ -262,14 +223,14 @@ var M = () => {
262
223
  }),
263
224
  /* @__PURE__ */ c(d, {
264
225
  path: "publisher/product/:productId/reviews",
265
- element: /* @__PURE__ */ c(j, {
226
+ element: /* @__PURE__ */ c(O, {
266
227
  title: "Publisher portal",
267
228
  featureFlag: "store.publisher-portal",
268
229
  allowed: o.canPublish,
269
- isLoading: A,
230
+ isLoading: D,
270
231
  children: /* @__PURE__ */ c(a, {
271
232
  fallback: /* @__PURE__ */ c(i, {}),
272
- children: /* @__PURE__ */ c(O, {})
233
+ children: /* @__PURE__ */ c(E, {})
273
234
  })
274
235
  })
275
236
  }),
@@ -283,6 +244,6 @@ var M = () => {
283
244
  ] });
284
245
  };
285
246
  //#endregion
286
- export { M as StoreRoutes };
247
+ export { k as StoreRoutes };
287
248
 
288
249
  //# sourceMappingURL=StoreRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StoreRoutes.js","names":[],"sources":["../src/StoreRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, type FC, type ReactNode } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useStore } from './providers/StoreProvider';\nimport { useStorePermissions, STORE_PERMISSIONS } from './hooks/useStorePermissions';\nimport { AccessDenied, PageLoadingFallback } from './components/RouteGuards';\n\n// Lazy loaded pages\nconst MarketplaceHomePage = lazy(() =>\n import('./pages/MarketplaceHomePage').then((m) => ({ default: m.MarketplaceHomePage }))\n);\nconst InstalledAppsPage = lazy(() =>\n import('./pages/InstalledAppsPage').then((m) => ({ default: m.InstalledAppsPage }))\n);\nconst ProductDetailPage = lazy(() =>\n import('./pages/ProductDetailPage').then((m) => ({ default: m.ProductDetailPage }))\n);\nconst CartPage = lazy(() => import('./pages/CartPage').then((m) => ({ default: m.CartPage })));\nconst OrdersPage = lazy(() =>\n import('./pages/OrdersPage').then((m) => ({ default: m.OrdersPage }))\n);\nconst PublisherSubmitPage = lazy(() =>\n import('./pages/PublisherSubmitPage').then((m) => ({ default: m.PublisherSubmitPage }))\n);\nconst MyLicensesPage = lazy(() =>\n import('./pages/MyLicensesPage').then((m) => ({ default: m.MyLicensesPage }))\n);\nconst OrderConfirmationPage = lazy(() =>\n import('./pages/OrderConfirmationPage').then((m) => ({ default: m.OrderConfirmationPage }))\n);\nconst PublisherDashboardPage = lazy(() =>\n import('./pages/PublisherDashboardPage').then((m) => ({ default: m.PublisherDashboardPage }))\n);\nconst PublisherSubmissionsPage = lazy(() =>\n import('./pages/PublisherSubmissionsPage').then((m) => ({ default: m.PublisherSubmissionsPage }))\n);\nconst PublisherRevenuePage = lazy(() =>\n import('./pages/PublisherRevenuePage').then((m) => ({ default: m.PublisherRevenuePage }))\n);\nconst ProductCategoryPage = lazy(() =>\n import('./pages/ProductCategoryPage').then((m) => ({ default: m.ProductCategoryPage }))\n);\nconst SearchResultsPage = lazy(() =>\n import('./pages/SearchResultsPage').then((m) => ({ default: m.SearchResultsPage }))\n);\nconst AppDetailPage = lazy(() =>\n import('./pages/AppDetailPage').then((m) => ({ default: m.AppDetailPage }))\n);\nconst AppSettingsPage = lazy(() =>\n import('./pages/AppSettingsPage').then((m) => ({ default: m.AppSettingsPage }))\n);\nconst ProductReviewsPage = lazy(() =>\n import('./pages/ProductReviewsPage').then((m) => ({ default: m.ProductReviewsPage }))\n);\nconst StoresPage = lazy(() =>\n import('./pages/StoresPage').then((m) => ({ default: m.StoresPage }))\n);\n\nfunction FeatureDisabled({ title, featureFlag }: { title: string; featureFlag: string }) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center p-6\">\n <div className=\"max-w-md rounded-lg border border-border bg-card p-6 text-center shadow-sm\">\n <h2 className=\"text-lg font-semibold text-foreground\">{title} is not enabled</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Ask an administrator to enable the <span className=\"font-mono\">{featureFlag}</span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\ninterface StoreRouteGateProps {\n title: string;\n featureFlag: string;\n allowed: boolean;\n isLoading: boolean;\n children: ReactNode;\n}\n\nfunction StoreRouteGate({ title, featureFlag, allowed, isLoading, children }: StoreRouteGateProps) {\n if (isLoading) {\n return <PageLoadingFallback />;\n }\n return (\n <FeatureGate\n flag={featureFlag}\n defaultValue\n fallback={<FeatureDisabled title={title} featureFlag={featureFlag} />}\n >\n {allowed ? children : <AccessDenied />}\n </FeatureGate>\n );\n}\n\n/**\n * StoreRoutes component\n *\n * Internal routing for the Store microfrontend. Every route is gated by both\n * a live feature flag (via FeatureGate) and an RBAC permission check so that\n * features can be toggled per-org without a deployment.\n *\n * Flag namespace: store.*\n */\nexport const StoreRoutes: FC = () => {\n const { basePath } = useStore();\n const { permissions, hasPermission, isLoading } = useStorePermissions();\n\n return (\n <Routes>\n {/* Default redirect */}\n <Route index element={<Navigate to=\"marketplace\" replace />} />\n\n {/* Marketplace */}\n <Route\n path=\"marketplace\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <MarketplaceHomePage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"marketplace/category/:categorySlug\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <ProductCategoryPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"marketplace/search\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <SearchResultsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"marketplace/product/:productId\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <ProductDetailPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Cart */}\n <Route\n path=\"cart\"\n element={\n <StoreRouteGate\n title=\"Cart\"\n featureFlag=\"store.cart\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <CartPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Orders */}\n <Route\n path=\"orders/:orderId/confirmation\"\n element={\n <StoreRouteGate\n title=\"Order confirmation\"\n featureFlag=\"store.orders\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <OrderConfirmationPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"orders\"\n element={\n <StoreRouteGate\n title=\"Orders\"\n featureFlag=\"store.orders\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <OrdersPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Installed Apps */}\n <Route\n path=\"installed\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <InstalledAppsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"installed/:installationId\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <AppDetailPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"installed/:installationId/settings\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <AppSettingsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Licenses */}\n <Route\n path=\"licenses\"\n element={\n <StoreRouteGate\n title=\"Licenses\"\n featureFlag=\"store.licenses\"\n allowed={permissions.canManageLicenses}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <MyLicensesPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Multi-store browsing */}\n <Route\n path=\"stores\"\n element={\n <StoreRouteGate\n title=\"Stores\"\n featureFlag=\"store.stores\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <StoresPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Publisher Portal */}\n <Route\n path=\"publisher\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherDashboardPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/submit\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherSubmitPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/submissions\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherSubmissionsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/revenue\"\n element={\n <StoreRouteGate\n title=\"Publisher revenue\"\n featureFlag=\"store.publisher-portal.revenue\"\n allowed={hasPermission(STORE_PERMISSIONS.EARNINGS_READ)}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherRevenuePage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/product/:productId/reviews\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <ProductReviewsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Catch-all redirect */}\n <Route path=\"*\" element={<Navigate to={`${basePath}/marketplace`} replace />} />\n </Routes>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"StoreRoutes.js","names":[],"sources":["../src/StoreRoutes.tsx"],"sourcesContent":["import { lazy, Suspense, type FC, type ReactNode } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useStore } from './providers/StoreProvider';\nimport { useStorePermissions, STORE_PERMISSIONS } from './hooks/useStorePermissions';\nimport { AccessDenied, PageLoadingFallback } from './components/RouteGuards';\n\n// Lazy loaded pages\nconst MarketplaceHomePage = lazy(() =>\n import('./pages/MarketplaceHomePage').then((m) => ({ default: m.MarketplaceHomePage }))\n);\nconst InstalledAppsPage = lazy(() =>\n import('./pages/InstalledAppsPage').then((m) => ({ default: m.InstalledAppsPage }))\n);\nconst ProductDetailPage = lazy(() =>\n import('./pages/ProductDetailPage').then((m) => ({ default: m.ProductDetailPage }))\n);\nconst CartPage = lazy(() => import('./pages/CartPage').then((m) => ({ default: m.CartPage })));\nconst OrdersPage = lazy(() =>\n import('./pages/OrdersPage').then((m) => ({ default: m.OrdersPage }))\n);\nconst PublisherSubmitPage = lazy(() =>\n import('./pages/PublisherSubmitPage').then((m) => ({ default: m.PublisherSubmitPage }))\n);\nconst MyLicensesPage = lazy(() =>\n import('./pages/MyLicensesPage').then((m) => ({ default: m.MyLicensesPage }))\n);\nconst OrderConfirmationPage = lazy(() =>\n import('./pages/OrderConfirmationPage').then((m) => ({ default: m.OrderConfirmationPage }))\n);\nconst PublisherDashboardPage = lazy(() =>\n import('./pages/PublisherDashboardPage').then((m) => ({ default: m.PublisherDashboardPage }))\n);\nconst PublisherSubmissionsPage = lazy(() =>\n import('./pages/PublisherSubmissionsPage').then((m) => ({ default: m.PublisherSubmissionsPage }))\n);\nconst PublisherRevenuePage = lazy(() =>\n import('./pages/PublisherRevenuePage').then((m) => ({ default: m.PublisherRevenuePage }))\n);\nconst AppDetailPage = lazy(() =>\n import('./pages/AppDetailPage').then((m) => ({ default: m.AppDetailPage }))\n);\nconst AppSettingsPage = lazy(() =>\n import('./pages/AppSettingsPage').then((m) => ({ default: m.AppSettingsPage }))\n);\nconst ProductReviewsPage = lazy(() =>\n import('./pages/ProductReviewsPage').then((m) => ({ default: m.ProductReviewsPage }))\n);\n\nfunction FeatureDisabled({ title, featureFlag }: { title: string; featureFlag: string }) {\n return (\n <div className=\"flex min-h-[400px] items-center justify-center p-6\">\n <div className=\"max-w-md rounded-lg border border-border bg-card p-6 text-center shadow-sm\">\n <h2 className=\"text-lg font-semibold text-foreground\">{title} is not enabled</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Ask an administrator to enable the <span className=\"font-mono\">{featureFlag}</span>{' '}\n feature flag for this organization.\n </p>\n </div>\n </div>\n );\n}\n\ninterface StoreRouteGateProps {\n title: string;\n featureFlag: string;\n allowed: boolean;\n isLoading: boolean;\n children: ReactNode;\n}\n\nfunction StoreRouteGate({ title, featureFlag, allowed, isLoading, children }: StoreRouteGateProps) {\n if (isLoading) {\n return <PageLoadingFallback />;\n }\n return (\n <FeatureGate\n flag={featureFlag}\n defaultValue\n fallback={<FeatureDisabled title={title} featureFlag={featureFlag} />}\n >\n {allowed ? children : <AccessDenied />}\n </FeatureGate>\n );\n}\n\n/**\n * StoreRoutes component\n *\n * Internal routing for the Store microfrontend. Every route is gated by both\n * a live feature flag (via FeatureGate) and an RBAC permission check so that\n * features can be toggled per-org without a deployment.\n *\n * Flag namespace: store.*\n */\nexport const StoreRoutes: FC = () => {\n const { basePath } = useStore();\n const { permissions, hasPermission, isLoading } = useStorePermissions();\n\n return (\n <Routes>\n {/* Default redirect */}\n <Route index element={<Navigate to=\"marketplace\" replace />} />\n\n {/* Marketplace */}\n <Route\n path=\"marketplace\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <MarketplaceHomePage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"marketplace/product/:productId\"\n element={\n <StoreRouteGate\n title=\"Marketplace\"\n featureFlag=\"store.marketplace\"\n allowed={permissions.canBrowse}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <ProductDetailPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Cart */}\n <Route\n path=\"cart\"\n element={\n <StoreRouteGate\n title=\"Cart\"\n featureFlag=\"store.cart\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <CartPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Orders */}\n <Route\n path=\"orders/:orderId/confirmation\"\n element={\n <StoreRouteGate\n title=\"Order confirmation\"\n featureFlag=\"store.orders\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <OrderConfirmationPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"orders\"\n element={\n <StoreRouteGate\n title=\"Orders\"\n featureFlag=\"store.orders\"\n allowed={permissions.canPurchase}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <OrdersPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Installed Apps */}\n <Route\n path=\"installed\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <InstalledAppsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"installed/:installationId\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <AppDetailPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"installed/:installationId/settings\"\n element={\n <StoreRouteGate\n title=\"Installed apps\"\n featureFlag=\"store.installed\"\n allowed={permissions.canInstall}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <AppSettingsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Licenses */}\n <Route\n path=\"licenses\"\n element={\n <StoreRouteGate\n title=\"Licenses\"\n featureFlag=\"store.licenses\"\n allowed={permissions.canManageLicenses}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <MyLicensesPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Publisher Portal */}\n <Route\n path=\"publisher\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherDashboardPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/submit\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherSubmitPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/submissions\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherSubmissionsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/revenue\"\n element={\n <StoreRouteGate\n title=\"Publisher revenue\"\n featureFlag=\"store.publisher-portal.revenue\"\n allowed={hasPermission(STORE_PERMISSIONS.EARNINGS_READ)}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <PublisherRevenuePage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n <Route\n path=\"publisher/product/:productId/reviews\"\n element={\n <StoreRouteGate\n title=\"Publisher portal\"\n featureFlag=\"store.publisher-portal\"\n allowed={permissions.canPublish}\n isLoading={isLoading}\n >\n <Suspense fallback={<PageLoadingFallback />}>\n <ProductReviewsPage />\n </Suspense>\n </StoreRouteGate>\n }\n />\n\n {/* Catch-all redirect */}\n <Route path=\"*\" element={<Navigate to={`${basePath}/marketplace`} replace />} />\n </Routes>\n );\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-store",
3
- "version": "2026.530.1",
3
+ "version": "2026.601.1",
4
4
  "description": "Store microfrontend for Burdenoff products",
5
5
  "type": "module",
6
6
  "files": [
@@ -1,85 +0,0 @@
1
- import { useStore as e } from "../providers/StoreProvider.js";
2
- import { useBrowseStoreWithContext as t } from "../hooks/useStoreGraphQL.js";
3
- import { useMemo as n } from "react";
4
- import { useI18n as r } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
- import { ArrowLeft as i } from "lucide-react";
6
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
- import { useNavigate as s, useParams as c } from "react-router-dom";
8
- //#region src/pages/ProductCategoryPage.tsx
9
- var l = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ o("button", {
10
- type: "button",
11
- onClick: () => t(e.id),
12
- className: "cursor-pointer rounded-xl border border-border-default bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken",
13
- children: [
14
- /* @__PURE__ */ a("h3", {
15
- className: "font-semibold text-text-primary",
16
- children: e.name
17
- }),
18
- /* @__PURE__ */ a("p", {
19
- className: "mt-1 text-xs text-text-muted",
20
- children: e.type
21
- }),
22
- /* @__PURE__ */ a("p", {
23
- className: "mt-2 text-sm text-text-muted line-clamp-2",
24
- children: e.description || n
25
- })
26
- ]
27
- }), u = () => {
28
- let u = s(), { basePath: d } = e(), { categorySlug: f } = c(), { t: p } = r(), m = n(() => decodeURIComponent(f ?? ""), [f]), { products: h, loading: g, error: _ } = t({
29
- filter: m ? { category: m } : void 0,
30
- pagination: { limit: 30 }
31
- });
32
- return /* @__PURE__ */ o("div", {
33
- className: "flex h-full flex-col",
34
- children: [/* @__PURE__ */ a("header", {
35
- className: "border-b border-border-default bg-bg-surface px-6 py-4",
36
- children: /* @__PURE__ */ o("div", {
37
- className: "mx-auto flex max-w-6xl items-center gap-3",
38
- children: [/* @__PURE__ */ a("button", {
39
- type: "button",
40
- onClick: () => u(-1),
41
- "aria-label": "Go back",
42
- className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
43
- children: /* @__PURE__ */ a(i, { className: "size-5" })
44
- }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h1", {
45
- className: "text-2xl font-bold text-text-primary",
46
- children: p("pages.category.title", {
47
- defaultValue: `Category: ${m || "All"}`,
48
- name: m || "All"
49
- })
50
- }), /* @__PURE__ */ a("p", {
51
- className: "text-sm text-text-muted",
52
- children: p("pages.category.subtitle", { defaultValue: "Browse products filtered by category" })
53
- })] })]
54
- })
55
- }), /* @__PURE__ */ a("main", {
56
- className: "flex-1 overflow-y-auto p-6",
57
- children: /* @__PURE__ */ a("div", {
58
- className: "mx-auto max-w-6xl",
59
- children: g ? /* @__PURE__ */ a("p", {
60
- role: "status",
61
- className: "text-sm text-text-muted",
62
- children: p("common.loading", { defaultValue: "Loading products..." })
63
- }) : _ ? /* @__PURE__ */ a("p", {
64
- role: "alert",
65
- className: "text-sm text-status-error-text",
66
- children: _.message
67
- }) : h.length === 0 ? /* @__PURE__ */ a("p", {
68
- className: "text-sm text-text-muted",
69
- children: p("pages.category.noProducts", { defaultValue: "No products found for this category." })
70
- }) : /* @__PURE__ */ a("ul", {
71
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
72
- children: h.map((e) => /* @__PURE__ */ a("li", { children: /* @__PURE__ */ a(l, {
73
- product: e,
74
- noDesc: p("pages.productDetail.noDesc", { defaultValue: "No description available." }),
75
- onOpen: (e) => u(`${d}/marketplace/product/${e}`)
76
- }) }, e.id))
77
- })
78
- })
79
- })]
80
- });
81
- };
82
- //#endregion
83
- export { u as ProductCategoryPage };
84
-
85
- //# sourceMappingURL=ProductCategoryPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ProductCategoryPage.js","names":[],"sources":["../../src/pages/ProductCategoryPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { ArrowLeft } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useBrowseStoreWithContext, type StoreProduct } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nconst ProductTile: FC<{ product: StoreProduct; onOpen: (id: string) => void; noDesc: string }> = ({\n product,\n onOpen,\n noDesc,\n}) => (\n <button\n type=\"button\"\n onClick={() => onOpen(product.id)}\n className=\"cursor-pointer rounded-xl border border-border-default bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken\"\n >\n <h3 className=\"font-semibold text-text-primary\">{product.name}</h3>\n <p className=\"mt-1 text-xs text-text-muted\">{product.type}</p>\n <p className=\"mt-2 text-sm text-text-muted line-clamp-2\">{product.description || noDesc}</p>\n </button>\n);\n\nexport const ProductCategoryPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { categorySlug } = useParams<{ categorySlug: string }>();\n const { t } = useI18n();\n\n const category = useMemo(() => decodeURIComponent(categorySlug ?? ''), [categorySlug]);\n const { products, loading, error } = useBrowseStoreWithContext({\n filter: category ? { category } : undefined,\n pagination: { limit: 30 },\n });\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-default bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-6xl items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.category.title', {\n defaultValue: `Category: ${category || 'All'}`,\n name: category || 'All',\n })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.category.subtitle', {\n defaultValue: 'Browse products filtered by category',\n })}\n </p>\n </div>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl\">\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n {t('common.loading', { defaultValue: 'Loading products...' })}\n </p>\n ) : error ? (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error.message}\n </p>\n ) : products.length === 0 ? (\n <p className=\"text-sm text-text-muted\">\n {t('pages.category.noProducts', {\n defaultValue: 'No products found for this category.',\n })}\n </p>\n ) : (\n <ul className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {products.map((product) => (\n <li key={product.id}>\n <ProductTile\n product={product}\n noDesc={t('pages.productDetail.noDesc', {\n defaultValue: 'No description available.',\n })}\n onOpen={(id) => navigate(`${basePath}/marketplace/product/${id}`)}\n />\n </li>\n ))}\n </ul>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":";;;;;;;;AAQA,IAAM,KAA4F,EAChG,YACA,WACA,gBAEA,kBAAC,UAAD;CACE,MAAK;CACL,eAAe,EAAO,EAAQ,GAAG;CACjC,WAAU;WAHZ;EAKE,kBAAC,MAAD;GAAI,WAAU;aAAmC,EAAQ;GAAU,CAAA;EACnE,kBAAC,KAAD;GAAG,WAAU;aAAgC,EAAQ;GAAS,CAAA;EAC9D,kBAAC,KAAD;GAAG,WAAU;aAA6C,EAAQ,eAAe;GAAW,CAAA;EACrF;IAGE,UAAgC;CAC3C,IAAM,IAAW,GAAa,EACxB,EAAE,gBAAa,GAAU,EACzB,EAAE,oBAAiB,GAAqC,EACxD,EAAE,SAAM,GAAS,EAEjB,IAAW,QAAc,mBAAmB,KAAgB,GAAG,EAAE,CAAC,EAAa,CAAC,EAChF,EAAE,aAAU,YAAS,aAAU,EAA0B;EAC7D,QAAQ,IAAW,EAAE,aAAU,GAAG,KAAA;EAClC,YAAY,EAAE,OAAO,IAAI;EAC1B,CAAC;AAEF,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GAAQ,WAAU;aAChB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAS,GAAG;KAC3B,cAAW;KACX,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;KACzB,CAAA,EACT,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAE,wBAAwB;MACzB,cAAc,aAAa,KAAY;MACvC,MAAM,KAAY;MACnB,CAAC;KACC,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,2BAA2B,EAC5B,cAAc,wCACf,CAAC;KACA,CAAA,CACA,EAAA,CAAA,CACF;;GACC,CAAA,EAET,kBAAC,QAAD;GAAM,WAAU;aACd,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,KAAD;KAAG,MAAK;KAAS,WAAU;eACxB,EAAE,kBAAkB,EAAE,cAAc,uBAAuB,CAAC;KAC3D,CAAA,GACF,IACF,kBAAC,KAAD;KAAG,MAAK;KAAQ,WAAU;eACvB,EAAM;KACL,CAAA,GACF,EAAS,WAAW,IACtB,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,6BAA6B,EAC9B,cAAc,wCACf,CAAC;KACA,CAAA,GAEJ,kBAAC,MAAD;KAAI,WAAU;eACX,EAAS,KAAK,MACb,kBAAC,MAAD,EAAA,UACE,kBAAC,GAAD;MACW;MACT,QAAQ,EAAE,8BAA8B,EACtC,cAAc,6BACf,CAAC;MACF,SAAS,MAAO,EAAS,GAAG,EAAS,uBAAuB,IAAK;MACjE,CAAA,EACC,EARI,EAAQ,GAQZ,CACL;KACC,CAAA;IAEH,CAAA;GACD,CAAA,CACH"}
@@ -1,128 +0,0 @@
1
- import { useStore as e } from "../providers/StoreProvider.js";
2
- import { useBrowseStoreWithContext as t } from "../hooks/useStoreGraphQL.js";
3
- import { useId as n, useMemo as r, useState as i } from "react";
4
- import { useI18n as a } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
5
- import { ArrowLeft as o, Search as s } from "lucide-react";
6
- import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
7
- import { useNavigate as d, useSearchParams as f } from "react-router-dom";
8
- //#region src/pages/SearchResultsPage.tsx
9
- var p = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ u("button", {
10
- type: "button",
11
- onClick: () => t(e.id),
12
- className: "cursor-pointer rounded-xl border border-border-default bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken",
13
- children: [
14
- /* @__PURE__ */ l("h3", {
15
- className: "font-semibold text-text-primary",
16
- children: e.name
17
- }),
18
- /* @__PURE__ */ l("p", {
19
- className: "mt-1 text-xs text-text-muted",
20
- children: e.type
21
- }),
22
- /* @__PURE__ */ l("p", {
23
- className: "mt-2 text-sm text-text-muted line-clamp-2",
24
- children: e.description || n
25
- })
26
- ]
27
- }), m = () => {
28
- let m = d(), { basePath: h } = e(), g = n(), [_, v] = f(), [y, b] = i(_.get("q") ?? ""), { t: x } = a(), S = r(() => y.trim(), [y]), { products: C, totalCount: w, hasMore: T, loading: E, error: D, loadMore: O } = t({
29
- filter: S ? { search: S } : void 0,
30
- pagination: { limit: 30 }
31
- }), k = () => {
32
- let e = y.trim();
33
- v(e ? { q: e } : {});
34
- };
35
- return /* @__PURE__ */ u("div", {
36
- className: "flex h-full flex-col",
37
- children: [/* @__PURE__ */ l("header", {
38
- className: "border-b border-border-default bg-bg-surface px-6 py-4",
39
- children: /* @__PURE__ */ u("div", {
40
- className: "mx-auto max-w-6xl",
41
- children: [/* @__PURE__ */ u("div", {
42
- className: "mb-3 flex items-center gap-3",
43
- children: [/* @__PURE__ */ l("button", {
44
- type: "button",
45
- onClick: () => m(-1),
46
- "aria-label": "Go back",
47
- className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
48
- children: /* @__PURE__ */ l(o, { className: "size-5" })
49
- }), /* @__PURE__ */ l("h1", {
50
- className: "text-2xl font-bold text-text-primary",
51
- children: x("pages.search.title", { defaultValue: "Search Results" })
52
- })]
53
- }), /* @__PURE__ */ u("div", {
54
- className: "flex gap-2",
55
- children: [
56
- /* @__PURE__ */ l("label", {
57
- htmlFor: g,
58
- className: "sr-only",
59
- children: x("pages.search.searchLabel", { defaultValue: "Search store products" })
60
- }),
61
- /* @__PURE__ */ l("input", {
62
- id: g,
63
- "aria-label": x("pages.search.searchLabel", { defaultValue: "Search store products" }),
64
- value: y,
65
- onChange: (e) => b(e.target.value),
66
- onKeyDown: (e) => {
67
- e.key === "Enter" && k();
68
- },
69
- placeholder: "Search apps, workflows, integrations...",
70
- className: "w-full rounded-lg border border-border-default bg-bg-sunken px-3 py-2 text-sm text-text-primary outline-none focus:border-action-primary-bg"
71
- }),
72
- /* @__PURE__ */ u("button", {
73
- type: "button",
74
- onClick: k,
75
- className: "inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text",
76
- children: [/* @__PURE__ */ l(s, { className: "size-4" }), " Search"]
77
- })
78
- ]
79
- })]
80
- })
81
- }), /* @__PURE__ */ l("main", {
82
- className: "flex-1 overflow-y-auto p-6",
83
- children: /* @__PURE__ */ u("div", {
84
- className: "mx-auto max-w-6xl",
85
- children: [/* @__PURE__ */ l("p", {
86
- "aria-live": "polite",
87
- className: "mb-4 text-sm text-text-muted",
88
- children: S ? x("pages.search.resultsFor", {
89
- defaultValue: `${w} results for "${S}"`,
90
- query: S,
91
- count: w
92
- }) : x("pages.search.enterQuery", { defaultValue: "Enter a query to search" })
93
- }), E && C.length === 0 ? /* @__PURE__ */ l("p", {
94
- role: "status",
95
- className: "text-sm text-text-muted",
96
- children: "Searching…"
97
- }) : D ? /* @__PURE__ */ l("p", {
98
- role: "alert",
99
- className: "text-sm text-status-error-text",
100
- children: D.message
101
- }) : C.length === 0 ? /* @__PURE__ */ l("p", {
102
- className: "text-sm text-text-muted",
103
- children: "No matching products found."
104
- }) : /* @__PURE__ */ u(c, { children: [/* @__PURE__ */ l("ul", {
105
- className: "grid gap-4 sm:grid-cols-2 lg:grid-cols-3",
106
- children: C.map((e) => /* @__PURE__ */ l("li", { children: /* @__PURE__ */ l(p, {
107
- product: e,
108
- noDesc: x("common.noResults", { defaultValue: "No description available." }),
109
- onOpen: (e) => m(`${h}/marketplace/product/${e}`)
110
- }) }, e.id))
111
- }), T && /* @__PURE__ */ l("div", {
112
- className: "flex justify-center pt-4",
113
- children: /* @__PURE__ */ l("button", {
114
- type: "button",
115
- onClick: O,
116
- disabled: E,
117
- className: "rounded-lg border border-border-default px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-subtle disabled:opacity-50",
118
- children: E ? "Loading…" : "Load more"
119
- })
120
- })] })]
121
- })
122
- })]
123
- });
124
- };
125
- //#endregion
126
- export { m as SearchResultsPage };
127
-
128
- //# sourceMappingURL=SearchResultsPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SearchResultsPage.js","names":[],"sources":["../../src/pages/SearchResultsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo, useState, useId } from 'react';\nimport { useNavigate, useSearchParams } from 'react-router-dom';\nimport { ArrowLeft, Search } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useBrowseStoreWithContext, type StoreProduct } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nconst SearchResultCard: FC<{\n product: StoreProduct;\n onOpen: (id: string) => void;\n noDesc: string;\n}> = ({ product, onOpen, noDesc }) => (\n <button\n type=\"button\"\n onClick={() => onOpen(product.id)}\n className=\"cursor-pointer rounded-xl border border-border-default bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken\"\n >\n <h3 className=\"font-semibold text-text-primary\">{product.name}</h3>\n <p className=\"mt-1 text-xs text-text-muted\">{product.type}</p>\n <p className=\"mt-2 text-sm text-text-muted line-clamp-2\">{product.description || noDesc}</p>\n </button>\n);\n\nexport const SearchResultsPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const searchInputId = useId();\n const [searchParams, setSearchParams] = useSearchParams();\n const initialQuery = searchParams.get('q') ?? '';\n const [query, setQuery] = useState(initialQuery);\n const { t } = useI18n();\n\n const trimmedQuery = useMemo(() => query.trim(), [query]);\n const { products, totalCount, hasMore, loading, error, loadMore } = useBrowseStoreWithContext({\n filter: trimmedQuery ? { search: trimmedQuery } : undefined,\n pagination: { limit: 30 },\n });\n\n const handleSearch = () => {\n const next = query.trim();\n if (next) {\n setSearchParams({ q: next });\n } else {\n setSearchParams({});\n }\n };\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-default bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto max-w-6xl\">\n <div className=\"mb-3 flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-5\" />\n </button>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.search.title', { defaultValue: 'Search Results' })}\n </h1>\n </div>\n <div className=\"flex gap-2\">\n <label htmlFor={searchInputId} className=\"sr-only\">\n {t('pages.search.searchLabel', { defaultValue: 'Search store products' })}\n </label>\n <input\n id={searchInputId}\n aria-label={t('pages.search.searchLabel', { defaultValue: 'Search store products' })}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') handleSearch();\n }}\n placeholder=\"Search apps, workflows, integrations...\"\n className=\"w-full rounded-lg border border-border-default bg-bg-sunken px-3 py-2 text-sm text-text-primary outline-none focus:border-action-primary-bg\"\n />\n <button\n type=\"button\"\n onClick={handleSearch}\n className=\"inline-flex cursor-pointer items-center gap-1.5 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Search className=\"size-4\" /> Search\n </button>\n </div>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl\">\n <p aria-live=\"polite\" className=\"mb-4 text-sm text-text-muted\">\n {trimmedQuery\n ? t('pages.search.resultsFor', {\n defaultValue: `${totalCount} results for \"${trimmedQuery}\"`,\n query: trimmedQuery,\n count: totalCount,\n })\n : t('pages.search.enterQuery', { defaultValue: 'Enter a query to search' })}\n </p>\n {loading && products.length === 0 ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Searching…\n </p>\n ) : error ? (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error.message}\n </p>\n ) : products.length === 0 ? (\n <p className=\"text-sm text-text-muted\">No matching products found.</p>\n ) : (\n <>\n <ul className=\"grid gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {products.map((product) => (\n <li key={product.id}>\n <SearchResultCard\n product={product}\n noDesc={t('common.noResults', { defaultValue: 'No description available.' })}\n onOpen={(id) => navigate(`${basePath}/marketplace/product/${id}`)}\n />\n </li>\n ))}\n </ul>\n {hasMore && (\n <div className=\"flex justify-center pt-4\">\n <button\n type=\"button\"\n onClick={loadMore}\n disabled={loading}\n className=\"rounded-lg border border-border-default px-6 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-subtle disabled:opacity-50\"\n >\n {loading ? 'Loading\\u2026' : 'Load more'}\n </button>\n </div>\n )}\n </>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,153 +0,0 @@
1
- import { useStore as e } from "../providers/StoreProvider.js";
2
- import { useCallback as t, useEffect as n, useState as r } from "react";
3
- import { Check as i, Plus as a, RefreshCw as o, Store as s } from "lucide-react";
4
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
5
- import { graphqlFetch as u } from "@burdenoff/fe-libs/shared/graphql";
6
- //#region src/pages/StoresPage.tsx
7
- var d = "\n query BrowseableStores {\n stores {\n id\n slug\n name\n type\n isPublic\n requiresApproval\n currency\n logoUrl\n description\n }\n mySubscribedStores {\n id\n }\n }\n", f = "\n mutation Subscribe($storeId: ID!) {\n subscribeToStore(storeId: $storeId) {\n id\n storeId\n }\n }\n", p = "\n mutation Unsubscribe($storeId: ID!) {\n unsubscribeFromStore(storeId: $storeId)\n }\n", m = () => {
8
- let { authToken: m } = e(), [h, g] = r([]), [_, v] = r(/* @__PURE__ */ new Set()), [y, b] = r(!1), [x, S] = r(null), [C, w] = r(null), T = t(async () => {
9
- b(!0), w(null);
10
- try {
11
- let e = await u({
12
- gateway: "global",
13
- query: d,
14
- authToken: m || void 0
15
- });
16
- if (e.errors?.length) throw Error(e.errors[0]?.message ?? "Failed to load stores");
17
- g(e.data?.stores ?? []), v(new Set((e.data?.mySubscribedStores ?? []).map((e) => e.id)));
18
- } catch (e) {
19
- w(e instanceof Error ? e.message : "Failed to load stores");
20
- } finally {
21
- b(!1);
22
- }
23
- }, [m]);
24
- n(() => {
25
- T();
26
- }, [T]);
27
- let E = async (e) => {
28
- S(e), w(null);
29
- try {
30
- let t = _.has(e);
31
- await u({
32
- gateway: "global",
33
- query: t ? p : f,
34
- variables: { storeId: e },
35
- authToken: m || void 0
36
- }), v((n) => {
37
- let r = new Set(n);
38
- return t ? r.delete(e) : r.add(e), r;
39
- });
40
- } catch (e) {
41
- w(e instanceof Error ? e.message : "Action failed");
42
- } finally {
43
- S(null);
44
- }
45
- };
46
- return /* @__PURE__ */ l("div", {
47
- className: "min-h-screen bg-surface-default",
48
- children: [/* @__PURE__ */ c("header", {
49
- className: "border-b border-border-default bg-surface-raised",
50
- children: /* @__PURE__ */ l("div", {
51
- className: "mx-auto max-w-5xl px-6 py-4",
52
- children: [/* @__PURE__ */ l("div", {
53
- className: "flex items-center justify-between",
54
- children: [/* @__PURE__ */ l("div", {
55
- className: "flex items-center gap-2",
56
- children: [/* @__PURE__ */ c(s, { className: "size-5 text-text-primary" }), /* @__PURE__ */ c("h1", {
57
- className: "text-xl font-semibold text-text-primary",
58
- children: "Stores"
59
- })]
60
- }), /* @__PURE__ */ l("button", {
61
- type: "button",
62
- onClick: () => void T(),
63
- disabled: y,
64
- className: "inline-flex items-center gap-2 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary hover:bg-surface-hover",
65
- children: [/* @__PURE__ */ c(o, { className: `size-4 ${y ? "animate-spin" : ""}` }), "Refresh"]
66
- })]
67
- }), /* @__PURE__ */ c("p", {
68
- className: "mt-1 text-sm text-text-secondary",
69
- children: "Subscribe to additional stores to discover more products. Public stores are auto-subscribed."
70
- })]
71
- })
72
- }), /* @__PURE__ */ l("main", {
73
- className: "mx-auto max-w-5xl p-6",
74
- children: [C && /* @__PURE__ */ c("div", {
75
- role: "alert",
76
- className: "mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger",
77
- children: C
78
- }), y && h.length === 0 ? /* @__PURE__ */ c("output", {
79
- className: "block py-16 text-center text-text-secondary",
80
- children: "Loading stores…"
81
- }) : h.length === 0 ? /* @__PURE__ */ c("div", {
82
- className: "py-16 text-center text-text-secondary",
83
- children: "No stores available."
84
- }) : /* @__PURE__ */ c("ul", {
85
- className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
86
- children: h.map((e) => {
87
- let t = _.has(e.id);
88
- return /* @__PURE__ */ l("li", {
89
- className: "rounded-lg border border-border-default bg-surface-raised p-4",
90
- children: [/* @__PURE__ */ l("div", {
91
- className: "flex items-start gap-3",
92
- children: [e.logoUrl ? /* @__PURE__ */ c("img", {
93
- src: e.logoUrl,
94
- alt: "",
95
- className: "size-12 flex-shrink-0 rounded-md object-cover"
96
- }) : /* @__PURE__ */ c("div", {
97
- className: "flex size-12 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary",
98
- children: /* @__PURE__ */ c(s, { className: "size-5" })
99
- }), /* @__PURE__ */ l("div", {
100
- className: "min-w-0 flex-1",
101
- children: [
102
- /* @__PURE__ */ l("div", {
103
- className: "flex items-center gap-2",
104
- children: [/* @__PURE__ */ c("h3", {
105
- className: "truncate text-base font-semibold text-text-primary",
106
- children: e.name
107
- }), /* @__PURE__ */ c("span", {
108
- className: "rounded-full bg-surface-accent-muted px-2 py-0.5 text-xs font-medium text-text-accent",
109
- children: e.type
110
- })]
111
- }),
112
- /* @__PURE__ */ c("p", {
113
- className: "mt-0.5 font-mono text-xs text-text-tertiary",
114
- children: e.slug
115
- }),
116
- e.description && /* @__PURE__ */ c("p", {
117
- className: "mt-2 line-clamp-2 text-sm text-text-secondary",
118
- children: e.description
119
- })
120
- ]
121
- })]
122
- }), /* @__PURE__ */ l("div", {
123
- className: "mt-3 flex items-center justify-between",
124
- children: [/* @__PURE__ */ c("span", {
125
- className: "text-xs text-text-tertiary",
126
- children: e.currency
127
- }), e.slug === "public" ? /* @__PURE__ */ l("span", {
128
- className: "inline-flex items-center gap-1 rounded-md bg-surface-accent-muted px-2 py-1 text-xs text-text-accent",
129
- children: [/* @__PURE__ */ c(i, { className: "size-3" }), "Default"]
130
- }) : t ? /* @__PURE__ */ l("button", {
131
- type: "button",
132
- onClick: () => void E(e.id),
133
- disabled: x === e.id,
134
- className: "inline-flex items-center gap-1 rounded-md border border-border-default bg-surface-default px-3 py-1 text-xs text-text-primary hover:bg-surface-hover disabled:opacity-60",
135
- children: [/* @__PURE__ */ c(i, { className: "size-3" }), "Subscribed"]
136
- }) : /* @__PURE__ */ l("button", {
137
- type: "button",
138
- onClick: () => void E(e.id),
139
- disabled: x === e.id,
140
- className: "inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:opacity-90 disabled:opacity-60",
141
- children: [/* @__PURE__ */ c(a, { className: "size-3" }), "Subscribe"]
142
- })]
143
- })]
144
- }, e.id);
145
- })
146
- })]
147
- })]
148
- });
149
- };
150
- //#endregion
151
- export { m as StoresPage };
152
-
153
- //# sourceMappingURL=StoresPage.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StoresPage.js","names":[],"sources":["../../src/pages/StoresPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { Store as StoreIcon, Check, Plus, RefreshCw } from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useStore } from '../providers/StoreProvider';\n\ntype StoreRecord = {\n id: string;\n slug: string;\n name: string;\n type: 'PUBLIC' | 'PRIVATE' | 'ENTERPRISE';\n isPublic: boolean;\n requiresApproval: boolean;\n currency: string;\n logoUrl?: string | null;\n description?: string | null;\n};\n\nconst STORES_QUERY = /* GraphQL */ `\n query BrowseableStores {\n stores {\n id\n slug\n name\n type\n isPublic\n requiresApproval\n currency\n logoUrl\n description\n }\n mySubscribedStores {\n id\n }\n }\n`;\n\nconst SUBSCRIBE_MUTATION = /* GraphQL */ `\n mutation Subscribe($storeId: ID!) {\n subscribeToStore(storeId: $storeId) {\n id\n storeId\n }\n }\n`;\n\nconst UNSUBSCRIBE_MUTATION = /* GraphQL */ `\n mutation Unsubscribe($storeId: ID!) {\n unsubscribeFromStore(storeId: $storeId)\n }\n`;\n\nexport const StoresPage: FC = () => {\n const { authToken } = useStore();\n const [stores, setStores] = useState<StoreRecord[]>([]);\n const [subscribed, setSubscribed] = useState<Set<string>>(new Set());\n const [loading, setLoading] = useState(false);\n const [actingId, setActingId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const load = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const result = await graphqlFetch<{\n stores: StoreRecord[];\n mySubscribedStores: Array<{ id: string }>;\n }>({\n gateway: 'global',\n query: STORES_QUERY,\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load stores');\n }\n setStores(result.data?.stores ?? []);\n setSubscribed(new Set((result.data?.mySubscribedStores ?? []).map((s) => s.id)));\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load stores');\n } finally {\n setLoading(false);\n }\n }, [authToken]);\n\n useEffect(() => {\n void load();\n }, [load]);\n\n const toggle = async (storeId: string) => {\n setActingId(storeId);\n setError(null);\n try {\n const isSubbed = subscribed.has(storeId);\n await graphqlFetch({\n gateway: 'global',\n query: isSubbed ? UNSUBSCRIBE_MUTATION : SUBSCRIBE_MUTATION,\n variables: { storeId },\n authToken: authToken || undefined,\n });\n setSubscribed((prev) => {\n const next = new Set(prev);\n if (isSubbed) next.delete(storeId);\n else next.add(storeId);\n return next;\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Action failed');\n } finally {\n setActingId(null);\n }\n };\n\n return (\n <div className=\"min-h-screen bg-surface-default\">\n <header className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-5xl px-6 py-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <StoreIcon className=\"size-5 text-text-primary\" />\n <h1 className=\"text-xl font-semibold text-text-primary\">Stores</h1>\n </div>\n <button\n type=\"button\"\n onClick={() => void load()}\n disabled={loading}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-default bg-surface-default px-3 py-1.5 text-sm text-text-primary hover:bg-surface-hover\"\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n Refresh\n </button>\n </div>\n <p className=\"mt-1 text-sm text-text-secondary\">\n Subscribe to additional stores to discover more products. Public stores are\n auto-subscribed.\n </p>\n </div>\n </header>\n\n <main className=\"mx-auto max-w-5xl p-6\">\n {error && (\n <div\n role=\"alert\"\n className=\"mb-4 rounded-md border border-border-danger bg-surface-danger-muted px-4 py-3 text-sm text-text-danger\"\n >\n {error}\n </div>\n )}\n\n {loading && stores.length === 0 ? (\n <output className=\"block py-16 text-center text-text-secondary\">Loading stores…</output>\n ) : stores.length === 0 ? (\n <div className=\"py-16 text-center text-text-secondary\">No stores available.</div>\n ) : (\n <ul className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n {stores.map((s) => {\n const isSubbed = subscribed.has(s.id);\n return (\n <li\n key={s.id}\n className=\"rounded-lg border border-border-default bg-surface-raised p-4\"\n >\n <div className=\"flex items-start gap-3\">\n {s.logoUrl ? (\n <img\n src={s.logoUrl}\n alt=\"\"\n className=\"size-12 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex size-12 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary\">\n <StoreIcon className=\"size-5\" />\n </div>\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"truncate text-base font-semibold text-text-primary\">\n {s.name}\n </h3>\n <span className=\"rounded-full bg-surface-accent-muted px-2 py-0.5 text-xs font-medium text-text-accent\">\n {s.type}\n </span>\n </div>\n <p className=\"mt-0.5 font-mono text-xs text-text-tertiary\">{s.slug}</p>\n {s.description && (\n <p className=\"mt-2 line-clamp-2 text-sm text-text-secondary\">\n {s.description}\n </p>\n )}\n </div>\n </div>\n <div className=\"mt-3 flex items-center justify-between\">\n <span className=\"text-xs text-text-tertiary\">{s.currency}</span>\n {s.slug === 'public' ? (\n <span className=\"inline-flex items-center gap-1 rounded-md bg-surface-accent-muted px-2 py-1 text-xs text-text-accent\">\n <Check className=\"size-3\" />\n Default\n </span>\n ) : isSubbed ? (\n <button\n type=\"button\"\n onClick={() => void toggle(s.id)}\n disabled={actingId === s.id}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-default bg-surface-default px-3 py-1 text-xs text-text-primary hover:bg-surface-hover disabled:opacity-60\"\n >\n <Check className=\"size-3\" />\n Subscribed\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => void toggle(s.id)}\n disabled={actingId === s.id}\n className=\"inline-flex items-center gap-1 rounded-md bg-action-primary-bg px-3 py-1 text-xs font-medium text-action-primary-text hover:opacity-90 disabled:opacity-60\"\n >\n <Plus className=\"size-3\" />\n Subscribe\n </button>\n )}\n </div>\n </li>\n );\n })}\n </ul>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}