@wopr-network/platform-ui-core 1.27.8 → 1.27.9

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 (353) hide show
  1. package/next.config.ts +1 -2
  2. package/package.json +17 -17
  3. package/src/__tests__/account-switcher.test.tsx +21 -20
  4. package/src/__tests__/activity-page.test.tsx +2 -6
  5. package/src/__tests__/add-payment-method-dialog.test.tsx +9 -32
  6. package/src/__tests__/admin-api.test.ts +1 -6
  7. package/src/__tests__/admin-gpu-api.test.ts +1 -3
  8. package/src/__tests__/admin-marketplace-api.test.ts +1 -4
  9. package/src/__tests__/admin-middleware.test.ts +76 -83
  10. package/src/__tests__/affiliate-dashboard.test.tsx +3 -3
  11. package/src/__tests__/api-401-redirect.test.ts +46 -9
  12. package/src/__tests__/api-client.test.ts +3 -5
  13. package/src/__tests__/api-config.test.ts +22 -42
  14. package/src/__tests__/api-fleet-resources.test.ts +1 -2
  15. package/src/__tests__/api-fleet-trpc.test.ts +2 -8
  16. package/src/__tests__/api-null-guards.test.ts +3 -1
  17. package/src/__tests__/audit-log-table-pagination.test.tsx +2 -6
  18. package/src/__tests__/auth-password-reset.test.tsx +7 -21
  19. package/src/__tests__/auth-redirect.test.tsx +8 -2
  20. package/src/__tests__/auth.test.tsx +25 -23
  21. package/src/__tests__/auto-topup-card.test.tsx +4 -12
  22. package/src/__tests__/backups-tab.test.tsx +3 -4
  23. package/src/__tests__/billing-layout-nav-hidden.test.tsx +5 -37
  24. package/src/__tests__/billing-payment-org-invoices.test.tsx +2 -18
  25. package/src/__tests__/billing.test.tsx +8 -39
  26. package/src/__tests__/bot-settings/resources-tab.test.tsx +1 -3
  27. package/src/__tests__/bot-settings/storage-tab.test.tsx +1 -3
  28. package/src/__tests__/bot-settings/vps-upgrade-card.test.tsx +1 -3
  29. package/src/__tests__/bot-settings-restart.test.tsx +1 -3
  30. package/src/__tests__/bot-settings.test.tsx +2 -6
  31. package/src/__tests__/brand.test.ts +6 -26
  32. package/src/__tests__/buy-credits-panel.test.tsx +1 -3
  33. package/src/__tests__/buy-crypto-credits-panel.test.tsx +101 -119
  34. package/src/__tests__/capability-conflicts.test.ts +2 -8
  35. package/src/__tests__/capability-resolver.test.tsx +2 -12
  36. package/src/__tests__/channel-wizard.test.tsx +4 -17
  37. package/src/__tests__/chat/chat-panel.test.tsx +1 -4
  38. package/src/__tests__/chat-store.test.ts +5 -15
  39. package/src/__tests__/command-center.test.tsx +10 -12
  40. package/src/__tests__/compliance-retention-edit.test.tsx +3 -6
  41. package/src/__tests__/confirmation-tracker.test.tsx +3 -18
  42. package/src/__tests__/coupon-input.test.tsx +1 -3
  43. package/src/__tests__/create-instance.test.tsx +1 -3
  44. package/src/__tests__/credit-balance.test.tsx +4 -12
  45. package/src/__tests__/credits.test.tsx +32 -85
  46. package/src/__tests__/email-verification-banner.test.tsx +2 -6
  47. package/src/__tests__/error-boundaries.test.tsx +0 -1
  48. package/src/__tests__/fetch-pricing.test.ts +2 -1
  49. package/src/__tests__/field-oauth.test.tsx +2 -6
  50. package/src/__tests__/fixtures/mock-manifests-data.js +1 -3
  51. package/src/__tests__/fixtures/mock-manifests.ts +2 -4
  52. package/src/__tests__/fleet-health-timestamp.test.tsx +1 -8
  53. package/src/__tests__/fleet-health-update.test.tsx +1 -8
  54. package/src/__tests__/gpu-dashboard.test.tsx +2 -6
  55. package/src/__tests__/instance-detail.test.tsx +3 -9
  56. package/src/__tests__/instance-list.test.tsx +1 -5
  57. package/src/__tests__/layout-snapshots.test.tsx +64 -11
  58. package/src/__tests__/marketplace-admin.test.tsx +2 -6
  59. package/src/__tests__/marketplace.test.tsx +11 -35
  60. package/src/__tests__/merge-api-rates.test.ts +1 -6
  61. package/src/__tests__/middleware.test.ts +32 -219
  62. package/src/__tests__/next-config-headers.test.ts +1 -3
  63. package/src/__tests__/notifications.test.tsx +4 -11
  64. package/src/__tests__/oauth-buttons.test.tsx +36 -59
  65. package/src/__tests__/oauth-error-mapping.test.tsx +2 -6
  66. package/src/__tests__/observability.test.tsx +23 -36
  67. package/src/__tests__/onboarding-page.test.tsx +4 -6
  68. package/src/__tests__/org-billing-api.test.tsx +1 -6
  69. package/src/__tests__/plugin-install-flow.test.tsx +28 -58
  70. package/src/__tests__/plugin-registry.test.tsx +3 -11
  71. package/src/__tests__/plugin-tool-sync.test.ts +1 -3
  72. package/src/__tests__/plugins-catalog-error.test.tsx +2 -6
  73. package/src/__tests__/plugins-toggle-race.test.tsx +3 -5
  74. package/src/__tests__/portfolio-chart.test.tsx +2 -6
  75. package/src/__tests__/promotion-form.test.tsx +2 -6
  76. package/src/__tests__/promotions-list.test.tsx +1 -3
  77. package/src/__tests__/provider-key-api.test.ts +2 -1
  78. package/src/__tests__/resend-verification-button.test.tsx +8 -24
  79. package/src/__tests__/secrets-audit-pagination.test.tsx +1 -3
  80. package/src/__tests__/settings.test.tsx +11 -21
  81. package/src/__tests__/setup-checklist.test.tsx +3 -9
  82. package/src/__tests__/setup.ts +25 -6
  83. package/src/__tests__/snapshot-api.test.ts +2 -1
  84. package/src/__tests__/step-superpowers.test.tsx +1 -3
  85. package/src/__tests__/tenant-context.test.tsx +1 -6
  86. package/src/__tests__/tenant-keys-api.test.ts +3 -4
  87. package/src/__tests__/tenant-table-pagination.test.tsx +2 -6
  88. package/src/__tests__/terminal-log-cleanup.test.tsx +0 -1
  89. package/src/__tests__/transaction-history.test.tsx +190 -238
  90. package/src/__tests__/trpc-types.test.ts +2 -6
  91. package/src/__tests__/use-chat.test.ts +1 -3
  92. package/src/__tests__/use-plugin-setup-chat-stale-closure.test.ts +1 -4
  93. package/src/__tests__/use-sidecar-bridge.test.tsx +105 -0
  94. package/src/__tests__/use-webmcp.test.ts +1 -3
  95. package/src/__tests__/validate-elevenlabs-key.test.ts +2 -1
  96. package/src/__tests__/verify-page.test.tsx +4 -13
  97. package/src/__tests__/verify-redirect.test.tsx +2 -6
  98. package/src/app/(auth)/error.tsx +1 -7
  99. package/src/app/(auth)/forgot-password/page.tsx +4 -18
  100. package/src/app/(auth)/login/page.tsx +5 -22
  101. package/src/app/(auth)/reset-password/page.tsx +2 -12
  102. package/src/app/(auth)/signup/page.tsx +10 -44
  103. package/src/app/(auth)/verify/page.tsx +47 -0
  104. package/src/app/(dashboard)/billing/credits/page.tsx +14 -67
  105. package/src/app/(dashboard)/billing/error.tsx +2 -10
  106. package/src/app/(dashboard)/billing/layout.tsx +12 -62
  107. package/src/app/(dashboard)/billing/payment/page.tsx +17 -68
  108. package/src/app/(dashboard)/billing/plans/page.tsx +3 -9
  109. package/src/app/(dashboard)/billing/usage/hosted/page.tsx +8 -25
  110. package/src/app/(dashboard)/billing/usage/page.tsx +63 -103
  111. package/src/app/(dashboard)/changesets/[id]/changeset-detail-client.tsx +9 -27
  112. package/src/app/(dashboard)/changesets/[id]/error.tsx +2 -6
  113. package/src/app/(dashboard)/changesets/error.tsx +1 -7
  114. package/src/app/(dashboard)/chat/page.tsx +2 -6
  115. package/src/app/(dashboard)/dashboard/network/page.tsx +5 -19
  116. package/src/app/(dashboard)/error.tsx +1 -7
  117. package/src/app/(dashboard)/layout.tsx +15 -36
  118. package/src/app/(dashboard)/marketplace/[plugin]/page.tsx +14 -51
  119. package/src/app/(dashboard)/marketplace/error.tsx +1 -7
  120. package/src/app/(dashboard)/marketplace/page.tsx +6 -27
  121. package/src/app/(dashboard)/not-found.tsx +2 -5
  122. package/src/app/(dashboard)/onboarding/page.tsx +5 -22
  123. package/src/app/(dashboard)/settings/account/page.tsx +1 -6
  124. package/src/app/(dashboard)/settings/activity/page.tsx +8 -34
  125. package/src/app/(dashboard)/settings/api-keys/page.tsx +15 -60
  126. package/src/app/(dashboard)/settings/brain/page.tsx +9 -31
  127. package/src/app/(dashboard)/settings/error.tsx +2 -10
  128. package/src/app/(dashboard)/settings/notifications/page.tsx +2 -6
  129. package/src/app/(dashboard)/settings/org/page.tsx +13 -56
  130. package/src/app/(dashboard)/settings/page.tsx +1 -0
  131. package/src/app/(dashboard)/settings/profile/page.tsx +126 -73
  132. package/src/app/(dashboard)/settings/providers/page.tsx +21 -78
  133. package/src/app/(dashboard)/settings/secrets/page.tsx +13 -58
  134. package/src/app/(dashboard)/settings/security/page.tsx +31 -111
  135. package/src/app/admin/email-templates/email-templates-client.tsx +15 -58
  136. package/src/app/admin/error.tsx +1 -7
  137. package/src/app/admin/fleet-updates/error.tsx +1 -7
  138. package/src/app/admin/fleet-updates/fleet-updates-client.tsx +10 -50
  139. package/src/app/admin/layout.tsx +4 -0
  140. package/src/app/admin/payment-methods/page.tsx +9 -38
  141. package/src/app/admin/products/error.tsx +2 -7
  142. package/src/app/admin/products/page.tsx +1 -4
  143. package/src/app/admin/promotions/[id]/page.tsx +9 -38
  144. package/src/app/admin/promotions/page.tsx +9 -36
  145. package/src/app/admin/rate-overrides/page.tsx +9 -45
  146. package/src/app/auth/callback/[provider]/page.tsx +1 -8
  147. package/src/app/auth/verify/page.tsx +9 -36
  148. package/src/app/channels/error.tsx +2 -10
  149. package/src/app/channels/layout.tsx +9 -0
  150. package/src/app/channels/page.tsx +8 -20
  151. package/src/app/channels/setup/[plugin]/page.tsx +3 -5
  152. package/src/app/error.tsx +1 -7
  153. package/src/app/fleet/error.tsx +1 -7
  154. package/src/app/fleet/layout.tsx +5 -0
  155. package/src/app/fleet/settings/page.tsx +1 -3
  156. package/src/app/global-error.tsx +2 -10
  157. package/src/app/globals.css +1 -4
  158. package/src/app/instances/[id]/instance-detail-client.tsx +51 -125
  159. package/src/app/instances/error.tsx +2 -10
  160. package/src/app/instances/instance-list-client.tsx +20 -69
  161. package/src/app/instances/layout.tsx +9 -0
  162. package/src/app/instances/new/create-instance-client.tsx +10 -31
  163. package/src/app/layout.tsx +2 -10
  164. package/src/app/not-found.tsx +1 -3
  165. package/src/app/page.tsx +1 -2
  166. package/src/app/plugins/error.tsx +2 -10
  167. package/src/app/plugins/layout.tsx +5 -0
  168. package/src/app/plugins/page.tsx +16 -48
  169. package/src/app/pricing/error.tsx +1 -7
  170. package/src/app/privacy/page.tsx +93 -150
  171. package/src/app/status/error.tsx +1 -7
  172. package/src/app/terms/page.tsx +89 -144
  173. package/src/components/account-switcher.tsx +25 -52
  174. package/src/components/admin/accounting-dashboard.tsx +1 -3
  175. package/src/components/admin/admin-guard.tsx +1 -3
  176. package/src/components/admin/admin-nav.tsx +1 -3
  177. package/src/components/admin/affiliate-dashboard.tsx +25 -94
  178. package/src/components/admin/audit-log-table.tsx +13 -49
  179. package/src/components/admin/billing-health-dashboard.tsx +7 -25
  180. package/src/components/admin/bulk-actions-bar.test.tsx +1 -7
  181. package/src/components/admin/bulk-actions-bar.tsx +1 -3
  182. package/src/components/admin/bulk-export-dialog.test.tsx +1 -7
  183. package/src/components/admin/bulk-export-dialog.tsx +6 -32
  184. package/src/components/admin/bulk-grant-dialog.test.tsx +2 -6
  185. package/src/components/admin/bulk-grant-dialog.tsx +4 -15
  186. package/src/components/admin/bulk-preview-dialog.tsx +3 -12
  187. package/src/components/admin/bulk-reactivate-dialog.tsx +1 -7
  188. package/src/components/admin/bulk-select-all-banner.tsx +1 -6
  189. package/src/components/admin/bulk-suspend-dialog.tsx +5 -12
  190. package/src/components/admin/bulk-undo-toast.tsx +1 -2
  191. package/src/components/admin/compliance-dashboard.tsx +31 -101
  192. package/src/components/admin/gpu-dashboard.tsx +21 -70
  193. package/src/components/admin/grant-credits-dialog.tsx +4 -17
  194. package/src/components/admin/incident-dashboard.tsx +10 -25
  195. package/src/components/admin/inference-dashboard.tsx +14 -54
  196. package/src/components/admin/marketplace-admin.tsx +18 -60
  197. package/src/components/admin/migrations-dashboard.tsx +9 -42
  198. package/src/components/admin/onboarding-dashboard.tsx +14 -64
  199. package/src/components/admin/pool-config-dashboard.tsx +4 -10
  200. package/src/components/admin/products/fleet-form.tsx +2 -11
  201. package/src/components/admin/products/nav-editor.tsx +3 -10
  202. package/src/components/admin/promotions/promotion-form.tsx +9 -42
  203. package/src/components/admin/roles-dashboard.tsx +7 -34
  204. package/src/components/admin/suspend-dialog.tsx +4 -11
  205. package/src/components/admin/tenant-notes-panel.tsx +1 -3
  206. package/src/components/admin/tenant-row-actions.tsx +4 -20
  207. package/src/components/admin/tenant-table.tsx +12 -49
  208. package/src/components/auth/auth-redirect.tsx +11 -3
  209. package/src/components/auth/email-verification-result-banner.tsx +1 -3
  210. package/src/components/auth/resend-verification-button.tsx +2 -10
  211. package/src/components/auth/wopr-wordmark.tsx +1 -3
  212. package/src/components/billing/add-payment-method-dialog.tsx +1 -2
  213. package/src/components/billing/affiliate-dashboard.tsx +4 -16
  214. package/src/components/billing/amount-selector.tsx +1 -3
  215. package/src/components/billing/auto-topup-card.tsx +2 -11
  216. package/src/components/billing/buy-credits-panel.tsx +4 -14
  217. package/src/components/billing/byok-callout.tsx +6 -8
  218. package/src/components/billing/confirmation-tracker.tsx +4 -14
  219. package/src/components/billing/credit-balance-badge.tsx +22 -0
  220. package/src/components/billing/credit-balance.tsx +3 -9
  221. package/src/components/billing/crypto-checkout.tsx +5 -24
  222. package/src/components/billing/degraded-state-banner.tsx +1 -3
  223. package/src/components/billing/deposit-view.tsx +301 -41
  224. package/src/components/billing/dividend-banner.tsx +1 -3
  225. package/src/components/billing/dividend-eligibility.tsx +3 -12
  226. package/src/components/billing/dividend-pool-stats.tsx +6 -20
  227. package/src/components/billing/first-dividend-dialog.tsx +2 -2
  228. package/src/components/billing/org-billing-page.tsx +8 -31
  229. package/src/components/billing/payment-method-picker.tsx +2 -10
  230. package/src/components/billing/suspension-banner.tsx +2 -7
  231. package/src/components/billing/transaction-history.tsx +10 -58
  232. package/src/components/billing/unified-checkout.tsx +547 -0
  233. package/src/components/bot-settings/backups-tab.tsx +9 -33
  234. package/src/components/bot-settings/bot-settings-client.tsx +32 -134
  235. package/src/components/bot-settings/resources-tab.tsx +2 -9
  236. package/src/components/bot-settings/storage-tab.tsx +19 -48
  237. package/src/components/bot-settings/vps-info-panel.tsx +3 -11
  238. package/src/components/bot-settings/vps-upgrade-card.tsx +3 -4
  239. package/src/components/brand-hydrator.tsx +13 -0
  240. package/src/components/channel-wizard/field-interactive.tsx +1 -3
  241. package/src/components/channel-wizard/field-qr.tsx +10 -39
  242. package/src/components/channel-wizard/step-renderer.tsx +5 -28
  243. package/src/components/channel-wizard/wizard.tsx +6 -31
  244. package/src/components/chat/chat-message.tsx +1 -4
  245. package/src/components/chat/chat-panel.tsx +4 -18
  246. package/src/components/chat/chat-widget.tsx +3 -14
  247. package/src/components/dashboard/command-center.tsx +15 -61
  248. package/src/components/fleet/update-settings-card.tsx +7 -23
  249. package/src/components/instance-update-banner.tsx +130 -0
  250. package/src/components/instances/friends-tab.test.tsx +2 -9
  251. package/src/components/instances/friends-tab.tsx +18 -74
  252. package/src/components/instances/update-available-badge.tsx +2 -11
  253. package/src/components/landing/hero.tsx +3 -9
  254. package/src/components/landing/landing-page.tsx +1 -3
  255. package/src/components/landing/portfolio-chart.tsx +4 -9
  256. package/src/components/landing/story-sections.tsx +1 -3
  257. package/src/components/landing/terminal-sequence.tsx +4 -17
  258. package/src/components/marketplace/empty-state.tsx +2 -6
  259. package/src/components/marketplace/first-visit-hero.tsx +1 -3
  260. package/src/components/marketplace/install-wizard.tsx +20 -77
  261. package/src/components/marketplace/marketplace-tabs.tsx +1 -4
  262. package/src/components/marketplace/plugin-card.tsx +2 -9
  263. package/src/components/marketplace/superpower-content.tsx +1 -3
  264. package/src/components/marketplace/terminal-search.tsx +2 -8
  265. package/src/components/oauth-buttons.tsx +29 -14
  266. package/src/components/observability/fleet-health.tsx +5 -18
  267. package/src/components/observability/health-overview.tsx +7 -20
  268. package/src/components/observability/logs-viewer.tsx +8 -32
  269. package/src/components/observability/metrics-dashboard.tsx +2 -15
  270. package/src/components/onboarding/fallback-setup.tsx +6 -25
  271. package/src/components/onboarding/setup-checklist.tsx +18 -51
  272. package/src/components/onboarding/step-superpowers.tsx +1 -4
  273. package/src/components/plugin-setup/setup-chat-panel.tsx +6 -22
  274. package/src/components/pricing/dividend-calculator.tsx +6 -12
  275. package/src/components/pricing/dividend-stats.tsx +5 -17
  276. package/src/components/pricing/pricing-page.tsx +17 -36
  277. package/src/components/settings/create-org-wizard.tsx +2 -5
  278. package/src/components/sidebar.tsx +7 -42
  279. package/src/components/sidecar-frame.tsx +78 -0
  280. package/src/components/status/status-page.tsx +6 -28
  281. package/src/components/ui/alert-dialog.tsx +8 -25
  282. package/src/components/ui/badge.tsx +2 -8
  283. package/src/components/ui/banner.tsx +1 -6
  284. package/src/components/ui/card.tsx +5 -24
  285. package/src/components/ui/checkbox.tsx +1 -5
  286. package/src/components/ui/collapsible.tsx +3 -8
  287. package/src/components/ui/dialog.tsx +4 -10
  288. package/src/components/ui/dropdown-menu.tsx +9 -18
  289. package/src/components/ui/form.tsx +2 -16
  290. package/src/components/ui/popover.tsx +3 -23
  291. package/src/components/ui/progress.tsx +1 -5
  292. package/src/components/ui/radio-group.tsx +3 -15
  293. package/src/components/ui/select.tsx +4 -17
  294. package/src/components/ui/sheet.tsx +5 -19
  295. package/src/components/ui/skeleton.tsx +1 -7
  296. package/src/components/ui/table.tsx +5 -22
  297. package/src/components/ui/tabs.tsx +3 -13
  298. package/src/components/ui/tooltip.tsx +1 -1
  299. package/src/components/unified-sidebar.tsx +493 -0
  300. package/src/hooks/__tests__/use-fleet-sse.test.ts +1 -4
  301. package/src/hooks/__tests__/use-save-queue.test.ts +2 -8
  302. package/src/hooks/use-credit-balance.ts +27 -0
  303. package/src/hooks/use-my-org-role.ts +1 -3
  304. package/src/hooks/use-plugin-registry.ts +8 -14
  305. package/src/hooks/use-plugin-setup-chat.ts +2 -5
  306. package/src/hooks/use-sidecar-bridge.tsx +148 -0
  307. package/src/hooks/use-webmcp.ts +1 -4
  308. package/src/lib/__tests__/admin-api.test.ts +1 -3
  309. package/src/lib/__tests__/api-bot-crud.test.ts +8 -18
  310. package/src/lib/__tests__/api-fetch.test.ts +4 -16
  311. package/src/lib/__tests__/org-billing-api.test.ts +1 -3
  312. package/src/lib/__tests__/pricing-data.test.ts +0 -8
  313. package/src/lib/__tests__/settings-api.test.ts +1 -3
  314. package/src/lib/admin-affiliate-api.ts +2 -7
  315. package/src/lib/admin-api.ts +6 -26
  316. package/src/lib/admin-incident-api.ts +11 -19
  317. package/src/lib/admin-marketplace-api.ts +1 -5
  318. package/src/lib/api-config.test.ts +5 -50
  319. package/src/lib/api.ts +143 -122
  320. package/src/lib/auth-client.ts +1 -2
  321. package/src/lib/bot-settings-data.ts +11 -36
  322. package/src/lib/brand-config.ts +56 -115
  323. package/src/lib/brand.ts +2 -15
  324. package/src/lib/chat/use-chat.ts +2 -7
  325. package/src/lib/cost-comparison-data.test.ts +1 -3
  326. package/src/lib/cost-comparison-data.ts +1 -4
  327. package/src/lib/errors.ts +1 -4
  328. package/src/lib/fetch-utils.test.ts +26 -9
  329. package/src/lib/fetch-utils.ts +40 -11
  330. package/src/lib/logger.ts +2 -0
  331. package/src/lib/marketplace-data.ts +3 -11
  332. package/src/lib/oauth-errors.ts +2 -4
  333. package/src/lib/onboarding-data.ts +3 -11
  334. package/src/lib/org-api.ts +2 -10
  335. package/src/lib/org-billing-api.ts +5 -19
  336. package/src/lib/plugin/tool-definitions.ts +1 -2
  337. package/src/lib/require-auth.ts +57 -0
  338. package/src/lib/settings-api.ts +1 -4
  339. package/src/lib/sidecar-routes.ts +43 -0
  340. package/src/lib/trpc-server.ts +49 -0
  341. package/src/lib/trpc-types.ts +4 -6
  342. package/src/lib/trpc.tsx +12 -4
  343. package/src/lib/validate-redirect-url.ts +1 -4
  344. package/src/lib/webmcp/marketplace-onboarding-tools.ts +6 -16
  345. package/src/lib/webmcp/register.ts +1 -4
  346. package/src/lib/webmcp/tools.ts +2 -9
  347. package/src/proxy.ts +35 -212
  348. package/src/types/missing-deps.d.ts +2 -8
  349. package/tsconfig.json +1 -8
  350. package/biome.json +0 -52
  351. package/src/__tests__/__snapshots__/layout-snapshots.test.tsx.snap +0 -741
  352. package/src/__tests__/billing-byok-callout.test.tsx +0 -76
  353. package/src/lib/__tests__/__snapshots__/pricing-data.test.ts.snap +0 -112
@@ -1,13 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { AnimatePresence, motion } from "framer-motion";
4
- import {
5
- CreditCardIcon,
6
- DownloadIcon,
7
- ExternalLinkIcon,
8
- LockIcon,
9
- ShieldCheckIcon,
10
- } from "lucide-react";
4
+ import { CreditCardIcon, DownloadIcon, ExternalLinkIcon, LockIcon, ShieldCheckIcon } from "lucide-react";
11
5
  import { type FormEvent, useCallback, useEffect, useState } from "react";
12
6
  import { AddPaymentMethodDialog } from "@/components/billing/add-payment-method-dialog";
13
7
  import { ByokCallout } from "@/components/billing/byok-callout";
@@ -19,21 +13,9 @@ import { Input } from "@/components/ui/input";
19
13
  import { Label } from "@/components/ui/label";
20
14
  import { Separator } from "@/components/ui/separator";
21
15
  import { Skeleton } from "@/components/ui/skeleton";
22
- import {
23
- Table,
24
- TableBody,
25
- TableCell,
26
- TableHead,
27
- TableHeader,
28
- TableRow,
29
- } from "@/components/ui/table";
16
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
30
17
  import type { BillingInfo, Invoice } from "@/lib/api";
31
- import {
32
- getBillingInfo,
33
- removePaymentMethod,
34
- setDefaultPaymentMethod,
35
- updateBillingEmail,
36
- } from "@/lib/api";
18
+ import { getBillingInfo, removePaymentMethod, setDefaultPaymentMethod, updateBillingEmail } from "@/lib/api";
37
19
  import { useSession } from "@/lib/auth-client";
38
20
  import { brandName } from "@/lib/brand-config";
39
21
  import { formatCreditStandard } from "@/lib/format-credit";
@@ -236,9 +218,7 @@ export default function PaymentPage() {
236
218
  <div className="max-w-3xl space-y-6">
237
219
  <div>
238
220
  <h1 className="text-2xl font-bold tracking-tight">Payment</h1>
239
- <p className="text-sm text-muted-foreground">
240
- Manage your payment methods and view billing history
241
- </p>
221
+ <p className="text-sm text-muted-foreground">Manage your payment methods and view billing history</p>
242
222
  </div>
243
223
 
244
224
  <ByokCallout compact />
@@ -247,9 +227,7 @@ export default function PaymentPage() {
247
227
  <Card>
248
228
  <CardHeader>
249
229
  <CardTitle>Payment Methods</CardTitle>
250
- <CardDescription>
251
- Cards on file for {brandName()} platform charges (not AI provider costs)
252
- </CardDescription>
230
+ <CardDescription>Cards on file for {brandName()} platform charges (not AI provider costs)</CardDescription>
253
231
  </CardHeader>
254
232
  <CardContent className="space-y-4">
255
233
  {info.paymentMethods.length === 0 ? (
@@ -257,13 +235,9 @@ export default function PaymentPage() {
257
235
  ) : (
258
236
  <div className="space-y-3">
259
237
  {info.paymentMethods.map((pm) => {
260
- const brandClass =
261
- BRAND_STYLES[pm.brand.toLowerCase()] ?? "bg-muted text-muted-foreground";
238
+ const brandClass = BRAND_STYLES[pm.brand.toLowerCase()] ?? "bg-muted text-muted-foreground";
262
239
  return (
263
- <div
264
- key={pm.id}
265
- className="flex items-center justify-between rounded-md border p-3"
266
- >
240
+ <div key={pm.id} className="flex items-center justify-between rounded-md border p-3">
267
241
  <div className="flex items-center gap-3">
268
242
  <div
269
243
  className={cn(
@@ -322,11 +296,7 @@ export default function PaymentPage() {
322
296
  <Button variant="outline" onClick={() => setShowAddPayment(true)}>
323
297
  Add payment method
324
298
  </Button>
325
- <AddPaymentMethodDialog
326
- open={showAddPayment}
327
- onOpenChange={setShowAddPayment}
328
- onSuccess={load}
329
- />
299
+ <AddPaymentMethodDialog open={showAddPayment} onOpenChange={setShowAddPayment} onSuccess={load} />
330
300
  <div className="flex flex-wrap items-center gap-4 text-xs text-muted-foreground">
331
301
  <span className="flex items-center gap-1">
332
302
  <LockIcon className="size-3" />
@@ -375,18 +345,13 @@ export default function PaymentPage() {
375
345
  <Card>
376
346
  <CardHeader>
377
347
  <CardTitle>Org Payment Methods</CardTitle>
378
- <CardDescription>
379
- Cards on file for org-level charges ({orgContext.orgName})
380
- </CardDescription>
348
+ <CardDescription>Cards on file for org-level charges ({orgContext.orgName})</CardDescription>
381
349
  </CardHeader>
382
350
  <CardContent className="space-y-4">
383
351
  {orgLoading ? (
384
352
  <div className="space-y-3">
385
353
  {["sk-org-a", "sk-org-b"].map((skId) => (
386
- <div
387
- key={skId}
388
- className="flex items-center justify-between rounded-md border p-3"
389
- >
354
+ <div key={skId} className="flex items-center justify-between rounded-md border p-3">
390
355
  <Skeleton className="h-4 w-40" />
391
356
  <Skeleton className="h-8 w-16" />
392
357
  </div>
@@ -397,17 +362,11 @@ export default function PaymentPage() {
397
362
  ) : (
398
363
  <div className="space-y-3">
399
364
  {orgPaymentMethods.map((pm) => (
400
- <div
401
- key={pm.id}
402
- className="flex items-center justify-between rounded-md border p-3"
403
- >
365
+ <div key={pm.id} className="flex items-center justify-between rounded-md border p-3">
404
366
  <p className="text-sm font-medium font-mono">
405
367
  **** {pm.last4}
406
368
  {pm.isDefault && (
407
- <Badge
408
- variant="outline"
409
- className="ml-2 border-primary/25 text-primary text-xs"
410
- >
369
+ <Badge variant="outline" className="ml-2 border-primary/25 text-primary text-xs">
411
370
  Default
412
371
  </Badge>
413
372
  )}
@@ -455,10 +414,7 @@ export default function PaymentPage() {
455
414
  {orgLoading ? (
456
415
  <div className="space-y-3">
457
416
  {["sk-oinv-a", "sk-oinv-b"].map((skId) => (
458
- <div
459
- key={skId}
460
- className="flex items-center justify-between rounded-md border p-3"
461
- >
417
+ <div key={skId} className="flex items-center justify-between rounded-md border p-3">
462
418
  <Skeleton className="h-4 w-32" />
463
419
  <Skeleton className="h-4 w-20" />
464
420
  </div>
@@ -503,11 +459,7 @@ export default function PaymentPage() {
503
459
  <TableCell>
504
460
  {invoice.downloadUrl ? (
505
461
  <Button variant="ghost" size="sm" asChild>
506
- <a
507
- href={invoice.downloadUrl}
508
- target="_blank"
509
- rel="noopener noreferrer"
510
- >
462
+ <a href={invoice.downloadUrl} target="_blank" rel="noopener noreferrer">
511
463
  <DownloadIcon className="mr-1 size-3" />
512
464
  Download PDF
513
465
  </a>
@@ -536,9 +488,7 @@ export default function PaymentPage() {
536
488
  {/* Billing History */}
537
489
  <div>
538
490
  <h2 className="text-lg font-semibold">Billing History</h2>
539
- <p className="mb-4 text-sm text-muted-foreground">
540
- Past invoices for {brandName()} platform services
541
- </p>
491
+ <p className="mb-4 text-sm text-muted-foreground">Past invoices for {brandName()} platform services</p>
542
492
  </div>
543
493
 
544
494
  {info.invoices.length === 0 ? (
@@ -643,11 +593,10 @@ function InvoiceRow({
643
593
  className="overflow-hidden"
644
594
  >
645
595
  <div className="bg-muted/50 p-4">
646
- <p className="mb-2 text-xs font-semibold text-muted-foreground">
647
- Hosted Usage Line Items
648
- </p>
596
+ <p className="mb-2 text-xs font-semibold text-muted-foreground">Hosted Usage Line Items</p>
649
597
  <div className="space-y-1 text-xs">
650
598
  {invoice.hostedLineItems?.map((item, i) => (
599
+ // biome-ignore lint/suspicious/noArrayIndexKey: static list, index key is safe
651
600
  <div key={`${invoice.id}-item-${i}`} className="flex justify-between">
652
601
  <span>
653
602
  {item.capability} — {item.units.toLocaleString()} units @{" "}
@@ -18,16 +18,12 @@ export default function PlansPage() {
18
18
 
19
19
  <Card className="border-terminal shadow-[0_0_12px_rgba(0,255,65,0.15)]">
20
20
  <CardHeader className="text-center">
21
- <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">
22
- {productName()}
23
- </CardTitle>
21
+ <CardTitle className="text-sm uppercase tracking-widest text-muted-foreground">{productName()}</CardTitle>
24
22
  </CardHeader>
25
23
  <CardContent className="flex flex-col items-center gap-4 text-center">
26
24
  <p className="text-5xl font-bold text-terminal">
27
25
  ${pricingData.bot_price.amount}
28
- <span className="text-xl font-normal text-muted-foreground">
29
- /{pricingData.bot_price.period}
30
- </span>
26
+ <span className="text-xl font-normal text-muted-foreground">/{pricingData.bot_price.period}</span>
31
27
  </p>
32
28
  <p className="text-muted-foreground">per bot</p>
33
29
  <ul className="space-y-2 text-sm">
@@ -38,9 +34,7 @@ export default function PlansPage() {
38
34
  </li>
39
35
  ))}
40
36
  </ul>
41
- <p className="text-xs text-muted-foreground">
42
- Usage is billed from credits at transparent per-use rates.
43
- </p>
37
+ <p className="text-xs text-muted-foreground">Usage is billed from credits at transparent per-use rates.</p>
44
38
  <Button variant="outline" size="sm" asChild>
45
39
  <Link href="/pricing">View full pricing</Link>
46
40
  </Button>
@@ -8,22 +8,9 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com
8
8
  import { CreditDetailed } from "@/components/ui/credit-detailed";
9
9
  import { Input } from "@/components/ui/input";
10
10
  import { Label } from "@/components/ui/label";
11
- import {
12
- Select,
13
- SelectContent,
14
- SelectItem,
15
- SelectTrigger,
16
- SelectValue,
17
- } from "@/components/ui/select";
11
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
18
12
  import { Skeleton } from "@/components/ui/skeleton";
19
- import {
20
- Table,
21
- TableBody,
22
- TableCell,
23
- TableHead,
24
- TableHeader,
25
- TableRow,
26
- } from "@/components/ui/table";
13
+ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
27
14
  import type { HostedCapability, HostedUsageEvent } from "@/lib/api";
28
15
  import { getHostedUsageEvents } from "@/lib/api";
29
16
  import { formatCreditDetailed, formatCreditStandard } from "@/lib/format-credit";
@@ -230,13 +217,11 @@ export default function HostedUsageDetailPage() {
230
217
  </SelectTrigger>
231
218
  <SelectContent>
232
219
  <SelectItem value="all">All capabilities</SelectItem>
233
- {(Object.entries(CAPABILITY_LABELS) as [HostedCapability, string][]).map(
234
- ([cap, label]) => (
235
- <SelectItem key={cap} value={cap}>
236
- {label}
237
- </SelectItem>
238
- ),
239
- )}
220
+ {(Object.entries(CAPABILITY_LABELS) as [HostedCapability, string][]).map(([cap, label]) => (
221
+ <SelectItem key={cap} value={cap}>
222
+ {label}
223
+ </SelectItem>
224
+ ))}
240
225
  </SelectContent>
241
226
  </Select>
242
227
  <Button variant="outline" size="sm" onClick={handleExportCsv}>
@@ -324,9 +309,7 @@ export default function HostedUsageDetailPage() {
324
309
  })}
325
310
  </TableCell>
326
311
  <TableCell>
327
- <Badge variant="outline">
328
- {CAPABILITY_LABELS[event.capability] ?? event.capability}
329
- </Badge>
312
+ <Badge variant="outline">{CAPABILITY_LABELS[event.capability] ?? event.capability}</Badge>
330
313
  </TableCell>
331
314
  <TableCell>{event.provider}</TableCell>
332
315
  <TableCell className="text-right">
@@ -2,17 +2,7 @@
2
2
 
3
3
  import Link from "next/link";
4
4
  import { useCallback, useEffect, useState } from "react";
5
- import {
6
- Area,
7
- AreaChart,
8
- Bar,
9
- BarChart,
10
- CartesianGrid,
11
- ResponsiveContainer,
12
- Tooltip,
13
- XAxis,
14
- YAxis,
15
- } from "recharts";
5
+ import { Area, AreaChart, Bar, BarChart, CartesianGrid, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
16
6
  import { ByokCallout } from "@/components/billing/byok-callout";
17
7
  import { Button } from "@/components/ui/button";
18
8
  import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
@@ -231,9 +221,7 @@ export default function UsagePage() {
231
221
  <div className="space-y-1 text-sm">
232
222
  <div className="flex justify-between">
233
223
  <span className="text-muted-foreground">Total spend this period</span>
234
- <span className="font-medium tabular-nums">
235
- {formatCreditStandard(summary.totalSpend)}
236
- </span>
224
+ <span className="font-medium tabular-nums">{formatCreditStandard(summary.totalSpend)}</span>
237
225
  </div>
238
226
  <div className="flex justify-between">
239
227
  <span className="text-muted-foreground">Included credit</span>
@@ -254,24 +242,11 @@ export default function UsagePage() {
254
242
  <Card>
255
243
  <CardHeader>
256
244
  <CardTitle>Platform Usage</CardTitle>
257
- <CardDescription>
258
- Your {brandName()} orchestration usage this billing period
259
- </CardDescription>
245
+ <CardDescription>Your {brandName()} orchestration usage this billing period</CardDescription>
260
246
  </CardHeader>
261
247
  <CardContent className="space-y-5">
262
- <UsageMeter
263
- label="Instances"
264
- current={usage.instancesRunning}
265
- cap={usage.instanceCap}
266
- unit=""
267
- />
268
- <UsageMeter
269
- label="Storage"
270
- current={usage.storageUsedGb}
271
- cap={usage.storageCapGb}
272
- unit="GB"
273
- decimals={1}
274
- />
248
+ <UsageMeter label="Instances" current={usage.instancesRunning} cap={usage.instanceCap} unit="" />
249
+ <UsageMeter label="Storage" current={usage.storageUsedGb} cap={usage.storageCapGb} unit="GB" decimals={1} />
275
250
  <div className="space-y-1.5">
276
251
  <div className="flex justify-between text-sm">
277
252
  <span className="text-muted-foreground">API calls</span>
@@ -291,10 +266,7 @@ export default function UsagePage() {
291
266
  <CardContent className="space-y-4">
292
267
  {hostedUsage.capabilities.length > 0 && (
293
268
  <div className="w-full">
294
- <ResponsiveContainer
295
- width="100%"
296
- height={hostedUsage.capabilities.length * 40 + 20}
297
- >
269
+ <ResponsiveContainer width="100%" height={hostedUsage.capabilities.length * 40 + 20}>
298
270
  <BarChart
299
271
  data={hostedUsage.capabilities.map((cap) => ({
300
272
  label: CAPABILITY_LABELS[cap.capability] ?? cap.label,
@@ -334,9 +306,7 @@ export default function UsagePage() {
334
306
  <div className="space-y-2">
335
307
  {hostedUsage.capabilities.map((cap) => (
336
308
  <div key={cap.capability} className="flex items-center justify-between text-sm">
337
- <span className="font-medium">
338
- {CAPABILITY_LABELS[cap.capability] ?? cap.label}
339
- </span>
309
+ <span className="font-medium">{CAPABILITY_LABELS[cap.capability] ?? cap.label}</span>
340
310
  <div className="flex items-center gap-4 text-muted-foreground">
341
311
  <span>
342
312
  {cap.units.toLocaleString()} {cap.unitLabel}
@@ -384,11 +354,7 @@ export default function UsagePage() {
384
354
  <Label htmlFor="cost-tracker-toggle" className="text-sm text-muted-foreground">
385
355
  {showCostTracker ? "On" : "Off"}
386
356
  </Label>
387
- <Switch
388
- id="cost-tracker-toggle"
389
- checked={showCostTracker}
390
- onCheckedChange={setShowCostTracker}
391
- />
357
+ <Switch id="cost-tracker-toggle" checked={showCostTracker} onCheckedChange={setShowCostTracker} />
392
358
  </div>
393
359
  </div>
394
360
  </CardHeader>
@@ -404,8 +370,7 @@ export default function UsagePage() {
404
370
  <span className="font-medium">{cost.provider}</span>
405
371
  <div className="flex items-center gap-4 text-muted-foreground">
406
372
  <span>
407
- {(cost.inputTokens / 1000).toFixed(0)}k in /{" "}
408
- {(cost.outputTokens / 1000).toFixed(0)}k out
373
+ {(cost.inputTokens / 1000).toFixed(0)}k in / {(cost.outputTokens / 1000).toFixed(0)}k out
409
374
  </span>
410
375
  <span className="font-medium text-foreground min-w-[7rem]">
411
376
  ~<CreditDetailed value={cost.estimatedCost} />
@@ -415,8 +380,7 @@ export default function UsagePage() {
415
380
  ))}
416
381
  </div>
417
382
  <p className="text-xs text-muted-foreground">
418
- These are your direct costs with your providers — {brandName()} does not charge for
419
- inference.
383
+ These are your direct costs with your providers — {brandName()} does not charge for inference.
420
384
  </p>
421
385
  </CardContent>
422
386
  )}
@@ -429,9 +393,7 @@ export default function UsagePage() {
429
393
  <div className="flex items-center justify-between">
430
394
  <div className="space-y-1">
431
395
  <CardTitle>Spending Controls</CardTitle>
432
- <CardDescription>
433
- Set alerts and hard caps to manage your hosted AI spend
434
- </CardDescription>
396
+ <CardDescription>Set alerts and hard caps to manage your hosted AI spend</CardDescription>
435
397
  </div>
436
398
  <div className="flex items-center gap-2">
437
399
  <Label htmlFor="spending-controls-toggle" className="text-sm text-muted-foreground">
@@ -503,63 +465,61 @@ export default function UsagePage() {
503
465
  {/* Per-capability limits */}
504
466
  <div className="space-y-3">
505
467
  <h4 className="text-sm font-semibold">Per-Capability Limits</h4>
506
- {(Object.entries(CAPABILITY_LABELS) as [HostedCapability, string][]).map(
507
- ([cap, label]) => (
508
- <div key={cap} className="space-y-1">
509
- <p className="text-xs font-medium text-muted-foreground">{label}</p>
510
- <div className="grid gap-4 sm:grid-cols-2">
511
- <Input
512
- type="number"
513
- min={0}
514
- step={1}
515
- placeholder="Alert at $/mo"
516
- aria-label={`${label} alert limit`}
517
- value={spendingLimits.perCapability[cap]?.alertAt ?? ""}
518
- onChange={(e) => {
519
- const existing = spendingLimits.perCapability[cap] ?? {
520
- alertAt: null,
521
- hardCap: null,
522
- };
523
- setSpendingLimits({
524
- ...spendingLimits,
525
- perCapability: {
526
- ...spendingLimits.perCapability,
527
- [cap]: {
528
- ...existing,
529
- alertAt: e.target.value ? Number(e.target.value) : null,
530
- },
468
+ {(Object.entries(CAPABILITY_LABELS) as [HostedCapability, string][]).map(([cap, label]) => (
469
+ <div key={cap} className="space-y-1">
470
+ <p className="text-xs font-medium text-muted-foreground">{label}</p>
471
+ <div className="grid gap-4 sm:grid-cols-2">
472
+ <Input
473
+ type="number"
474
+ min={0}
475
+ step={1}
476
+ placeholder="Alert at $/mo"
477
+ aria-label={`${label} alert limit`}
478
+ value={spendingLimits.perCapability[cap]?.alertAt ?? ""}
479
+ onChange={(e) => {
480
+ const existing = spendingLimits.perCapability[cap] ?? {
481
+ alertAt: null,
482
+ hardCap: null,
483
+ };
484
+ setSpendingLimits({
485
+ ...spendingLimits,
486
+ perCapability: {
487
+ ...spendingLimits.perCapability,
488
+ [cap]: {
489
+ ...existing,
490
+ alertAt: e.target.value ? Number(e.target.value) : null,
531
491
  },
532
- });
533
- }}
534
- />
535
- <Input
536
- type="number"
537
- min={0}
538
- step={1}
539
- placeholder="Hard cap $/mo"
540
- aria-label={`${label} hard cap`}
541
- value={spendingLimits.perCapability[cap]?.hardCap ?? ""}
542
- onChange={(e) => {
543
- const existing = spendingLimits.perCapability[cap] ?? {
544
- alertAt: null,
545
- hardCap: null,
546
- };
547
- setSpendingLimits({
548
- ...spendingLimits,
549
- perCapability: {
550
- ...spendingLimits.perCapability,
551
- [cap]: {
552
- ...existing,
553
- hardCap: e.target.value ? Number(e.target.value) : null,
554
- },
492
+ },
493
+ });
494
+ }}
495
+ />
496
+ <Input
497
+ type="number"
498
+ min={0}
499
+ step={1}
500
+ placeholder="Hard cap $/mo"
501
+ aria-label={`${label} hard cap`}
502
+ value={spendingLimits.perCapability[cap]?.hardCap ?? ""}
503
+ onChange={(e) => {
504
+ const existing = spendingLimits.perCapability[cap] ?? {
505
+ alertAt: null,
506
+ hardCap: null,
507
+ };
508
+ setSpendingLimits({
509
+ ...spendingLimits,
510
+ perCapability: {
511
+ ...spendingLimits.perCapability,
512
+ [cap]: {
513
+ ...existing,
514
+ hardCap: e.target.value ? Number(e.target.value) : null,
555
515
  },
556
- });
557
- }}
558
- />
559
- </div>
516
+ },
517
+ });
518
+ }}
519
+ />
560
520
  </div>
561
- ),
562
- )}
521
+ </div>
522
+ ))}
563
523
  </div>
564
524
 
565
525
  {limitsMsg && <p className="text-sm text-muted-foreground">{limitsMsg}</p>}
@@ -20,12 +20,7 @@ import { Separator } from "@/components/ui/separator";
20
20
  import { Skeleton } from "@/components/ui/skeleton";
21
21
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
22
22
  import { getChangeset } from "@/lib/changeset-api";
23
- import type {
24
- ChangesetDetail,
25
- ChangesetFile,
26
- ChangesetReviewStatus,
27
- ChangesetStatus,
28
- } from "@/lib/changeset-types";
23
+ import type { ChangesetDetail, ChangesetFile, ChangesetReviewStatus, ChangesetStatus } from "@/lib/changeset-types";
29
24
  import { toUserMessage } from "@/lib/errors";
30
25
  import { formatRelativeTime } from "@/lib/format";
31
26
  import { cn } from "@/lib/utils";
@@ -98,6 +93,7 @@ function DiffBlock({ patch }: { patch: string }) {
98
93
  lineClass = "text-red-400 bg-red-500/10";
99
94
  }
100
95
  return (
96
+ // biome-ignore lint/suspicious/noArrayIndexKey: static list, index key is safe
101
97
  <div key={`${idx}-${line.slice(0, 20)}`} className={lineClass}>
102
98
  {line}
103
99
  </div>
@@ -197,9 +193,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
197
193
  <ChangesetStatusBadge status={changeset.status} />
198
194
  <ReviewStatusBadge status={changeset.reviewStatus} />
199
195
  </div>
200
- {changeset.description && (
201
- <p className="text-sm text-muted-foreground">{changeset.description}</p>
202
- )}
196
+ {changeset.description && <p className="text-sm text-muted-foreground">{changeset.description}</p>}
203
197
  </div>
204
198
 
205
199
  {/* Metadata */}
@@ -252,9 +246,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
252
246
  <span className="text-sm text-muted-foreground">
253
247
  {changeset.files.length} file{changeset.files.length !== 1 ? "s" : ""} changed
254
248
  </span>
255
- <span className="text-sm font-mono text-emerald-400">
256
- +{changeset.totalAdditions}
257
- </span>
249
+ <span className="text-sm font-mono text-emerald-400">+{changeset.totalAdditions}</span>
258
250
  <span className="text-sm font-mono text-red-400">-{changeset.totalDeletions}</span>
259
251
  </CardContent>
260
252
  </Card>
@@ -268,9 +260,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
268
260
  <TabsContent value="reviews" className="space-y-4">
269
261
  {changeset.reviews.length === 0 ? (
270
262
  <Card>
271
- <CardContent className="py-8 text-center text-sm text-muted-foreground">
272
- No reviews yet.
273
- </CardContent>
263
+ <CardContent className="py-8 text-center text-sm text-muted-foreground">No reviews yet.</CardContent>
274
264
  </Card>
275
265
  ) : (
276
266
  changeset.reviews.map((review) => (
@@ -283,9 +273,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
283
273
  </div>
284
274
  <div className="flex items-center gap-2">
285
275
  <ReviewStatusBadge status={review.status} />
286
- <span className="text-xs text-muted-foreground">
287
- {formatRelativeTime(review.createdAt)}
288
- </span>
276
+ <span className="text-xs text-muted-foreground">{formatRelativeTime(review.createdAt)}</span>
289
277
  </div>
290
278
  </div>
291
279
  </CardHeader>
@@ -303,9 +291,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
303
291
  <TabsContent value="comments" className="space-y-4">
304
292
  {changeset.comments.length === 0 ? (
305
293
  <Card>
306
- <CardContent className="py-8 text-center text-sm text-muted-foreground">
307
- No comments yet.
308
- </CardContent>
294
+ <CardContent className="py-8 text-center text-sm text-muted-foreground">No comments yet.</CardContent>
309
295
  </Card>
310
296
  ) : (
311
297
  changeset.comments.map((comment) => (
@@ -316,9 +302,7 @@ export function ChangesetDetailClient({ changesetId }: { changesetId: string })
316
302
  <User className="size-3.5 text-muted-foreground" />
317
303
  <span className="text-sm font-medium">{comment.author}</span>
318
304
  </div>
319
- <span className="text-xs text-muted-foreground">
320
- {formatRelativeTime(comment.createdAt)}
321
- </span>
305
+ <span className="text-xs text-muted-foreground">{formatRelativeTime(comment.createdAt)}</span>
322
306
  </div>
323
307
  </CardHeader>
324
308
  <CardContent className="pt-0">
@@ -370,9 +354,7 @@ function FileCard({ file }: { file: ChangesetFile }) {
370
354
  )}
371
355
  <FileStatusBadge status={file.status} />
372
356
  <span className="font-mono text-sm">
373
- {file.status === "renamed" && file.previousPath
374
- ? `${file.previousPath} → ${file.path}`
375
- : file.path}
357
+ {file.status === "renamed" && file.previousPath ? `${file.previousPath} → ${file.path}` : file.path}
376
358
  </span>
377
359
  </div>
378
360
  <div className="flex items-center gap-3">
@@ -28,9 +28,7 @@ export default function ChangesetDetailError({
28
28
  <CardTitle>Changeset Error</CardTitle>
29
29
  </CardHeader>
30
30
  <CardContent className="space-y-4 text-center">
31
- <p className="text-sm text-muted-foreground">
32
- Something went wrong while loading this changeset.
33
- </p>
31
+ <p className="text-sm text-muted-foreground">Something went wrong while loading this changeset.</p>
34
32
  <div className="flex justify-center gap-3">
35
33
  <Button variant="outline" onClick={reset}>
36
34
  Retry
@@ -41,9 +39,7 @@ export default function ChangesetDetailError({
41
39
  </div>
42
40
  {process.env.NODE_ENV === "development" && (
43
41
  <details className="mt-4 text-left">
44
- <summary className="cursor-pointer text-xs text-muted-foreground">
45
- Error details
46
- </summary>
42
+ <summary className="cursor-pointer text-xs text-muted-foreground">Error details</summary>
47
43
  <pre className="mt-2 overflow-auto rounded bg-muted p-2 text-xs">
48
44
  {error.message}
49
45
  {error.stack && `\n\n${error.stack}`}
@@ -8,13 +8,7 @@ import { logger } from "@/lib/logger";
8
8
 
9
9
  const log = logger("error-boundary:changesets");
10
10
 
11
- export default function ChangesetsError({
12
- error,
13
- reset,
14
- }: {
15
- error: Error & { digest?: string };
16
- reset: () => void;
17
- }) {
11
+ export default function ChangesetsError({ error, reset }: { error: Error & { digest?: string }; reset: () => void }) {
18
12
  const [showDetails, setShowDetails] = useState(false);
19
13
  const isDev = process.env.NODE_ENV === "development";
20
14