@burdenoff/microfe-store 2026.624.3 → 2026.624.6

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 (160) hide show
  1. package/dist/StoreRoutes.js +3 -3
  2. package/dist/StoreRoutes.js.map +1 -1
  3. package/dist/components/AccessDenied.js +3 -3
  4. package/dist/components/AccessDenied.js.map +1 -1
  5. package/dist/components/InstallAppModal.js +119 -106
  6. package/dist/components/InstallAppModal.js.map +1 -1
  7. package/dist/components/cart/CartDrawer.js +6 -6
  8. package/dist/components/cart/CartDrawer.js.map +1 -1
  9. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/errors/CombinedGraphQLErrors.js +1 -1
  10. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +1 -0
  11. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/errors/utils.js +1 -1
  12. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/errors/utils.js.map +1 -0
  13. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/link/core/ApolloLink.js +2 -2
  14. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/core/ApolloLink.js.map +1 -0
  15. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/link/subscriptions/index.js +2 -2
  16. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/subscriptions/index.js.map +1 -0
  17. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/link/utils/createOperation.js +1 -1
  18. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/link/utils/createOperation.js.map +1 -0
  19. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/caching/sizes.js.map +1 -0
  20. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/graphql/print.js +1 -1
  21. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/graphql/print.js.map +1 -0
  22. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/caches.js +2 -2
  23. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/caches.js.map +1 -0
  24. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/checkDocument.js +1 -1
  25. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +1 -0
  26. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/getMainDefinition.js +1 -1
  27. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMainDefinition.js.map +1 -0
  28. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +9 -0
  29. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +1 -0
  30. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/getOperationDefinition.js +1 -1
  31. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +1 -0
  32. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationName.js +8 -0
  33. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +1 -0
  34. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/globals/global.js +1 -1
  35. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/global.js.map +1 -0
  36. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/maybe.js +10 -0
  37. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +1 -0
  38. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/isNonNullObject.js +8 -0
  39. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/isNonNullObject.js.map +1 -0
  40. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/makeUniqueId.js +1 -1
  41. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +1 -0
  42. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/memoize.js +2 -2
  43. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/memoize.js.map +1 -0
  44. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/internal/stringifyForDisplay.js +1 -1
  45. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +1 -0
  46. package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo}/client/utilities/invariant/index.js +1 -1
  47. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/utilities/invariant/index.js.map +1 -0
  48. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/version.js +6 -0
  49. package/dist/node_modules/.bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@apollo/client/version.js.map +1 -0
  50. package/dist/node_modules/{@wry → .bun/@wry_caches@1.0.1/node_modules/@wry}/caches/lib/weak.js +1 -1
  51. package/dist/node_modules/.bun/@wry_caches@1.0.1/node_modules/@wry/caches/lib/weak.js.map +1 -0
  52. package/dist/node_modules/{@wry → .bun/@wry_trie@0.5.0/node_modules/@wry}/trie/lib/index.js +1 -1
  53. package/dist/node_modules/.bun/@wry_trie@0.5.0/node_modules/@wry/trie/lib/index.js.map +1 -0
  54. package/dist/node_modules/{graphql-ws → .bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws}/dist/client.js +1 -1
  55. package/dist/node_modules/.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws/dist/client.js.map +1 -0
  56. package/dist/node_modules/{graphql-ws → .bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws}/dist/common-CGW11Fyb.js +1 -1
  57. package/dist/node_modules/.bun/graphql-ws@6.0.8_796ebe57c2b0ffe0/node_modules/graphql-ws/dist/common-CGW11Fyb.js.map +1 -0
  58. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/NotificationFactories.js +1 -1
  59. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +1 -0
  60. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/Observable.js +1 -1
  61. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Observable.js.map +1 -0
  62. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/Subscriber.js +2 -2
  63. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +1 -0
  64. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/Subscription.js +2 -2
  65. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +1 -0
  66. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/config.js +1 -1
  67. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/config.js.map +1 -0
  68. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/observable/empty.js +1 -1
  69. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +1 -0
  70. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/scheduler/timeoutProvider.js +2 -2
  71. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +1 -0
  72. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/symbol/observable.js +1 -1
  73. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +1 -0
  74. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/util/UnsubscriptionError.js +1 -1
  75. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +1 -0
  76. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +11 -0
  77. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +1 -0
  78. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/util/createErrorClass.js +1 -1
  79. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +1 -0
  80. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/util/errorContext.js +1 -1
  81. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +1 -0
  82. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/identity.js +8 -0
  83. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +1 -0
  84. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +8 -0
  85. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +1 -0
  86. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/noop.js +6 -0
  87. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +1 -0
  88. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/util/pipe.js +1 -1
  89. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +1 -0
  90. package/dist/node_modules/{rxjs → .bun/rxjs@7.8.2/node_modules/rxjs}/dist/esm5/internal/util/reportUnhandledError.js +1 -1
  91. package/dist/node_modules/.bun/rxjs@7.8.2/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +1 -0
  92. package/dist/node_modules/{rxjs → .bun/tslib@2.8.1}/node_modules/tslib/tslib.es6.js +1 -1
  93. package/dist/node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.es6.js.map +1 -0
  94. package/dist/pages/AdminDashboardPage.js +1 -1
  95. package/dist/pages/AdminDashboardPage.js.map +1 -1
  96. package/dist/pages/AdminStoresPage.js +372 -390
  97. package/dist/pages/AdminStoresPage.js.map +1 -1
  98. package/dist/pages/AdminSubmissionsQueuePage.js +144 -130
  99. package/dist/pages/AdminSubmissionsQueuePage.js.map +1 -1
  100. package/dist/pages/AppSettingsPage.js +292 -65
  101. package/dist/pages/AppSettingsPage.js.map +1 -1
  102. package/dist/pages/InstalledAppsPage.js +98 -69
  103. package/dist/pages/InstalledAppsPage.js.map +1 -1
  104. package/dist/pages/MarketplaceHomePage.js +1 -1
  105. package/dist/pages/MarketplaceHomePage.js.map +1 -1
  106. package/dist/providers/StoreProvider.js +3 -3
  107. package/package.json +2 -2
  108. package/dist/node_modules/@apollo/client/errors/CombinedGraphQLErrors.js.map +0 -1
  109. package/dist/node_modules/@apollo/client/errors/utils.js.map +0 -1
  110. package/dist/node_modules/@apollo/client/link/core/ApolloLink.js.map +0 -1
  111. package/dist/node_modules/@apollo/client/link/subscriptions/index.js.map +0 -1
  112. package/dist/node_modules/@apollo/client/link/utils/createOperation.js.map +0 -1
  113. package/dist/node_modules/@apollo/client/utilities/caching/sizes.js.map +0 -1
  114. package/dist/node_modules/@apollo/client/utilities/graphql/print.js.map +0 -1
  115. package/dist/node_modules/@apollo/client/utilities/internal/caches.js.map +0 -1
  116. package/dist/node_modules/@apollo/client/utilities/internal/checkDocument.js.map +0 -1
  117. package/dist/node_modules/@apollo/client/utilities/internal/getMainDefinition.js.map +0 -1
  118. package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js +0 -9
  119. package/dist/node_modules/@apollo/client/utilities/internal/getMemoryInternals.js.map +0 -1
  120. package/dist/node_modules/@apollo/client/utilities/internal/getOperationDefinition.js.map +0 -1
  121. package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js +0 -8
  122. package/dist/node_modules/@apollo/client/utilities/internal/getOperationName.js.map +0 -1
  123. package/dist/node_modules/@apollo/client/utilities/internal/globals/global.js.map +0 -1
  124. package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js +0 -10
  125. package/dist/node_modules/@apollo/client/utilities/internal/globals/maybe.js.map +0 -1
  126. package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js +0 -8
  127. package/dist/node_modules/@apollo/client/utilities/internal/isNonNullObject.js.map +0 -1
  128. package/dist/node_modules/@apollo/client/utilities/internal/makeUniqueId.js.map +0 -1
  129. package/dist/node_modules/@apollo/client/utilities/internal/memoize.js.map +0 -1
  130. package/dist/node_modules/@apollo/client/utilities/internal/stringifyForDisplay.js.map +0 -1
  131. package/dist/node_modules/@apollo/client/utilities/invariant/index.js.map +0 -1
  132. package/dist/node_modules/@apollo/client/version.js +0 -6
  133. package/dist/node_modules/@apollo/client/version.js.map +0 -1
  134. package/dist/node_modules/@wry/caches/lib/weak.js.map +0 -1
  135. package/dist/node_modules/@wry/trie/lib/index.js.map +0 -1
  136. package/dist/node_modules/graphql-ws/dist/client.js.map +0 -1
  137. package/dist/node_modules/graphql-ws/dist/common-CGW11Fyb.js.map +0 -1
  138. package/dist/node_modules/rxjs/dist/esm5/internal/NotificationFactories.js.map +0 -1
  139. package/dist/node_modules/rxjs/dist/esm5/internal/Observable.js.map +0 -1
  140. package/dist/node_modules/rxjs/dist/esm5/internal/Subscriber.js.map +0 -1
  141. package/dist/node_modules/rxjs/dist/esm5/internal/Subscription.js.map +0 -1
  142. package/dist/node_modules/rxjs/dist/esm5/internal/config.js.map +0 -1
  143. package/dist/node_modules/rxjs/dist/esm5/internal/observable/empty.js.map +0 -1
  144. package/dist/node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js.map +0 -1
  145. package/dist/node_modules/rxjs/dist/esm5/internal/symbol/observable.js.map +0 -1
  146. package/dist/node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js.map +0 -1
  147. package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js +0 -11
  148. package/dist/node_modules/rxjs/dist/esm5/internal/util/arrRemove.js.map +0 -1
  149. package/dist/node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js.map +0 -1
  150. package/dist/node_modules/rxjs/dist/esm5/internal/util/errorContext.js.map +0 -1
  151. package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js +0 -8
  152. package/dist/node_modules/rxjs/dist/esm5/internal/util/identity.js.map +0 -1
  153. package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js +0 -8
  154. package/dist/node_modules/rxjs/dist/esm5/internal/util/isFunction.js.map +0 -1
  155. package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js +0 -6
  156. package/dist/node_modules/rxjs/dist/esm5/internal/util/noop.js.map +0 -1
  157. package/dist/node_modules/rxjs/dist/esm5/internal/util/pipe.js.map +0 -1
  158. package/dist/node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js.map +0 -1
  159. package/dist/node_modules/rxjs/node_modules/tslib/tslib.es6.js.map +0 -1
  160. /package/dist/node_modules/{@apollo → .bun/@apollo_client@4.1.9_e571b0b00fd00a97/node_modules/@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 } 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 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-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 <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.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-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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"}
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,95 +1,322 @@
1
1
  import { useStore as e } from "../providers/StoreProvider.js";
2
2
  import { useInstallation as t } from "../hooks/useInstallations.js";
3
- import { useI18n as n } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
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";
3
+ import { StoreInstallationStatus as n } from "../generated/global-types.js";
4
+ import { useState as r } from "react";
5
+ import { useI18n as i } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
+ import { ArrowLeft as a, CheckCircle2 as o, ChevronDown as s, ChevronRight as c, ExternalLink as l, Globe as u, Key as d, Link2 as f, Link2Off as p, RefreshCw as m, ShieldCheck as h, Webhook as g, Zap as _ } from "lucide-react";
7
+ import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
8
+ import { useNavigate as x, useParams as S } from "react-router-dom";
7
9
  //#region src/pages/AppSettingsPage.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", {
10
+ function C(e) {
11
+ let t = e.context;
12
+ if (!t) return { connected: !1 };
13
+ let n = t.connected === !0 || !!t.accessToken || !!t.oauth?.accessToken || t.connection?.status === "connected", r = t.account, i = t.oauth;
14
+ return {
15
+ connected: n,
16
+ accountName: r?.name ?? t.accountName ?? i?.accountName,
17
+ accountEmail: r?.email ?? t.accountEmail ?? i?.email,
18
+ connectedAt: t.connectedAt ?? i?.connectedAt,
19
+ expiresAt: t.expiresAt ?? i?.expiresAt
20
+ };
21
+ }
22
+ function w(e) {
23
+ let t = e.manifest, n = e.context, r = t?.permissions ?? n?.scopes ?? n?.oauth?.scopes;
24
+ return r ? Array.isArray(r) ? r.map(String) : typeof r == "string" ? r.split(/[\s,]+/).filter(Boolean) : [] : [];
25
+ }
26
+ function T(e) {
27
+ let t = e.manifest, n = e.context, r = t?.webhooks ?? n?.webhooks ?? t?.events;
28
+ return !r || !Array.isArray(r) ? [] : r.map((e) => {
29
+ if (typeof e == "string") return { event: e };
30
+ let t = e;
31
+ return {
32
+ event: String(t.event ?? t.name ?? t.type ?? "Unknown event"),
33
+ endpoint: t.endpoint,
34
+ active: t.active !== !1
35
+ };
36
+ });
37
+ }
38
+ function E(e) {
39
+ let t = e.manifest, n = t?.oauth ?? t?.auth;
40
+ return n ? {
41
+ authorizationUrl: n.authorizationUrl,
42
+ tokenUrl: n.tokenUrl,
43
+ redirectUri: n.redirectUri,
44
+ clientId: n.clientId
45
+ } : {};
46
+ }
47
+ function D({ children: e }) {
48
+ return /* @__PURE__ */ y("div", {
49
+ className: "rounded-xl border border-border-default bg-bg-surface p-5",
50
+ children: e
51
+ });
52
+ }
53
+ function O({ icon: e, title: t }) {
54
+ return /* @__PURE__ */ b("div", {
55
+ className: "mb-4 flex items-center gap-2",
56
+ children: [/* @__PURE__ */ y("span", {
57
+ className: "text-text-muted",
58
+ children: e
59
+ }), /* @__PURE__ */ y("h2", {
60
+ className: "text-base font-semibold text-text-primary",
61
+ children: t
62
+ })]
63
+ });
64
+ }
65
+ function k({ label: e, value: t }) {
66
+ return /* @__PURE__ */ b("div", {
67
+ className: "flex items-start justify-between gap-4 py-2",
68
+ children: [/* @__PURE__ */ y("span", {
69
+ className: "text-sm text-text-muted",
70
+ children: e
71
+ }), /* @__PURE__ */ y("span", {
72
+ className: "text-right text-sm font-medium text-text-primary",
73
+ children: t
74
+ })]
75
+ });
76
+ }
77
+ function A({ installation: e }) {
78
+ let t = C(e), r = E(e), i = e.status === n.Active;
79
+ return /* @__PURE__ */ b(D, { children: [
80
+ /* @__PURE__ */ y(O, {
81
+ icon: /* @__PURE__ */ y(f, { className: "size-5" }),
82
+ title: "Connection"
83
+ }),
84
+ /* @__PURE__ */ y("div", {
85
+ className: "mb-4 flex items-center gap-3 rounded-lg bg-bg-sunken px-4 py-3",
86
+ children: t.connected ? /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(o, { className: "size-5 shrink-0 text-status-success-text" }), /* @__PURE__ */ b("div", { children: [
87
+ /* @__PURE__ */ y("p", {
88
+ className: "text-sm font-medium text-text-primary",
89
+ children: "Connected"
90
+ }),
91
+ t.accountName && /* @__PURE__ */ b("p", {
92
+ className: "text-xs text-text-muted",
93
+ children: [t.accountName, t.accountEmail ? ` · ${t.accountEmail}` : ""]
94
+ }),
95
+ t.connectedAt && /* @__PURE__ */ b("p", {
96
+ className: "text-xs text-text-muted",
97
+ children: ["Since ", new Date(t.connectedAt).toLocaleDateString()]
98
+ })
99
+ ] })] }) : /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y(p, { className: "size-5 shrink-0 text-text-muted" }), /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
100
+ className: "text-sm font-medium text-text-primary",
101
+ children: "Not connected"
102
+ }), /* @__PURE__ */ y("p", {
103
+ className: "text-xs text-text-muted",
104
+ children: "Authorize this integration to start using it"
105
+ })] })] })
106
+ }),
107
+ t.expiresAt && /* @__PURE__ */ b("p", {
108
+ className: "mb-3 text-xs text-text-muted",
109
+ children: ["Token expires: ", new Date(t.expiresAt).toLocaleString()]
110
+ }),
111
+ /* @__PURE__ */ b("div", {
112
+ className: "flex flex-wrap gap-3",
113
+ children: [
114
+ !t.connected && i && r.authorizationUrl && /* @__PURE__ */ b("a", {
115
+ href: r.authorizationUrl,
116
+ target: "_blank",
117
+ rel: "noopener noreferrer",
118
+ 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 hover:opacity-90",
119
+ children: [
120
+ /* @__PURE__ */ y(_, { className: "size-4" }),
121
+ "Connect",
122
+ /* @__PURE__ */ y(l, { className: "size-3.5" })
123
+ ]
124
+ }),
125
+ t.connected && /* @__PURE__ */ b(v, { children: [r.authorizationUrl && /* @__PURE__ */ b("a", {
126
+ href: r.authorizationUrl,
127
+ target: "_blank",
128
+ rel: "noopener noreferrer",
129
+ 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",
130
+ children: [/* @__PURE__ */ y(m, { className: "size-4" }), "Reconnect"]
131
+ }), /* @__PURE__ */ b("button", {
132
+ type: "button",
133
+ className: "inline-flex cursor-pointer items-center gap-2 rounded-lg border border-status-error-border px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle",
134
+ children: [/* @__PURE__ */ y(p, { className: "size-4" }), "Revoke access"]
135
+ })] }),
136
+ !t.connected && !r.authorizationUrl && /* @__PURE__ */ y("p", {
137
+ className: "text-xs text-text-muted",
138
+ children: "OAuth URL not configured. Contact the app developer to complete the setup."
139
+ })
140
+ ]
141
+ }),
142
+ r.clientId && /* @__PURE__ */ b("p", {
143
+ className: "mt-3 text-xs text-text-muted",
144
+ children: ["Client ID: ", r.clientId]
145
+ })
146
+ ] });
147
+ }
148
+ function j({ installation: e }) {
149
+ let t = w(e);
150
+ return t.length === 0 ? null : /* @__PURE__ */ b(D, { children: [
151
+ /* @__PURE__ */ y(O, {
152
+ icon: /* @__PURE__ */ y(h, { className: "size-5" }),
153
+ title: "Granted Permissions"
154
+ }),
155
+ /* @__PURE__ */ y("div", {
156
+ className: "flex flex-wrap gap-2",
157
+ children: t.map((e) => /* @__PURE__ */ b("span", {
158
+ className: "inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary",
159
+ children: [/* @__PURE__ */ y(d, { className: "size-3 text-text-muted" }), e]
160
+ }, e))
161
+ }),
162
+ /* @__PURE__ */ y("p", {
163
+ className: "mt-3 text-xs text-text-muted",
164
+ children: "These are the scopes this integration is allowed to access in your workspace."
165
+ })
166
+ ] });
167
+ }
168
+ function M({ installation: e }) {
169
+ let t = T(e);
170
+ return t.length === 0 ? null : /* @__PURE__ */ b(D, { children: [/* @__PURE__ */ y(O, {
171
+ icon: /* @__PURE__ */ y(g, { className: "size-5" }),
172
+ title: "Event Subscriptions"
173
+ }), /* @__PURE__ */ y("ul", {
174
+ className: "space-y-2",
175
+ children: t.map((e, t) => /* @__PURE__ */ b("li", {
176
+ className: "flex items-center justify-between rounded-lg bg-bg-sunken px-4 py-3",
177
+ children: [/* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
178
+ className: "text-sm font-medium text-text-primary",
179
+ children: e.event
180
+ }), e.endpoint && /* @__PURE__ */ y("p", {
181
+ className: "mt-0.5 font-mono text-xs text-text-muted",
182
+ children: e.endpoint
183
+ })] }), /* @__PURE__ */ y("span", {
184
+ className: `rounded-full px-2 py-0.5 text-xs font-medium ${e.active === !1 ? "bg-bg-sunken text-text-muted" : "bg-status-success-bg-subtle text-status-success-text"}`,
185
+ children: e.active === !1 ? "Inactive" : "Active"
186
+ })]
187
+ }, t))
188
+ })] });
189
+ }
190
+ function N({ installation: e }) {
191
+ return /* @__PURE__ */ b(D, { children: [/* @__PURE__ */ y(O, {
192
+ icon: /* @__PURE__ */ y(u, { className: "size-5" }),
193
+ title: "Installation Details"
194
+ }), /* @__PURE__ */ b("div", {
195
+ className: "divide-y divide-border-default",
196
+ children: [
197
+ /* @__PURE__ */ y(k, {
198
+ label: "Product ID",
199
+ value: e.productId
200
+ }),
201
+ e.version && /* @__PURE__ */ y(k, {
202
+ label: "Version",
203
+ value: `v${e.version}`
204
+ }),
205
+ /* @__PURE__ */ y(k, {
206
+ label: "Status",
207
+ value: e.status
208
+ }),
209
+ /* @__PURE__ */ y(k, {
210
+ label: "Workspace",
211
+ value: e.workspaceName ?? e.workspaceId
212
+ }),
213
+ /* @__PURE__ */ y(k, {
214
+ label: "Installed",
215
+ value: new Date(e.installedAt).toLocaleString()
216
+ }),
217
+ /* @__PURE__ */ y(k, {
218
+ label: "Last updated",
219
+ value: new Date(e.updatedAt).toLocaleString()
220
+ }),
221
+ e.organizationId && /* @__PURE__ */ y(k, {
222
+ label: "Organization",
223
+ value: e.organizationId
224
+ }),
225
+ /* @__PURE__ */ y(k, {
226
+ label: "Installed by",
227
+ value: e.installedById
228
+ })
229
+ ]
230
+ })] });
231
+ }
232
+ function P({ installation: e }) {
233
+ let [t, n] = r(!1);
234
+ return e.manifest && Object.keys(e.manifest).length > 0 || e.metadata && Object.keys(e.metadata).length > 0 || e.context && Object.keys(e.context).length > 0 ? /* @__PURE__ */ b(D, { children: [/* @__PURE__ */ b("button", {
235
+ type: "button",
236
+ onClick: () => n((e) => !e),
237
+ className: "flex w-full cursor-pointer items-center justify-between text-left",
238
+ children: [/* @__PURE__ */ y("span", {
239
+ className: "text-base font-semibold text-text-primary",
240
+ children: "Raw configuration"
241
+ }), y(t ? s : c, { className: "size-4 text-text-muted" })]
242
+ }), t && /* @__PURE__ */ b("div", {
243
+ className: "mt-4 grid gap-4 lg:grid-cols-2",
244
+ children: [e.manifest && Object.keys(e.manifest).length > 0 && /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
245
+ className: "mb-2 text-xs font-medium uppercase tracking-wide text-text-muted",
246
+ children: "Manifest"
247
+ }), /* @__PURE__ */ y("pre", {
248
+ className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
249
+ children: JSON.stringify(e.manifest, null, 2)
250
+ })] }), (e.metadata || e.context) && /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("p", {
251
+ className: "mb-2 text-xs font-medium uppercase tracking-wide text-text-muted",
252
+ children: "Runtime state"
253
+ }), /* @__PURE__ */ y("pre", {
254
+ className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
255
+ children: JSON.stringify({
256
+ metadata: e.metadata ?? {},
257
+ context: e.context ?? {}
258
+ }, null, 2)
259
+ })] })]
260
+ })] }) : null;
261
+ }
262
+ var F = () => {
263
+ let n = x(), { basePath: r } = e(), { installationId: o } = S(), { installation: s, loading: c, error: l } = t(o), { t: u } = i();
264
+ return /* @__PURE__ */ b("div", {
11
265
  className: "flex h-full flex-col",
12
- children: [/* @__PURE__ */ a("header", {
266
+ children: [/* @__PURE__ */ y("header", {
13
267
  className: "border-b border-border-default bg-bg-surface px-6 py-4",
14
- children: /* @__PURE__ */ o("div", {
268
+ children: /* @__PURE__ */ b("div", {
15
269
  className: "mx-auto flex max-w-4xl items-center gap-3",
16
- children: [/* @__PURE__ */ a("button", {
270
+ children: [/* @__PURE__ */ y("button", {
17
271
  type: "button",
18
- onClick: () => l(-1),
272
+ onClick: () => n(-1),
19
273
  "aria-label": "Go back",
20
274
  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", {
275
+ children: /* @__PURE__ */ y(a, { className: "size-5" })
276
+ }), /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y("h1", {
23
277
  className: "text-2xl font-bold text-text-primary",
24
- children: h("pages.appSettings.title", { defaultValue: "App Settings" })
25
- }), /* @__PURE__ */ a("p", {
278
+ children: u("pages.appSettings.title", { defaultValue: "Integration Settings" })
279
+ }), /* @__PURE__ */ y("p", {
26
280
  className: "text-sm text-text-muted",
27
- children: h("pages.appSettings.subtitle", { defaultValue: "Review current installation configuration" })
281
+ children: u("pages.appSettings.subtitle", { defaultValue: "Manage your connection, permissions and webhook events" })
28
282
  })] })]
29
283
  })
30
- }), /* @__PURE__ */ a("main", {
284
+ }), /* @__PURE__ */ y("main", {
31
285
  className: "flex-1 overflow-y-auto p-6",
32
- children: /* @__PURE__ */ a("div", {
286
+ children: /* @__PURE__ */ y("div", {
33
287
  className: "mx-auto max-w-4xl",
34
- children: p ? /* @__PURE__ */ a("p", {
288
+ children: c ? /* @__PURE__ */ y("p", {
35
289
  role: "status",
36
290
  className: "text-sm text-text-muted",
37
291
  children: "Loading settings…"
38
- }) : m ? /* @__PURE__ */ a("p", {
292
+ }) : l ? /* @__PURE__ */ y("p", {
39
293
  role: "alert",
40
294
  className: "text-sm text-status-error-text",
41
- children: m.message
42
- }) : f ? /* @__PURE__ */ o("div", {
43
- className: "space-y-4 rounded-xl border border-border-default bg-bg-surface p-5",
295
+ children: l.message
296
+ }) : s ? /* @__PURE__ */ b("div", {
297
+ className: "space-y-4",
44
298
  children: [
45
- /* @__PURE__ */ o("div", {
46
- className: "flex items-center gap-2",
47
- children: [/* @__PURE__ */ a(i, { className: "size-5 text-text-primary" }), /* @__PURE__ */ a("h2", {
48
- className: "text-lg font-semibold text-text-primary",
49
- children: h("pages.appSettings.configSnapshot", { defaultValue: "Configuration snapshot" })
50
- })]
51
- }),
52
- /* @__PURE__ */ a("p", {
53
- className: "text-sm text-text-muted",
54
- children: h("pages.appSettings.configDescription", { defaultValue: "Store-level configuration for this installation is read-only here." })
55
- }),
56
- /* @__PURE__ */ o("div", {
57
- className: "grid gap-4 lg:grid-cols-2",
58
- children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
59
- className: "mb-2 text-sm font-medium text-text-primary",
60
- children: "Manifest"
61
- }), /* @__PURE__ */ a("pre", {
62
- className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
63
- children: JSON.stringify(f.manifest ?? {}, null, 2)
64
- })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
65
- className: "mb-2 text-sm font-medium text-text-primary",
66
- children: "Metadata & Context"
67
- }), /* @__PURE__ */ a("pre", {
68
- className: "overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted",
69
- children: JSON.stringify({
70
- metadata: f.metadata ?? {},
71
- context: f.context ?? {},
72
- version: f.version,
73
- status: f.status
74
- }, null, 2)
75
- })] })]
76
- }),
77
- /* @__PURE__ */ o("div", {
78
- className: "flex flex-wrap gap-3",
79
- children: [/* @__PURE__ */ a("button", {
299
+ /* @__PURE__ */ y(A, { installation: s }),
300
+ /* @__PURE__ */ y(j, { installation: s }),
301
+ /* @__PURE__ */ y(M, { installation: s }),
302
+ /* @__PURE__ */ y(N, { installation: s }),
303
+ /* @__PURE__ */ y(P, { installation: s }),
304
+ /* @__PURE__ */ b("div", {
305
+ className: "flex flex-wrap gap-3 pt-2",
306
+ children: [/* @__PURE__ */ y("button", {
80
307
  type: "button",
81
- onClick: () => l(`${u}/installed/${f.id}`),
308
+ onClick: () => n(`${r}/installed/${s.id}`),
82
309
  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",
83
- children: h("pages.appSettings.viewInstallation", { defaultValue: "View Installation" })
84
- }), /* @__PURE__ */ a("button", {
310
+ children: u("pages.appSettings.viewInstallation", { defaultValue: "View Installation" })
311
+ }), /* @__PURE__ */ y("button", {
85
312
  type: "button",
86
- onClick: () => l(`${u}/marketplace/product/${f.productId}`),
313
+ onClick: () => n(`${r}/marketplace/product/${s.productId}`),
87
314
  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 hover:opacity-90",
88
- children: h("pages.appDetail.viewProduct", { defaultValue: "View Product" })
315
+ children: u("pages.appDetail.viewProduct", { defaultValue: "View Product" })
89
316
  })]
90
317
  })
91
318
  ]
92
- }) : /* @__PURE__ */ a("p", {
319
+ }) : /* @__PURE__ */ y("p", {
93
320
  className: "text-sm text-text-muted",
94
321
  children: "Installation not found."
95
322
  })
@@ -98,6 +325,6 @@ var l = () => {
98
325
  });
99
326
  };
100
327
  //#endregion
101
- export { l as AppSettingsPage };
328
+ export { F as AppSettingsPage };
102
329
 
103
330
  //# sourceMappingURL=AppSettingsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AppSettingsPage.js","names":[],"sources":["../../src/pages/AppSettingsPage.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 AppSettingsPage: 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.appSettings.title', { defaultValue: 'App Settings' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.appSettings.subtitle', {\n defaultValue: 'Review current installation configuration',\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 settings…\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=\"space-y-4 rounded-xl border border-border-default bg-bg-surface p-5\">\n <div className=\"flex items-center gap-2\">\n <Settings className=\"size-5 text-text-primary\" />\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {t('pages.appSettings.configSnapshot', {\n defaultValue: 'Configuration snapshot',\n })}\n </h2>\n </div>\n\n <p className=\"text-sm text-text-muted\">\n {t('pages.appSettings.configDescription', {\n defaultValue:\n 'Store-level configuration for this installation is read-only here.',\n })}\n </p>\n\n <div className=\"grid gap-4 lg:grid-cols-2\">\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Manifest</p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(installation.manifest ?? {}, null, 2)}\n </pre>\n </div>\n\n <div>\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Metadata & Context</p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(\n {\n metadata: installation.metadata ?? {},\n context: installation.context ?? {},\n version: installation.version,\n status: installation.status,\n },\n null,\n 2\n )}\n </pre>\n </div>\n </div>\n\n <div className=\"flex flex-wrap gap-3\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/installed/${installation.id}`)}\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 {t('pages.appSettings.viewInstallation', { defaultValue: 'View Installation' })}\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-semibold 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":";;;;;;;AAOA,IAAa,UAA4B;CACvC,IAAM,IAAW,GAAa,EACxB,EAAE,gBAAa,GAAU,EACzB,EAAE,sBAAmB,GAAuC,EAC5D,EAAE,iBAAc,YAAS,aAAU,EAAgB,EAAe,EAClE,EAAE,SAAM,GAAS;AAEvB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,UAAD;GAAQ,WAAU;aAChB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAS,GAAG;KAC3B,cAAW;KACX,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,UAAW,CAAA;KACzB,CAAA,EACT,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;KAAI,WAAU;eACX,EAAE,2BAA2B,EAAE,cAAc,gBAAgB,CAAC;KAC5D,CAAA,EACL,kBAAC,KAAD;KAAG,WAAU;eACV,EAAE,8BAA8B,EAC/B,cAAc,6CACf,CAAC;KACA,CAAA,CACA,EAAA,CAAA,CACF;;GACC,CAAA,EAET,kBAAC,QAAD;GAAM,WAAU;aACd,kBAAC,OAAD;IAAK,WAAU;cACZ,IACC,kBAAC,KAAD;KAAG,MAAK;KAAS,WAAU;eAA0B;KAEjD,CAAA,GACF,IACF,kBAAC,KAAD;KAAG,MAAK;KAAQ,WAAU;eACvB,EAAM;KACL,CAAA,GACD,IAGH,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,GAAD,EAAU,WAAU,4BAA6B,CAAA,EACjD,kBAAC,MAAD;QAAI,WAAU;kBACX,EAAE,oCAAoC,EACrC,cAAc,0BACf,CAAC;QACC,CAAA,CACD;;MAEN,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAE,uCAAuC,EACxC,cACE,sEACH,CAAC;OACA,CAAA;MAEJ,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA6C;QAAY,CAAA,EACtE,kBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,UAAU,EAAa,YAAY,EAAE,EAAE,MAAM,EAAE;QACjD,CAAA,CACF,EAAA,CAAA,EAEN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA6C;QAAsB,CAAA,EAChF,kBAAC,OAAD;QAAK,WAAU;kBACZ,KAAK,UACJ;SACE,UAAU,EAAa,YAAY,EAAE;SACrC,SAAS,EAAa,WAAW,EAAE;SACnC,SAAS,EAAa;SACtB,QAAQ,EAAa;SACtB,EACD,MACA,EACD;QACG,CAAA,CACF,EAAA,CAAA,CACF;;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,EAAS,GAAG,EAAS,aAAa,EAAa,KAAK;QACnE,WAAU;kBAET,EAAE,sCAAsC,EAAE,cAAc,qBAAqB,CAAC;QACxE,CAAA,EACT,kBAAC,UAAD;QACE,MAAK;QACL,eACE,EAAS,GAAG,EAAS,uBAAuB,EAAa,YAAY;QAEvE,WAAU;kBAET,EAAE,+BAA+B,EAAE,cAAc,gBAAgB,CAAC;QAC5D,CAAA,CACL;;MACF;SA9DN,kBAAC,KAAD;KAAG,WAAU;eAA0B;KAA2B,CAAA;IAgEhE,CAAA;GACD,CAAA,CACH"}
1
+ {"version":3,"file":"AppSettingsPage.js","names":[],"sources":["../../src/pages/AppSettingsPage.tsx"],"sourcesContent":["import { type FC, useState } from 'react';\nimport { useNavigate, useParams } from 'react-router-dom';\nimport {\n ArrowLeft,\n CheckCircle2,\n ChevronDown,\n ChevronRight,\n ExternalLink,\n Globe,\n Key,\n Link2,\n Link2Off,\n RefreshCw,\n ShieldCheck,\n Webhook,\n Zap,\n} from 'lucide-react';\nimport { useStore } from '../providers/StoreProvider';\nimport { useInstallation } from '../hooks/useInstallations';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { StoreInstallationStatus } from '../generated/global-types';\nimport type { InstalledApp } from '../hooks/useInstallations';\n\n// ---------------------------------------------------------------------------\n// Helpers to parse free-form manifest / context JSON\n// ---------------------------------------------------------------------------\n\nfunction getConnectionState(installation: InstalledApp): {\n connected: boolean;\n accountName?: string;\n accountEmail?: string;\n connectedAt?: string;\n expiresAt?: string;\n} {\n const ctx = installation.context as Record<string, unknown> | null | undefined;\n if (!ctx) return { connected: false };\n\n const connected =\n ctx['connected'] === true ||\n Boolean(ctx['accessToken']) ||\n Boolean((ctx['oauth'] as Record<string, unknown> | undefined)?.['accessToken']) ||\n (ctx['connection'] as Record<string, unknown> | undefined)?.['status'] === 'connected';\n\n const account = ctx['account'] as Record<string, unknown> | undefined;\n const oauth = ctx['oauth'] as Record<string, unknown> | undefined;\n\n return {\n connected,\n accountName:\n (account?.['name'] as string | undefined) ??\n (ctx['accountName'] as string | undefined) ??\n (oauth?.['accountName'] as string | undefined),\n accountEmail:\n (account?.['email'] as string | undefined) ??\n (ctx['accountEmail'] as string | undefined) ??\n (oauth?.['email'] as string | undefined),\n connectedAt:\n (ctx['connectedAt'] as string | undefined) ??\n (oauth?.['connectedAt'] as string | undefined),\n expiresAt:\n (ctx['expiresAt'] as string | undefined) ?? (oauth?.['expiresAt'] as string | undefined),\n };\n}\n\nfunction getPermissions(installation: InstalledApp): string[] {\n const manifest = installation.manifest as Record<string, unknown> | null | undefined;\n const ctx = installation.context as Record<string, unknown> | null | undefined;\n\n const raw =\n (manifest?.['permissions'] as unknown[] | undefined) ??\n (ctx?.['scopes'] as unknown[] | undefined) ??\n (ctx?.['oauth'] as Record<string, unknown> | undefined)?.['scopes'];\n\n if (!raw) return [];\n if (Array.isArray(raw)) return raw.map(String);\n if (typeof raw === 'string') return raw.split(/[\\s,]+/).filter(Boolean);\n return [];\n}\n\nfunction getWebhooks(\n installation: InstalledApp\n): Array<{ event: string; endpoint?: string; active?: boolean }> {\n const manifest = installation.manifest as Record<string, unknown> | null | undefined;\n const ctx = installation.context as Record<string, unknown> | null | undefined;\n\n const raw =\n (manifest?.['webhooks'] as unknown[] | undefined) ??\n (ctx?.['webhooks'] as unknown[] | undefined) ??\n (manifest?.['events'] as unknown[] | undefined);\n\n if (!raw || !Array.isArray(raw)) return [];\n\n return raw.map((item) => {\n if (typeof item === 'string') return { event: item };\n const obj = item as Record<string, unknown>;\n return {\n event: String(obj['event'] ?? obj['name'] ?? obj['type'] ?? 'Unknown event'),\n endpoint: obj['endpoint'] as string | undefined,\n active: obj['active'] !== false,\n };\n });\n}\n\nfunction getOAuthEndpoints(installation: InstalledApp): {\n authorizationUrl?: string;\n tokenUrl?: string;\n redirectUri?: string;\n clientId?: string;\n} {\n const manifest = installation.manifest as Record<string, unknown> | null | undefined;\n const oauth =\n (manifest?.['oauth'] as Record<string, unknown> | undefined) ??\n (manifest?.['auth'] as Record<string, unknown> | undefined);\n if (!oauth) return {};\n return {\n authorizationUrl: oauth['authorizationUrl'] as string | undefined,\n tokenUrl: oauth['tokenUrl'] as string | undefined,\n redirectUri: oauth['redirectUri'] as string | undefined,\n clientId: oauth['clientId'] as string | undefined,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Sub-components\n// ---------------------------------------------------------------------------\n\nfunction SectionCard({ children }: { children: React.ReactNode }) {\n return (\n <div className=\"rounded-xl border border-border-default bg-bg-surface p-5\">{children}</div>\n );\n}\n\nfunction SectionTitle({ icon, title }: { icon: React.ReactNode; title: string }) {\n return (\n <div className=\"mb-4 flex items-center gap-2\">\n <span className=\"text-text-muted\">{icon}</span>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n </div>\n );\n}\n\nfunction InfoRow({ label, value }: { label: string; value: React.ReactNode }) {\n return (\n <div className=\"flex items-start justify-between gap-4 py-2\">\n <span className=\"text-sm text-text-muted\">{label}</span>\n <span className=\"text-right text-sm font-medium text-text-primary\">{value}</span>\n </div>\n );\n}\n\nfunction ConnectionSection({ installation }: { installation: InstalledApp }) {\n const conn = getConnectionState(installation);\n const oauth = getOAuthEndpoints(installation);\n const isActive = installation.status === StoreInstallationStatus.Active;\n\n return (\n <SectionCard>\n <SectionTitle icon={<Link2 className=\"size-5\" />} title=\"Connection\" />\n\n <div className=\"mb-4 flex items-center gap-3 rounded-lg bg-bg-sunken px-4 py-3\">\n {conn.connected ? (\n <>\n <CheckCircle2 className=\"size-5 shrink-0 text-status-success-text\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Connected</p>\n {conn.accountName && (\n <p className=\"text-xs text-text-muted\">\n {conn.accountName}\n {conn.accountEmail ? ` · ${conn.accountEmail}` : ''}\n </p>\n )}\n {conn.connectedAt && (\n <p className=\"text-xs text-text-muted\">\n Since {new Date(conn.connectedAt).toLocaleDateString()}\n </p>\n )}\n </div>\n </>\n ) : (\n <>\n <Link2Off className=\"size-5 shrink-0 text-text-muted\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">Not connected</p>\n <p className=\"text-xs text-text-muted\">\n Authorize this integration to start using it\n </p>\n </div>\n </>\n )}\n </div>\n\n {conn.expiresAt && (\n <p className=\"mb-3 text-xs text-text-muted\">\n Token expires: {new Date(conn.expiresAt).toLocaleString()}\n </p>\n )}\n\n <div className=\"flex flex-wrap gap-3\">\n {!conn.connected && isActive && oauth.authorizationUrl && (\n <a\n href={oauth.authorizationUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\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 hover:opacity-90\"\n >\n <Zap className=\"size-4\" />\n Connect\n <ExternalLink className=\"size-3.5\" />\n </a>\n )}\n {conn.connected && (\n <>\n {oauth.authorizationUrl && (\n <a\n href={oauth.authorizationUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\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 <RefreshCw className=\"size-4\" />\n Reconnect\n </a>\n )}\n <button\n type=\"button\"\n className=\"inline-flex cursor-pointer items-center gap-2 rounded-lg border border-status-error-border px-4 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle\"\n >\n <Link2Off className=\"size-4\" />\n Revoke access\n </button>\n </>\n )}\n {!conn.connected && !oauth.authorizationUrl && (\n <p className=\"text-xs text-text-muted\">\n OAuth URL not configured. Contact the app developer to complete the setup.\n </p>\n )}\n </div>\n\n {oauth.clientId && (\n <p className=\"mt-3 text-xs text-text-muted\">Client ID: {oauth.clientId}</p>\n )}\n </SectionCard>\n );\n}\n\nfunction PermissionsSection({ installation }: { installation: InstalledApp }) {\n const permissions = getPermissions(installation);\n if (permissions.length === 0) return null;\n\n return (\n <SectionCard>\n <SectionTitle icon={<ShieldCheck className=\"size-5\" />} title=\"Granted Permissions\" />\n <div className=\"flex flex-wrap gap-2\">\n {permissions.map((perm) => (\n <span\n key={perm}\n className=\"inline-flex items-center gap-1.5 rounded-full bg-bg-sunken px-3 py-1 text-xs font-medium text-text-primary\"\n >\n <Key className=\"size-3 text-text-muted\" />\n {perm}\n </span>\n ))}\n </div>\n <p className=\"mt-3 text-xs text-text-muted\">\n These are the scopes this integration is allowed to access in your workspace.\n </p>\n </SectionCard>\n );\n}\n\nfunction WebhooksSection({ installation }: { installation: InstalledApp }) {\n const webhooks = getWebhooks(installation);\n if (webhooks.length === 0) return null;\n\n return (\n <SectionCard>\n <SectionTitle icon={<Webhook className=\"size-5\" />} title=\"Event Subscriptions\" />\n <ul className=\"space-y-2\">\n {webhooks.map((wh, idx) => (\n <li\n key={idx}\n className=\"flex items-center justify-between rounded-lg bg-bg-sunken px-4 py-3\"\n >\n <div>\n <p className=\"text-sm font-medium text-text-primary\">{wh.event}</p>\n {wh.endpoint && (\n <p className=\"mt-0.5 font-mono text-xs text-text-muted\">{wh.endpoint}</p>\n )}\n </div>\n <span\n className={`rounded-full px-2 py-0.5 text-xs font-medium ${\n wh.active !== false\n ? 'bg-status-success-bg-subtle text-status-success-text'\n : 'bg-bg-sunken text-text-muted'\n }`}\n >\n {wh.active !== false ? 'Active' : 'Inactive'}\n </span>\n </li>\n ))}\n </ul>\n </SectionCard>\n );\n}\n\nfunction InstallationDetailsSection({ installation }: { installation: InstalledApp }) {\n return (\n <SectionCard>\n <SectionTitle icon={<Globe className=\"size-5\" />} title=\"Installation Details\" />\n <div className=\"divide-y divide-border-default\">\n <InfoRow label=\"Product ID\" value={installation.productId} />\n {installation.version && <InfoRow label=\"Version\" value={`v${installation.version}`} />}\n <InfoRow label=\"Status\" value={installation.status} />\n <InfoRow label=\"Workspace\" value={installation.workspaceName ?? installation.workspaceId} />\n <InfoRow label=\"Installed\" value={new Date(installation.installedAt).toLocaleString()} />\n <InfoRow label=\"Last updated\" value={new Date(installation.updatedAt).toLocaleString()} />\n {installation.organizationId && (\n <InfoRow label=\"Organization\" value={installation.organizationId} />\n )}\n <InfoRow label=\"Installed by\" value={installation.installedById} />\n </div>\n </SectionCard>\n );\n}\n\nfunction RawConfigSection({ installation }: { installation: InstalledApp }) {\n const [open, setOpen] = useState(false);\n\n const hasData =\n (installation.manifest && Object.keys(installation.manifest).length > 0) ||\n (installation.metadata && Object.keys(installation.metadata).length > 0) ||\n (installation.context && Object.keys(installation.context).length > 0);\n\n if (!hasData) return null;\n\n return (\n <SectionCard>\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"flex w-full cursor-pointer items-center justify-between text-left\"\n >\n <span className=\"text-base font-semibold text-text-primary\">Raw configuration</span>\n {open ? (\n <ChevronDown className=\"size-4 text-text-muted\" />\n ) : (\n <ChevronRight className=\"size-4 text-text-muted\" />\n )}\n </button>\n\n {open && (\n <div className=\"mt-4 grid gap-4 lg:grid-cols-2\">\n {installation.manifest && Object.keys(installation.manifest).length > 0 && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-muted\">\n Manifest\n </p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(installation.manifest, null, 2)}\n </pre>\n </div>\n )}\n {(installation.metadata || installation.context) && (\n <div>\n <p className=\"mb-2 text-xs font-medium uppercase tracking-wide text-text-muted\">\n Runtime state\n </p>\n <pre className=\"overflow-x-auto whitespace-pre-wrap rounded-lg bg-bg-sunken p-3 text-xs text-text-muted\">\n {JSON.stringify(\n {\n metadata: installation.metadata ?? {},\n context: installation.context ?? {},\n },\n null,\n 2\n )}\n </pre>\n </div>\n )}\n </div>\n )}\n </SectionCard>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Page\n// ---------------------------------------------------------------------------\n\nexport const AppSettingsPage: 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.appSettings.title', { defaultValue: 'Integration Settings' })}\n </h1>\n <p className=\"text-sm text-text-muted\">\n {t('pages.appSettings.subtitle', {\n defaultValue: 'Manage your connection, permissions and webhook events',\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 settings…\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=\"space-y-4\">\n <ConnectionSection installation={installation} />\n <PermissionsSection installation={installation} />\n <WebhooksSection installation={installation} />\n <InstallationDetailsSection installation={installation} />\n <RawConfigSection installation={installation} />\n\n <div className=\"flex flex-wrap gap-3 pt-2\">\n <button\n type=\"button\"\n onClick={() => navigate(`${basePath}/installed/${installation.id}`)}\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 {t('pages.appSettings.viewInstallation', { defaultValue: 'View Installation' })}\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-semibold 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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"}