@wopr-network/platform-ui-core 1.27.7 → 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 +14 -17
  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
@@ -19,9 +19,7 @@ export default function TermsPage() {
19
19
  <p className="mt-2 text-sm text-muted-foreground">Last updated: February 2026</p>
20
20
 
21
21
  <nav className="mt-6 rounded-sm border border-border bg-card p-4">
22
- <p className="mb-3 text-xs font-medium uppercase tracking-[0.15em] text-muted-foreground">
23
- Contents
24
- </p>
22
+ <p className="mb-3 text-xs font-medium uppercase tracking-[0.15em] text-muted-foreground">Contents</p>
25
23
  <ol className="list-none space-y-1.5 text-sm text-muted-foreground">
26
24
  <li>
27
25
  <a href="#section-1" className="underline underline-offset-4 hover:text-foreground">
@@ -110,8 +108,8 @@ export default function TermsPage() {
110
108
  <section id="section-1" className="scroll-mt-16">
111
109
  <h2 className="mb-2 text-base font-semibold text-foreground">1. Acceptance of Terms</h2>
112
110
  <p>
113
- By creating an account or using {brand.productName} at {brand.domain}, you agree to be
114
- bound by these Terms of Service and our{" "}
111
+ By creating an account or using {brand.productName} at {brand.domain}, you agree to be bound by these
112
+ Terms of Service and our{" "}
115
113
  <Link href="/privacy" className="text-foreground underline underline-offset-4">
116
114
  Privacy Policy
117
115
  </Link>
@@ -120,21 +118,17 @@ export default function TermsPage() {
120
118
  </section>
121
119
 
122
120
  <section id="section-2" className="scroll-mt-16">
123
- <h2 className="mb-2 text-base font-semibold text-foreground">
124
- 2. Description of Service
125
- </h2>
121
+ <h2 className="mb-2 text-base font-semibold text-foreground">2. Description of Service</h2>
126
122
  <p>
127
- {brand.productName} provides AI bot orchestration services. You bring your own API
128
- keys for AI providers (the &ldquo;bring your own key&rdquo; model).{" "}
129
- {brand.productName} manages orchestration, memory, plugins, and channel integrations.
130
- The service is available at
123
+ {brand.productName} provides AI bot orchestration services. You bring your own API keys for AI providers
124
+ (the &ldquo;bring your own key&rdquo; model). {brand.productName} manages orchestration, memory, plugins,
125
+ and channel integrations. The service is available at
131
126
  {brand.domain}.
132
127
  </p>
133
128
  <p className="mt-2">
134
- {brand.productName} does not provide AI models directly. We orchestrate your
135
- interactions with your chosen AI providers using your API keys. Additionally, we offer
136
- optional hosted capabilities (such as voice synthesis and image generation) that
137
- consume credits on a per-use basis.
129
+ {brand.productName} does not provide AI models directly. We orchestrate your interactions with your chosen
130
+ AI providers using your API keys. Additionally, we offer optional hosted capabilities (such as voice
131
+ synthesis and image generation) that consume credits on a per-use basis.
138
132
  </p>
139
133
  </section>
140
134
 
@@ -142,159 +136,124 @@ export default function TermsPage() {
142
136
  <h2 className="mb-2 text-base font-semibold text-foreground">3. Account Terms</h2>
143
137
  <ul className="ml-4 mt-2 list-disc space-y-1">
144
138
  <li>You must be at least 13 years of age to use this service.</li>
139
+ <li>You must provide accurate and complete information when creating your account.</li>
145
140
  <li>
146
- You must provide accurate and complete information when creating your account.
141
+ You are responsible for maintaining the security of your account and password. {brand.productName} will
142
+ not be liable for any loss or damage from your failure to maintain account security.
147
143
  </li>
148
144
  <li>
149
- You are responsible for maintaining the security of your account and password.{" "}
150
- {brand.productName} will not be liable for any loss or damage from your failure to
151
- maintain account security.
152
- </li>
153
- <li>
154
- You are responsible for all activity that occurs under your account, including
155
- actions taken by bots you configure.
156
- </li>
157
- <li>
158
- One person per account. Accounts are not to be shared between multiple individuals.
159
- </li>
160
- <li>
161
- Accounts must be registered by a human. Automated account creation is not permitted.
145
+ You are responsible for all activity that occurs under your account, including actions taken by bots you
146
+ configure.
162
147
  </li>
148
+ <li>One person per account. Accounts are not to be shared between multiple individuals.</li>
149
+ <li>Accounts must be registered by a human. Automated account creation is not permitted.</li>
163
150
  </ul>
164
151
  </section>
165
152
 
166
153
  <section id="section-4" className="scroll-mt-16">
167
- <h2 className="mb-2 text-base font-semibold text-foreground">
168
- 4. Payment, Refunds, and Plan Changes
169
- </h2>
154
+ <h2 className="mb-2 text-base font-semibold text-foreground">4. Payment, Refunds, and Plan Changes</h2>
170
155
  <p>
171
- Paid plans are billed monthly via Stripe. AI provider costs are billed separately by
172
- your chosen provider and are not included in {brand.productName} charges.
156
+ Paid plans are billed monthly via Stripe. AI provider costs are billed separately by your chosen provider
157
+ and are not included in {brand.productName} charges.
173
158
  </p>
174
159
  <ul className="ml-4 mt-2 list-disc space-y-1">
160
+ <li>Hosted capability credits are consumed on a per-use basis and are non-refundable once consumed.</li>
175
161
  <li>
176
- Hosted capability credits are consumed on a per-use basis and are non-refundable
177
- once consumed.
178
- </li>
179
- <li>
180
- Upgrades and downgrades take effect immediately. When upgrading, you will be charged
181
- a prorated amount for the remainder of the billing period.
162
+ Upgrades and downgrades take effect immediately. When upgrading, you will be charged a prorated amount
163
+ for the remainder of the billing period.
182
164
  </li>
183
165
  <li>
184
- Upon cancellation, you retain access through the end of your current billing period.
185
- No prorated refunds are issued for partial months.
166
+ Upon cancellation, you retain access through the end of your current billing period. No prorated refunds
167
+ are issued for partial months.
186
168
  </li>
187
169
  <li>
188
- We reserve the right to change pricing with 30 days&apos; advance notice. Price
189
- changes do not apply retroactively.
170
+ We reserve the right to change pricing with 30 days&apos; advance notice. Price changes do not apply
171
+ retroactively.
190
172
  </li>
191
173
  </ul>
192
174
  </section>
193
175
 
194
176
  <section id="section-5" className="scroll-mt-16">
195
- <h2 className="mb-2 text-base font-semibold text-foreground">
196
- 5. Cancellation and Termination
197
- </h2>
198
- <p>
199
- You may cancel your account at any time from your account settings. Upon cancellation:
200
- </p>
177
+ <h2 className="mb-2 text-base font-semibold text-foreground">5. Cancellation and Termination</h2>
178
+ <p>You may cancel your account at any time from your account settings. Upon cancellation:</p>
201
179
  <ul className="ml-4 mt-2 list-disc space-y-1">
202
180
  <li>Your account data will be retained for 30 days, then permanently deleted.</li>
203
181
  <li>
204
182
  You may request immediate deletion by contacting{" "}
205
- <a
206
- href={`mailto:${brand.emails.legal}`}
207
- className="text-foreground underline underline-offset-4"
208
- >
183
+ <a href={`mailto:${brand.emails.legal}`} className="text-foreground underline underline-offset-4">
209
184
  {brand.emails.legal}
210
185
  </a>
211
186
  .
212
187
  </li>
213
- <li>
214
- Deleted data cannot be recovered. Export your data before canceling if you need it.
215
- </li>
188
+ <li>Deleted data cannot be recovered. Export your data before canceling if you need it.</li>
216
189
  </ul>
217
190
  <p className="mt-2">
218
- We may suspend or terminate your account for violations of these terms. Where
219
- possible, we will provide notice before suspension. For serious violations (abuse,
220
- fraud, illegal activity), we reserve the right to terminate immediately without
221
- notice.
191
+ We may suspend or terminate your account for violations of these terms. Where possible, we will provide
192
+ notice before suspension. For serious violations (abuse, fraud, illegal activity), we reserve the right to
193
+ terminate immediately without notice.
222
194
  </p>
223
195
  </section>
224
196
 
225
197
  <section id="section-6" className="scroll-mt-16">
226
- <h2 className="mb-2 text-base font-semibold text-foreground">
227
- 6. Modifications to the Service
228
- </h2>
198
+ <h2 className="mb-2 text-base font-semibold text-foreground">6. Modifications to the Service</h2>
229
199
  <p>
230
- We reserve the right to modify, suspend, or discontinue any part of the service at any
231
- time. For material changes that significantly affect your use of the service, we will
232
- provide 30 days&apos; advance notice via email or through the platform. We will not be
233
- liable to you or any third party for any modification, suspension, or discontinuation.
200
+ We reserve the right to modify, suspend, or discontinue any part of the service at any time. For material
201
+ changes that significantly affect your use of the service, we will provide 30 days&apos; advance notice
202
+ via email or through the platform. We will not be liable to you or any third party for any modification,
203
+ suspension, or discontinuation.
234
204
  </p>
235
205
  </section>
236
206
 
237
207
  <section id="section-7" className="scroll-mt-16">
238
- <h2 className="mb-2 text-base font-semibold text-foreground">
239
- 7. Uptime, Security, and Privacy
240
- </h2>
208
+ <h2 className="mb-2 text-base font-semibold text-foreground">7. Uptime, Security, and Privacy</h2>
241
209
  <p>
242
- We make best-effort commitments to maintain service availability but do not guarantee
243
- specific uptime percentages for free or standard-tier plans. Our handling of your
244
- personal data is governed by our{" "}
210
+ We make best-effort commitments to maintain service availability but do not guarantee specific uptime
211
+ percentages for free or standard-tier plans. Our handling of your personal data is governed by our{" "}
245
212
  <Link href="/privacy" className="text-foreground underline underline-offset-4">
246
213
  Privacy Policy
247
214
  </Link>
248
- . We take security seriously and implement reasonable safeguards, but no service can
249
- guarantee absolute security.
215
+ . We take security seriously and implement reasonable safeguards, but no service can guarantee absolute
216
+ security.
250
217
  </p>
251
218
  </section>
252
219
 
253
220
  <section id="section-8" className="scroll-mt-16">
254
- <h2 className="mb-2 text-base font-semibold text-foreground">
255
- 8. Copyright and Content Ownership
256
- </h2>
221
+ <h2 className="mb-2 text-base font-semibold text-foreground">8. Copyright and Content Ownership</h2>
257
222
  <ul className="ml-4 mt-2 list-disc space-y-1">
258
223
  <li>
259
- You retain ownership of your content, including bot configurations, prompts, and
260
- data you provide to the service.
224
+ You retain ownership of your content, including bot configurations, prompts, and data you provide to the
225
+ service.
261
226
  </li>
262
227
  <li>
263
- You grant {brand.productName} a limited, non-exclusive license to process your
264
- content solely for the purpose of providing the service.
228
+ You grant {brand.productName} a limited, non-exclusive license to process your content solely for the
229
+ purpose of providing the service.
265
230
  </li>
266
231
  <li>
267
- {brand.companyLegalName} retains ownership of the platform, its code, documentation,
268
- and all related intellectual property.
232
+ {brand.companyLegalName} retains ownership of the platform, its code, documentation, and all related
233
+ intellectual property.
269
234
  </li>
270
235
  <li>
271
- AI-generated outputs belong to you, subject to the terms of service of your chosen
272
- AI provider. {brand.productName} makes no claims to AI-generated content.
236
+ AI-generated outputs belong to you, subject to the terms of service of your chosen AI provider.{" "}
237
+ {brand.productName} makes no claims to AI-generated content.
273
238
  </li>
274
239
  </ul>
275
240
  </section>
276
241
 
277
242
  <section id="section-9" className="scroll-mt-16">
278
- <h2 className="mb-2 text-base font-semibold text-foreground">
279
- 9. API Keys and Third-Party Services
280
- </h2>
243
+ <h2 className="mb-2 text-base font-semibold text-foreground">9. API Keys and Third-Party Services</h2>
281
244
  <ul className="ml-4 mt-2 list-disc space-y-1">
245
+ <li>You are solely responsible for your API keys and all usage charges incurred through them.</li>
282
246
  <li>
283
- You are solely responsible for your API keys and all usage charges incurred through
284
- them.
285
- </li>
286
- <li>
287
- {brand.productName} is not liable for charges from your AI providers, including
288
- charges resulting from bot activity you have configured.
247
+ {brand.productName} is not liable for charges from your AI providers, including charges resulting from
248
+ bot activity you have configured.
289
249
  </li>
290
250
  <li>
291
- You must comply with the terms of service of any AI provider whose API keys you use
292
- with {brand.productName}.
251
+ You must comply with the terms of service of any AI provider whose API keys you use with{" "}
252
+ {brand.productName}.
293
253
  </li>
294
254
  <li>
295
- If an AI provider revokes or restricts your API key, the corresponding functionality
296
- in {brand.productName} will be unavailable. This is not a service failure on our
297
- part.
255
+ If an AI provider revokes or restricts your API key, the corresponding functionality in{" "}
256
+ {brand.productName} will be unavailable. This is not a service failure on our part.
298
257
  </li>
299
258
  </ul>
300
259
  </section>
@@ -304,84 +263,73 @@ export default function TermsPage() {
304
263
  <p>You agree not to use {brand.productName} to:</p>
305
264
  <ul className="ml-4 mt-2 list-disc space-y-1">
306
265
  <li>Engage in any illegal activity or violate applicable laws and regulations</li>
266
+ <li>Generate, distribute, or facilitate harassment, abuse, threats, or harmful content</li>
307
267
  <li>
308
- Generate, distribute, or facilitate harassment, abuse, threats, or harmful content
309
- </li>
310
- <li>
311
- Attempt to disrupt the service, degrade performance for other users, or compromise
312
- system integrity
313
- </li>
314
- <li>
315
- Reverse engineer, decompile, or attempt to extract the source code of the platform
268
+ Attempt to disrupt the service, degrade performance for other users, or compromise system integrity
316
269
  </li>
270
+ <li>Reverse engineer, decompile, or attempt to extract the source code of the platform</li>
317
271
  <li>Circumvent rate limits, usage restrictions, or other technical safeguards</li>
318
272
  <li>Impersonate other individuals or entities through your bots</li>
319
273
  </ul>
320
274
  <p className="mt-2">
321
- We reserve the right to remove content and suspend or terminate accounts that violate
322
- this policy. Repeated or serious violations may result in permanent bans.
275
+ We reserve the right to remove content and suspend or terminate accounts that violate this policy.
276
+ Repeated or serious violations may result in permanent bans.
323
277
  </p>
324
278
  </section>
325
279
 
326
280
  <section id="section-11" className="scroll-mt-16">
327
281
  <h2 className="mb-2 text-base font-semibold text-foreground">11. Liability</h2>
328
282
  <p>
329
- The service is provided &ldquo;as is&rdquo; and &ldquo;as available&rdquo; without
330
- warranties of any kind, whether express or implied, including but not limited to
331
- implied warranties of merchantability, fitness for a particular purpose, and
332
- non-infringement.
283
+ The service is provided &ldquo;as is&rdquo; and &ldquo;as available&rdquo; without warranties of any kind,
284
+ whether express or implied, including but not limited to implied warranties of merchantability, fitness
285
+ for a particular purpose, and non-infringement.
333
286
  </p>
334
287
  <p className="mt-2">
335
- To the maximum extent permitted by law, {brand.companyLegalName} shall not be liable
336
- for any indirect, incidental, special, consequential, or punitive damages, or any loss
337
- of profits or revenues, whether incurred directly or indirectly, arising from your use
338
- of the service.
288
+ To the maximum extent permitted by law, {brand.companyLegalName} shall not be liable for any indirect,
289
+ incidental, special, consequential, or punitive damages, or any loss of profits or revenues, whether
290
+ incurred directly or indirectly, arising from your use of the service.
339
291
  </p>
340
292
  <p className="mt-2">
341
- Our total liability for any claim arising from or related to these terms or the
342
- service shall not exceed the amount you paid to {brand.productName} in the 12 months
343
- preceding the claim. We are not liable for actions taken by AI providers or for
344
- AI-generated content.
293
+ Our total liability for any claim arising from or related to these terms or the service shall not exceed
294
+ the amount you paid to {brand.productName} in the 12 months preceding the claim. We are not liable for
295
+ actions taken by AI providers or for AI-generated content.
345
296
  </p>
346
297
  </section>
347
298
 
348
299
  <section id="section-12" className="scroll-mt-16">
349
300
  <h2 className="mb-2 text-base font-semibold text-foreground">12. Indemnification</h2>
350
301
  <p>
351
- You agree to indemnify, defend, and hold harmless {brand.companyLegalName}, its
352
- officers, directors, employees, and agents from and against any claims, liabilities,
353
- damages, losses, and expenses (including reasonable attorneys&apos; fees) arising out
354
- of or in any way connected with your use of the service, your content, or your
355
- violation of these terms.
302
+ You agree to indemnify, defend, and hold harmless {brand.companyLegalName}, its officers, directors,
303
+ employees, and agents from and against any claims, liabilities, damages, losses, and expenses (including
304
+ reasonable attorneys&apos; fees) arising out of or in any way connected with your use of the service, your
305
+ content, or your violation of these terms.
356
306
  </p>
357
307
  </section>
358
308
 
359
309
  <section id="section-13" className="scroll-mt-16">
360
310
  <h2 className="mb-2 text-base font-semibold text-foreground">13. Governing Law</h2>
361
311
  <p>
362
- These terms shall be governed by and construed in accordance with the laws of the
363
- State of Delaware, United States, without regard to its conflict of law provisions.
364
- Any disputes arising under these terms shall be resolved in the state or federal
365
- courts located in Delaware.
312
+ These terms shall be governed by and construed in accordance with the laws of the State of Delaware,
313
+ United States, without regard to its conflict of law provisions. Any disputes arising under these terms
314
+ shall be resolved in the state or federal courts located in Delaware.
366
315
  </p>
367
316
  </section>
368
317
 
369
318
  <section id="section-14" className="scroll-mt-16">
370
319
  <h2 className="mb-2 text-base font-semibold text-foreground">14. Severability</h2>
371
320
  <p>
372
- If any provision of these terms is found to be unenforceable or invalid by a court of
373
- competent jurisdiction, that provision will be limited or eliminated to the minimum
374
- extent necessary so that these terms shall otherwise remain in full force and effect.
321
+ If any provision of these terms is found to be unenforceable or invalid by a court of competent
322
+ jurisdiction, that provision will be limited or eliminated to the minimum extent necessary so that these
323
+ terms shall otherwise remain in full force and effect.
375
324
  </p>
376
325
  </section>
377
326
 
378
327
  <section id="section-15" className="scroll-mt-16">
379
328
  <h2 className="mb-2 text-base font-semibold text-foreground">15. Changes to Terms</h2>
380
329
  <p>
381
- We may update these Terms of Service from time to time. If we make material changes,
382
- we will notify you at least 30 days in advance via email or through a prominent notice
383
- on the service. Your continued use of {brand.productName} after the updated terms take
384
- effect constitutes acceptance of the new terms.
330
+ We may update these Terms of Service from time to time. If we make material changes, we will notify you at
331
+ least 30 days in advance via email or through a prominent notice on the service. Your continued use of{" "}
332
+ {brand.productName} after the updated terms take effect constitutes acceptance of the new terms.
385
333
  </p>
386
334
  </section>
387
335
 
@@ -389,10 +337,7 @@ export default function TermsPage() {
389
337
  <h2 className="mb-2 text-base font-semibold text-foreground">16. Contact</h2>
390
338
  <p>
391
339
  Questions about these terms? Email us at{" "}
392
- <a
393
- href={`mailto:${brand.emails.legal}`}
394
- className="text-foreground underline underline-offset-4"
395
- >
340
+ <a href={`mailto:${brand.emails.legal}`} className="text-foreground underline underline-offset-4">
396
341
  {brand.emails.legal}
397
342
  </a>
398
343
  .
@@ -1,20 +1,27 @@
1
1
  "use client";
2
2
 
3
- import { BuildingIcon, CheckIcon, ChevronsUpDownIcon, UserIcon } from "lucide-react";
3
+ import { BuildingIcon, UserIcon } from "lucide-react";
4
4
  import Image from "next/image";
5
- import {
6
- DropdownMenu,
7
- DropdownMenuContent,
8
- DropdownMenuItem,
9
- DropdownMenuLabel,
10
- DropdownMenuSeparator,
11
- DropdownMenuTrigger,
12
- } from "@/components/ui/dropdown-menu";
5
+ import { useState } from "react";
13
6
  import type { TenantOption } from "@/lib/tenant-context";
14
7
  import { useTenant } from "@/lib/tenant-context";
15
8
 
9
+ function FallbackIcon({ tenant, size }: { tenant: TenantOption; size: number }) {
10
+ const Icon = tenant.type === "org" ? BuildingIcon : UserIcon;
11
+ return (
12
+ <span
13
+ className="flex items-center justify-center rounded-full bg-sidebar-accent"
14
+ style={{ width: size, height: size }}
15
+ >
16
+ <Icon className="size-3 text-muted-foreground" />
17
+ </span>
18
+ );
19
+ }
20
+
16
21
  function TenantAvatar({ tenant, size = 20 }: { tenant: TenantOption; size?: number }) {
17
- if (tenant.image) {
22
+ const [imgError, setImgError] = useState(false);
23
+
24
+ if (tenant.image && !imgError) {
18
25
  return (
19
26
  <Image
20
27
  src={tenant.image}
@@ -23,60 +30,26 @@ function TenantAvatar({ tenant, size = 20 }: { tenant: TenantOption; size?: numb
23
30
  height={size}
24
31
  className="rounded-full object-cover"
25
32
  style={{ width: size, height: size }}
33
+ onError={() => setImgError(true)}
26
34
  />
27
35
  );
28
36
  }
29
- const Icon = tenant.type === "org" ? BuildingIcon : UserIcon;
30
- return (
31
- <span
32
- className="flex items-center justify-center rounded-full bg-sidebar-accent"
33
- style={{ width: size, height: size }}
34
- >
35
- <Icon className="size-3 text-muted-foreground" />
36
- </span>
37
- );
37
+ return <FallbackIcon tenant={tenant} size={size} />;
38
38
  }
39
39
 
40
40
  export function AccountSwitcher() {
41
- const { activeTenantId, tenants, isLoading, switchTenant } = useTenant();
41
+ const { activeTenantId, tenants, isLoading } = useTenant();
42
42
 
43
- if (isLoading || tenants.length <= 1) return null;
43
+ if (isLoading || tenants.length === 0) return null;
44
44
 
45
45
  const activeTenant = tenants.find((t) => t.id === activeTenantId) ?? tenants[0];
46
46
 
47
47
  return (
48
48
  <div className="border-b border-sidebar-border px-3 py-1">
49
- <DropdownMenu>
50
- <DropdownMenuTrigger className="flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-sidebar-accent hover:text-sidebar-accent-foreground outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring">
51
- <TenantAvatar tenant={activeTenant} />
52
- <span className="flex-1 truncate text-left text-sidebar-foreground">
53
- {activeTenant.name}
54
- </span>
55
- <span className="text-[10px] font-medium uppercase tracking-widest text-terminal-dim/60">
56
- {activeTenant.type === "org" ? "ORG" : "PERSONAL"}
57
- </span>
58
- <ChevronsUpDownIcon className="size-4 shrink-0 text-muted-foreground" />
59
- </DropdownMenuTrigger>
60
- <DropdownMenuContent align="start" className="w-[var(--radix-dropdown-menu-trigger-width)]">
61
- <DropdownMenuLabel className="text-xs font-normal uppercase tracking-wider text-muted-foreground">
62
- Switch account
63
- </DropdownMenuLabel>
64
- <DropdownMenuSeparator />
65
- {tenants.map((tenant) => (
66
- <DropdownMenuItem
67
- key={tenant.id}
68
- onClick={() => switchTenant(tenant.id)}
69
- className="flex items-center gap-2"
70
- >
71
- <TenantAvatar tenant={tenant} />
72
- <span className="flex-1 truncate text-sm">{tenant.name}</span>
73
- {tenant.id === activeTenantId && (
74
- <CheckIcon className="size-4 shrink-0 text-terminal" />
75
- )}
76
- </DropdownMenuItem>
77
- ))}
78
- </DropdownMenuContent>
79
- </DropdownMenu>
49
+ <div className="flex w-full items-center gap-2 px-3 py-2 text-sm font-medium">
50
+ <TenantAvatar tenant={activeTenant} />
51
+ <span className="flex-1 truncate text-left text-sidebar-foreground">{activeTenant.name}</span>
52
+ </div>
80
53
  </div>
81
54
  );
82
55
  }
@@ -34,9 +34,7 @@ function MetricCard({
34
34
  return (
35
35
  <Card className={className}>
36
36
  <CardHeader className="pb-2">
37
- <CardTitle className="text-xs text-muted-foreground font-normal uppercase tracking-wider">
38
- {label}
39
- </CardTitle>
37
+ <CardTitle className="text-xs text-muted-foreground font-normal uppercase tracking-wider">{label}</CardTitle>
40
38
  </CardHeader>
41
39
  <CardContent>
42
40
  <div className="text-2xl font-bold font-mono">{value}</div>
@@ -25,9 +25,7 @@ export function AdminGuard({ children }: { children: React.ReactNode }) {
25
25
  <div className="flex h-screen flex-col items-center justify-center gap-4">
26
26
  <ShieldAlert className="size-12 text-red-500" />
27
27
  <p className="text-lg font-bold uppercase tracking-widest text-red-500">ACCESS DENIED</p>
28
- <p className="text-sm text-muted-foreground">
29
- You do not have permission to view this page.
30
- </p>
28
+ <p className="text-sm text-muted-foreground">You do not have permission to view this page.</p>
31
29
  </div>
32
30
  );
33
31
  }
@@ -52,9 +52,7 @@ export function AdminNav() {
52
52
  href={item.href}
53
53
  className={cn(
54
54
  "rounded-sm px-3 py-1.5 text-sm font-medium transition-colors hover:bg-accent inline-flex items-center gap-1.5",
55
- pathname.startsWith(item.href)
56
- ? "bg-terminal/10 text-terminal"
57
- : "text-muted-foreground",
55
+ pathname.startsWith(item.href) ? "bg-terminal/10 text-terminal" : "text-muted-foreground",
58
56
  )}
59
57
  >
60
58
  {item.label}