@burdenoff/microfe-store 2026.525.3 → 2026.527.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.
Files changed (69) hide show
  1. package/dist/StoreAdminRoutes.js +10 -9
  2. package/dist/StoreAdminRoutes.js.map +1 -1
  3. package/dist/StoreRoutes.js +2 -1
  4. package/dist/StoreRoutes.js.map +1 -1
  5. package/dist/components/AccessDenied.js +23 -0
  6. package/dist/components/AccessDenied.js.map +1 -0
  7. package/dist/components/InstallAppModal.js +183 -129
  8. package/dist/components/InstallAppModal.js.map +1 -1
  9. package/dist/components/PermissionGuard.js +8 -0
  10. package/dist/components/PermissionGuard.js.map +1 -0
  11. package/dist/components/RouteGuards.js +7 -21
  12. package/dist/components/RouteGuards.js.map +1 -1
  13. package/dist/components/cart/CartDrawer.js +20 -14
  14. package/dist/components/cart/CartDrawer.js.map +1 -1
  15. package/dist/hooks/useStoreGraphQL.js +22 -20
  16. package/dist/hooks/useStoreGraphQL.js.map +1 -1
  17. package/dist/hooks/useStoreGraphQLWithContext.js.map +1 -1
  18. package/dist/hooks/useStorePermissions.js +4 -1
  19. package/dist/hooks/useStorePermissions.js.map +1 -1
  20. package/dist/index.js +4 -4
  21. package/dist/pages/AdminDashboardPage.js +182 -183
  22. package/dist/pages/AdminDashboardPage.js.map +1 -1
  23. package/dist/pages/AdminReviewModerationPage.js +7 -6
  24. package/dist/pages/AdminReviewModerationPage.js.map +1 -1
  25. package/dist/pages/AdminStoresPage.js +193 -185
  26. package/dist/pages/AdminStoresPage.js.map +1 -1
  27. package/dist/pages/AdminSubmissionsQueuePage.js +140 -142
  28. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -1
  29. package/dist/pages/AppDetailPage.js +6 -3
  30. package/dist/pages/AppDetailPage.js.map +1 -1
  31. package/dist/pages/AppSettingsPage.js +6 -3
  32. package/dist/pages/AppSettingsPage.js.map +1 -1
  33. package/dist/pages/CartPage.js +23 -15
  34. package/dist/pages/CartPage.js.map +1 -1
  35. package/dist/pages/InstalledAppsPage.js +26 -15
  36. package/dist/pages/InstalledAppsPage.js.map +1 -1
  37. package/dist/pages/MarketplaceHomePage.js +275 -247
  38. package/dist/pages/MarketplaceHomePage.js.map +1 -1
  39. package/dist/pages/MyLicensesPage.js +10 -8
  40. package/dist/pages/MyLicensesPage.js.map +1 -1
  41. package/dist/pages/OrderConfirmationPage.js +72 -75
  42. package/dist/pages/OrderConfirmationPage.js.map +1 -1
  43. package/dist/pages/OrdersPage.js +22 -20
  44. package/dist/pages/OrdersPage.js.map +1 -1
  45. package/dist/pages/ProductCategoryPage.js +3 -1
  46. package/dist/pages/ProductCategoryPage.js.map +1 -1
  47. package/dist/pages/ProductDetailPage.js +458 -443
  48. package/dist/pages/ProductDetailPage.js.map +1 -1
  49. package/dist/pages/ProductReviewsPage.js +4 -3
  50. package/dist/pages/ProductReviewsPage.js.map +1 -1
  51. package/dist/pages/PublisherDashboardPage.js +13 -7
  52. package/dist/pages/PublisherDashboardPage.js.map +1 -1
  53. package/dist/pages/PublisherRevenuePage.js +7 -5
  54. package/dist/pages/PublisherRevenuePage.js.map +1 -1
  55. package/dist/pages/PublisherSubmissionsPage.js +12 -7
  56. package/dist/pages/PublisherSubmissionsPage.js.map +1 -1
  57. package/dist/pages/PublisherSubmitPage.js +6 -0
  58. package/dist/pages/PublisherSubmitPage.js.map +1 -1
  59. package/dist/pages/SearchResultsPage.js +6 -3
  60. package/dist/pages/SearchResultsPage.js.map +1 -1
  61. package/dist/pages/StoresPage.js +73 -74
  62. package/dist/pages/StoresPage.js.map +1 -1
  63. package/dist/providers/StoreProvider.js +25 -25
  64. package/dist/providers/StoreProvider.js.map +1 -1
  65. package/dist/utils/index.js +29 -19
  66. package/dist/utils/index.js.map +1 -1
  67. package/package.json +1 -1
  68. package/dist/components/index.js +0 -3
  69. package/dist/components/marketplace/ProductCard.js +0 -2
@@ -24,10 +24,11 @@ var m = () => {
24
24
  children: [/* @__PURE__ */ f("div", {
25
25
  className: "flex items-center gap-3",
26
26
  children: [/* @__PURE__ */ d("button", {
27
+ type: "button",
27
28
  onClick: () => m(-1),
28
29
  "aria-label": "Go back",
29
30
  className: "cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary",
30
- children: /* @__PURE__ */ d(i, { className: "h-5 w-5" })
31
+ children: /* @__PURE__ */ d(i, { className: "size-5" })
31
32
  }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("h1", {
32
33
  className: "text-2xl font-bold text-text-primary",
33
34
  children: g("pages.publisherDashboard.title", { defaultValue: "Publisher Dashboard" })
@@ -36,9 +37,10 @@ var m = () => {
36
37
  children: g("pages.publisherDashboard.subtitle", { defaultValue: "Manage your published products and performance" })
37
38
  })] })]
38
39
  }), /* @__PURE__ */ f("button", {
40
+ type: "button",
39
41
  onClick: () => m(`${h}/publisher/submit`),
40
42
  className: "inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text",
41
- children: [/* @__PURE__ */ d(l, { className: "h-4 w-4" }), "Submit Product"]
43
+ children: [/* @__PURE__ */ d(l, { className: "size-4" }), "Submit Product"]
42
44
  })]
43
45
  })
44
46
  }), /* @__PURE__ */ d("main", {
@@ -87,9 +89,10 @@ var m = () => {
87
89
  className: "text-lg font-semibold text-text-primary",
88
90
  children: g("pages.publisherDashboard.yourProducts", { defaultValue: "Your Products" })
89
91
  }), /* @__PURE__ */ f("button", {
92
+ type: "button",
90
93
  onClick: () => m(`${h}/publisher/revenue`),
91
94
  className: "inline-flex cursor-pointer items-center gap-1.5 text-sm font-medium text-text-link hover:underline",
92
- children: [/* @__PURE__ */ d(o, { className: "h-4 w-4" }), "Revenue"]
95
+ children: [/* @__PURE__ */ d(o, { className: "size-4" }), "Revenue"]
93
96
  })]
94
97
  }), v ? /* @__PURE__ */ d("p", {
95
98
  role: "status",
@@ -102,13 +105,14 @@ var m = () => {
102
105
  className: "text-sm text-status-error-text",
103
106
  children: g("pages.publisherDashboard.failedToLoad", { defaultValue: "Failed to load publisher products." })
104
107
  }), /* @__PURE__ */ d("button", {
108
+ type: "button",
105
109
  onClick: () => b(),
106
110
  className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text",
107
111
  children: "Retry"
108
112
  })]
109
113
  }) : _.length === 0 ? /* @__PURE__ */ f("div", {
110
114
  className: "rounded-lg border border-border-default bg-bg-sunken p-6 text-center",
111
- children: [/* @__PURE__ */ d(c, { className: "mx-auto mb-2 h-8 w-8 text-text-muted" }), /* @__PURE__ */ d("p", {
115
+ children: [/* @__PURE__ */ d(c, { className: "mx-auto mb-2 size-8 text-text-muted" }), /* @__PURE__ */ d("p", {
112
116
  className: "text-sm text-text-muted",
113
117
  children: g("pages.publisherDashboard.noProducts", { defaultValue: "No published products yet. Submit your first product to get started." })
114
118
  })]
@@ -117,6 +121,7 @@ var m = () => {
117
121
  children: _.map((e) => /* @__PURE__ */ f("li", {
118
122
  className: "flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken",
119
123
  children: [/* @__PURE__ */ f("button", {
124
+ type: "button",
120
125
  onClick: () => m(`${h}/marketplace/product/${e.id}`),
121
126
  className: "flex flex-1 cursor-pointer items-center justify-between text-left",
122
127
  children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
@@ -129,17 +134,18 @@ var m = () => {
129
134
  className: "flex items-center gap-4 text-xs text-text-muted",
130
135
  children: [/* @__PURE__ */ f("span", {
131
136
  className: "inline-flex items-center gap-1",
132
- children: [/* @__PURE__ */ d(u, { className: "h-3.5 w-3.5" }), (e.rating ?? 0).toFixed(1)]
137
+ children: [/* @__PURE__ */ d(u, { className: "size-3.5" }), (e.rating ?? 0).toFixed(1)]
133
138
  }), /* @__PURE__ */ f("span", {
134
139
  className: "inline-flex items-center gap-1",
135
- children: [/* @__PURE__ */ d(a, { className: "h-3.5 w-3.5" }), e.downloads]
140
+ children: [/* @__PURE__ */ d(a, { className: "size-3.5" }), e.downloads]
136
141
  })]
137
142
  })]
138
143
  }), /* @__PURE__ */ f("button", {
144
+ type: "button",
139
145
  onClick: () => m(`${h}/publisher/product/${e.id}/reviews`),
140
146
  className: "ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline",
141
147
  title: "View reviews",
142
- children: [/* @__PURE__ */ d(s, { className: "h-3.5 w-3.5" }), "Reviews"]
148
+ children: [/* @__PURE__ */ d(s, { className: "size-3.5" }), "Reviews"]
143
149
  })]
144
150
  }, e.id))
145
151
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"PublisherDashboardPage.js","names":[],"sources":["../../src/pages/PublisherDashboardPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Package2, Star, Download, Plus, LineChart, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const PublisherDashboardPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { t } = useI18n();\n const { products, loading, error, refetch } = useMyPublishedProducts();\n\n const metrics = useMemo(() => {\n const totalProducts = products.length;\n const totalDownloads = products.reduce((sum, p) => sum + (p.downloads ?? 0), 0);\n const avgRating =\n totalProducts > 0 ? products.reduce((sum, p) => sum + (p.rating ?? 0), 0) / totalProducts : 0;\n return {\n totalProducts,\n totalDownloads,\n avgRating,\n };\n }, [products]);\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 justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n onClick={() => navigate(-1)}\n aria-label=\"Go back\"\n className=\"cursor-pointer rounded-lg p-2 text-text-muted transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-5 w-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherDashboard.title', { defaultValue: 'Publisher Dashboard' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherDashboard.subtitle', {\n defaultValue: 'Manage your published products and performance',\n })}\n </p>\n </div>\n </div>\n\n <button\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Plus className=\"h-4 w-4\" />\n Submit Product\n </button>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalProducts', {\n defaultValue: 'Published products',\n })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{metrics.totalProducts}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalInstalls', { defaultValue: 'Total downloads' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{metrics.totalDownloads}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.avgRating', { defaultValue: 'Average rating' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {metrics.avgRating.toFixed(1)}\n </p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherDashboard.yourProducts', { defaultValue: 'Your Products' })}\n </h2>\n <button\n onClick={() => navigate(`${basePath}/publisher/revenue`)}\n className=\"inline-flex cursor-pointer items-center gap-1.5 text-sm font-medium text-text-link hover:underline\"\n >\n <LineChart className=\"h-4 w-4\" />\n Revenue\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n {t('common.loading', { defaultValue: 'Loading...' })}\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherDashboard.failedToLoad', {\n defaultValue: 'Failed to load publisher products.',\n })}\n </p>\n <button\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-6 text-center\">\n <Package2 className=\"mx-auto mb-2 h-8 w-8 text-text-muted\" />\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherDashboard.noProducts', {\n defaultValue:\n 'No published products yet. Submit your first product to get started.',\n })}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken\"\n >\n <button\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">{product.status}</p>\n </div>\n <div className=\"flex items-center gap-4 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <Star className=\"h-3.5 w-3.5\" />\n {(product.rating ?? 0).toFixed(1)}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Download className=\"h-3.5 w-3.5\" />\n {product.downloads}\n </span>\n </div>\n </button>\n <button\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"h-3.5 w-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PublisherDashboardPage.js","names":[],"sources":["../../src/pages/PublisherDashboardPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Package2, Star, Download, Plus, LineChart, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const PublisherDashboardPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { t } = useI18n();\n const { products, loading, error, refetch } = useMyPublishedProducts();\n\n const metrics = useMemo(() => {\n const totalProducts = products.length;\n const totalDownloads = products.reduce((sum, p) => sum + (p.downloads ?? 0), 0);\n const avgRating =\n totalProducts > 0 ? products.reduce((sum, p) => sum + (p.rating ?? 0), 0) / totalProducts : 0;\n return {\n totalProducts,\n totalDownloads,\n avgRating,\n };\n }, [products]);\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 justify-between\">\n <div className=\"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 transition-colors 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.publisherDashboard.title', { defaultValue: 'Publisher Dashboard' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherDashboard.subtitle', {\n defaultValue: 'Manage your published products and performance',\n })}\n </p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-semibold text-action-primary-text\"\n >\n <Plus className=\"size-4\" />\n Submit Product\n </button>\n </div>\n </header>\n\n <main className=\"flex-1 overflow-y-auto p-6\">\n <div className=\"mx-auto max-w-6xl space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalProducts', {\n defaultValue: 'Published products',\n })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{metrics.totalProducts}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.totalInstalls', { defaultValue: 'Total downloads' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{metrics.totalDownloads}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <p className=\"text-xs uppercase tracking-wide text-text-muted\">\n {t('pages.publisherDashboard.avgRating', { defaultValue: 'Average rating' })}\n </p>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {metrics.avgRating.toFixed(1)}\n </p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherDashboard.yourProducts', { defaultValue: 'Your Products' })}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/revenue`)}\n className=\"inline-flex cursor-pointer items-center gap-1.5 text-sm font-medium text-text-link hover:underline\"\n >\n <LineChart className=\"size-4\" />\n Revenue\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n {t('common.loading', { defaultValue: 'Loading...' })}\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherDashboard.failedToLoad', {\n defaultValue: 'Failed to load publisher products.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-6 text-center\">\n <Package2 className=\"mx-auto mb-2 size-8 text-text-muted\" />\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherDashboard.noProducts', {\n defaultValue:\n 'No published products yet. Submit your first product to get started.',\n })}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken\"\n >\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">{product.status}</p>\n </div>\n <div className=\"flex items-center gap-4 text-xs text-text-muted\">\n <span className=\"inline-flex items-center gap-1\">\n <Star className=\"size-3.5\" />\n {(product.rating ?? 0).toFixed(1)}\n </span>\n <span className=\"inline-flex items-center gap-1\">\n <Download className=\"size-3.5\" />\n {product.downloads}\n </span>\n </div>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"size-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -18,10 +18,11 @@ var d = () => {
18
18
  children: /* @__PURE__ */ l("div", {
19
19
  className: "mx-auto flex max-w-6xl items-center gap-3",
20
20
  children: [/* @__PURE__ */ c("button", {
21
+ type: "button",
21
22
  onClick: () => d(-1),
22
23
  "aria-label": "Go back",
23
24
  className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
24
- children: /* @__PURE__ */ c(r, { className: "h-5 w-5" })
25
+ children: /* @__PURE__ */ c(r, { className: "size-5" })
25
26
  }), /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("h1", {
26
27
  className: "text-2xl font-bold text-text-primary",
27
28
  children: g("pages.publisherRevenue.title", { defaultValue: "Revenue" })
@@ -37,7 +38,7 @@ var d = () => {
37
38
  children: p ? /* @__PURE__ */ c("p", {
38
39
  role: "status",
39
40
  className: "text-sm text-text-muted",
40
- children: "Loading earnings..."
41
+ children: "Loading earnings"
41
42
  }) : m ? /* @__PURE__ */ l("div", {
42
43
  role: "alert",
43
44
  className: "space-y-2 rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6",
@@ -45,6 +46,7 @@ var d = () => {
45
46
  className: "text-sm text-status-error-text",
46
47
  children: g("pages.publisherRevenue.failedToLoad", { defaultValue: "Failed to load earnings data." })
47
48
  }), /* @__PURE__ */ c("button", {
49
+ type: "button",
48
50
  onClick: () => h(),
49
51
  className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text",
50
52
  children: "Retry"
@@ -57,7 +59,7 @@ var d = () => {
57
59
  children: [/* @__PURE__ */ l("div", {
58
60
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
59
61
  children: [
60
- /* @__PURE__ */ c(o, { className: "h-4 w-4" }),
62
+ /* @__PURE__ */ c(o, { className: "size-4" }),
61
63
  " ",
62
64
  g("pages.publisherRevenue.totalEarnings", { defaultValue: "Total earnings" })
63
65
  ]
@@ -71,7 +73,7 @@ var d = () => {
71
73
  children: [/* @__PURE__ */ l("div", {
72
74
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
73
75
  children: [
74
- /* @__PURE__ */ c(i, { className: "h-4 w-4" }),
76
+ /* @__PURE__ */ c(i, { className: "size-4" }),
75
77
  " ",
76
78
  g("pages.publisherRevenue.monthlyEarnings", { defaultValue: "Monthly earnings" })
77
79
  ]
@@ -85,7 +87,7 @@ var d = () => {
85
87
  children: [/* @__PURE__ */ l("div", {
86
88
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
87
89
  children: [
88
- /* @__PURE__ */ c(a, { className: "h-4 w-4" }),
90
+ /* @__PURE__ */ c(a, { className: "size-4" }),
89
91
  " ",
90
92
  g("pages.publisherRevenue.monthlyOrders", { defaultValue: "Monthly orders" })
91
93
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"PublisherRevenuePage.js","names":[],"sources":["../../src/pages/PublisherRevenuePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Wallet, Clock3, TrendingUp } from 'lucide-react';\nimport { useDeveloperEarnings } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface EarningsPayload {\n totalEarnings: number;\n monthlyEarnings: number;\n totalOrders: number;\n monthlyOrders: number;\n currency: string;\n earnings?: Array<{\n month: string;\n year: number;\n earnings: number;\n orders: number;\n currency: string;\n }>;\n topSellingItems?: Array<{\n storeProduct: { id: string; name: string };\n totalSales: number;\n totalEarnings: number;\n monthlySales: number;\n monthlyEarnings: number;\n currency: string;\n }>;\n}\n\nexport const PublisherRevenuePage: FC = () => {\n const navigate = useNavigate();\n const { earnings, loading, error, refetch } = useDeveloperEarnings();\n const { t } = useI18n();\n\n const data = (earnings as EarningsPayload | null) ?? null;\n const currency = data?.currency || 'USD';\n\n const fmt = useMemo(\n () =>\n new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n maximumFractionDigits: 2,\n }),\n [currency]\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 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=\"h-5 w-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherRevenue.title', { defaultValue: 'Revenue' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.subtitle', {\n defaultValue: 'Track publisher earnings and payouts',\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 space-y-6\">\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading earnings...\n </p>\n ) : error ? (\n <div\n role=\"alert\"\n className=\"space-y-2 rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6\"\n >\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherRevenue.failedToLoad', {\n defaultValue: 'Failed to load earnings data.',\n })}\n </p>\n <button\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : !data ? (\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-8 text-center text-sm text-text-muted\">\n {t('pages.publisherRevenue.noRevenue', {\n defaultValue: 'No revenue data available yet.',\n })}\n </div>\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Wallet className=\"h-4 w-4\" />{' '}\n {t('pages.publisherRevenue.totalEarnings', { defaultValue: 'Total earnings' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {fmt.format(data.totalEarnings)}\n </p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"h-4 w-4\" />{' '}\n {t('pages.publisherRevenue.monthlyEarnings', {\n defaultValue: 'Monthly earnings',\n })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {fmt.format(data.monthlyEarnings)}\n </p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <TrendingUp className=\"h-4 w-4\" />{' '}\n {t('pages.publisherRevenue.monthlyOrders', { defaultValue: 'Monthly orders' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{data.monthlyOrders}</p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <h2 className=\"mb-3 text-lg font-semibold text-text-primary\">\n {t('pages.publisherRevenue.topSelling', { defaultValue: 'Top Selling Items' })}\n </h2>\n {!data.topSellingItems || data.topSellingItems.length === 0 ? (\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.noSales', {\n defaultValue: 'No product sales found for this period.',\n })}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {data.topSellingItems.map((item) => (\n <li\n key={item.storeProduct.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {item.storeProduct.name}\n </p>\n <p className=\"text-xs text-text-muted\">\n {item.totalSales} total sales • {item.monthlySales} this period\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary\">\n {fmt.format(item.totalEarnings)}\n </p>\n </li>\n ))}\n </ul>\n )}\n </div>\n </>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PublisherRevenuePage.js","names":[],"sources":["../../src/pages/PublisherRevenuePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, Wallet, Clock3, TrendingUp } from 'lucide-react';\nimport { useDeveloperEarnings } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface EarningsPayload {\n totalEarnings: number;\n monthlyEarnings: number;\n totalOrders: number;\n monthlyOrders: number;\n currency: string;\n earnings?: Array<{\n month: string;\n year: number;\n earnings: number;\n orders: number;\n currency: string;\n }>;\n topSellingItems?: Array<{\n storeProduct: { id: string; name: string };\n totalSales: number;\n totalEarnings: number;\n monthlySales: number;\n monthlyEarnings: number;\n currency: string;\n }>;\n}\n\nexport const PublisherRevenuePage: FC = () => {\n const navigate = useNavigate();\n const { earnings, loading, error, refetch } = useDeveloperEarnings();\n const { t } = useI18n();\n\n const data = (earnings as EarningsPayload | null) ?? null;\n const currency = data?.currency || 'USD';\n\n const fmt = useMemo(\n () =>\n new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n maximumFractionDigits: 2,\n }),\n [currency]\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.publisherRevenue.title', { defaultValue: 'Revenue' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.subtitle', {\n defaultValue: 'Track publisher earnings and payouts',\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 space-y-6\">\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading earnings…\n </p>\n ) : error ? (\n <div\n role=\"alert\"\n className=\"space-y-2 rounded-xl border border-status-error-border bg-status-error-bg-subtle p-6\"\n >\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherRevenue.failedToLoad', {\n defaultValue: 'Failed to load earnings data.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : !data ? (\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-8 text-center text-sm text-text-muted\">\n {t('pages.publisherRevenue.noRevenue', {\n defaultValue: 'No revenue data available yet.',\n })}\n </div>\n ) : (\n <>\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Wallet className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.totalEarnings', { defaultValue: 'Total earnings' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {fmt.format(data.totalEarnings)}\n </p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.monthlyEarnings', {\n defaultValue: 'Monthly earnings',\n })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">\n {fmt.format(data.monthlyEarnings)}\n </p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <TrendingUp className=\"size-4\" />{' '}\n {t('pages.publisherRevenue.monthlyOrders', { defaultValue: 'Monthly orders' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{data.monthlyOrders}</p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <h2 className=\"mb-3 text-lg font-semibold text-text-primary\">\n {t('pages.publisherRevenue.topSelling', { defaultValue: 'Top Selling Items' })}\n </h2>\n {!data.topSellingItems || data.topSellingItems.length === 0 ? (\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherRevenue.noSales', {\n defaultValue: 'No product sales found for this period.',\n })}\n </p>\n ) : (\n <ul className=\"space-y-2\">\n {data.topSellingItems.map((item) => (\n <li\n key={item.storeProduct.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {item.storeProduct.name}\n </p>\n <p className=\"text-xs text-text-muted\">\n {item.totalSales} total sales • {item.monthlySales} this period\n </p>\n </div>\n <p className=\"text-sm font-semibold text-text-primary\">\n {fmt.format(item.totalEarnings)}\n </p>\n </li>\n ))}\n </ul>\n )}\n </div>\n </>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -34,10 +34,11 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
34
34
  children: /* @__PURE__ */ f("div", {
35
35
  className: "mx-auto flex max-w-6xl items-center gap-3",
36
36
  children: [/* @__PURE__ */ d("button", {
37
+ type: "button",
37
38
  onClick: () => h(-1),
38
39
  "aria-label": "Go back",
39
40
  className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
40
- children: /* @__PURE__ */ d(a, { className: "h-5 w-5" })
41
+ children: /* @__PURE__ */ d(a, { className: "size-5" })
41
42
  }), /* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("h1", {
42
43
  className: "text-2xl font-bold text-text-primary",
43
44
  children: w("pages.publisherSubmissions.title", { defaultValue: "Submissions" })
@@ -58,7 +59,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
58
59
  children: [/* @__PURE__ */ f("div", {
59
60
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
60
61
  children: [
61
- /* @__PURE__ */ d(s, { className: "h-4 w-4" }),
62
+ /* @__PURE__ */ d(s, { className: "size-4" }),
62
63
  " ",
63
64
  w("store.status.pending", { defaultValue: "Pending" })
64
65
  ]
@@ -72,7 +73,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
72
73
  children: [/* @__PURE__ */ f("div", {
73
74
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
74
75
  children: [
75
- /* @__PURE__ */ d(o, { className: "h-4 w-4" }),
76
+ /* @__PURE__ */ d(o, { className: "size-4" }),
76
77
  " ",
77
78
  w("store.status.approved", { defaultValue: "Approved" })
78
79
  ]
@@ -86,7 +87,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
86
87
  children: [/* @__PURE__ */ f("div", {
87
88
  className: "inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted",
88
89
  children: [
89
- /* @__PURE__ */ d(u, { className: "h-4 w-4" }),
90
+ /* @__PURE__ */ d(u, { className: "size-4" }),
90
91
  " ",
91
92
  w("store.status.rejected", { defaultValue: "Rejected" })
92
93
  ]
@@ -104,6 +105,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
104
105
  className: "text-lg font-semibold text-text-primary",
105
106
  children: w("pages.publisherSubmissions.timeline", { defaultValue: "Submission Timeline" })
106
107
  }), /* @__PURE__ */ d("button", {
108
+ type: "button",
107
109
  onClick: () => h(`${g}/publisher/submit`),
108
110
  className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-semibold text-action-primary-text",
109
111
  children: w("pages.publisherSubmissions.newSubmission", { defaultValue: "New Submission" })
@@ -111,7 +113,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
111
113
  }), b ? /* @__PURE__ */ d("p", {
112
114
  role: "status",
113
115
  className: "text-sm text-text-muted",
114
- children: "Loading submissions..."
116
+ children: "Loading submissions"
115
117
  }) : x ? /* @__PURE__ */ f("div", {
116
118
  role: "alert",
117
119
  className: "space-y-2",
@@ -119,13 +121,14 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
119
121
  className: "text-sm text-status-error-text",
120
122
  children: w("pages.publisherSubmissions.failedToLoad", { defaultValue: "Failed to load submissions." })
121
123
  }), /* @__PURE__ */ d("button", {
124
+ type: "button",
122
125
  onClick: () => S(),
123
126
  className: "cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text",
124
127
  children: "Retry"
125
128
  })]
126
129
  }) : v.length === 0 ? /* @__PURE__ */ f("div", {
127
130
  className: "rounded-lg border border-border-default bg-bg-sunken p-8 text-center",
128
- children: [/* @__PURE__ */ d(c, { className: "mx-auto mb-2 h-10 w-10 text-text-muted" }), /* @__PURE__ */ d("p", {
131
+ children: [/* @__PURE__ */ d(c, { className: "mx-auto mb-2 size-10 text-text-muted" }), /* @__PURE__ */ d("p", {
129
132
  className: "text-sm text-text-muted",
130
133
  children: w("pages.publisherSubmissions.emptyTitle", { defaultValue: "No submissions found yet." })
131
134
  })]
@@ -134,6 +137,7 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
134
137
  children: [v.map((e) => /* @__PURE__ */ f("li", {
135
138
  className: "flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken",
136
139
  children: [/* @__PURE__ */ f("button", {
140
+ type: "button",
137
141
  onClick: () => h(`${g}/marketplace/product/${e.id}`),
138
142
  className: "flex flex-1 cursor-pointer items-center justify-between text-left",
139
143
  children: [/* @__PURE__ */ f("div", { children: [/* @__PURE__ */ d("p", {
@@ -147,10 +151,11 @@ var m = (e) => e === "PUBLISHED" || e === "APPROVED" ? "bg-status-success-bg-sub
147
151
  children: e.status
148
152
  })]
149
153
  }), /* @__PURE__ */ f("button", {
154
+ type: "button",
150
155
  onClick: () => h(`${g}/publisher/product/${e.id}/reviews`),
151
156
  className: "ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline",
152
157
  title: "View reviews",
153
- children: [/* @__PURE__ */ d(l, { className: "h-3.5 w-3.5" }), "Reviews"]
158
+ children: [/* @__PURE__ */ d(l, { className: "size-3.5" }), "Reviews"]
154
159
  })]
155
160
  }, e.id)), y && /* @__PURE__ */ d("li", {
156
161
  className: "flex justify-center pt-4 list-none",
@@ -1 +1 @@
1
- {"version":3,"file":"PublisherSubmissionsPage.js","names":[],"sources":["../../src/pages/PublisherSubmissionsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, FileCheck2, Clock3, CheckCircle2, XCircle, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useSubmissionStatusUpdatedSubscription } from '../generated/global-operations';\n\nconst statusClass = (status: string): string => {\n if (status === 'PUBLISHED' || status === 'APPROVED') {\n return 'bg-status-success-bg-subtle text-status-success-text';\n }\n if (status === 'REJECTED' || status === 'UNLISTED') {\n return 'bg-status-error-bg-subtle text-status-error-text';\n }\n if (status === 'PENDING' || status === 'SUBMITTED' || status === 'UNDER_REVIEW') {\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n }\n return 'bg-bg-sunken text-text-muted';\n};\n\nexport const PublisherSubmissionsPage: FC = () => {\n const navigate = useNavigate();\n const { basePath, currentUser } = useStore();\n const { products, hasMore, loading, error, refetch, loadMore } = useMyPublishedProducts();\n const { t } = useI18n();\n\n const publisherId = currentUser?.id;\n useSubmissionStatusUpdatedSubscription({\n variables: { publisherId: publisherId ?? '' },\n skip: !publisherId,\n onData: () => {\n void refetch();\n },\n onError: (err) => {\n console.warn('SubmissionStatusUpdated subscription error:', err.message);\n },\n });\n\n const grouped = useMemo(() => {\n const approved = products.filter(\n (p) => p.status === 'PUBLISHED' || p.status === 'APPROVED'\n ).length;\n const rejected = products.filter(\n (p) => p.status === 'REJECTED' || p.status === 'UNLISTED'\n ).length;\n const pending = products.length - approved - rejected;\n return { approved, rejected, pending };\n }, [products]);\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 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=\"h-5 w-5\" />\n </button>\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">\n {t('pages.publisherSubmissions.title', { defaultValue: 'Submissions' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherSubmissions.subtitle', {\n defaultValue: 'Track approval status for your store products',\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 space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"h-4 w-4\" />{' '}\n {t('store.status.pending', { defaultValue: 'Pending' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.pending}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <CheckCircle2 className=\"h-4 w-4\" />{' '}\n {t('store.status.approved', { defaultValue: 'Approved' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.approved}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <XCircle className=\"h-4 w-4\" />{' '}\n {t('store.status.rejected', { defaultValue: 'Rejected' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.rejected}</p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherSubmissions.timeline', { defaultValue: 'Submission Timeline' })}\n </h2>\n <button\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-semibold text-action-primary-text\"\n >\n {t('pages.publisherSubmissions.newSubmission', { defaultValue: 'New Submission' })}\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading submissions...\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherSubmissions.failedToLoad', {\n defaultValue: 'Failed to load submissions.',\n })}\n </p>\n <button\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-8 text-center\">\n <FileCheck2 className=\"mx-auto mb-2 h-10 w-10 text-text-muted\" />\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherSubmissions.emptyTitle', {\n defaultValue: 'No submissions found yet.',\n })}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken\"\n >\n <button\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">Reviews: {product.reviewCount}</p>\n </div>\n <span\n className={`rounded-full px-2.5 py-1 text-xs font-semibold ${statusClass(product.status)}`}\n >\n {product.status}\n </span>\n </button>\n <button\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"h-3.5 w-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n {hasMore && (\n <li className=\"flex justify-center pt-4 list-none\">\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 </li>\n )}\n </ul>\n )}\n </div>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PublisherSubmissionsPage.js","names":[],"sources":["../../src/pages/PublisherSubmissionsPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useMemo } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { ArrowLeft, FileCheck2, Clock3, CheckCircle2, XCircle, MessageSquare } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useMyPublishedProducts } from '../hooks/useStoreGraphQL';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useSubmissionStatusUpdatedSubscription } from '../generated/global-operations';\n\nconst statusClass = (status: string): string => {\n if (status === 'PUBLISHED' || status === 'APPROVED') {\n return 'bg-status-success-bg-subtle text-status-success-text';\n }\n if (status === 'REJECTED' || status === 'UNLISTED') {\n return 'bg-status-error-bg-subtle text-status-error-text';\n }\n if (status === 'PENDING' || status === 'SUBMITTED' || status === 'UNDER_REVIEW') {\n return 'bg-status-warning-bg-subtle text-status-warning-text';\n }\n return 'bg-bg-sunken text-text-muted';\n};\n\nexport const PublisherSubmissionsPage: FC = () => {\n const navigate = useNavigate();\n const { basePath, currentUser } = useStore();\n const { products, hasMore, loading, error, refetch, loadMore } = useMyPublishedProducts();\n const { t } = useI18n();\n\n const publisherId = currentUser?.id;\n useSubmissionStatusUpdatedSubscription({\n variables: { publisherId: publisherId ?? '' },\n skip: !publisherId,\n onData: () => {\n void refetch();\n },\n onError: (err) => {\n console.warn('SubmissionStatusUpdated subscription error:', err.message);\n },\n });\n\n const grouped = useMemo(() => {\n const approved = products.filter(\n (p) => p.status === 'PUBLISHED' || p.status === 'APPROVED'\n ).length;\n const rejected = products.filter(\n (p) => p.status === 'REJECTED' || p.status === 'UNLISTED'\n ).length;\n const pending = products.length - approved - rejected;\n return { approved, rejected, pending };\n }, [products]);\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.publisherSubmissions.title', { defaultValue: 'Submissions' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherSubmissions.subtitle', {\n defaultValue: 'Track approval status for your store products',\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 space-y-6\">\n <div className=\"grid gap-4 sm:grid-cols-3\">\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <Clock3 className=\"size-4\" />{' '}\n {t('store.status.pending', { defaultValue: 'Pending' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.pending}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <CheckCircle2 className=\"size-4\" />{' '}\n {t('store.status.approved', { defaultValue: 'Approved' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.approved}</p>\n </div>\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-4\">\n <div className=\"inline-flex items-center gap-2 text-xs uppercase tracking-wide text-text-muted\">\n <XCircle className=\"size-4\" />{' '}\n {t('store.status.rejected', { defaultValue: 'Rejected' })}\n </div>\n <p className=\"mt-2 text-2xl font-bold text-text-primary\">{grouped.rejected}</p>\n </div>\n </div>\n\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.publisherSubmissions.timeline', { defaultValue: 'Submission Timeline' })}\n </h2>\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/publisher/submit`)}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-sm font-semibold text-action-primary-text\"\n >\n {t('pages.publisherSubmissions.newSubmission', { defaultValue: 'New Submission' })}\n </button>\n </div>\n\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading submissions…\n </p>\n ) : error ? (\n <div role=\"alert\" className=\"space-y-2\">\n <p className=\"text-sm text-status-error-text\">\n {t('pages.publisherSubmissions.failedToLoad', {\n defaultValue: 'Failed to load submissions.',\n })}\n </p>\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"cursor-pointer rounded-lg bg-action-primary-bg px-3 py-1.5 text-xs font-semibold text-action-primary-text\"\n >\n Retry\n </button>\n </div>\n ) : products.length === 0 ? (\n <div className=\"rounded-lg border border-border-default bg-bg-sunken p-8 text-center\">\n <FileCheck2 className=\"mx-auto mb-2 size-10 text-text-muted\" />\n <p className=\"text-sm text-text-muted\">\n {t('pages.publisherSubmissions.emptyTitle', {\n defaultValue: 'No submissions found yet.',\n })}\n </p>\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {products.map((product) => (\n <li\n key={product.id}\n className=\"flex items-center justify-between rounded-lg border border-border-default p-3 transition-colors hover:bg-bg-sunken\"\n >\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/marketplace/product/${product.id}`)}\n className=\"flex flex-1 cursor-pointer items-center justify-between text-left\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">{product.name}</p>\n <p className=\"text-xs text-text-muted\">Reviews: {product.reviewCount}</p>\n </div>\n <span\n className={`rounded-full px-2.5 py-1 text-xs font-semibold ${statusClass(product.status)}`}\n >\n {product.status}\n </span>\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/publisher/product/${product.id}/reviews`)\n }\n className=\"ml-3 inline-flex cursor-pointer items-center gap-1 rounded-md px-2 py-1 text-xs font-medium text-text-link hover:bg-bg-sunken hover:underline\"\n title=\"View reviews\"\n >\n <MessageSquare className=\"size-3.5\" />\n Reviews\n </button>\n </li>\n ))}\n {hasMore && (\n <li className=\"flex justify-center pt-4 list-none\">\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 </li>\n )}\n </ul>\n )}\n </div>\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -94,6 +94,7 @@ var o = JSON.stringify({
94
94
  className: "text-sm text-text-secondary",
95
95
  children: "Product Name"
96
96
  }), /* @__PURE__ */ r("input", {
97
+ "aria-label": "Product Name",
97
98
  value: c,
98
99
  onChange: (e) => l(e.target.value),
99
100
  required: !0,
@@ -108,6 +109,7 @@ var o = JSON.stringify({
108
109
  className: "text-sm text-text-secondary",
109
110
  children: "Slug"
110
111
  }), /* @__PURE__ */ r("input", {
112
+ "aria-label": "Slug",
111
113
  value: u,
112
114
  onChange: (e) => d(e.target.value),
113
115
  required: !0,
@@ -122,6 +124,7 @@ var o = JSON.stringify({
122
124
  className: "text-sm text-text-secondary",
123
125
  children: "Type"
124
126
  }), /* @__PURE__ */ i("select", {
127
+ "aria-label": "Product type",
125
128
  value: m,
126
129
  onChange: (e) => h(e.target.value),
127
130
  className: "w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary",
@@ -156,6 +159,7 @@ var o = JSON.stringify({
156
159
  children: "Price"
157
160
  }), /* @__PURE__ */ r("input", {
158
161
  type: "number",
162
+ "aria-label": "Price",
159
163
  min: "0",
160
164
  step: "0.01",
161
165
  value: g,
@@ -171,6 +175,7 @@ var o = JSON.stringify({
171
175
  className: "text-sm text-text-secondary",
172
176
  children: "Description"
173
177
  }), /* @__PURE__ */ r("textarea", {
178
+ "aria-label": "Description",
174
179
  value: f,
175
180
  onChange: (e) => p(e.target.value),
176
181
  rows: 3,
@@ -185,6 +190,7 @@ var o = JSON.stringify({
185
190
  children: "Manifest (JSON)"
186
191
  }),
187
192
  /* @__PURE__ */ r("textarea", {
193
+ "aria-label": "Manifest JSON",
188
194
  value: v,
189
195
  onChange: (e) => y(e.target.value),
190
196
  rows: 16,
@@ -1 +1 @@
1
- {"version":3,"file":"PublisherSubmitPage.js","names":[],"sources":["../../src/pages/PublisherSubmitPage.tsx"],"sourcesContent":["import { useApolloClient } from '@apollo/client/react';\nimport { useMemo, useState, type FC, type FormEvent } from 'react';\n\nimport { CreateProductForPublisherDocument } from '../generated/global-operations';\n\nconst DEFAULT_MANIFEST = JSON.stringify(\n {\n schemaVersion: '1.0.0',\n itemType: 'app',\n author: { name: 'Publisher Team' },\n compatibility: {\n minVersion: '2026.1.0',\n products: ['workspaces'],\n },\n permissions: ['workspace:read'],\n dependencies: {\n integrations: [],\n },\n },\n null,\n 2\n);\n\nexport const PublisherSubmitPage: FC = () => {\n const client = useApolloClient();\n\n const [name, setName] = useState('');\n const [slug, setSlug] = useState('');\n const [description, setDescription] = useState('');\n const [type, setType] = useState('APP');\n const [price, setPrice] = useState('0');\n const [manifestText, setManifestText] = useState(DEFAULT_MANIFEST);\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState<string | null>(null);\n\n const parsedManifest = useMemo(() => {\n try {\n return { value: JSON.parse(manifestText), error: null as string | null };\n } catch {\n return { value: null, error: 'Manifest JSON is invalid.' };\n }\n }, [manifestText]);\n\n const submitProduct = async (event: FormEvent) => {\n event.preventDefault();\n setError(null);\n setSuccess(null);\n\n if (!name.trim()) {\n setError('Product name is required.');\n return;\n }\n if (!slug.trim()) {\n setError('Product slug is required.');\n return;\n }\n if (parsedManifest.error || !parsedManifest.value) {\n setError(parsedManifest.error || 'Manifest JSON is required.');\n return;\n }\n\n const numericPrice = Number(price);\n if (!Number.isFinite(numericPrice) || numericPrice < 0) {\n setError('Price must be a valid non-negative number.');\n return;\n }\n\n setSubmitting(true);\n try {\n const result = await client.mutate<{\n createProduct?: { id: string; slug: string; status: string };\n }>({\n mutation: CreateProductForPublisherDocument,\n variables: {\n input: {\n name: name.trim(),\n slug: slug.trim(),\n type,\n price: numericPrice,\n pricingModel: numericPrice === 0 ? 'FREE' : 'PAID_ONETIME',\n description: description.trim() || undefined,\n manifest: parsedManifest.value,\n },\n },\n });\n\n const created = result.data?.createProduct;\n if (!created) {\n setError('Product creation failed: no product returned by API.');\n return;\n }\n\n setSuccess(`Created ${created.slug} (${created.status})`);\n setName('');\n setSlug('');\n setDescription('');\n } catch (mutationError) {\n const message = mutationError instanceof Error ? mutationError.message : 'Unknown error';\n setError(message);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <main className=\"mx-auto max-w-4xl p-6\">\n <header className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold text-text-primary\">Submit Product</h1>\n <p className=\"mt-1 text-sm text-text-muted\">\n Create a store product with manifest JSON (raw mode).\n </p>\n </header>\n\n <form onSubmit={submitProduct} className=\"space-y-4\" aria-label=\"Submit Product\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Product Name</span>\n <input\n value={name}\n onChange={(event) => setName(event.target.value)}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n placeholder=\"Acme Automation\"\n />\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Slug</span>\n <input\n value={slug}\n onChange={(event) => setSlug(event.target.value)}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n placeholder=\"acme-automation\"\n />\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Type</span>\n <select\n value={type}\n onChange={(event) => setType(event.target.value)}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"APP\">APP</option>\n <option value=\"AGENT\">AGENT</option>\n <option value=\"NODE\">NODE</option>\n <option value=\"WIDGET\">WIDGET</option>\n <option value=\"WORKFLOW\">WORKFLOW</option>\n </select>\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Price</span>\n <input\n type=\"number\"\n min=\"0\"\n step=\"0.01\"\n value={price}\n onChange={(event) => setPrice(event.target.value)}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n </div>\n\n <label className=\"block space-y-1\">\n <span className=\"text-sm text-text-secondary\">Description</span>\n <textarea\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n rows={3}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n\n <label className=\"block space-y-1\">\n <span className=\"text-sm text-text-secondary\">Manifest (JSON)</span>\n <textarea\n value={manifestText}\n onChange={(event) => setManifestText(event.target.value)}\n rows={16}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 font-mono text-xs text-text-primary\"\n />\n {parsedManifest.error && (\n <p className=\"text-xs text-status-error-text\">{parsedManifest.error}</p>\n )}\n </label>\n\n {error && (\n <p\n role=\"alert\"\n className=\"rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {error}\n </p>\n )}\n {success && (\n <p\n role=\"status\"\n className=\"rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm text-status-success-text\"\n >\n {success}\n </p>\n )}\n\n <button\n type=\"submit\"\n disabled={submitting}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {submitting ? 'Submitting...' : 'Submit Product'}\n </button>\n </form>\n </main>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"PublisherSubmitPage.js","names":[],"sources":["../../src/pages/PublisherSubmitPage.tsx"],"sourcesContent":["import { useApolloClient } from '@apollo/client/react';\nimport { useMemo, useState, type FC, type FormEvent } from 'react';\n\nimport { CreateProductForPublisherDocument } from '../generated/global-operations';\n\nconst DEFAULT_MANIFEST = JSON.stringify(\n {\n schemaVersion: '1.0.0',\n itemType: 'app',\n author: { name: 'Publisher Team' },\n compatibility: {\n minVersion: '2026.1.0',\n products: ['workspaces'],\n },\n permissions: ['workspace:read'],\n dependencies: {\n integrations: [],\n },\n },\n null,\n 2\n);\n\nexport const PublisherSubmitPage: FC = () => {\n const client = useApolloClient();\n\n const [name, setName] = useState('');\n const [slug, setSlug] = useState('');\n const [description, setDescription] = useState('');\n const [type, setType] = useState('APP');\n const [price, setPrice] = useState('0');\n const [manifestText, setManifestText] = useState(DEFAULT_MANIFEST);\n const [submitting, setSubmitting] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState<string | null>(null);\n\n const parsedManifest = useMemo(() => {\n try {\n return { value: JSON.parse(manifestText), error: null as string | null };\n } catch {\n return { value: null, error: 'Manifest JSON is invalid.' };\n }\n }, [manifestText]);\n\n const submitProduct = async (event: FormEvent) => {\n event.preventDefault();\n setError(null);\n setSuccess(null);\n\n if (!name.trim()) {\n setError('Product name is required.');\n return;\n }\n if (!slug.trim()) {\n setError('Product slug is required.');\n return;\n }\n if (parsedManifest.error || !parsedManifest.value) {\n setError(parsedManifest.error || 'Manifest JSON is required.');\n return;\n }\n\n const numericPrice = Number(price);\n if (!Number.isFinite(numericPrice) || numericPrice < 0) {\n setError('Price must be a valid non-negative number.');\n return;\n }\n\n setSubmitting(true);\n try {\n const result = await client.mutate<{\n createProduct?: { id: string; slug: string; status: string };\n }>({\n mutation: CreateProductForPublisherDocument,\n variables: {\n input: {\n name: name.trim(),\n slug: slug.trim(),\n type,\n price: numericPrice,\n pricingModel: numericPrice === 0 ? 'FREE' : 'PAID_ONETIME',\n description: description.trim() || undefined,\n manifest: parsedManifest.value,\n },\n },\n });\n\n const created = result.data?.createProduct;\n if (!created) {\n setError('Product creation failed: no product returned by API.');\n return;\n }\n\n setSuccess(`Created ${created.slug} (${created.status})`);\n setName('');\n setSlug('');\n setDescription('');\n } catch (mutationError) {\n const message = mutationError instanceof Error ? mutationError.message : 'Unknown error';\n setError(message);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <main className=\"mx-auto max-w-4xl p-6\">\n <header className=\"mb-6\">\n <h1 className=\"text-2xl font-semibold text-text-primary\">Submit Product</h1>\n <p className=\"mt-1 text-sm text-text-muted\">\n Create a store product with manifest JSON (raw mode).\n </p>\n </header>\n\n <form onSubmit={submitProduct} className=\"space-y-4\" aria-label=\"Submit Product\">\n <div className=\"grid gap-4 md:grid-cols-2\">\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Product Name</span>\n <input\n aria-label=\"Product Name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n placeholder=\"Acme Automation\"\n />\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Slug</span>\n <input\n aria-label=\"Slug\"\n value={slug}\n onChange={(event) => setSlug(event.target.value)}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n placeholder=\"acme-automation\"\n />\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Type</span>\n <select\n aria-label=\"Product type\"\n value={type}\n onChange={(event) => setType(event.target.value)}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"APP\">APP</option>\n <option value=\"AGENT\">AGENT</option>\n <option value=\"NODE\">NODE</option>\n <option value=\"WIDGET\">WIDGET</option>\n <option value=\"WORKFLOW\">WORKFLOW</option>\n </select>\n </label>\n\n <label className=\"space-y-1\">\n <span className=\"text-sm text-text-secondary\">Price</span>\n <input\n type=\"number\"\n aria-label=\"Price\"\n min=\"0\"\n step=\"0.01\"\n value={price}\n onChange={(event) => setPrice(event.target.value)}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n </div>\n\n <label className=\"block space-y-1\">\n <span className=\"text-sm text-text-secondary\">Description</span>\n <textarea\n aria-label=\"Description\"\n value={description}\n onChange={(event) => setDescription(event.target.value)}\n rows={3}\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </label>\n\n <label className=\"block space-y-1\">\n <span className=\"text-sm text-text-secondary\">Manifest (JSON)</span>\n <textarea\n aria-label=\"Manifest JSON\"\n value={manifestText}\n onChange={(event) => setManifestText(event.target.value)}\n rows={16}\n required\n aria-required=\"true\"\n className=\"w-full rounded-md border border-border-default bg-bg-surface px-3 py-2 font-mono text-xs text-text-primary\"\n />\n {parsedManifest.error && (\n <p className=\"text-xs text-status-error-text\">{parsedManifest.error}</p>\n )}\n </label>\n\n {error && (\n <p\n role=\"alert\"\n className=\"rounded-md bg-status-error-bg-subtle px-3 py-2 text-sm text-status-error-text\"\n >\n {error}\n </p>\n )}\n {success && (\n <p\n role=\"status\"\n className=\"rounded-md bg-status-success-bg-subtle px-3 py-2 text-sm text-status-success-text\"\n >\n {success}\n </p>\n )}\n\n <button\n type=\"submit\"\n disabled={submitting}\n className=\"rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {submitting ? 'Submitting...' : 'Submit Product'}\n </button>\n </form>\n </main>\n );\n};\n"],"mappings":";;;;;AAKA,IAAM,IAAmB,KAAK,UAC5B;CACE,eAAe;CACf,UAAU;CACV,QAAQ,EAAE,MAAM,kBAAkB;CAClC,eAAe;EACb,YAAY;EACZ,UAAU,CAAC,aAAa;EACzB;CACD,aAAa,CAAC,iBAAiB;CAC/B,cAAc,EACZ,cAAc,EAAE,EACjB;CACF,EACD,MACA,EACD,EAEY,UAAgC;CAC3C,IAAM,IAAS,GAAiB,EAE1B,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAM,KAAW,EAAS,MAAM,EACjC,CAAC,GAAO,KAAY,EAAS,IAAI,EACjC,CAAC,GAAc,KAAmB,EAAS,EAAiB,EAC5D,CAAC,GAAY,KAAiB,EAAS,GAAM,EAC7C,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAS,KAAc,EAAwB,KAAK,EAErD,IAAiB,QAAc;AACnC,MAAI;AACF,UAAO;IAAE,OAAO,KAAK,MAAM,EAAa;IAAE,OAAO;IAAuB;UAClE;AACN,UAAO;IAAE,OAAO;IAAM,OAAO;IAA6B;;IAE3D,CAAC,EAAa,CAAC;AA+DlB,QACE,kBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,kBAAC,UAAD;GAAQ,WAAU;aAAlB,CACE,kBAAC,MAAD;IAAI,WAAU;cAA2C;IAAmB,CAAA,EAC5E,kBAAC,KAAD;IAAG,WAAU;cAA+B;IAExC,CAAA,CACG;MAET,kBAAC,QAAD;GAAM,UAtEY,OAAO,MAAqB;AAKhD,QAJA,EAAM,gBAAgB,EACtB,EAAS,KAAK,EACd,EAAW,KAAK,EAEZ,CAAC,EAAK,MAAM,EAAE;AAChB,OAAS,4BAA4B;AACrC;;AAEF,QAAI,CAAC,EAAK,MAAM,EAAE;AAChB,OAAS,4BAA4B;AACrC;;AAEF,QAAI,EAAe,SAAS,CAAC,EAAe,OAAO;AACjD,OAAS,EAAe,SAAS,6BAA6B;AAC9D;;IAGF,IAAM,IAAe,OAAO,EAAM;AAClC,QAAI,CAAC,OAAO,SAAS,EAAa,IAAI,IAAe,GAAG;AACtD,OAAS,6CAA6C;AACtD;;AAGF,MAAc,GAAK;AACnB,QAAI;KAkBF,IAAM,KAjBS,MAAM,EAAO,OAEzB;MACD,UAAU;MACV,WAAW,EACT,OAAO;OACL,MAAM,EAAK,MAAM;OACjB,MAAM,EAAK,MAAM;OACjB;OACA,OAAO;OACP,cAAc,MAAiB,IAAI,SAAS;OAC5C,aAAa,EAAY,MAAM,IAAI,KAAA;OACnC,UAAU,EAAe;OAC1B,EACF;MACF,CAAC,EAEqB,MAAM;AAC7B,SAAI,CAAC,GAAS;AACZ,QAAS,uDAAuD;AAChE;;AAMF,KAHA,EAAW,WAAW,EAAQ,KAAK,IAAI,EAAQ,OAAO,GAAG,EACzD,EAAQ,GAAG,EACX,EAAQ,GAAG,EACX,EAAe,GAAG;aACX,GAAe;AAEtB,OADgB,aAAyB,QAAQ,EAAc,UAAU,gBACxD;cACT;AACR,OAAc,GAAM;;;GAaW,WAAU;GAAY,cAAW;aAAhE;IACE,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAmB,CAAA,EACjE,kBAAC,SAAD;QACE,cAAW;QACX,OAAO;QACP,WAAW,MAAU,EAAQ,EAAM,OAAO,MAAM;QAChD,UAAA;QACA,iBAAc;QACd,WAAU;QACV,aAAY;QACZ,CAAA,CACI;;MAER,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAW,CAAA,EACzD,kBAAC,SAAD;QACE,cAAW;QACX,OAAO;QACP,WAAW,MAAU,EAAQ,EAAM,OAAO,MAAM;QAChD,UAAA;QACA,iBAAc;QACd,WAAU;QACV,aAAY;QACZ,CAAA,CACI;;MAER,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAW,CAAA,EACzD,kBAAC,UAAD;QACE,cAAW;QACX,OAAO;QACP,WAAW,MAAU,EAAQ,EAAM,OAAO,MAAM;QAChD,WAAU;kBAJZ;SAME,kBAAC,UAAD;UAAQ,OAAM;oBAAM;UAAY,CAAA;SAChC,kBAAC,UAAD;UAAQ,OAAM;oBAAQ;UAAc,CAAA;SACpC,kBAAC,UAAD;UAAQ,OAAM;oBAAO;UAAa,CAAA;SAClC,kBAAC,UAAD;UAAQ,OAAM;oBAAS;UAAe,CAAA;SACtC,kBAAC,UAAD;UAAQ,OAAM;oBAAW;UAAiB,CAAA;SACnC;UACH;;MAER,kBAAC,SAAD;OAAO,WAAU;iBAAjB,CACE,kBAAC,QAAD;QAAM,WAAU;kBAA8B;QAAY,CAAA,EAC1D,kBAAC,SAAD;QACE,MAAK;QACL,cAAW;QACX,KAAI;QACJ,MAAK;QACL,OAAO;QACP,WAAW,MAAU,EAAS,EAAM,OAAO,MAAM;QACjD,WAAU;QACV,CAAA,CACI;;MACJ;;IAEN,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,QAAD;MAAM,WAAU;gBAA8B;MAAkB,CAAA,EAChE,kBAAC,YAAD;MACE,cAAW;MACX,OAAO;MACP,WAAW,MAAU,EAAe,EAAM,OAAO,MAAM;MACvD,MAAM;MACN,WAAU;MACV,CAAA,CACI;;IAER,kBAAC,SAAD;KAAO,WAAU;eAAjB;MACE,kBAAC,QAAD;OAAM,WAAU;iBAA8B;OAAsB,CAAA;MACpE,kBAAC,YAAD;OACE,cAAW;OACX,OAAO;OACP,WAAW,MAAU,EAAgB,EAAM,OAAO,MAAM;OACxD,MAAM;OACN,UAAA;OACA,iBAAc;OACd,WAAU;OACV,CAAA;MACD,EAAe,SACd,kBAAC,KAAD;OAAG,WAAU;iBAAkC,EAAe;OAAU,CAAA;MAEpE;;IAEP,KACC,kBAAC,KAAD;KACE,MAAK;KACL,WAAU;eAET;KACC,CAAA;IAEL,KACC,kBAAC,KAAD;KACE,MAAK;KACL,WAAU;eAET;KACC,CAAA;IAGN,kBAAC,UAAD;KACE,MAAK;KACL,UAAU;KACV,WAAU;eAET,IAAa,kBAAkB;KACzB,CAAA;IACJ;KACF"}
@@ -7,6 +7,7 @@ import { Fragment as c, jsx as l, jsxs as u } from "react/jsx-runtime";
7
7
  import { useNavigate as d, useSearchParams as f } from "react-router-dom";
8
8
  //#region src/pages/SearchResultsPage.tsx
9
9
  var p = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ u("button", {
10
+ type: "button",
10
11
  onClick: () => t(e.id),
11
12
  className: "cursor-pointer rounded-xl border border-border-default bg-bg-surface p-4 text-left transition-colors hover:bg-bg-sunken",
12
13
  children: [
@@ -40,10 +41,11 @@ var p = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ u("button", {
40
41
  children: [/* @__PURE__ */ u("div", {
41
42
  className: "mb-3 flex items-center gap-3",
42
43
  children: [/* @__PURE__ */ l("button", {
44
+ type: "button",
43
45
  onClick: () => m(-1),
44
46
  "aria-label": "Go back",
45
47
  className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
46
- children: /* @__PURE__ */ l(o, { className: "h-5 w-5" })
48
+ children: /* @__PURE__ */ l(o, { className: "size-5" })
47
49
  }), /* @__PURE__ */ l("h1", {
48
50
  className: "text-2xl font-bold text-text-primary",
49
51
  children: x("pages.search.title", { defaultValue: "Search Results" })
@@ -68,9 +70,10 @@ var p = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ u("button", {
68
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"
69
71
  }),
70
72
  /* @__PURE__ */ u("button", {
73
+ type: "button",
71
74
  onClick: k,
72
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",
73
- children: [/* @__PURE__ */ l(s, { className: "h-4 w-4" }), " Search"]
76
+ children: [/* @__PURE__ */ l(s, { className: "size-4" }), " Search"]
74
77
  })
75
78
  ]
76
79
  })]
@@ -90,7 +93,7 @@ var p = ({ product: e, onOpen: t, noDesc: n }) => /* @__PURE__ */ u("button", {
90
93
  }), E && C.length === 0 ? /* @__PURE__ */ l("p", {
91
94
  role: "status",
92
95
  className: "text-sm text-text-muted",
93
- children: "Searching..."
96
+ children: "Searching"
94
97
  }) : D ? /* @__PURE__ */ l("p", {
95
98
  role: "alert",
96
99
  className: "text-sm text-status-error-text",