@burdenoff/microfe-store 2026.625.5 → 2026.626.2

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 (189) hide show
  1. package/dist/StoreRoot.js +47 -90
  2. package/dist/StoreRoot.js.map +1 -1
  3. package/dist/StoreRoutes.js +93 -158
  4. package/dist/StoreRoutes.js.map +1 -1
  5. package/dist/components/AccessDenied.js +3 -3
  6. package/dist/components/AccessDenied.js.map +1 -1
  7. package/dist/components/InstallAppModal.js +175 -255
  8. package/dist/components/InstallAppModal.js.map +1 -1
  9. package/dist/components/cart/CartDrawer.js +10 -10
  10. package/dist/components/cart/CartDrawer.js.map +1 -1
  11. package/dist/hooks/useStoreGraphQL.js +107 -177
  12. package/dist/hooks/useStoreGraphQL.js.map +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/errors/CombinedGraphQLErrors.js +1 -1
  15. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -0
  16. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/errors/utils.js +1 -1
  17. package/dist/node_modules/@apollo/client/errors/utils.js.map +1 -0
  18. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/link/core/ApolloLink.js +2 -2
  19. package/dist/node_modules/@apollo/client/link/core/ApolloLink.js.map +1 -0
  20. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/link/subscriptions/index.js +2 -2
  21. package/dist/node_modules/@apollo/client/link/subscriptions/index.js.map +1 -0
  22. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/link/utils/createOperation.js +1 -1
  23. package/dist/node_modules/@apollo/client/link/utils/createOperation.js.map +1 -0
  24. package/dist/node_modules/@apollo/client/utilities/caching/sizes.js.map +1 -0
  25. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/graphql/print.js +1 -1
  26. package/dist/node_modules/@apollo/client/utilities/graphql/print.js.map +1 -0
  27. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/caches.js +2 -2
  28. package/dist/node_modules/@apollo/client/utilities/internal/caches.js.map +1 -0
  29. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/checkDocument.js +1 -1
  30. package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +1 -0
  31. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/getMainDefinition.js +1 -1
  32. package/dist/node_modules/@apollo/client/utilities/internal/getMainDefinition.js.map +1 -0
  33. package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +9 -0
  34. package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +1 -0
  35. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/getOperationDefinition.js +1 -1
  36. package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +1 -0
  37. package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js +8 -0
  38. package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +1 -0
  39. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/globals/global.js +1 -1
  40. package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js.map +1 -0
  41. package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js +10 -0
  42. package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +1 -0
  43. package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js +8 -0
  44. package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js.map +1 -0
  45. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/makeUniqueId.js +1 -1
  46. package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +1 -0
  47. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/memoize.js +2 -2
  48. package/dist/node_modules/@apollo/client/utilities/internal/memoize.js.map +1 -0
  49. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/internal/stringifyForDisplay.js +1 -1
  50. package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +1 -0
  51. package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/invariant/index.js +1 -1
  52. package/dist/node_modules/@apollo/client/utilities/invariant/index.js.map +1 -0
  53. package/dist/node_modules/@apollo/client/version.js +6 -0
  54. package/dist/node_modules/@apollo/client/version.js.map +1 -0
  55. package/dist/node_modules/{.bun/@wry_caches@1.0.1/node_modules/@wry → @wry}/caches/lib/weak.js +1 -1
  56. package/dist/node_modules/@wry/caches/lib/weak.js.map +1 -0
  57. package/dist/node_modules/{.bun/@wry_trie@0.5.0/node_modules/@wry → @wry}/trie/lib/index.js +1 -1
  58. package/dist/node_modules/@wry/trie/lib/index.js.map +1 -0
  59. package/dist/node_modules/{.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws → graphql-ws}/dist/client.js +1 -1
  60. package/dist/node_modules/graphql-ws/dist/client.js.map +1 -0
  61. package/dist/node_modules/{.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws → graphql-ws}/dist/common-CGW11Fyb.js +1 -1
  62. package/dist/node_modules/graphql-ws/dist/common-CGW11Fyb.js.map +1 -0
  63. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/NotificationFactories.js +1 -1
  64. package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +1 -0
  65. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/Observable.js +1 -1
  66. package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js.map +1 -0
  67. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/Subscriber.js +2 -2
  68. package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +1 -0
  69. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/Subscription.js +2 -2
  70. package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +1 -0
  71. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/config.js +1 -1
  72. package/dist/node_modules/rxjs/dist/esm5/internal/config.js.map +1 -0
  73. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/observable/empty.js +1 -1
  74. package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +1 -0
  75. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/scheduler/timeoutProvider.js +2 -2
  76. package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +1 -0
  77. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/symbol/observable.js +1 -1
  78. package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +1 -0
  79. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/util/UnsubscriptionError.js +1 -1
  80. package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +1 -0
  81. package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +11 -0
  82. package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +1 -0
  83. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/util/createErrorClass.js +1 -1
  84. package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +1 -0
  85. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/util/errorContext.js +1 -1
  86. package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +1 -0
  87. package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js +8 -0
  88. package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +1 -0
  89. package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +8 -0
  90. package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +1 -0
  91. package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js +6 -0
  92. package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +1 -0
  93. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/util/pipe.js +1 -1
  94. package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +1 -0
  95. package/dist/node_modules/{.bun/rxjs@7.8.2/node_modules/rxjs → rxjs}/dist/esm5/internal/util/reportUnhandledError.js +1 -1
  96. package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +1 -0
  97. package/dist/node_modules/{.bun/tslib@2.8.1 → rxjs}/node_modules/tslib/tslib.es6.js +1 -1
  98. package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js.map +1 -0
  99. package/dist/pages/AdminDashboardPage.js +118 -91
  100. package/dist/pages/AdminDashboardPage.js.map +1 -1
  101. package/dist/pages/AdminReviewModerationPage.js +67 -61
  102. package/dist/pages/AdminReviewModerationPage.js.map +1 -1
  103. package/dist/pages/AdminStoresPage.js +424 -371
  104. package/dist/pages/AdminStoresPage.js.map +1 -1
  105. package/dist/pages/AdminSubmissionsQueuePage.js +303 -286
  106. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -1
  107. package/dist/pages/AppDetailPage.js +172 -135
  108. package/dist/pages/AppDetailPage.js.map +1 -1
  109. package/dist/pages/AppSettingsPage.js +83 -300
  110. package/dist/pages/AppSettingsPage.js.map +1 -1
  111. package/dist/pages/CartPage.js +71 -79
  112. package/dist/pages/CartPage.js.map +1 -1
  113. package/dist/pages/InstalledAppsPage.js +120 -337
  114. package/dist/pages/InstalledAppsPage.js.map +1 -1
  115. package/dist/pages/MarketplaceHomePage.js +196 -205
  116. package/dist/pages/MarketplaceHomePage.js.map +1 -1
  117. package/dist/pages/MyLicensesPage.js +70 -75
  118. package/dist/pages/MyLicensesPage.js.map +1 -1
  119. package/dist/pages/OrderConfirmationPage.js +70 -37
  120. package/dist/pages/OrderConfirmationPage.js.map +1 -1
  121. package/dist/pages/OrdersPage.js +60 -68
  122. package/dist/pages/OrdersPage.js.map +1 -1
  123. package/dist/pages/ProductDetailPage.js +794 -752
  124. package/dist/pages/ProductDetailPage.js.map +1 -1
  125. package/dist/providers/StoreProvider.js +3 -3
  126. package/package.json +2 -2
  127. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +0 -1
  128. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/errors/utils.js.map +0 -1
  129. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/core/ApolloLink.js.map +0 -1
  130. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/subscriptions/index.js.map +0 -1
  131. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/utils/createOperation.js.map +0 -1
  132. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/caching/sizes.js.map +0 -1
  133. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/graphql/print.js.map +0 -1
  134. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/caches.js.map +0 -1
  135. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +0 -1
  136. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMainDefinition.js.map +0 -1
  137. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +0 -9
  138. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +0 -1
  139. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +0 -1
  140. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationName.js +0 -8
  141. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +0 -1
  142. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/global.js.map +0 -1
  143. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/maybe.js +0 -10
  144. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +0 -1
  145. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/isNonNullObject.js +0 -8
  146. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/isNonNullObject.js.map +0 -1
  147. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +0 -1
  148. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/memoize.js.map +0 -1
  149. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +0 -1
  150. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/invariant/index.js.map +0 -1
  151. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/version.js +0 -6
  152. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/version.js.map +0 -1
  153. package/dist/node_modules/.bun/@wry_caches@1.0.1/node_modules/@wry/caches/lib/weak.js.map +0 -1
  154. package/dist/node_modules/.bun/@wry_trie@0.5.0/node_modules/@wry/trie/lib/index.js.map +0 -1
  155. package/dist/node_modules/.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws/dist/client.js.map +0 -1
  156. package/dist/node_modules/.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws/dist/common-CGW11Fyb.js.map +0 -1
  157. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +0 -1
  158. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Observable.js.map +0 -1
  159. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +0 -1
  160. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +0 -1
  161. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/config.js.map +0 -1
  162. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +0 -1
  163. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +0 -1
  164. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +0 -1
  165. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +0 -1
  166. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +0 -11
  167. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +0 -1
  168. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +0 -1
  169. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +0 -1
  170. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/identity.js +0 -8
  171. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +0 -1
  172. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +0 -8
  173. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +0 -1
  174. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/noop.js +0 -6
  175. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +0 -1
  176. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +0 -1
  177. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +0 -1
  178. package/dist/node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.es6.js.map +0 -1
  179. package/dist/pages/ProductReviewsPage.js +0 -87
  180. package/dist/pages/ProductReviewsPage.js.map +0 -1
  181. package/dist/pages/PublisherDashboardPage.js +0 -160
  182. package/dist/pages/PublisherDashboardPage.js.map +0 -1
  183. package/dist/pages/PublisherRevenuePage.js +0 -140
  184. package/dist/pages/PublisherRevenuePage.js.map +0 -1
  185. package/dist/pages/PublisherSubmissionsPage.js +0 -179
  186. package/dist/pages/PublisherSubmissionsPage.js.map +0 -1
  187. package/dist/pages/PublisherSubmitPage.js +0 -230
  188. package/dist/pages/PublisherSubmitPage.js.map +0 -1
  189. /package/dist/node_modules/{.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo → @apollo}/client/utilities/caching/sizes.js +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"AdminSubmissionsQueuePage.js","names":[],"sources":["../../src/pages/AdminSubmissionsQueuePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { ArrowLeft, Check, X, RefreshCw, PackageCheck, ChevronDown, ChevronUp, ExternalLink } from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useNavigate } from 'react-router-dom';\nimport { useStore } from '../providers/StoreProvider';\nimport { formatPriceForModel } from '../utils';\n\ntype PendingProduct = {\n id: string;\n slug: string;\n name: string;\n type: string;\n nature: string;\n status: string;\n pricingModel: string;\n price: number;\n currency: string;\n description?: string | null;\n submittedAt?: string | null;\n submittedBy?: string | null;\n category?: string | null;\n icon?: string | null;\n productId?: string | null;\n publisher?: { id: string; name: string; email: string } | null;\n};\n\ntype ProductStatus = 'PENDING_REVIEW' | 'PUBLISHED' | 'REJECTED' | 'ALL';\n\nconst PENDING_PRODUCTS_QUERY = /* GraphQL */ `\n query PendingReviewProducts($limit: Int, $offset: Int) {\n pendingReviewProducts(limit: $limit, offset: $offset) {\n totalCount\n products {\n id\n slug\n name\n type\n nature\n status\n pricingModel\n price\n currency\n description\n submittedAt\n submittedBy\n category\n icon\n productId\n publisher {\n id\n name\n email\n }\n }\n }\n }\n`;\n\nconst ALL_PRODUCTS_QUERY = /* GraphQL */ `\n query AdminProducts($limit: Int, $offset: Int, $status: ProductStatus) {\n products(filter: { status: $status }, limit: $limit, offset: $offset) {\n id\n slug\n name\n type\n nature\n status\n pricingModel\n price\n currency\n description\n submittedAt\n submittedBy\n category\n icon\n productId\n publisher {\n id\n name\n email\n }\n }\n }\n`;\n\nconst APPROVE_PRODUCT_MUTATION = /* GraphQL */ `\n mutation ApproveProduct($id: ID!, $notes: String) {\n approveProduct(id: $id, notes: $notes) {\n id\n status\n publishedAt\n }\n }\n`;\n\nconst REJECT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation RejectProduct($id: ID!, $reason: String!) {\n rejectProduct(id: $id, reason: $reason) {\n id\n status\n rejectedReason\n }\n }\n`;\n\nconst STATUS_FILTERS: Array<{ label: string; value: ProductStatus }> = [\n { label: 'Pending review', value: 'PENDING_REVIEW' },\n { label: 'Published', value: 'PUBLISHED' },\n { label: 'Rejected', value: 'REJECTED' },\n { label: 'All', value: 'ALL' },\n];\n\nexport const AdminSubmissionsQueuePage: FC = () => {\n const navigate = useNavigate();\n const { authToken, basePath } = useStore();\n const [products, setProducts] = useState<PendingProduct[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [actingId, setActingId] = useState<string | null>(null);\n const [statusFilter, setStatusFilter] = useState<ProductStatus>('PENDING_REVIEW');\n const [rejectingId, setRejectingId] = useState<string | null>(null);\n const [rejectReason, setRejectReason] = useState('');\n const [viewingId, setViewingId] = useState<string | null>(null);\n\n const loadProducts = useCallback(\n async (filter: ProductStatus) => {\n setLoading(true);\n setError(null);\n try {\n if (filter === 'PENDING_REVIEW') {\n const result = await graphqlFetch<{\n pendingReviewProducts: { totalCount: number; products: PendingProduct[] };\n }>({\n gateway: 'global',\n query: PENDING_PRODUCTS_QUERY,\n variables: { limit: 100, offset: 0 },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load pending products');\n }\n setProducts(result.data?.pendingReviewProducts.products ?? []);\n setTotalCount(result.data?.pendingReviewProducts.totalCount ?? 0);\n } else {\n const result = await graphqlFetch<{ products: PendingProduct[] }>({\n gateway: 'global',\n query: ALL_PRODUCTS_QUERY,\n variables: {\n limit: 100,\n offset: 0,\n ...(filter !== 'ALL' && { status: filter }),\n },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load products');\n }\n const list = result.data?.products ?? [];\n setProducts(list);\n setTotalCount(list.length);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load products');\n } finally {\n setLoading(false);\n }\n },\n [authToken]\n );\n\n useEffect(() => {\n void loadProducts(statusFilter);\n }, [loadProducts, statusFilter]);\n\n const approve = async (id: string) => {\n setActingId(id);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: 'global',\n query: APPROVE_PRODUCT_MUTATION,\n variables: { id, notes: null },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Approval failed');\n }\n await loadProducts(statusFilter);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Approval failed');\n } finally {\n setActingId(null);\n }\n };\n\n const reject = async (id: string) => {\n if (!rejectReason.trim()) {\n setError('Rejection reason is required');\n return;\n }\n setActingId(id);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: 'global',\n query: REJECT_PRODUCT_MUTATION,\n variables: { id, reason: rejectReason.trim() },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Rejection failed');\n }\n setRejectingId(null);\n setRejectReason('');\n await loadProducts(statusFilter);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Rejection failed');\n } finally {\n setActingId(null);\n }\n };\n\n return (\n <div className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <header className=\"border-b border-border-default bg-surface-raised\">\n <div className=\"mx-auto max-w-7xl px-6 py-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/dashboard`)}\n className=\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <div className=\"flex items-center gap-2\">\n <PackageCheck className=\"size-5 text-text-primary\" />\n <h1 className=\"text-xl font-semibold text-text-primary\">Submission queue</h1>\n <span className=\"rounded-full bg-surface-accent-muted px-2 py-0.5 text-xs font-medium text-text-accent\">\n {totalCount}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => void loadProducts(statusFilter)}\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 disabled={loading}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n Refresh\n </button>\n </div>\n\n {/* Status filter pills */}\n <div className=\"mt-4 flex gap-2\">\n {STATUS_FILTERS.map((f) => (\n <button\n key={f.value}\n type=\"button\"\n onClick={() => setStatusFilter(f.value)}\n className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${\n statusFilter === f.value\n ? 'bg-surface-accent text-text-on-accent'\n : 'bg-surface-muted text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {f.label}\n </button>\n ))}\n </div>\n </div>\n </header>\n\n <main className=\"mx-auto max-w-7xl 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 && products.length === 0 ? (\n <output className=\"block py-16 text-center text-text-secondary\">\n Loading submissions…\n </output>\n ) : products.length === 0 ? (\n <div className=\"py-16 text-center text-text-secondary\">\n No products matching the current filter.\n </div>\n ) : (\n <ul className=\"space-y-3\">\n {products.map((p) => (\n <li\n key={p.id}\n className=\"overflow-hidden rounded-lg border border-border-default bg-surface-raised\"\n >\n <div className=\"flex items-start gap-4 p-4\">\n {p.icon ? (\n <img\n src={p.icon}\n alt=\"\"\n className=\"size-14 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex size-14 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary\">\n {p.type}\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 {p.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 {p.type}\n </span>\n <span className=\"rounded-full bg-surface-muted px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {p.nature}\n </span>\n </div>\n <div className=\"mt-0.5 text-xs text-text-tertiary\">{p.slug}</div>\n <div className=\"mt-1 flex items-center gap-3 text-xs text-text-secondary\">\n <span>Publisher: {p.publisher?.name ?? 'Unknown'}</span>\n <span>Price: {formatPriceForModel(p.price, p.currency, p.pricingModel)}</span>\n {p.submittedAt && (\n <span>Submitted {new Date(p.submittedAt).toLocaleString()}</span>\n )}\n </div>\n {p.description && (\n <p className=\"mt-2 line-clamp-2 text-sm text-text-secondary\">\n {p.description}\n </p>\n )}\n </div>\n <div className=\"flex flex-shrink-0 flex-col gap-2\">\n {p.productId && (\n <a\n href={`/devportal/apps/${p.productId}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 rounded-md border border-border-default px-3 py-1.5 text-xs text-text-secondary hover:bg-surface-hover\"\n >\n <ExternalLink className=\"size-3.5\" />\n View app\n </a>\n )}\n <button\n type=\"button\"\n onClick={() => setViewingId(viewingId === p.id ? null : p.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-default px-3 py-1.5 text-xs text-text-secondary hover:bg-surface-hover\"\n >\n {viewingId === p.id ? (\n <ChevronUp className=\"size-3.5\" />\n ) : (\n <ChevronDown className=\"size-3.5\" />\n )}\n Details\n </button>\n <button\n type=\"button\"\n onClick={() => void approve(p.id)}\n disabled={actingId === p.id}\n className=\"inline-flex items-center gap-1 rounded-md bg-surface-success px-3 py-1.5 text-xs font-medium text-text-on-success hover:bg-surface-success-hover disabled:opacity-60\"\n >\n <Check className=\"size-3.5\" />\n Approve\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setRejectingId(p.id);\n setRejectReason('');\n }}\n disabled={actingId === p.id}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-danger bg-surface-danger-muted px-3 py-1.5 text-xs font-medium text-text-danger hover:bg-surface-danger hover:text-text-on-danger disabled:opacity-60\"\n >\n <X className=\"size-3.5\" />\n Reject\n </button>\n </div>\n </div>\n\n {viewingId === p.id && (\n <div className=\"border-t border-border-default bg-surface-muted p-4\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-3 text-xs sm:grid-cols-3\">\n <div>\n <dt className=\"font-medium text-text-secondary\">Slug</dt>\n <dd className=\"mt-0.5 font-mono text-text-primary\">{p.slug}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Type</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.type}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Nature</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.nature}</dd>\n </div>\n {p.category && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Category</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.category}</dd>\n </div>\n )}\n <div>\n <dt className=\"font-medium text-text-secondary\">Pricing</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {formatPriceForModel(p.price, p.currency, p.pricingModel)}{' '}\n <span className=\"text-text-tertiary\">({p.pricingModel})</span>\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Publisher</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {p.publisher?.name ?? '—'}\n {p.publisher?.email && (\n <span className=\"block text-text-tertiary\">{p.publisher.email}</span>\n )}\n </dd>\n </div>\n {p.productId && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Devportal app ID</dt>\n <dd className=\"mt-0.5 font-mono text-text-primary\">{p.productId}</dd>\n </div>\n )}\n {p.submittedBy && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Submitted by</dt>\n <dd className=\"mt-0.5 font-mono text-text-primary\">{p.submittedBy}</dd>\n </div>\n )}\n {p.submittedAt && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Submitted at</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {new Date(p.submittedAt).toLocaleString()}\n </dd>\n </div>\n )}\n {p.description && (\n <div className=\"col-span-2 sm:col-span-3\">\n <dt className=\"font-medium text-text-secondary\">Description</dt>\n <dd className=\"mt-0.5 whitespace-pre-wrap text-text-primary\">\n {p.description}\n </dd>\n </div>\n )}\n </dl>\n </div>\n )}\n\n {rejectingId === p.id && (\n <div className=\"border-t border-border-default bg-surface-muted px-4 py-3\">\n <label\n htmlFor={`reject-reason-${p.id}`}\n className=\"block text-xs font-medium text-text-secondary\"\n >\n Rejection reason (required)\n </label>\n <textarea\n id={`reject-reason-${p.id}`}\n aria-label=\"Rejection reason\"\n value={rejectReason}\n onChange={(e) => setRejectReason(e.target.value)}\n rows={3}\n required\n aria-required=\"true\"\n className=\"mt-1 w-full rounded-md border border-border-default bg-surface-default px-3 py-2 text-sm text-text-primary focus:border-border-accent focus:outline-none\"\n placeholder=\"Explain why this submission is being rejected…\"\n />\n <div className=\"mt-2 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setRejectingId(null);\n setRejectReason('');\n }}\n className=\"rounded-md border border-border-default bg-surface-default px-3 py-1 text-xs text-text-primary hover:bg-surface-hover\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => void reject(p.id)}\n disabled={!rejectReason.trim() || actingId === p.id}\n className=\"rounded-md bg-surface-danger px-3 py-1 text-xs font-medium text-text-on-danger hover:bg-surface-danger-hover disabled:opacity-60\"\n >\n Submit rejection\n </button>\n </div>\n </div>\n )}\n </li>\n ))}\n </ul>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminSubmissionsQueuePage.js","names":[],"sources":["../../src/pages/AdminSubmissionsQueuePage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useCallback, useEffect, useState } from 'react';\nimport { ArrowLeft, Check, X, RefreshCw, PackageCheck, ChevronDown, ChevronUp } from 'lucide-react';\nimport { graphqlFetch } from '@burdenoff/fe-libs/shared/graphql';\nimport { useNavigate } from 'react-router-dom';\nimport { useStore } from '../providers/StoreProvider';\nimport { formatPriceForModel } from '../utils';\nimport { PagePurpose, IllustratedEmptyState, NextSteps } from '@burdenoff/fe-libs/ui';\n\ntype PendingProduct = {\n id: string;\n slug: string;\n name: string;\n type: string;\n nature: string;\n status: string;\n pricingModel: string;\n price: number;\n currency: string;\n description?: string | null;\n submittedAt?: string | null;\n submittedBy?: string | null;\n category?: string | null;\n icon?: string | null;\n publisher?: { id: string; name: string; email: string } | null;\n};\n\ntype ProductStatus = 'PENDING_REVIEW' | 'PUBLISHED' | 'REJECTED' | 'ALL';\n\nconst PENDING_PRODUCTS_QUERY = /* GraphQL */ `\n query PendingReviewProducts($limit: Int, $offset: Int) {\n pendingReviewProducts(limit: $limit, offset: $offset) {\n totalCount\n products {\n id\n slug\n name\n type\n nature\n status\n pricingModel\n price\n currency\n description\n submittedAt\n submittedBy\n category\n icon\n publisher {\n id\n name\n email\n }\n }\n }\n }\n`;\n\nconst ALL_PRODUCTS_QUERY = /* GraphQL */ `\n query AdminProducts($limit: Int, $offset: Int, $status: ProductStatus) {\n products(filter: { status: $status }, limit: $limit, offset: $offset) {\n id\n slug\n name\n type\n nature\n status\n pricingModel\n price\n currency\n description\n submittedAt\n submittedBy\n category\n icon\n publisher {\n id\n name\n email\n }\n }\n }\n`;\n\nconst APPROVE_PRODUCT_MUTATION = /* GraphQL */ `\n mutation ApproveProduct($id: ID!, $notes: String) {\n approveProduct(id: $id, notes: $notes) {\n id\n status\n publishedAt\n }\n }\n`;\n\nconst REJECT_PRODUCT_MUTATION = /* GraphQL */ `\n mutation RejectProduct($id: ID!, $reason: String!) {\n rejectProduct(id: $id, reason: $reason) {\n id\n status\n rejectedReason\n }\n }\n`;\n\nconst STATUS_FILTERS: Array<{ label: string; value: ProductStatus }> = [\n { label: 'Pending review', value: 'PENDING_REVIEW' },\n { label: 'Published', value: 'PUBLISHED' },\n { label: 'Rejected', value: 'REJECTED' },\n { label: 'All', value: 'ALL' },\n];\n\nexport const AdminSubmissionsQueuePage: FC = () => {\n const navigate = useNavigate();\n const { authToken, basePath } = useStore();\n const [products, setProducts] = useState<PendingProduct[]>([]);\n const [totalCount, setTotalCount] = useState(0);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [actingId, setActingId] = useState<string | null>(null);\n const [statusFilter, setStatusFilter] = useState<ProductStatus>('PENDING_REVIEW');\n const [rejectingId, setRejectingId] = useState<string | null>(null);\n const [rejectReason, setRejectReason] = useState('');\n const [viewingId, setViewingId] = useState<string | null>(null);\n\n const loadProducts = useCallback(\n async (filter: ProductStatus) => {\n setLoading(true);\n setError(null);\n try {\n if (filter === 'PENDING_REVIEW') {\n const result = await graphqlFetch<{\n pendingReviewProducts: { totalCount: number; products: PendingProduct[] };\n }>({\n gateway: 'global',\n query: PENDING_PRODUCTS_QUERY,\n variables: { limit: 100, offset: 0 },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load pending products');\n }\n setProducts(result.data?.pendingReviewProducts.products ?? []);\n setTotalCount(result.data?.pendingReviewProducts.totalCount ?? 0);\n } else {\n const result = await graphqlFetch<{ products: PendingProduct[] }>({\n gateway: 'global',\n query: ALL_PRODUCTS_QUERY,\n variables: {\n limit: 100,\n offset: 0,\n ...(filter !== 'ALL' && { status: filter }),\n },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Failed to load products');\n }\n const list = result.data?.products ?? [];\n setProducts(list);\n setTotalCount(list.length);\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load products');\n } finally {\n setLoading(false);\n }\n },\n [authToken]\n );\n\n useEffect(() => {\n void loadProducts(statusFilter);\n }, [loadProducts, statusFilter]);\n\n const approve = async (id: string) => {\n setActingId(id);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: 'global',\n query: APPROVE_PRODUCT_MUTATION,\n variables: { id, notes: null },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Approval failed');\n }\n await loadProducts(statusFilter);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Approval failed');\n } finally {\n setActingId(null);\n }\n };\n\n const reject = async (id: string) => {\n if (!rejectReason.trim()) {\n setError('Rejection reason is required');\n return;\n }\n setActingId(id);\n setError(null);\n try {\n const result = await graphqlFetch({\n gateway: 'global',\n query: REJECT_PRODUCT_MUTATION,\n variables: { id, reason: rejectReason.trim() },\n authToken: authToken || undefined,\n });\n if (result.errors?.length) {\n throw new Error(result.errors[0]?.message ?? 'Rejection failed');\n }\n setRejectingId(null);\n setRejectReason('');\n await loadProducts(statusFilter);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Rejection failed');\n } finally {\n setActingId(null);\n }\n };\n\n return (\n <div className=\"min-h-screen bg-surface-default\">\n {/* Header */}\n <header className=\"border-b border-border-seam bg-surface-raised\">\n <div className=\"mx-auto max-w-7xl px-6 py-4\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/dashboard`)}\n className=\"inline-flex items-center gap-2 rounded-md px-3 py-1.5 text-sm text-text-secondary hover:bg-surface-hover hover:text-text-primary\"\n >\n <ArrowLeft className=\"size-4\" />\n Back\n </button>\n <div className=\"flex items-center gap-2\">\n <PackageCheck className=\"size-5 text-text-primary\" />\n <h1 className=\"text-xl font-semibold text-text-primary\">Submission queue</h1>\n <span className=\"rounded-full bg-surface-accent-muted px-2 py-0.5 text-xs font-medium text-text-accent\">\n {totalCount}\n </span>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={() => void loadProducts(statusFilter)}\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 disabled={loading}\n >\n <RefreshCw className={`size-4 ${loading ? 'animate-spin' : ''}`} />\n Refresh\n </button>\n </div>\n\n {/* Status filter pills */}\n <div className=\"mt-4 flex gap-2\">\n {STATUS_FILTERS.map((f) => (\n <button\n key={f.value}\n type=\"button\"\n onClick={() => setStatusFilter(f.value)}\n className={`rounded-full px-3 py-1 text-xs font-medium transition-colors ${\n statusFilter === f.value\n ? 'bg-surface-accent text-text-on-accent'\n : 'bg-surface-muted text-text-secondary hover:bg-surface-hover'\n }`}\n >\n {f.label}\n </button>\n ))}\n </div>\n </div>\n </header>\n\n <main className=\"mx-auto max-w-7xl p-6\">\n <PagePurpose className=\"mb-4\">\n This is the marketplace gatekeeper. Every product a publisher submits lands here for\n review before customers can see it — open each one to inspect its details, pricing and\n publisher, then approve it to go live or reject it with a clear reason the publisher will\n read. Keeping this queue empty means new apps reach customers quickly.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"store-admin-submissions\"\n steps={[\n {\n id: 'review-pending',\n label: 'Review the pending queue',\n description: 'Start with submissions awaiting review and expand Details to inspect.',\n onClick: () => setStatusFilter('PENDING_REVIEW'),\n },\n {\n id: 'approve',\n label: 'Approve solid submissions',\n description: 'Approve a product to publish it instantly to the marketplace.',\n done: statusFilter === 'PUBLISHED' && products.length > 0,\n },\n {\n id: 'reject-clear',\n label: 'Reject with a clear reason',\n description: 'Rejections require a reason — publishers see it, so be specific.',\n },\n ]}\n />\n\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 && products.length === 0 ? (\n <output className=\"block py-16 text-center text-text-secondary\">\n Loading submissions…\n </output>\n ) : products.length === 0 ? (\n <IllustratedEmptyState\n illustration={statusFilter === 'PENDING_REVIEW' ? 'empty-notifications' : 'empty-data'}\n title={\n statusFilter === 'PENDING_REVIEW'\n ? 'Queue is clear'\n : 'No products match this filter'\n }\n description={\n statusFilter === 'PENDING_REVIEW'\n ? 'There are no submissions awaiting review right now. New submissions will appear here as publishers send them in.'\n : 'Nothing matches the current status filter. Switch filters above to see products in other states.'\n }\n />\n ) : (\n <ul className=\"space-y-3\">\n {products.map((p) => (\n <li\n key={p.id}\n className=\"overflow-hidden rounded-lg border border-border-seam bg-surface-raised transition-[box-shadow,border-color] hover:border-border-strong hover:shadow-[var(--shadow-pop)]\"\n >\n <div className=\"flex items-start gap-4 p-4\">\n {p.icon ? (\n <img\n src={p.icon}\n alt=\"\"\n className=\"size-14 flex-shrink-0 rounded-md object-cover\"\n />\n ) : (\n <div className=\"flex size-14 flex-shrink-0 items-center justify-center rounded-md bg-surface-muted text-xs text-text-secondary\">\n {p.type}\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 {p.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 {p.type}\n </span>\n <span className=\"rounded-full bg-surface-muted px-2 py-0.5 text-xs font-medium text-text-secondary\">\n {p.nature}\n </span>\n </div>\n <div className=\"mt-0.5 text-xs text-text-tertiary\">{p.slug}</div>\n <div className=\"mt-1 flex items-center gap-3 text-xs text-text-secondary\">\n <span>Publisher: {p.publisher?.name ?? 'Unknown'}</span>\n <span>Price: {formatPriceForModel(p.price, p.currency, p.pricingModel)}</span>\n {p.submittedAt && (\n <span>Submitted {new Date(p.submittedAt).toLocaleString()}</span>\n )}\n </div>\n {p.description && (\n <p className=\"mt-2 line-clamp-2 text-sm text-text-secondary\">\n {p.description}\n </p>\n )}\n </div>\n <div className=\"flex flex-shrink-0 flex-col gap-2\">\n <button\n type=\"button\"\n onClick={() => setViewingId(viewingId === p.id ? null : p.id)}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-default px-3 py-1.5 text-xs text-text-secondary hover:bg-surface-hover\"\n >\n {viewingId === p.id ? (\n <ChevronUp className=\"size-3.5\" />\n ) : (\n <ChevronDown className=\"size-3.5\" />\n )}\n Details\n </button>\n <button\n type=\"button\"\n onClick={() => void approve(p.id)}\n disabled={actingId === p.id}\n className=\"inline-flex items-center gap-1 rounded-md bg-surface-success px-3 py-1.5 text-xs font-medium text-text-on-success hover:bg-surface-success-hover disabled:opacity-60\"\n >\n <Check className=\"size-3.5\" />\n Approve\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setRejectingId(p.id);\n setRejectReason('');\n }}\n disabled={actingId === p.id}\n className=\"inline-flex items-center gap-1 rounded-md border border-border-danger bg-surface-danger-muted px-3 py-1.5 text-xs font-medium text-text-danger hover:bg-surface-danger hover:text-text-on-danger disabled:opacity-60\"\n >\n <X className=\"size-3.5\" />\n Reject\n </button>\n </div>\n </div>\n\n {viewingId === p.id && (\n <div className=\"border-t border-border-seam bg-surface-muted p-4\">\n <dl className=\"grid grid-cols-2 gap-x-6 gap-y-3 text-xs sm:grid-cols-3\">\n <div>\n <dt className=\"font-medium text-text-secondary\">Slug</dt>\n <dd className=\"mt-0.5 font-mono text-text-primary\">{p.slug}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Type</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.type}</dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Nature</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.nature}</dd>\n </div>\n {p.category && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Category</dt>\n <dd className=\"mt-0.5 text-text-primary\">{p.category}</dd>\n </div>\n )}\n <div>\n <dt className=\"font-medium text-text-secondary\">Pricing</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {formatPriceForModel(p.price, p.currency, p.pricingModel)}{' '}\n <span className=\"text-text-tertiary\">({p.pricingModel})</span>\n </dd>\n </div>\n <div>\n <dt className=\"font-medium text-text-secondary\">Publisher</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {p.publisher?.name ?? '—'}\n {p.publisher?.email && (\n <span className=\"block text-text-tertiary\">{p.publisher.email}</span>\n )}\n </dd>\n </div>\n {p.submittedBy && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Submitted by</dt>\n <dd className=\"mt-0.5 font-mono text-text-primary\">{p.submittedBy}</dd>\n </div>\n )}\n {p.submittedAt && (\n <div>\n <dt className=\"font-medium text-text-secondary\">Submitted at</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {new Date(p.submittedAt).toLocaleString()}\n </dd>\n </div>\n )}\n {p.description && (\n <div className=\"col-span-2 sm:col-span-3\">\n <dt className=\"font-medium text-text-secondary\">Description</dt>\n <dd className=\"mt-0.5 whitespace-pre-wrap text-text-primary\">\n {p.description}\n </dd>\n </div>\n )}\n </dl>\n </div>\n )}\n\n {rejectingId === p.id && (\n <div className=\"border-t border-border-seam bg-surface-muted px-4 py-3\">\n <label\n htmlFor={`reject-reason-${p.id}`}\n className=\"block text-xs font-medium text-text-secondary\"\n >\n Rejection reason (required)\n </label>\n <textarea\n id={`reject-reason-${p.id}`}\n aria-label=\"Rejection reason\"\n value={rejectReason}\n onChange={(e) => setRejectReason(e.target.value)}\n rows={3}\n required\n aria-required=\"true\"\n className=\"mt-1 w-full rounded-md border border-border-default bg-surface-default px-3 py-2 text-sm text-text-primary focus:border-border-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n placeholder=\"Explain why this submission is being rejected…\"\n />\n <div className=\"mt-2 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={() => {\n setRejectingId(null);\n setRejectReason('');\n }}\n className=\"rounded-md border border-border-default bg-surface-default px-3 py-1 text-xs text-text-primary hover:bg-surface-hover\"\n >\n Cancel\n </button>\n <button\n type=\"button\"\n onClick={() => void reject(p.id)}\n disabled={!rejectReason.trim() || actingId === p.id}\n className=\"rounded-md bg-surface-danger px-3 py-1 text-xs font-medium text-text-on-danger hover:bg-surface-danger-hover disabled:opacity-60\"\n >\n Submit rejection\n </button>\n </div>\n </div>\n )}\n </li>\n ))}\n </ul>\n )}\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -2,168 +2,205 @@ import { useStore as e } from "../providers/StoreProvider.js";
2
2
  import { useInstallation as t } from "../hooks/useInstallations.js";
3
3
  import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
4
4
  import { ArrowLeft as r, Settings as i } from "lucide-react";
5
- import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
- import { useNavigate as s, useParams as c } from "react-router-dom";
5
+ import { Fragment as a, jsx as o, jsxs as s } from "react/jsx-runtime";
6
+ import { useNavigate as c, useParams as l } from "react-router-dom";
7
+ import { EmphasisPanel as u, IllustratedEmptyState as d, NextSteps as f, PagePurpose as p, ShowMore as m } from "@burdenoff/fe-libs/ui";
7
8
  //#region src/pages/AppDetailPage.tsx
8
- var l = () => {
9
- let l = s(), { basePath: u } = e(), { installationId: d } = c(), { installation: f, loading: p, error: m } = t(d), { t: h } = n();
10
- return /* @__PURE__ */ o("div", {
9
+ var h = () => {
10
+ let h = c(), { basePath: g } = e(), { installationId: _ } = l(), { installation: v, loading: y, error: b } = t(_), { t: x } = n();
11
+ return /* @__PURE__ */ s("div", {
11
12
  className: "flex h-full flex-col",
12
- children: [/* @__PURE__ */ a("header", {
13
- className: "border-b border-border-default bg-bg-surface px-6 py-4",
14
- children: /* @__PURE__ */ o("div", {
13
+ children: [/* @__PURE__ */ o("header", {
14
+ className: "border-b border-border-seam bg-bg-surface px-6 py-4",
15
+ children: /* @__PURE__ */ s("div", {
15
16
  className: "mx-auto flex max-w-4xl items-center gap-3",
16
- children: [/* @__PURE__ */ a("button", {
17
+ children: [/* @__PURE__ */ o("button", {
17
18
  type: "button",
18
- onClick: () => l(-1),
19
+ onClick: () => h(-1),
19
20
  "aria-label": "Go back",
20
21
  className: "cursor-pointer rounded-lg p-2 text-text-muted hover:bg-bg-sunken hover:text-text-primary",
21
- children: /* @__PURE__ */ a(r, { className: "size-5" })
22
- }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h1", {
22
+ children: /* @__PURE__ */ o(r, { className: "size-5" })
23
+ }), /* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h1", {
23
24
  className: "text-2xl font-bold text-text-primary",
24
- children: h("pages.appDetail.title", { defaultValue: "Installed App Details" })
25
- }), /* @__PURE__ */ a("p", {
25
+ children: x("pages.appDetail.title", { defaultValue: "Installed App Details" })
26
+ }), /* @__PURE__ */ o("p", {
26
27
  className: "text-sm text-text-muted",
27
- children: h("pages.appDetail.subtitle", { defaultValue: "Inspect installation status and metadata" })
28
+ children: x("pages.appDetail.subtitle", { defaultValue: "Inspect installation status and metadata" })
28
29
  })] })]
29
30
  })
30
- }), /* @__PURE__ */ a("main", {
31
+ }), /* @__PURE__ */ o("main", {
31
32
  className: "flex-1 overflow-y-auto p-6",
32
- children: /* @__PURE__ */ a("div", {
33
+ children: /* @__PURE__ */ s("div", {
33
34
  className: "mx-auto max-w-4xl",
34
- children: p ? /* @__PURE__ */ a("p", {
35
+ children: [/* @__PURE__ */ o(p, {
36
+ className: "mb-4",
37
+ children: "The full record of one app installed into a workspace — its status, version, who installed it and when, plus its runtime metadata. Come here to confirm an app is healthy, dig into a failed install, or jump to its configuration before troubleshooting."
38
+ }), y ? /* @__PURE__ */ o("p", {
35
39
  role: "status",
36
40
  className: "text-sm text-text-muted",
37
41
  children: "Loading installation…"
38
- }) : m ? /* @__PURE__ */ a("p", {
42
+ }) : b ? /* @__PURE__ */ o("p", {
39
43
  role: "alert",
40
44
  className: "text-sm text-status-error-text",
41
- children: m.message
42
- }) : f ? /* @__PURE__ */ o("div", {
43
- className: "rounded-xl border border-border-default bg-bg-surface p-5",
44
- children: [
45
- /* @__PURE__ */ o("div", {
46
- className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
47
- children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("h2", {
48
- className: "text-lg font-semibold text-text-primary",
49
- children: f.workspaceName ?? f.workspaceId
50
- }), /* @__PURE__ */ o("p", {
51
- className: "mt-1 text-sm text-text-muted",
52
- children: ["Product ", f.productId]
53
- })] }), /* @__PURE__ */ a("span", {
54
- className: "inline-flex w-fit rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary",
55
- children: f.status
56
- })]
57
- }),
58
- /* @__PURE__ */ o("div", {
59
- className: "mt-4 grid gap-4 md:grid-cols-2",
60
- children: [/* @__PURE__ */ o("div", {
61
- className: "rounded-lg bg-bg-sunken p-4 text-sm text-text-muted",
62
- children: [
63
- /* @__PURE__ */ o("p", { children: [
64
- /* @__PURE__ */ a("span", {
45
+ children: b.message
46
+ }) : v ? /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o(f, {
47
+ className: "mb-4",
48
+ storageKey: "store-app-detail",
49
+ steps: [
50
+ {
51
+ id: "configure",
52
+ label: "Manage configuration",
53
+ description: "Adjust this installation's settings for the workspace.",
54
+ icon: /* @__PURE__ */ o(i, { className: "size-4" }),
55
+ onClick: () => h(`${g}/installed/${v.id}/settings`)
56
+ },
57
+ {
58
+ id: "view-product",
59
+ label: "Open the product page",
60
+ description: "See the latest version, changelog and reviews.",
61
+ onClick: () => h(`${g}/marketplace/product/${v.productId}`)
62
+ },
63
+ {
64
+ id: "back",
65
+ label: "Back to installed apps",
66
+ description: "Return to the full list of apps in your workspaces.",
67
+ onClick: () => h(`${g}/installed`)
68
+ }
69
+ ]
70
+ }), /* @__PURE__ */ s(u, { children: [
71
+ /* @__PURE__ */ s("div", {
72
+ className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
73
+ children: [/* @__PURE__ */ s("div", { children: [/* @__PURE__ */ o("h2", {
74
+ className: "text-lg font-semibold text-text-primary",
75
+ children: v.workspaceName ?? v.workspaceId
76
+ }), /* @__PURE__ */ s("p", {
77
+ className: "mt-1 text-sm text-text-muted",
78
+ children: ["Product ", v.productId]
79
+ })] }), /* @__PURE__ */ o("span", {
80
+ className: "inline-flex w-fit rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary",
81
+ children: v.status
82
+ })]
83
+ }),
84
+ /* @__PURE__ */ s("div", {
85
+ className: "mt-4 grid gap-4 md:grid-cols-2",
86
+ children: [/* @__PURE__ */ s("div", {
87
+ className: "rounded-lg bg-bg-sunken p-4 text-sm text-text-muted",
88
+ children: [
89
+ /* @__PURE__ */ s("p", { children: [
90
+ /* @__PURE__ */ o("span", {
91
+ className: "font-medium text-text-primary",
92
+ children: "Version:"
93
+ }),
94
+ " ",
95
+ v.version ?? "Not provided"
96
+ ] }),
97
+ /* @__PURE__ */ s("p", {
98
+ className: "mt-2",
99
+ children: [
100
+ /* @__PURE__ */ o("span", {
65
101
  className: "font-medium text-text-primary",
66
- children: "Version:"
102
+ children: "Installed at:"
67
103
  }),
68
104
  " ",
69
- f.version ?? "Not provided"
70
- ] }),
71
- /* @__PURE__ */ o("p", {
72
- className: "mt-2",
73
- children: [
74
- /* @__PURE__ */ a("span", {
75
- className: "font-medium text-text-primary",
76
- children: "Installed at:"
77
- }),
78
- " ",
79
- new Date(f.installedAt).toLocaleString()
80
- ]
81
- }),
82
- /* @__PURE__ */ o("p", {
83
- className: "mt-2",
84
- children: [
85
- /* @__PURE__ */ a("span", {
86
- className: "font-medium text-text-primary",
87
- children: "Updated at:"
88
- }),
89
- " ",
90
- new Date(f.updatedAt).toLocaleString()
91
- ]
92
- }),
93
- /* @__PURE__ */ o("p", {
94
- className: "mt-2",
95
- children: [
96
- /* @__PURE__ */ a("span", {
97
- className: "font-medium text-text-primary",
98
- children: "Workspace ID:"
99
- }),
100
- " ",
101
- f.workspaceId
102
- ]
103
- }),
104
- /* @__PURE__ */ o("p", {
105
- className: "mt-2",
106
- children: [
107
- /* @__PURE__ */ a("span", {
108
- className: "font-medium text-text-primary",
109
- children: "Organization ID:"
110
- }),
111
- " ",
112
- f.organizationId ?? "N/A"
113
- ]
114
- }),
115
- /* @__PURE__ */ o("p", {
116
- className: "mt-2",
117
- children: [
118
- /* @__PURE__ */ a("span", {
119
- className: "font-medium text-text-primary",
120
- children: "Installed by:"
121
- }),
122
- " ",
123
- f.installedById
124
- ]
125
- })
126
- ]
127
- }), /* @__PURE__ */ o("div", {
128
- className: "rounded-lg bg-bg-sunken p-4 text-sm text-text-muted",
129
- children: [/* @__PURE__ */ a("p", {
130
- className: "font-medium text-text-primary",
131
- children: "Runtime metadata"
132
- }), /* @__PURE__ */ a("pre", {
133
- className: "mt-3 overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-surface p-3 text-xs text-text-muted",
105
+ new Date(v.installedAt).toLocaleString()
106
+ ]
107
+ }),
108
+ /* @__PURE__ */ s("p", {
109
+ className: "mt-2",
110
+ children: [
111
+ /* @__PURE__ */ o("span", {
112
+ className: "font-medium text-text-primary",
113
+ children: "Updated at:"
114
+ }),
115
+ " ",
116
+ new Date(v.updatedAt).toLocaleString()
117
+ ]
118
+ }),
119
+ /* @__PURE__ */ s("p", {
120
+ className: "mt-2",
121
+ children: [
122
+ /* @__PURE__ */ o("span", {
123
+ className: "font-medium text-text-primary",
124
+ children: "Workspace ID:"
125
+ }),
126
+ " ",
127
+ v.workspaceId
128
+ ]
129
+ }),
130
+ /* @__PURE__ */ s("p", {
131
+ className: "mt-2",
132
+ children: [
133
+ /* @__PURE__ */ o("span", {
134
+ className: "font-medium text-text-primary",
135
+ children: "Organization ID:"
136
+ }),
137
+ " ",
138
+ v.organizationId ?? "N/A"
139
+ ]
140
+ }),
141
+ /* @__PURE__ */ s("p", {
142
+ className: "mt-2",
143
+ children: [
144
+ /* @__PURE__ */ o("span", {
145
+ className: "font-medium text-text-primary",
146
+ children: "Installed by:"
147
+ }),
148
+ " ",
149
+ v.installedById
150
+ ]
151
+ })
152
+ ]
153
+ }), /* @__PURE__ */ s("div", {
154
+ className: "rounded-lg bg-bg-sunken p-4 text-sm text-text-muted",
155
+ children: [/* @__PURE__ */ o("p", {
156
+ className: "font-medium text-text-primary",
157
+ children: "Runtime metadata"
158
+ }), /* @__PURE__ */ o(m, {
159
+ collapsedHeight: 120,
160
+ label: "metadata",
161
+ className: "mt-3",
162
+ children: /* @__PURE__ */ o("pre", {
163
+ className: "overflow-x-auto whitespace-pre-wrap rounded-lg border border-border-seam bg-bg-surface p-3 text-xs text-text-muted",
134
164
  children: JSON.stringify({
135
- metadata: f.metadata,
136
- context: f.context,
137
- uninstalledAt: f.uninstalledAt,
138
- uninstalledById: f.uninstalledById
165
+ metadata: v.metadata,
166
+ context: v.context,
167
+ uninstalledAt: v.uninstalledAt,
168
+ uninstalledById: v.uninstalledById
139
169
  }, null, 2)
140
- })]
141
- })]
142
- }),
143
- /* @__PURE__ */ o("div", {
144
- className: "mt-4 flex flex-wrap gap-3",
145
- children: [/* @__PURE__ */ o("button", {
146
- type: "button",
147
- onClick: () => l(`${u}/installed/${f.id}/settings`),
148
- className: "inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
149
- children: [/* @__PURE__ */ a(i, { className: "size-4" }), h("pages.appDetail.manageConfig", { defaultValue: "Manage Configuration" })]
150
- }), /* @__PURE__ */ a("button", {
151
- type: "button",
152
- onClick: () => l(`${u}/marketplace/product/${f.productId}`),
153
- className: "inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
154
- children: h("pages.appDetail.viewProduct", { defaultValue: "View Product" })
170
+ })
155
171
  })]
156
- })
157
- ]
158
- }) : /* @__PURE__ */ a("p", {
159
- className: "text-sm text-text-muted",
160
- children: "Installation not found."
161
- })
172
+ })]
173
+ }),
174
+ /* @__PURE__ */ s("div", {
175
+ className: "mt-4 flex flex-wrap gap-3",
176
+ children: [/* @__PURE__ */ s("button", {
177
+ type: "button",
178
+ onClick: () => h(`${g}/installed/${v.id}/settings`),
179
+ className: "inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
180
+ children: [/* @__PURE__ */ o(i, { className: "size-4" }), x("pages.appDetail.manageConfig", { defaultValue: "Manage Configuration" })]
181
+ }), /* @__PURE__ */ o("button", {
182
+ type: "button",
183
+ onClick: () => h(`${g}/marketplace/product/${v.productId}`),
184
+ className: "inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
185
+ children: x("pages.appDetail.viewProduct", { defaultValue: "View Product" })
186
+ })]
187
+ })
188
+ ] })] }) : /* @__PURE__ */ o(d, {
189
+ illustration: "empty-generic",
190
+ title: "Installation not found",
191
+ description: "This installation may have been uninstalled or never existed. Head back to your installed apps to find another.",
192
+ action: /* @__PURE__ */ o("button", {
193
+ type: "button",
194
+ onClick: () => h(`${g}/installed`),
195
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
196
+ children: "Back to installed apps"
197
+ })
198
+ })]
162
199
  })
163
200
  })]
164
201
  });
165
202
  };
166
203
  //#endregion
167
- export { l as AppDetailPage };
204
+ export { h as AppDetailPage };
168
205
 
169
206
  //# sourceMappingURL=AppDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppDetailPage.js","names":[],"sources":["../../src/pages/AppDetailPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { ArrowLeft, Settings } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useInstallation } from '../hooks/useInstallations';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const AppDetailPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { installationId } = useParams<{ installationId: string }>();\n const { installation, loading, error } = useInstallation(installationId);\n const { t } = useI18n();\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-4xl 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.appDetail.title', { defaultValue: 'Installed App Details' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.appDetail.subtitle', {\n defaultValue: 'Inspect installation status and metadata',\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-4xl\">\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading installation…\n </p>\n ) : error ? (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error.message}\n </p>\n ) : !installation ? (\n <p className=\"text-sm text-text-muted\">Installation not found.</p>\n ) : (\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {installation.workspaceName ?? installation.workspaceId}\n </h2>\n <p className=\"mt-1 text-sm text-text-muted\">Product {installation.productId}</p>\n </div>\n <span className=\"inline-flex w-fit rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary\">\n {installation.status}\n </span>\n </div>\n\n <div className=\"mt-4 grid gap-4 md:grid-cols-2\">\n <div className=\"rounded-lg bg-bg-sunken p-4 text-sm text-text-muted\">\n <p>\n <span className=\"font-medium text-text-primary\">Version:</span>{' '}\n {installation.version ?? 'Not provided'}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Installed at:</span>{' '}\n {new Date(installation.installedAt).toLocaleString()}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Updated at:</span>{' '}\n {new Date(installation.updatedAt).toLocaleString()}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Workspace ID:</span>{' '}\n {installation.workspaceId}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Organization ID:</span>{' '}\n {installation.organizationId ?? 'N/A'}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Installed by:</span>{' '}\n {installation.installedById}\n </p>\n </div>\n\n <div className=\"rounded-lg bg-bg-sunken p-4 text-sm text-text-muted\">\n <p className=\"font-medium text-text-primary\">Runtime metadata</p>\n <pre className=\"mt-3 overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-surface p-3 text-xs text-text-muted\">\n {JSON.stringify(\n {\n metadata: installation.metadata,\n context: installation.context,\n uninstalledAt: installation.uninstalledAt,\n uninstalledById: installation.uninstalledById,\n },\n null,\n 2\n )}\n </pre>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/installed/${installation.id}/settings`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <Settings className=\"size-4\" />\n {t('pages.appDetail.manageConfig', { defaultValue: 'Manage Configuration' })}\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/marketplace/product/${installation.productId}`)\n }\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n {t('pages.appDetail.viewProduct', { defaultValue: 'View Product' })}\n </button>\n </div>\n </div>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AppDetailPage.js","names":[],"sources":["../../src/pages/AppDetailPage.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport { ArrowLeft, Settings } from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useInstallation } from '../hooks/useInstallations';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n EmphasisPanel,\n ShowMore,\n PagePurpose,\n NextSteps,\n IllustratedEmptyState,\n} from '@burdenoff/fe-libs/ui';\n\nexport const AppDetailPage: FC = () => {\n const navigate = useNavigate();\n const { basePath } = useStore();\n const { installationId } = useParams<{ installationId: string }>();\n const { installation, loading, error } = useInstallation(installationId);\n const { t } = useI18n();\n\n return (\n <div className=\"flex h-full flex-col\">\n <header className=\"border-b border-border-seam bg-bg-surface px-6 py-4\">\n <div className=\"mx-auto flex max-w-4xl 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.appDetail.title', { defaultValue: 'Installed App Details' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.appDetail.subtitle', {\n defaultValue: 'Inspect installation status and metadata',\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-4xl\">\n <PagePurpose className=\"mb-4\">\n The full record of one app installed into a workspace — its status, version, who\n installed it and when, plus its runtime metadata. Come here to confirm an app is healthy,\n dig into a failed install, or jump to its configuration before troubleshooting.\n </PagePurpose>\n {loading ? (\n <p role=\"status\" className=\"text-sm text-text-muted\">\n Loading installation…\n </p>\n ) : error ? (\n <p role=\"alert\" className=\"text-sm text-status-error-text\">\n {error.message}\n </p>\n ) : !installation ? (\n <IllustratedEmptyState\n illustration=\"empty-generic\"\n title=\"Installation not found\"\n description=\"This installation may have been uninstalled or never existed. Head back to your installed apps to find another.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/installed`)}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Back to installed apps\n </button>\n }\n />\n ) : (\n <>\n <NextSteps\n className=\"mb-4\"\n storageKey=\"store-app-detail\"\n steps={[\n {\n id: 'configure',\n label: 'Manage configuration',\n description: \"Adjust this installation's settings for the workspace.\",\n icon: <Settings className=\"size-4\" />,\n onClick: () =>\n navigate(`${basePath}/installed/${installation.id}/settings`),\n },\n {\n id: 'view-product',\n label: 'Open the product page',\n description: 'See the latest version, changelog and reviews.',\n onClick: () =>\n navigate(`${basePath}/marketplace/product/${installation.productId}`),\n },\n {\n id: 'back',\n label: 'Back to installed apps',\n description: 'Return to the full list of apps in your workspaces.',\n onClick: () => navigate(`${basePath}/installed`),\n },\n ]}\n />\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {installation.workspaceName ?? installation.workspaceId}\n </h2>\n <p className=\"mt-1 text-sm text-text-muted\">Product {installation.productId}</p>\n </div>\n <span className=\"inline-flex w-fit rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary\">\n {installation.status}\n </span>\n </div>\n\n <div className=\"mt-4 grid gap-4 md:grid-cols-2\">\n <div className=\"rounded-lg bg-bg-sunken p-4 text-sm text-text-muted\">\n <p>\n <span className=\"font-medium text-text-primary\">Version:</span>{' '}\n {installation.version ?? 'Not provided'}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Installed at:</span>{' '}\n {new Date(installation.installedAt).toLocaleString()}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Updated at:</span>{' '}\n {new Date(installation.updatedAt).toLocaleString()}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Workspace ID:</span>{' '}\n {installation.workspaceId}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Organization ID:</span>{' '}\n {installation.organizationId ?? 'N/A'}\n </p>\n <p className=\"mt-2\">\n <span className=\"font-medium text-text-primary\">Installed by:</span>{' '}\n {installation.installedById}\n </p>\n </div>\n\n <div className=\"rounded-lg bg-bg-sunken p-4 text-sm text-text-muted\">\n <p className=\"font-medium text-text-primary\">Runtime metadata</p>\n <ShowMore collapsedHeight={120} label=\"metadata\" className=\"mt-3\">\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg border border-border-seam bg-bg-surface p-3 text-xs text-text-muted\">\n {JSON.stringify(\n {\n metadata: installation.metadata,\n context: installation.context,\n uninstalledAt: installation.uninstalledAt,\n uninstalledById: installation.uninstalledById,\n },\n null,\n 2\n )}\n </pre>\n </ShowMore>\n </div>\n </div>\n\n <div className=\"mt-4 flex flex-wrap gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/installed/${installation.id}/settings`)}\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg border border-border-default px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <Settings className=\"size-4\" />\n {t('pages.appDetail.manageConfig', { defaultValue: 'Manage Configuration' })}\n </button>\n <button\n type=\"button\"\n onClick={() =>\n navigate(`${basePath}/marketplace/product/${installation.productId}`)\n }\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n {t('pages.appDetail.viewProduct', { defaultValue: 'View Product' })}\n </button>\n </div>\n </EmphasisPanel>\n </>\n )}\n </div>\n </main>\n </div>\n );\n};\n"],"mappings":"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"}