@burdenoff/microfe-subscriberbot 2026.1023.2 → 2026.1030.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -1
  2. package/dist/subscriberbot/SubscriberBotRoutes.js +2 -2
  3. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  4. package/dist/subscriberbot/admin/AdminDashboardPage.js +5 -5
  5. package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
  6. package/dist/subscriberbot/components/PostureOptions.d.ts +10 -0
  7. package/dist/subscriberbot/components/PostureOptions.d.ts.map +1 -0
  8. package/dist/subscriberbot/components/PostureOptions.js +20 -0
  9. package/dist/subscriberbot/components/PostureOptions.js.map +1 -0
  10. package/dist/subscriberbot/components/index.d.ts +2 -0
  11. package/dist/subscriberbot/components/index.d.ts.map +1 -1
  12. package/dist/subscriberbot/components/index.js +1 -0
  13. package/dist/subscriberbot/hooks/index.d.ts +3 -0
  14. package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
  15. package/dist/subscriberbot/hooks/index.js +3 -1
  16. package/dist/subscriberbot/hooks/useAutonomousAgentMode.d.ts +15 -0
  17. package/dist/subscriberbot/hooks/useAutonomousAgentMode.d.ts.map +1 -0
  18. package/dist/subscriberbot/hooks/useAutonomousAgentMode.js +13 -0
  19. package/dist/subscriberbot/hooks/useAutonomousAgentMode.js.map +1 -0
  20. package/dist/subscriberbot/hooks/useRouteSelection.d.ts +15 -0
  21. package/dist/subscriberbot/hooks/useRouteSelection.d.ts.map +1 -0
  22. package/dist/subscriberbot/hooks/useRouteSelection.js +18 -0
  23. package/dist/subscriberbot/hooks/useRouteSelection.js.map +1 -0
  24. package/dist/subscriberbot/pages/AssetVaultPage.js +16 -16
  25. package/dist/subscriberbot/pages/DashboardPage.js +23 -23
  26. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  27. package/dist/subscriberbot/pages/InboxPage.d.ts.map +1 -1
  28. package/dist/subscriberbot/pages/InboxPage.js +249 -248
  29. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/InsightsPage.js +14 -14
  31. package/dist/subscriberbot/pages/InvoicesPage.js +66 -66
  32. package/dist/subscriberbot/pages/WorkflowsPage.d.ts.map +1 -1
  33. package/dist/subscriberbot/pages/WorkflowsPage.js +183 -182
  34. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  35. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
  36. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +184 -182
  37. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  38. package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts.map +1 -1
  39. package/dist/subscriberbot/pages/agents/AgentNewPage.js +77 -79
  40. package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -1
  41. package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts.map +1 -1
  42. package/dist/subscriberbot/pages/agents/AgentsListPage.js +134 -133
  43. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  44. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +64 -64
  45. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +3 -3
  46. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +18 -18
  47. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +76 -76
  48. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +6 -6
  49. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +7 -7
  50. package/dist/subscriberbot/utils/pageContext.d.ts +43 -11
  51. package/dist/subscriberbot/utils/pageContext.d.ts.map +1 -1
  52. package/dist/subscriberbot/utils/pageContext.js +42 -37
  53. package/dist/subscriberbot/utils/pageContext.js.map +1 -1
  54. package/package.json +4 -2
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriberBotRoutes.d.ts","sourceRoot":"","sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAkB,MAAM,OAAO,CAAC;AAsEhD,eAAO,MAAM,mBAAmB,EAAE,EA4DjC,CAAC"}
1
+ {"version":3,"file":"SubscriberBotRoutes.d.ts","sourceRoot":"","sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAkB,MAAM,OAAO,CAAC;AAsEhD,eAAO,MAAM,mBAAmB,EAAE,EA6DjC,CAAC"}
@@ -44,7 +44,7 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
44
44
  element: /* @__PURE__ */ c(g, {})
45
45
  }),
46
46
  /* @__PURE__ */ c(a, {
47
- path: "inbox",
47
+ path: "inbox/:selectedId?",
48
48
  element: /* @__PURE__ */ c(_, {})
49
49
  }),
50
50
  /* @__PURE__ */ c(a, {
@@ -72,7 +72,7 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
72
72
  element: /* @__PURE__ */ c(S, {})
73
73
  }),
74
74
  /* @__PURE__ */ c(a, {
75
- path: "workflows",
75
+ path: "workflows/:selectedId?",
76
76
  element: /* @__PURE__ */ c(y, {})
77
77
  }),
78
78
  /* @__PURE__ */ c(a, {
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriberBotRoutes.js","names":[],"sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"sourcesContent":["/**\n * SubscriberBot Routes\n * @module subscriberbot\n *\n * Domain routes for the Subscriber Bot product. The dashboard is eager-loaded\n * (primary landing); all other pages are lazy-loaded.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useSubscriberBot } from './context/SubscriberBotContext';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/DashboardPage';\n\n// Relationships\nconst RelationshipsListPage = lazy(() =>\n import('./pages/relationships/RelationshipsListPage').then((m) => ({\n default: m.RelationshipsListPage,\n }))\n);\nconst RelationshipNewPage = lazy(() =>\n import('./pages/relationships/RelationshipNewPage').then((m) => ({\n default: m.RelationshipNewPage,\n }))\n);\nconst RelationshipDetailPage = lazy(() =>\n import('./pages/relationships/RelationshipDetailPage').then((m) => ({\n default: m.RelationshipDetailPage,\n }))\n);\n\n// Providers\nconst ProvidersListPage = lazy(() =>\n import('./pages/providers/ProvidersListPage').then((m) => ({ default: m.ProvidersListPage }))\n);\nconst ProviderNewPage = lazy(() =>\n import('./pages/providers/ProviderNewPage').then((m) => ({ default: m.ProviderNewPage }))\n);\nconst ProviderDetailPage = lazy(() =>\n import('./pages/providers/ProviderDetailPage').then((m) => ({ default: m.ProviderDetailPage }))\n);\n\n// Inbox / Invoices / Workflows\nconst InboxPage = lazy(() => import('./pages/InboxPage').then((m) => ({ default: m.InboxPage })));\nconst InvoicesPage = lazy(() =>\n import('./pages/InvoicesPage').then((m) => ({ default: m.InvoicesPage }))\n);\nconst WorkflowsPage = lazy(() =>\n import('./pages/WorkflowsPage').then((m) => ({ default: m.WorkflowsPage }))\n);\n\n// Agents\nconst AgentsListPage = lazy(() =>\n import('./pages/agents/AgentsListPage').then((m) => ({ default: m.AgentsListPage }))\n);\nconst AgentNewPage = lazy(() =>\n import('./pages/agents/AgentNewPage').then((m) => ({ default: m.AgentNewPage }))\n);\nconst AgentDetailPage = lazy(() =>\n import('./pages/agents/AgentDetailPage').then((m) => ({ default: m.AgentDetailPage }))\n);\n\n// Insights + Asset Vault (aggregated real data)\nconst InsightsPage = lazy(() =>\n import('./pages/InsightsPage').then((m) => ({ default: m.InsightsPage }))\n);\nconst AssetVaultPage = lazy(() =>\n import('./pages/AssetVaultPage').then((m) => ({ default: m.AssetVaultPage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const SubscriberBotRoutes: FC = () => {\n const { basePath, isStandalone } = useSubscriberBot();\n const location = useLocation();\n\n // Normalize base path\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Overview / dashboard */}\n <Route index element={<DashboardPage />} />\n\n {/* Relationships (the core domain) */}\n <Route path=\"relationships\" element={<RelationshipsListPage />} />\n <Route path=\"relationships/new\" element={<RelationshipNewPage />} />\n <Route path=\"relationships/:id\" element={<RelationshipDetailPage />} />\n\n {/* Providers (registry) */}\n <Route path=\"providers\" element={<ProvidersListPage />} />\n <Route path=\"providers/new\" element={<ProviderNewPage />} />\n <Route path=\"providers/:id\" element={<ProviderDetailPage />} />\n\n {/* Universal Inbox */}\n <Route path=\"inbox\" element={<InboxPage />} />\n\n {/* Invoices */}\n <Route path=\"invoices\" element={<InvoicesPage />} />\n\n {/* Insights (spend analytics + renewal forecast) */}\n <Route path=\"insights\" element={<InsightsPage />} />\n\n {/* Digital Asset Vault */}\n <Route path=\"vault\" element={<AssetVaultPage />} />\n\n {/* AI Agents */}\n <Route path=\"agents\" element={<AgentsListPage />} />\n <Route path=\"agents/new\" element={<AgentNewPage />} />\n <Route path=\"agents/:id\" element={<AgentDetailPage />} />\n\n {/* Workflows */}\n <Route path=\"workflows\" element={<WorkflowsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"SubscriberBotRoutes.js","names":[],"sources":["../../src/subscriberbot/SubscriberBotRoutes.tsx"],"sourcesContent":["/**\n * SubscriberBot Routes\n * @module subscriberbot\n *\n * Domain routes for the Subscriber Bot product. The dashboard is eager-loaded\n * (primary landing); all other pages are lazy-loaded.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useSubscriberBot } from './context/SubscriberBotContext';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/DashboardPage';\n\n// Relationships\nconst RelationshipsListPage = lazy(() =>\n import('./pages/relationships/RelationshipsListPage').then((m) => ({\n default: m.RelationshipsListPage,\n }))\n);\nconst RelationshipNewPage = lazy(() =>\n import('./pages/relationships/RelationshipNewPage').then((m) => ({\n default: m.RelationshipNewPage,\n }))\n);\nconst RelationshipDetailPage = lazy(() =>\n import('./pages/relationships/RelationshipDetailPage').then((m) => ({\n default: m.RelationshipDetailPage,\n }))\n);\n\n// Providers\nconst ProvidersListPage = lazy(() =>\n import('./pages/providers/ProvidersListPage').then((m) => ({ default: m.ProvidersListPage }))\n);\nconst ProviderNewPage = lazy(() =>\n import('./pages/providers/ProviderNewPage').then((m) => ({ default: m.ProviderNewPage }))\n);\nconst ProviderDetailPage = lazy(() =>\n import('./pages/providers/ProviderDetailPage').then((m) => ({ default: m.ProviderDetailPage }))\n);\n\n// Inbox / Invoices / Workflows\nconst InboxPage = lazy(() => import('./pages/InboxPage').then((m) => ({ default: m.InboxPage })));\nconst InvoicesPage = lazy(() =>\n import('./pages/InvoicesPage').then((m) => ({ default: m.InvoicesPage }))\n);\nconst WorkflowsPage = lazy(() =>\n import('./pages/WorkflowsPage').then((m) => ({ default: m.WorkflowsPage }))\n);\n\n// Agents\nconst AgentsListPage = lazy(() =>\n import('./pages/agents/AgentsListPage').then((m) => ({ default: m.AgentsListPage }))\n);\nconst AgentNewPage = lazy(() =>\n import('./pages/agents/AgentNewPage').then((m) => ({ default: m.AgentNewPage }))\n);\nconst AgentDetailPage = lazy(() =>\n import('./pages/agents/AgentDetailPage').then((m) => ({ default: m.AgentDetailPage }))\n);\n\n// Insights + Asset Vault (aggregated real data)\nconst InsightsPage = lazy(() =>\n import('./pages/InsightsPage').then((m) => ({ default: m.InsightsPage }))\n);\nconst AssetVaultPage = lazy(() =>\n import('./pages/AssetVaultPage').then((m) => ({ default: m.AssetVaultPage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const SubscriberBotRoutes: FC = () => {\n const { basePath, isStandalone } = useSubscriberBot();\n const location = useLocation();\n\n // Normalize base path\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Overview / dashboard */}\n <Route index element={<DashboardPage />} />\n\n {/* Relationships (the core domain) */}\n <Route path=\"relationships\" element={<RelationshipsListPage />} />\n <Route path=\"relationships/new\" element={<RelationshipNewPage />} />\n <Route path=\"relationships/:id\" element={<RelationshipDetailPage />} />\n\n {/* Providers (registry) */}\n <Route path=\"providers\" element={<ProvidersListPage />} />\n <Route path=\"providers/new\" element={<ProviderNewPage />} />\n <Route path=\"providers/:id\" element={<ProviderDetailPage />} />\n\n {/* Universal Inbox */}\n {/* One optional-segment route so selecting a message never remounts the page */}\n <Route path=\"inbox/:selectedId?\" element={<InboxPage />} />\n\n {/* Invoices */}\n <Route path=\"invoices\" element={<InvoicesPage />} />\n\n {/* Insights (spend analytics + renewal forecast) */}\n <Route path=\"insights\" element={<InsightsPage />} />\n\n {/* Digital Asset Vault */}\n <Route path=\"vault\" element={<AssetVaultPage />} />\n\n {/* AI Agents */}\n <Route path=\"agents\" element={<AgentsListPage />} />\n <Route path=\"agents/new\" element={<AgentNewPage />} />\n <Route path=\"agents/:id\" element={<AgentDetailPage />} />\n\n {/* Workflows */}\n <Route path=\"workflows/:selectedId?\" element={<WorkflowsPage />} />\n\n {/* Fallback */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { PageLayout as e } from "../components/PageLayout.js";
2
2
  import { formatDate as t } from "../utils/formatters.js";
3
3
  import { StatusBadge as n } from "../components/StatusBadge.js";
4
- import { useAdapterSubmissions as r, useApproveAdapter as i, useMarketplaceReports as a, useModerateListing as ee, useProviders as te, useRejectAdapter as ne, useUpdateProvider as re } from "../hooks/useSubscriberBotApi.js";
5
- import { useTr as o } from "../hooks/useTr.js";
4
+ import { useTr as r } from "../hooks/useTr.js";
5
+ import { useAdapterSubmissions as i, useApproveAdapter as a, useMarketplaceReports as ee, useModerateListing as te, useProviders as ne, useRejectAdapter as re, useUpdateProvider as o } from "../hooks/useSubscriberBotApi.js";
6
6
  import "../hooks/index.js";
7
7
  import { Fragment as s, useState as c } from "react";
8
8
  import { CheckCircle2 as l, Plug as u, Settings2 as ie, Store as d, XCircle as ae } from "lucide-react";
@@ -10,7 +10,7 @@ import { jsx as f, jsxs as p } from "react/jsx-runtime";
10
10
  import { Button as m, Card as h, CardContent as g, CardDescription as _, CardHeader as v, CardTitle as y, EmptyState as b, Spinner as x, Table as S, TableBody as C, TableCell as w, TableHead as T, TableHeader as E, TableRow as D, Tabs as oe, TabsContent as O, TabsList as se, TabsTrigger as k, Textarea as A } from "@burdenoff/fe-libs/ui";
11
11
  //#region src/subscriberbot/admin/AdminDashboardPage.tsx
12
12
  var j = () => {
13
- let j = o(), [M, ce] = c("providers"), { data: le, isLoading: ue } = te({ pagination: { limit: 50 } }), N = re(), P = (e) => {
13
+ let j = r(), [M, ce] = c("providers"), { data: le, isLoading: ue } = ne({ pagination: { limit: 50 } }), N = o(), P = (e) => {
14
14
  N.mutate({
15
15
  id: e,
16
16
  input: { status: "VERIFIED" }
@@ -20,7 +20,7 @@ var j = () => {
20
20
  id: e,
21
21
  input: { status: "DEPRECATED" }
22
22
  });
23
- }, I = le?.items ?? [], { data: L, isLoading: R } = r({ pagination: { limit: 50 } }), z = i(), B = ne(), [V, H] = c(null), [U, W] = c(""), G = L?.items ?? [], de = (e) => {
23
+ }, I = le?.items ?? [], { data: L, isLoading: R } = i({ pagination: { limit: 50 } }), z = a(), B = re(), [V, H] = c(null), [U, W] = c(""), G = L?.items ?? [], de = (e) => {
24
24
  z.mutate({ id: e });
25
25
  }, fe = (e) => {
26
26
  H(e), W("");
@@ -31,7 +31,7 @@ var j = () => {
31
31
  }, { onSuccess: () => {
32
32
  H(null), W("");
33
33
  } });
34
- }, { data: me, isLoading: he } = a({ pagination: { limit: 50 } }), K = ee(), [ge, q] = c(null), [J, Y] = c(null), [X, Z] = c(""), Q = me?.items ?? [], $ = (e, t) => {
34
+ }, { data: me, isLoading: he } = ee({ pagination: { limit: 50 } }), K = te(), [ge, q] = c(null), [J, Y] = c(null), [X, Z] = c(""), Q = me?.items ?? [], $ = (e, t) => {
35
35
  q(e), Y(t), Z("");
36
36
  }, _e = (e) => {
37
37
  !J || !X.trim() || K.mutate({
@@ -1 +1 @@
1
- {"version":3,"file":"AdminDashboardPage.js","names":[],"sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"sourcesContent":["/**\n * SubscriberBot Admin Dashboard\n * @module subscriberbot/admin\n *\n * Product-specific admin surface mounted inside `admin-app`. It exposes the\n * three governance operations requested for SubscriberBot, all wired to the\n * real `wspace-subscriberbot-svc` admin governance schema (BOFF-3237):\n * 1. Provider registry curation — `subListProviders` / `subUpdateProvider`.\n * 2. Adapter approval queue — `subListAdapterSubmissions` /\n * `subApproveAdapter` / `subRejectAdapter`.\n * 3. Marketplace moderation queue — `subListMarketplaceReports` /\n * `subModerateListing`.\n */\n\nimport { Fragment, useState, type FC } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmptyState,\n Spinner,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { CheckCircle2, Plug, Settings2, Store, XCircle } from 'lucide-react';\n\nimport { PageLayout } from '../components/PageLayout';\nimport { StatusBadge } from '../components/StatusBadge';\nimport {\n useAdapterSubmissions,\n useApproveAdapter,\n useMarketplaceReports,\n useModerateListing,\n useProviders,\n useRejectAdapter,\n useUpdateProvider,\n} from '../hooks';\nimport { formatDate } from '../utils/formatters';\nimport { useTr } from '../hooks/useTr';\nimport type { SubModerationAction, SubProvider } from '../types';\n\nexport const AdminDashboardPage: FC = () => {\n const tr = useTr();\n const [activeTab, setActiveTab] = useState('providers');\n\n // --- Provider registry ----------------------------------------------\n const { data: providersData, isLoading: providersLoading } = useProviders({\n pagination: { limit: 50 },\n });\n const updateProvider = useUpdateProvider();\n\n const handleVerify = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'VERIFIED' } });\n };\n\n const handleDeprecate = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'DEPRECATED' } });\n };\n\n const providers = providersData?.items ?? [];\n\n // --- Adapter approvals -------------------------------------------------\n const { data: adapterSubmissionsData, isLoading: adaptersLoading } = useAdapterSubmissions({\n pagination: { limit: 50 },\n });\n const approveAdapter = useApproveAdapter();\n const rejectAdapter = useRejectAdapter();\n const [rejectingAdapterId, setRejectingAdapterId] = useState<string | null>(null);\n const [adapterRejectReason, setAdapterRejectReason] = useState('');\n\n const adapterSubmissions = adapterSubmissionsData?.items ?? [];\n\n const handleApproveAdapter = (id: string) => {\n approveAdapter.mutate({ id });\n };\n\n const handleStartRejectAdapter = (id: string) => {\n setRejectingAdapterId(id);\n setAdapterRejectReason('');\n };\n\n const handleConfirmRejectAdapter = (id: string) => {\n if (!adapterRejectReason.trim()) return;\n rejectAdapter.mutate(\n { id, reason: adapterRejectReason.trim() },\n {\n onSuccess: () => {\n setRejectingAdapterId(null);\n setAdapterRejectReason('');\n },\n }\n );\n };\n\n // --- Marketplace moderation ---------------------------------------------\n const { data: marketplaceReportsData, isLoading: reportsLoading } = useMarketplaceReports({\n pagination: { limit: 50 },\n });\n const moderateListing = useModerateListing();\n const [moderatingReportId, setModeratingReportId] = useState<string | null>(null);\n const [moderateAction, setModerateAction] = useState<SubModerationAction | null>(null);\n const [moderateReason, setModerateReason] = useState('');\n\n const marketplaceReports = marketplaceReportsData?.items ?? [];\n\n const handleStartModerate = (id: string, action: SubModerationAction) => {\n setModeratingReportId(id);\n setModerateAction(action);\n setModerateReason('');\n };\n\n const handleConfirmModerate = (id: string) => {\n if (!moderateAction || !moderateReason.trim()) return;\n moderateListing.mutate(\n { id, action: moderateAction, reason: moderateReason.trim() },\n {\n onSuccess: () => {\n setModeratingReportId(null);\n setModerateAction(null);\n setModerateReason('');\n },\n }\n );\n };\n\n return (\n <PageLayout\n title={tr('admin.title', 'SubscriberBot Admin')}\n description={tr(\n 'admin.description',\n 'Provider registry curation, adapter approvals, and marketplace moderation.'\n )}\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex\">\n <TabsTrigger value=\"providers\" className=\"gap-2\">\n <Settings2 size={16} />\n {tr('admin.tabs.providers', 'Provider Registry')}\n </TabsTrigger>\n <TabsTrigger value=\"adapters\" className=\"gap-2\">\n <Plug size={16} />\n {tr('admin.tabs.adapters', 'Adapter Approvals')}\n </TabsTrigger>\n <TabsTrigger value=\"marketplace\" className=\"gap-2\">\n <Store size={16} />\n {tr('admin.tabs.marketplace', 'Marketplace Moderation')}\n </TabsTrigger>\n </TabsList>\n\n {/* Provider registry curation — backed by real GraphQL queries. */}\n <TabsContent value=\"providers\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.providers.title', 'Provider registry')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.providers.description',\n 'Curate the global provider catalog. Verify submitted providers or deprecate stale entries.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {providersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : providers.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.providers.emptyTitle', 'No providers yet')}\n description={tr(\n 'admin.providers.emptyDescription',\n 'Once providers are created or claimed they will appear here for curation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.providers.table.name', 'Name')}</TableHead>\n <TableHead>{tr('admin.providers.table.category', 'Category')}</TableHead>\n <TableHead>{tr('admin.providers.table.status', 'Status')}</TableHead>\n <TableHead>{tr('admin.providers.table.created', 'Created')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.providers.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {providers.map((provider: SubProvider) => (\n <TableRow key={provider.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {provider.name}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{provider.category}</TableCell>\n <TableCell>\n <StatusBadge status={provider.status} />\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(provider.createdAt)}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex justify-end gap-2\">\n {provider.status !== 'VERIFIED' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleVerify(provider.id)}\n disabled={updateProvider.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.providers.verify', 'Verify')}\n </Button>\n )}\n {provider.status !== 'DEPRECATED' && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleDeprecate(provider.id)}\n disabled={updateProvider.isPending}\n >\n {tr('admin.providers.deprecate', 'Deprecate')}\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Adapter approval queue — backed by real GraphQL queries. */}\n <TabsContent value=\"adapters\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.adapters.title', 'Adapter approvals')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.adapters.description',\n 'Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {adaptersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : adapterSubmissions.length === 0 ? (\n <EmptyState\n icon={<Plug className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.adapters.emptyTitle', 'No adapter submissions')}\n description={tr(\n 'admin.adapters.emptyDescription',\n 'Submitted integration adapters will appear here for review.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.adapters.table.adapter', 'Adapter')}</TableHead>\n <TableHead>\n {tr('admin.adapters.table.workspace', 'Submitting workspace')}\n </TableHead>\n <TableHead>{tr('admin.adapters.table.submitted', 'Submitted')}</TableHead>\n <TableHead>{tr('admin.adapters.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.adapters.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {adapterSubmissions.map((submission) => (\n <Fragment key={submission.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {submission.adapterId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {submission.submitterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(submission.createdAt)}\n </TableCell>\n <TableCell>\n <StatusBadge status={submission.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {submission.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleApproveAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.adapters.approve', 'Approve')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleStartRejectAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <XCircle size={14} className=\"mr-1\" />\n {tr('admin.adapters.reject', 'Reject')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {rejectingAdapterId === submission.id && (\n <TableRow key={`${submission.id}-reject`}>\n <TableCell colSpan={5} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={adapterRejectReason}\n onChange={(event) => setAdapterRejectReason(event.target.value)}\n placeholder={tr(\n 'admin.adapters.rejectPlaceholder',\n 'Reason for rejecting this adapter submission (required)'\n )}\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleConfirmRejectAdapter(submission.id)}\n disabled={\n !adapterRejectReason.trim() || rejectAdapter.isPending\n }\n >\n {tr('admin.adapters.confirmReject', 'Confirm reject')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRejectingAdapterId(null)}\n disabled={rejectAdapter.isPending}\n >\n {tr('admin.adapters.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Marketplace moderation — backed by real GraphQL queries. */}\n <TabsContent value=\"marketplace\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.marketplace.title', 'Marketplace moderation')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.marketplace.description',\n 'Review reported marketplace listings and take moderation actions.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {reportsLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : marketplaceReports.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.marketplace.emptyTitle', 'No reported listings')}\n description={tr(\n 'admin.marketplace.emptyDescription',\n 'Reported marketplace listings will appear here for moderation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.marketplace.table.listing', 'Listing')}</TableHead>\n <TableHead>\n {tr('admin.marketplace.table.workspace', 'Reporting workspace')}\n </TableHead>\n <TableHead>{tr('admin.marketplace.table.reported', 'Reported')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.reason', 'Reason')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.marketplace.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {marketplaceReports.map((report) => (\n <Fragment key={report.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {report.listingId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {report.reporterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(report.createdAt)}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{report.reason}</TableCell>\n <TableCell>\n <StatusBadge status={report.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {report.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartModerate(report.id, 'DISMISS')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.dismiss', 'Dismiss')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleStartModerate(report.id, 'REMOVE_LISTING')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.remove', 'Remove')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {moderatingReportId === report.id && (\n <TableRow key={`${report.id}-moderate`}>\n <TableCell colSpan={6} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={moderateReason}\n onChange={(event) => setModerateReason(event.target.value)}\n placeholder={\n moderateAction === 'REMOVE_LISTING'\n ? tr(\n 'admin.marketplace.reasonPlaceholderRemove',\n 'Reason to remove this listing (required)'\n )\n : tr(\n 'admin.marketplace.reasonPlaceholderDismiss',\n 'Reason to dismiss this report (required)'\n )\n }\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant={\n moderateAction === 'REMOVE_LISTING'\n ? 'destructive'\n : 'outline'\n }\n onClick={() => handleConfirmModerate(report.id)}\n disabled={!moderateReason.trim() || moderateListing.isPending}\n >\n {moderateAction === 'REMOVE_LISTING'\n ? tr('admin.marketplace.confirmRemoval', 'Confirm removal')\n : tr(\n 'admin.marketplace.confirmDismissal',\n 'Confirm dismissal'\n )}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setModeratingReportId(null)}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"AdminDashboardPage.js","names":[],"sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"sourcesContent":["/**\n * SubscriberBot Admin Dashboard\n * @module subscriberbot/admin\n *\n * Product-specific admin surface mounted inside `admin-app`. It exposes the\n * three governance operations requested for SubscriberBot, all wired to the\n * real `wspace-subscriberbot-svc` admin governance schema (BOFF-3237):\n * 1. Provider registry curation — `subListProviders` / `subUpdateProvider`.\n * 2. Adapter approval queue — `subListAdapterSubmissions` /\n * `subApproveAdapter` / `subRejectAdapter`.\n * 3. Marketplace moderation queue — `subListMarketplaceReports` /\n * `subModerateListing`.\n */\n\nimport { Fragment, useState, type FC } from 'react';\nimport {\n Button,\n Card,\n CardContent,\n CardDescription,\n CardHeader,\n CardTitle,\n EmptyState,\n Spinner,\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n Textarea,\n} from '@burdenoff/fe-libs/ui';\nimport { CheckCircle2, Plug, Settings2, Store, XCircle } from 'lucide-react';\n\nimport { PageLayout } from '../components/PageLayout';\nimport { StatusBadge } from '../components/StatusBadge';\nimport {\n useAdapterSubmissions,\n useApproveAdapter,\n useMarketplaceReports,\n useModerateListing,\n useProviders,\n useRejectAdapter,\n useUpdateProvider,\n} from '../hooks';\nimport { formatDate } from '../utils/formatters';\nimport { useTr } from '../hooks/useTr';\nimport type { SubModerationAction, SubProvider } from '../types';\n\nexport const AdminDashboardPage: FC = () => {\n const tr = useTr();\n const [activeTab, setActiveTab] = useState('providers');\n\n // --- Provider registry ----------------------------------------------\n const { data: providersData, isLoading: providersLoading } = useProviders({\n pagination: { limit: 50 },\n });\n const updateProvider = useUpdateProvider();\n\n const handleVerify = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'VERIFIED' } });\n };\n\n const handleDeprecate = (id: string) => {\n updateProvider.mutate({ id, input: { status: 'DEPRECATED' } });\n };\n\n const providers = providersData?.items ?? [];\n\n // --- Adapter approvals -------------------------------------------------\n const { data: adapterSubmissionsData, isLoading: adaptersLoading } = useAdapterSubmissions({\n pagination: { limit: 50 },\n });\n const approveAdapter = useApproveAdapter();\n const rejectAdapter = useRejectAdapter();\n const [rejectingAdapterId, setRejectingAdapterId] = useState<string | null>(null);\n const [adapterRejectReason, setAdapterRejectReason] = useState('');\n\n const adapterSubmissions = adapterSubmissionsData?.items ?? [];\n\n const handleApproveAdapter = (id: string) => {\n approveAdapter.mutate({ id });\n };\n\n const handleStartRejectAdapter = (id: string) => {\n setRejectingAdapterId(id);\n setAdapterRejectReason('');\n };\n\n const handleConfirmRejectAdapter = (id: string) => {\n if (!adapterRejectReason.trim()) return;\n rejectAdapter.mutate(\n { id, reason: adapterRejectReason.trim() },\n {\n onSuccess: () => {\n setRejectingAdapterId(null);\n setAdapterRejectReason('');\n },\n }\n );\n };\n\n // --- Marketplace moderation ---------------------------------------------\n const { data: marketplaceReportsData, isLoading: reportsLoading } = useMarketplaceReports({\n pagination: { limit: 50 },\n });\n const moderateListing = useModerateListing();\n const [moderatingReportId, setModeratingReportId] = useState<string | null>(null);\n const [moderateAction, setModerateAction] = useState<SubModerationAction | null>(null);\n const [moderateReason, setModerateReason] = useState('');\n\n const marketplaceReports = marketplaceReportsData?.items ?? [];\n\n const handleStartModerate = (id: string, action: SubModerationAction) => {\n setModeratingReportId(id);\n setModerateAction(action);\n setModerateReason('');\n };\n\n const handleConfirmModerate = (id: string) => {\n if (!moderateAction || !moderateReason.trim()) return;\n moderateListing.mutate(\n { id, action: moderateAction, reason: moderateReason.trim() },\n {\n onSuccess: () => {\n setModeratingReportId(null);\n setModerateAction(null);\n setModerateReason('');\n },\n }\n );\n };\n\n return (\n <PageLayout\n title={tr('admin.title', 'SubscriberBot Admin')}\n description={tr(\n 'admin.description',\n 'Provider registry curation, adapter approvals, and marketplace moderation.'\n )}\n >\n <Tabs value={activeTab} onValueChange={setActiveTab} className=\"w-full\">\n <TabsList className=\"mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex\">\n <TabsTrigger value=\"providers\" className=\"gap-2\">\n <Settings2 size={16} />\n {tr('admin.tabs.providers', 'Provider Registry')}\n </TabsTrigger>\n <TabsTrigger value=\"adapters\" className=\"gap-2\">\n <Plug size={16} />\n {tr('admin.tabs.adapters', 'Adapter Approvals')}\n </TabsTrigger>\n <TabsTrigger value=\"marketplace\" className=\"gap-2\">\n <Store size={16} />\n {tr('admin.tabs.marketplace', 'Marketplace Moderation')}\n </TabsTrigger>\n </TabsList>\n\n {/* Provider registry curation — backed by real GraphQL queries. */}\n <TabsContent value=\"providers\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.providers.title', 'Provider registry')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.providers.description',\n 'Curate the global provider catalog. Verify submitted providers or deprecate stale entries.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {providersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : providers.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.providers.emptyTitle', 'No providers yet')}\n description={tr(\n 'admin.providers.emptyDescription',\n 'Once providers are created or claimed they will appear here for curation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.providers.table.name', 'Name')}</TableHead>\n <TableHead>{tr('admin.providers.table.category', 'Category')}</TableHead>\n <TableHead>{tr('admin.providers.table.status', 'Status')}</TableHead>\n <TableHead>{tr('admin.providers.table.created', 'Created')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.providers.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {providers.map((provider: SubProvider) => (\n <TableRow key={provider.id}>\n <TableCell className=\"font-medium text-text-primary\">\n {provider.name}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{provider.category}</TableCell>\n <TableCell>\n <StatusBadge status={provider.status} />\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(provider.createdAt)}\n </TableCell>\n <TableCell className=\"text-right\">\n <div className=\"flex justify-end gap-2\">\n {provider.status !== 'VERIFIED' && (\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleVerify(provider.id)}\n disabled={updateProvider.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.providers.verify', 'Verify')}\n </Button>\n )}\n {provider.status !== 'DEPRECATED' && (\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleDeprecate(provider.id)}\n disabled={updateProvider.isPending}\n >\n {tr('admin.providers.deprecate', 'Deprecate')}\n </Button>\n )}\n </div>\n </TableCell>\n </TableRow>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Adapter approval queue — backed by real GraphQL queries. */}\n <TabsContent value=\"adapters\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.adapters.title', 'Adapter approvals')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.adapters.description',\n 'Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {adaptersLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : adapterSubmissions.length === 0 ? (\n <EmptyState\n icon={<Plug className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.adapters.emptyTitle', 'No adapter submissions')}\n description={tr(\n 'admin.adapters.emptyDescription',\n 'Submitted integration adapters will appear here for review.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.adapters.table.adapter', 'Adapter')}</TableHead>\n <TableHead>\n {tr('admin.adapters.table.workspace', 'Submitting workspace')}\n </TableHead>\n <TableHead>{tr('admin.adapters.table.submitted', 'Submitted')}</TableHead>\n <TableHead>{tr('admin.adapters.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.adapters.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {adapterSubmissions.map((submission) => (\n <Fragment key={submission.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {submission.adapterId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {submission.submitterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(submission.createdAt)}\n </TableCell>\n <TableCell>\n <StatusBadge status={submission.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {submission.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleApproveAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <CheckCircle2 size={14} className=\"mr-1\" />\n {tr('admin.adapters.approve', 'Approve')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"secondary\"\n onClick={() => handleStartRejectAdapter(submission.id)}\n disabled={approveAdapter.isPending || rejectAdapter.isPending}\n >\n <XCircle size={14} className=\"mr-1\" />\n {tr('admin.adapters.reject', 'Reject')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {rejectingAdapterId === submission.id && (\n <TableRow key={`${submission.id}-reject`}>\n <TableCell colSpan={5} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={adapterRejectReason}\n onChange={(event) => setAdapterRejectReason(event.target.value)}\n placeholder={tr(\n 'admin.adapters.rejectPlaceholder',\n 'Reason for rejecting this adapter submission (required)'\n )}\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleConfirmRejectAdapter(submission.id)}\n disabled={\n !adapterRejectReason.trim() || rejectAdapter.isPending\n }\n >\n {tr('admin.adapters.confirmReject', 'Confirm reject')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setRejectingAdapterId(null)}\n disabled={rejectAdapter.isPending}\n >\n {tr('admin.adapters.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n\n {/* Marketplace moderation — backed by real GraphQL queries. */}\n <TabsContent value=\"marketplace\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.marketplace.title', 'Marketplace moderation')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.marketplace.description',\n 'Review reported marketplace listings and take moderation actions.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n {reportsLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n ) : marketplaceReports.length === 0 ? (\n <EmptyState\n icon={<Store className=\"size-6 text-action-primary-bg\" />}\n title={tr('admin.marketplace.emptyTitle', 'No reported listings')}\n description={tr(\n 'admin.marketplace.emptyDescription',\n 'Reported marketplace listings will appear here for moderation.'\n )}\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <Table>\n <TableHeader>\n <TableRow>\n <TableHead>{tr('admin.marketplace.table.listing', 'Listing')}</TableHead>\n <TableHead>\n {tr('admin.marketplace.table.workspace', 'Reporting workspace')}\n </TableHead>\n <TableHead>{tr('admin.marketplace.table.reported', 'Reported')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.reason', 'Reason')}</TableHead>\n <TableHead>{tr('admin.marketplace.table.status', 'Status')}</TableHead>\n <TableHead className=\"text-right\">\n {tr('admin.marketplace.table.actions', 'Actions')}\n </TableHead>\n </TableRow>\n </TableHeader>\n <TableBody>\n {marketplaceReports.map((report) => (\n <Fragment key={report.id}>\n <TableRow>\n <TableCell className=\"font-medium text-text-primary\">\n {report.listingId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {report.reporterWorkspaceId}\n </TableCell>\n <TableCell className=\"text-text-secondary\">\n {formatDate(report.createdAt)}\n </TableCell>\n <TableCell className=\"text-text-secondary\">{report.reason}</TableCell>\n <TableCell>\n <StatusBadge status={report.status} />\n </TableCell>\n <TableCell className=\"text-right\">\n {report.status === 'PENDING' && (\n <div className=\"flex justify-end gap-2\">\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => handleStartModerate(report.id, 'DISMISS')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.dismiss', 'Dismiss')}\n </Button>\n <Button\n size=\"sm\"\n variant=\"destructive\"\n onClick={() => handleStartModerate(report.id, 'REMOVE_LISTING')}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.remove', 'Remove')}\n </Button>\n </div>\n )}\n </TableCell>\n </TableRow>\n {moderatingReportId === report.id && (\n <TableRow key={`${report.id}-moderate`}>\n <TableCell colSpan={6} className=\"bg-bg-sunken\">\n <div className=\"flex flex-col gap-2 py-1 sm:flex-row sm:items-start\">\n <Textarea\n value={moderateReason}\n onChange={(event) => setModerateReason(event.target.value)}\n placeholder={\n moderateAction === 'REMOVE_LISTING'\n ? tr(\n 'admin.marketplace.reasonPlaceholderRemove',\n 'Reason to remove this listing (required)'\n )\n : tr(\n 'admin.marketplace.reasonPlaceholderDismiss',\n 'Reason to dismiss this report (required)'\n )\n }\n className=\"min-h-[60px] flex-1\"\n autoFocus\n />\n <div className=\"flex gap-2 sm:flex-col\">\n <Button\n size=\"sm\"\n variant={\n moderateAction === 'REMOVE_LISTING'\n ? 'destructive'\n : 'outline'\n }\n onClick={() => handleConfirmModerate(report.id)}\n disabled={!moderateReason.trim() || moderateListing.isPending}\n >\n {moderateAction === 'REMOVE_LISTING'\n ? tr('admin.marketplace.confirmRemoval', 'Confirm removal')\n : tr(\n 'admin.marketplace.confirmDismissal',\n 'Confirm dismissal'\n )}\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n onClick={() => setModeratingReportId(null)}\n disabled={moderateListing.isPending}\n >\n {tr('admin.marketplace.cancel', 'Cancel')}\n </Button>\n </div>\n </div>\n </TableCell>\n </TableRow>\n )}\n </Fragment>\n ))}\n </TableBody>\n </Table>\n </div>\n )}\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;;;;;;AAqDA,IAAa,UAA+B;CAC1C,IAAM,IAAK,EAAM,GACX,CAAC,GAAW,MAAgB,EAAS,WAAW,GAGhD,EAAE,MAAM,IAAe,WAAW,OAAqB,GAAa,EACxE,YAAY,EAAE,OAAO,GAAG,EAC1B,CAAC,GACK,IAAiB,EAAkB,GAEnC,KAAgB,MAAe;EACnC,EAAe,OAAO;GAAE;GAAI,OAAO,EAAE,QAAQ,WAAW;EAAE,CAAC;CAC7D,GAEM,KAAmB,MAAe;EACtC,EAAe,OAAO;GAAE;GAAI,OAAO,EAAE,QAAQ,aAAa;EAAE,CAAC;CAC/D,GAEM,IAAY,IAAe,SAAS,CAAC,GAGrC,EAAE,MAAM,GAAwB,WAAW,MAAoB,EAAsB,EACzF,YAAY,EAAE,OAAO,GAAG,EAC1B,CAAC,GACK,IAAiB,EAAkB,GACnC,IAAgB,GAAiB,GACjC,CAAC,GAAoB,KAAyB,EAAwB,IAAI,GAC1E,CAAC,GAAqB,KAA0B,EAAS,EAAE,GAE3D,IAAqB,GAAwB,SAAS,CAAC,GAEvD,MAAwB,MAAe;EAC3C,EAAe,OAAO,EAAE,MAAG,CAAC;CAC9B,GAEM,MAA4B,MAAe;EAE/C,AADA,EAAsB,CAAE,GACxB,EAAuB,EAAE;CAC3B,GAEM,MAA8B,MAAe;EAC5C,EAAoB,KAAK,KAC9B,EAAc,OACZ;GAAE;GAAI,QAAQ,EAAoB,KAAK;EAAE,GACzC,EACE,iBAAiB;GAEf,AADA,EAAsB,IAAI,GAC1B,EAAuB,EAAE;EAC3B,EACF,CACF;CACF,GAGM,EAAE,MAAM,IAAwB,WAAW,OAAmB,GAAsB,EACxF,YAAY,EAAE,OAAO,GAAG,EAC1B,CAAC,GACK,IAAkB,GAAmB,GACrC,CAAC,IAAoB,KAAyB,EAAwB,IAAI,GAC1E,CAAC,GAAgB,KAAqB,EAAqC,IAAI,GAC/E,CAAC,GAAgB,KAAqB,EAAS,EAAE,GAEjD,IAAqB,IAAwB,SAAS,CAAC,GAEvD,KAAuB,GAAY,MAAgC;EAGvE,AAFA,EAAsB,CAAE,GACxB,EAAkB,CAAM,GACxB,EAAkB,EAAE;CACtB,GAEM,MAAyB,MAAe;EACxC,CAAC,KAAkB,CAAC,EAAe,KAAK,KAC5C,EAAgB,OACd;GAAE;GAAI,QAAQ;GAAgB,QAAQ,EAAe,KAAK;EAAE,GAC5D,EACE,iBAAiB;GAGf,AAFA,EAAsB,IAAI,GAC1B,EAAkB,IAAI,GACtB,EAAkB,EAAE;EACtB,EACF,CACF;CACF;CAEA,OACE,kBAAC,GAAD;EACE,OAAO,EAAG,eAAe,qBAAqB;EAC9C,aAAa,EACX,qBACA,4EACF;YAEA,kBAAC,IAAD;GAAM,OAAO;GAAW,eAAe;GAAc,WAAU;aAA/D;IACE,kBAAC,IAAD;KAAU,WAAU;eAApB;MACE,kBAAC,GAAD;OAAa,OAAM;OAAY,WAAU;iBAAzC,CACE,kBAAC,IAAD,EAAW,MAAM,GAAK,CAAA,GACrB,EAAG,wBAAwB,mBAAmB,CACpC;;MACb,kBAAC,GAAD;OAAa,OAAM;OAAW,WAAU;iBAAxC,CACE,kBAAC,GAAD,EAAM,MAAM,GAAK,CAAA,GAChB,EAAG,uBAAuB,mBAAmB,CACnC;;MACb,kBAAC,GAAD;OAAa,OAAM;OAAc,WAAU;iBAA3C,CACE,kBAAC,GAAD,EAAO,MAAM,GAAK,CAAA,GACjB,EAAG,0BAA0B,wBAAwB,CAC3C;;KACL;;IAGV,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,yBAAyB,mBAAmB,EAAa,CAAA,GACxE,kBAAC,GAAD,EAAA,UACG,EACC,+BACA,4FACF,EACe,CAAA,CACP,EAAA,CAAA,GACZ,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA;KACjB,CAAA,IACH,EAAU,WAAW,IACvB,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAO,WAAU,gCAAiC,CAAA;MACxD,OAAO,EAAG,8BAA8B,kBAAkB;MAC1D,aAAa,EACX,oCACA,2EACF;KACD,CAAA,IAED,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,8BAA8B,MAAM,EAAa,CAAA;OAChE,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,UAAU,EAAa,CAAA;OACxE,kBAAC,GAAD,EAAA,UAAY,EAAG,gCAAgC,QAAQ,EAAa,CAAA;OACpE,kBAAC,GAAD,EAAA,UAAY,EAAG,iCAAiC,SAAS,EAAa,CAAA;OACtE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,iCAAiC,SAAS;OACrC,CAAA;MACH,EAAA,CAAA,EACC,CAAA,GACb,kBAAC,GAAD,EAAA,UACG,EAAU,KAAK,MACd,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAS;OACD,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAAuB,EAAS;OAAoB,CAAA;OACzE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAS,OAAS,CAAA,EAC9B,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAS,SAAS;OACrB,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBACnB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACG,EAAS,WAAW,cACnB,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAa,EAAS,EAAE;UACvC,UAAU,EAAe;oBAJ3B,CAME,kBAAC,GAAD;WAAc,MAAM;WAAI,WAAU;UAAQ,CAAA,GACzC,EAAG,0BAA0B,QAAQ,CAChC;aAET,EAAS,WAAW,gBACnB,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAgB,EAAS,EAAE;UAC1C,UAAU,EAAe;oBAExB,EAAG,6BAA6B,WAAW;SACtC,CAAA,CAEP;;OACI,CAAA;MACH,EAAA,GApCK,EAAS,EAoCd,CACX,EACQ,CAAA,CACN,EAAA,CAAA;KACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;IACK,CAAA;IAGb,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,wBAAwB,mBAAmB,EAAa,CAAA,GACvE,kBAAC,GAAD,EAAA,UACG,EACC,8BACA,2GACF,EACe,CAAA,CACP,EAAA,CAAA,GACZ,kBAAC,GAAD,EAAA,UACG,IACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA;KACjB,CAAA,IACH,EAAmB,WAAW,IAChC,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAM,WAAU,gCAAiC,CAAA;MACvD,OAAO,EAAG,6BAA6B,wBAAwB;MAC/D,aAAa,EACX,mCACA,6DACF;KACD,CAAA,IAED,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,gCAAgC,SAAS,EAAa,CAAA;OACrE,kBAAC,GAAD,EAAA,UACG,EAAG,kCAAkC,sBAAsB,EACnD,CAAA;OACX,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,WAAW,EAAa,CAAA;OACzE,kBAAC,GAAD,EAAA,UAAY,EAAG,+BAA+B,QAAQ,EAAa,CAAA;OACnE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,gCAAgC,SAAS;OACpC,CAAA;MACH,EAAA,CAAA,EACC,CAAA,GACb,kBAAC,GAAD,EAAA,UACG,EAAmB,KAAK,MACvB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW;OACH,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW;OACH,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAW,SAAS;OACvB,CAAA;OACX,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAW,OAAS,CAAA,EAChC,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,WAAW,aACrB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAAqB,EAAW,EAAE;UACjD,UAAU,EAAe,aAAa,EAAc;oBAJtD,CAME,kBAAC,GAAD;WAAc,MAAM;WAAI,WAAU;UAAQ,CAAA,GACzC,EAAG,0BAA0B,SAAS,CACjC;aACR,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAAyB,EAAW,EAAE;UACrD,UAAU,EAAe,aAAa,EAAc;oBAJtD,CAME,kBAAC,IAAD;WAAS,MAAM;WAAI,WAAU;UAAQ,CAAA,GACpC,EAAG,yBAAyB,QAAQ,CAC/B;WACL;;OAEE,CAAA;MACH,EAAA,CAAA,GACT,MAAuB,EAAW,MACjC,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,SAAS;OAAG,WAAU;iBAC/B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,OAAO;SACP,WAAW,MAAU,EAAuB,EAAM,OAAO,KAAK;SAC9D,aAAa,EACX,oCACA,yDACF;SACA,WAAU;SACV,WAAA;QACD,CAAA,GACD,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,GAA2B,EAAW,EAAE;UACvD,UACE,CAAC,EAAoB,KAAK,KAAK,EAAc;oBAG9C,EAAG,gCAAgC,gBAAgB;SAC9C,CAAA,GACR,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAsB,IAAI;UACzC,UAAU,EAAc;oBAEvB,EAAG,yBAAyB,QAAQ;SAC/B,CAAA,CACL;UACF;;MACI,CAAA,EACH,GAnCK,GAAG,EAAW,GAAG,QAmCtB,CAEJ,EAAA,GA7EK,EAAW,EA6EhB,CACX,EACQ,CAAA,CACN,EAAA,CAAA;KACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;IACK,CAAA;IAGb,kBAAC,GAAD;KAAa,OAAM;eACjB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAY,EAAG,2BAA2B,wBAAwB,EAAa,CAAA,GAC/E,kBAAC,GAAD,EAAA,UACG,EACC,iCACA,mEACF,EACe,CAAA,CACP,EAAA,CAAA,GACZ,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,MAAK,KAAM,CAAA;KACjB,CAAA,IACH,EAAmB,WAAW,IAChC,kBAAC,GAAD;MACE,MAAM,kBAAC,GAAD,EAAO,WAAU,gCAAiC,CAAA;MACxD,OAAO,EAAG,gCAAgC,sBAAsB;MAChE,aAAa,EACX,sCACA,gEACF;KACD,CAAA,IAED,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD,EAAA,UAAY,EAAG,mCAAmC,SAAS,EAAa,CAAA;OACxE,kBAAC,GAAD,EAAA,UACG,EAAG,qCAAqC,qBAAqB,EACrD,CAAA;OACX,kBAAC,GAAD,EAAA,UAAY,EAAG,oCAAoC,UAAU,EAAa,CAAA;OAC1E,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,QAAQ,EAAa,CAAA;OACtE,kBAAC,GAAD,EAAA,UAAY,EAAG,kCAAkC,QAAQ,EAAa,CAAA;OACtE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAG,mCAAmC,SAAS;OACvC,CAAA;MACH,EAAA,CAAA,EACC,CAAA,GACb,kBAAC,GAAD,EAAA,UACG,EAAmB,KAAK,MACvB,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAA;OACE,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO;OACC,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO;OACC,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAW,EAAO,SAAS;OACnB,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAAuB,EAAO;OAAkB,CAAA;OACrE,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD,EAAa,QAAQ,EAAO,OAAS,CAAA,EAC5B,CAAA;OACX,kBAAC,GAAD;QAAW,WAAU;kBAClB,EAAO,WAAW,aACjB,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAoB,EAAO,IAAI,SAAS;UACvD,UAAU,EAAgB;oBAEzB,EAAG,6BAA6B,SAAS;SACpC,CAAA,GACR,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAoB,EAAO,IAAI,gBAAgB;UAC9D,UAAU,EAAgB;oBAEzB,EAAG,4BAA4B,QAAQ;SAClC,CAAA,CACL;;OAEE,CAAA;MACH,EAAA,CAAA,GACT,OAAuB,EAAO,MAC7B,kBAAC,GAAD,EAAA,UACE,kBAAC,GAAD;OAAW,SAAS;OAAG,WAAU;iBAC/B,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD;SACE,OAAO;SACP,WAAW,MAAU,EAAkB,EAAM,OAAO,KAAK;SACzD,aACE,MAAmB,mBACf,EACE,6CACA,0CACF,IACA,EACE,8CACA,0CACF;SAEN,WAAU;SACV,WAAA;QACD,CAAA,GACD,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,GAAD;UACE,MAAK;UACL,SACE,MAAmB,mBACf,gBACA;UAEN,eAAe,GAAsB,EAAO,EAAE;UAC9C,UAAU,CAAC,EAAe,KAAK,KAAK,EAAgB;oBAEnD,MAAmB,mBAChB,EAAG,oCAAoC,iBAAiB,IACxD,EACE,sCACA,mBACF;SACE,CAAA,GACR,kBAAC,GAAD;UACE,MAAK;UACL,SAAQ;UACR,eAAe,EAAsB,IAAI;UACzC,UAAU,EAAgB;oBAEzB,EAAG,4BAA4B,QAAQ;SAClC,CAAA,CACL;UACF;;MACI,CAAA,EACH,GAjDK,GAAG,EAAO,GAAG,UAiDlB,CAEJ,EAAA,GA1FK,EAAO,EA0FZ,CACX,EACQ,CAAA,CACN,EAAA,CAAA;KACJ,CAAA,EAEI,CAAA,CACT,EAAA,CAAA;IACK,CAAA;GACT;;CACI,CAAA;AAEhB"}
@@ -0,0 +1,10 @@
1
+ import { SubAgentStatus } from '../types';
2
+
3
+ export interface PostureOptionsProps {
4
+ /** Postures to render, in display order. */
5
+ options: readonly SubAgentStatus[];
6
+ /** The record's current posture, if any (keeps an existing value selectable). */
7
+ currentStatus?: SubAgentStatus;
8
+ }
9
+ export declare function PostureOptions({ options, currentStatus }: PostureOptionsProps): import("react").JSX.Element;
10
+ //# sourceMappingURL=PostureOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostureOptions.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/components/PostureOptions.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,mBAAmB;IAClC,4CAA4C;IAC5C,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;IACnC,iFAAiF;IACjF,aAAa,CAAC,EAAE,cAAc,CAAC;CAChC;AAED,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,EAAE,mBAAmB,+BAmB7E"}
@@ -0,0 +1,20 @@
1
+ import { formatEnumLabel as e } from "../utils/formatters.js";
2
+ import { isPostureSelectable as t, useAutonomousAgentMode as n } from "../hooks/useAutonomousAgentMode.js";
3
+ import { useTr as r } from "../hooks/useTr.js";
4
+ import { Fragment as i, jsx as a } from "react/jsx-runtime";
5
+ //#region src/subscriberbot/components/PostureOptions.tsx
6
+ function o({ options: o, currentStatus: s }) {
7
+ let c = r(), l = n();
8
+ return /* @__PURE__ */ a(i, { children: o.map((n) => {
9
+ let r = c(`agents.postures.${n.toLowerCase()}`, e(n)), i = t(n, l, s);
10
+ return /* @__PURE__ */ a("option", {
11
+ value: n,
12
+ disabled: !i,
13
+ children: i ? r : c("agents.postures.unavailable", "{{label}} (not yet available)", { label: r })
14
+ }, n);
15
+ }) });
16
+ }
17
+ //#endregion
18
+ export { o as PostureOptions };
19
+
20
+ //# sourceMappingURL=PostureOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostureOptions.js","names":[],"sources":["../../../src/subscriberbot/components/PostureOptions.tsx"],"sourcesContent":["/**\n * PostureOptions — `<option>` list for editable agent-posture selects.\n * @module subscriberbot/components\n *\n * Renders every posture, but disables AUTONOMOUS (and labels it as not yet\n * available) while the fail-closed `subscriberbot.agents.autonomous` gate is\n * shut. Filter controls that only narrow a list should keep rendering plain\n * options; this component is for controls that write a posture.\n */\n\nimport { isPostureSelectable, useAutonomousAgentMode } from '../hooks/useAutonomousAgentMode';\nimport { useTr } from '../hooks/useTr';\nimport { formatEnumLabel } from '../utils/formatters';\nimport type { SubAgentStatus } from '../types';\n\nexport interface PostureOptionsProps {\n /** Postures to render, in display order. */\n options: readonly SubAgentStatus[];\n /** The record's current posture, if any (keeps an existing value selectable). */\n currentStatus?: SubAgentStatus;\n}\n\nexport function PostureOptions({ options, currentStatus }: PostureOptionsProps) {\n const tr = useTr();\n const autonomousAvailable = useAutonomousAgentMode();\n\n return (\n <>\n {options.map((s) => {\n const label = tr(`agents.postures.${s.toLowerCase()}`, formatEnumLabel(s));\n const selectable = isPostureSelectable(s, autonomousAvailable, currentStatus);\n return (\n <option key={s} value={s} disabled={!selectable}>\n {selectable\n ? label\n : tr('agents.postures.unavailable', '{{label}} (not yet available)', { label })}\n </option>\n );\n })}\n </>\n );\n}\n"],"mappings":";;;;;AAsBA,SAAgB,EAAe,EAAE,YAAS,oBAAsC;CAC9E,IAAM,IAAK,EAAM,GACX,IAAsB,EAAuB;CAEnD,OACE,kBAAA,GAAA,EAAA,UACG,EAAQ,KAAK,MAAM;EAClB,IAAM,IAAQ,EAAG,mBAAmB,EAAE,YAAY,KAAK,EAAgB,CAAC,CAAC,GACnE,IAAa,EAAoB,GAAG,GAAqB,CAAa;EAC5E,OACE,kBAAC,UAAD;GAAgB,OAAO;GAAG,UAAU,CAAC;aAClC,IACG,IACA,EAAG,+BAA+B,iCAAiC,EAAE,SAAM,CAAC;EAC1E,GAJK,CAIL;CAEZ,CAAC,EACD,CAAA;AAEN"}
@@ -7,6 +7,8 @@ export { MetricsCard } from './MetricsCard';
7
7
  export { StatusBadge } from './StatusBadge';
8
8
  export { EmptyState } from './EmptyState';
9
9
  export { Modal } from './Modal';
10
+ export { PostureOptions } from './PostureOptions';
11
+ export type { PostureOptionsProps } from './PostureOptions';
10
12
  export { LoadingView, ErrorView, Section } from './StateViews';
11
13
  export { Donut, Legend, BarList, Sparkline, Gauge, Timeline, MiniProgress, CHART_COLORS, } from './viz';
12
14
  export type { Segment, TimelineItem } from './viz';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,OAAO,CAAC;AACf,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/components/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,SAAS,EACT,KAAK,EACL,QAAQ,EACR,YAAY,EACZ,YAAY,GACb,MAAM,OAAO,CAAC;AACf,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC"}
@@ -3,5 +3,6 @@ import "./MetricsCard.js";
3
3
  import "./StatusBadge.js";
4
4
  import "./EmptyState.js";
5
5
  import "./Modal.js";
6
+ import "./PostureOptions.js";
6
7
  import "./StateViews.js";
7
8
  import "./viz.js";
@@ -3,6 +3,9 @@
3
3
  * @module subscriberbot/hooks
4
4
  */
5
5
  export { useTr } from './useTr';
6
+ export { useRouteSelection } from './useRouteSelection';
7
+ export type { SelectableSection } from './useRouteSelection';
8
+ export { useAutonomousAgentMode, isPostureSelectable, AUTONOMOUS_AGENT_FLAG, } from './useAutonomousAgentMode';
6
9
  export { useRelationships, useRelationship, useCreateRelationship, useUpdateRelationship, useTransitionRelationship, useCancelRelationship, useRenewalEvents, useEntitlements, useCreateEntitlement, useAssets, useCreateAsset, useUploadFile, useFileDownloadUrl, useProviders, useProvider, useCreateProvider, useUpdateProvider, useArchiveProvider, usePlans, useCreatePlan, useBenchmarkDataPoints, useInboxMessages, useMarkMessageRead, useIngestMessage, useInvoices, useMarkInvoicePaid, useCreateInvoice, usePaymentInstruments, useCreatePaymentInstrument, useRemovePaymentInstrument, useChannels, useCreateChannel, useVerifyChannel, useAgents, useAgent, useCreateAgent, useSetAgentStatus, useCreatePolicy, useWorkflows, useCreateWorkflow, useActivateWorkflow, useAdapterSubmissions, useApproveAdapter, useRejectAdapter, useMarketplaceReports, useModerateListing, } from './useSubscriberBotApi';
7
10
  export type { RelationshipListFilters, ProviderListFilters, InboxListFilters, InvoiceListFilters, AgentListFilters, AdapterSubmissionListFilters, MarketplaceReportListFilters, } from './useSubscriberBotApi';
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EAEnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAEL,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,SAAS,EACT,cAAc,EACd,aAAa,EACb,kBAAkB,EAElB,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,sBAAsB,EAEtB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAEhB,WAAW,EACX,kBAAkB,EAClB,gBAAgB,EAEhB,qBAAqB,EACrB,0BAA0B,EAC1B,0BAA0B,EAC1B,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAEhB,SAAS,EACT,QAAQ,EACR,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,iBAAiB,EACjB,mBAAmB,EAEnB,qBAAqB,EACrB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EACV,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC"}
@@ -1,2 +1,4 @@
1
- import "./useSubscriberBotApi.js";
1
+ import "./useAutonomousAgentMode.js";
2
2
  import "./useTr.js";
3
+ import "./useSubscriberBotApi.js";
4
+ import "./useRouteSelection.js";
@@ -0,0 +1,15 @@
1
+ import { SubAgentStatus } from '../types';
2
+
3
+ /** Platform feature flag that unlocks the AUTONOMOUS posture (fail-closed). */
4
+ export declare const AUTONOMOUS_AGENT_FLAG = "subscriberbot.agents.autonomous";
5
+ /** Returns `true` only when the AUTONOMOUS posture is explicitly enabled. */
6
+ export declare function useAutonomousAgentMode(): boolean;
7
+ /**
8
+ * Whether a posture option can be chosen in an editable control.
9
+ *
10
+ * AUTONOMOUS is selectable only when the gate is open, or when the record is
11
+ * already AUTONOMOUS (so the current value still renders as selected and the
12
+ * user can move it to a safer posture).
13
+ */
14
+ export declare function isPostureSelectable(option: SubAgentStatus, autonomousAvailable: boolean, currentStatus?: SubAgentStatus): boolean;
15
+ //# sourceMappingURL=useAutonomousAgentMode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutonomousAgentMode.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/useAutonomousAgentMode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,oCAAoC,CAAC;AAEvE,6EAA6E;AAC7E,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,cAAc,EACtB,mBAAmB,EAAE,OAAO,EAC5B,aAAa,CAAC,EAAE,cAAc,GAC7B,OAAO,CAGT"}
@@ -0,0 +1,13 @@
1
+ import { useFeatureFlag as e } from "@burdenoff/fe-libs/shared/feature-flags";
2
+ //#region src/subscriberbot/hooks/useAutonomousAgentMode.ts
3
+ var t = "subscriberbot.agents.autonomous";
4
+ function n() {
5
+ return e(t, !1);
6
+ }
7
+ function r(e, t, n) {
8
+ return e === "AUTONOMOUS" ? t || n === "AUTONOMOUS" : !0;
9
+ }
10
+ //#endregion
11
+ export { t as AUTONOMOUS_AGENT_FLAG, r as isPostureSelectable, n as useAutonomousAgentMode };
12
+
13
+ //# sourceMappingURL=useAutonomousAgentMode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutonomousAgentMode.js","names":[],"sources":["../../../src/subscriberbot/hooks/useAutonomousAgentMode.ts"],"sourcesContent":["/**\n * useAutonomousAgentMode — fail-closed gate for the AUTONOMOUS agent posture.\n * @module subscriberbot/hooks\n *\n * The backend (`wspace-subscriberbot-svc`) rejects `subSetAgentStatus` and\n * `subCreateAgent` with `AUTONOMOUS_MODE_UNAVAILABLE` unless the\n * `subscriberbot.agents.autonomous` platform flag is explicitly enabled\n * (BOFF-3643 / BOFF-3625). The policy-evaluation engine that would let an\n * agent act on its own does not exist yet, so the UI must not offer a posture\n * the service will refuse.\n *\n * Unlike most platform flags (default-allow), this one defaults to `false`:\n * a missing, unloaded or errored flag keeps AUTONOMOUS unavailable, mirroring\n * the service's fail-closed check.\n */\n\nimport { useFeatureFlag } from '@burdenoff/fe-libs/shared/feature-flags';\nimport type { SubAgentStatus } from '../types';\n\n/** Platform feature flag that unlocks the AUTONOMOUS posture (fail-closed). */\nexport const AUTONOMOUS_AGENT_FLAG = 'subscriberbot.agents.autonomous';\n\n/** Returns `true` only when the AUTONOMOUS posture is explicitly enabled. */\nexport function useAutonomousAgentMode(): boolean {\n return useFeatureFlag(AUTONOMOUS_AGENT_FLAG, false);\n}\n\n/**\n * Whether a posture option can be chosen in an editable control.\n *\n * AUTONOMOUS is selectable only when the gate is open, or when the record is\n * already AUTONOMOUS (so the current value still renders as selected and the\n * user can move it to a safer posture).\n */\nexport function isPostureSelectable(\n option: SubAgentStatus,\n autonomousAvailable: boolean,\n currentStatus?: SubAgentStatus\n): boolean {\n if (option !== 'AUTONOMOUS') return true;\n return autonomousAvailable || currentStatus === 'AUTONOMOUS';\n}\n"],"mappings":";;AAoBA,IAAa,IAAwB;AAGrC,SAAgB,IAAkC;CAChD,OAAO,EAAe,GAAuB,EAAK;AACpD;AASA,SAAgB,EACd,GACA,GACA,GACS;CAET,OADI,MAAW,eACR,KAAuB,MAAkB,eADZ;AAEtC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * URL-backed selection for list pages with a reading pane.
3
+ * @module subscriberbot/hooks
4
+ *
5
+ * The Universal Inbox and Workflows pages show one selected item beside the
6
+ * list. Keeping that selection in the URL (`/inbox/:selectedId`,
7
+ * `/workflows/:selectedId`) makes it deep-linkable and lets the assistant's
8
+ * page context resolve "this message" / "this workflow" to an entity id
9
+ * (see `utils/pageContext.ts`). Both routes are declared as one optional-segment
10
+ * route, so changing the selection does not remount the page or reset its
11
+ * filters and paging.
12
+ */
13
+ export type SelectableSection = 'inbox' | 'workflows';
14
+ export declare function useRouteSelection(section: SelectableSection): readonly [string | null, (id: string | null) => void];
15
+ //# sourceMappingURL=useRouteSelection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRouteSelection.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/hooks/useRouteSelection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,WAAW,CAAC;AAEtD,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,iBAAiB,GACzB,SAAS,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,CAevD"}
@@ -0,0 +1,18 @@
1
+ import { useSubscriberBot as e } from "../context/SubscriberBotContext.js";
2
+ import { useCallback as t } from "react";
3
+ import { useNavigate as n, useParams as r } from "react-router";
4
+ //#region src/subscriberbot/hooks/useRouteSelection.ts
5
+ function i(i) {
6
+ let { selectedId: a } = r(), o = n(), { getPath: s } = e(), c = t((e) => {
7
+ o(s(e ? `/${i}/${encodeURIComponent(e)}` : `/${i}`), { replace: !0 });
8
+ }, [
9
+ s,
10
+ o,
11
+ i
12
+ ]);
13
+ return [a ?? null, c];
14
+ }
15
+ //#endregion
16
+ export { i as useRouteSelection };
17
+
18
+ //# sourceMappingURL=useRouteSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRouteSelection.js","names":[],"sources":["../../../src/subscriberbot/hooks/useRouteSelection.ts"],"sourcesContent":["/**\n * URL-backed selection for list pages with a reading pane.\n * @module subscriberbot/hooks\n *\n * The Universal Inbox and Workflows pages show one selected item beside the\n * list. Keeping that selection in the URL (`/inbox/:selectedId`,\n * `/workflows/:selectedId`) makes it deep-linkable and lets the assistant's\n * page context resolve \"this message\" / \"this workflow\" to an entity id\n * (see `utils/pageContext.ts`). Both routes are declared as one optional-segment\n * route, so changing the selection does not remount the page or reset its\n * filters and paging.\n */\n\nimport { useCallback } from 'react';\nimport { useNavigate, useParams } from 'react-router';\nimport { useSubscriberBot } from '../context/SubscriberBotContext';\n\nexport type SelectableSection = 'inbox' | 'workflows';\n\nexport function useRouteSelection(\n section: SelectableSection\n): readonly [string | null, (id: string | null) => void] {\n const { selectedId } = useParams<{ selectedId?: string }>();\n const navigate = useNavigate();\n const { getPath } = useSubscriberBot();\n\n const select = useCallback(\n (id: string | null) => {\n const target = id ? `/${section}/${encodeURIComponent(id)}` : `/${section}`;\n // Replace rather than push: picking items should not fill the back stack.\n void navigate(getPath(target), { replace: true });\n },\n [getPath, navigate, section]\n );\n\n return [selectedId ?? null, select] as const;\n}\n"],"mappings":";;;;AAmBA,SAAgB,EACd,GACuD;CACvD,IAAM,EAAE,kBAAe,EAAmC,GACpD,IAAW,EAAY,GACvB,EAAE,eAAY,EAAiB,GAE/B,IAAS,GACZ,MAAsB;EAGrB,EAAc,EAFC,IAAK,IAAI,EAAQ,GAAG,mBAAmB,CAAE,MAAM,IAAI,GAEtC,GAAG,EAAE,SAAS,GAAK,CAAC;CAClD,GACA;EAAC;EAAS;EAAU;CAAO,CAC7B;CAEA,OAAO,CAAC,KAAc,MAAM,CAAM;AACpC"}
@@ -3,10 +3,10 @@ import { PageLayout as t } from "../components/PageLayout.js";
3
3
  import { MetricsCard as n } from "../components/MetricsCard.js";
4
4
  import { formatDate as r, formatEnumLabel as i } from "../utils/formatters.js";
5
5
  import { EmptyState as a } from "../components/EmptyState.js";
6
- import { ErrorView as o, LoadingView as s, Section as c } from "../components/StateViews.js";
6
+ import { useTr as o } from "../hooks/useTr.js";
7
+ import { ErrorView as s, LoadingView as c, Section as l } from "../components/StateViews.js";
7
8
  import "../components/index.js";
8
- import { useAllAssets as l, useFileDownloadUrl as u, useRelationships as d } from "../hooks/useSubscriberBotApi.js";
9
- import { useTr as f } from "../hooks/useTr.js";
9
+ import { useAllAssets as u, useFileDownloadUrl as d, useRelationships as f } from "../hooks/useSubscriberBotApi.js";
10
10
  import { useMemo as p, useState as m } from "react";
11
11
  import { AlarmClock as h, Award as g, Download as _, File as v, FileKey as y, FileText as b, Globe as x, Receipt as S, Search as C, ShieldCheck as w, Vault as T } from "lucide-react";
12
12
  import { jsx as E, jsxs as D } from "react/jsx-runtime";
@@ -42,14 +42,14 @@ var A = {
42
42
  return Number.isNaN(t) ? Infinity : t;
43
43
  };
44
44
  function P({ asset: t, subscription: n }) {
45
- let a = f(), o = u(), [s, c] = m(!1), l = A[t.type] ?? v, d = M(t.expiresAt);
45
+ let a = o(), s = d(), [c, l] = m(!1), u = A[t.type] ?? v, f = M(t.expiresAt);
46
46
  return /* @__PURE__ */ D(O, {
47
47
  treatment: "metric",
48
48
  className: "flex items-start gap-3 p-4",
49
49
  children: [
50
50
  /* @__PURE__ */ E("span", {
51
51
  className: "grid h-10 w-10 shrink-0 place-items-center rounded-lg bg-accent-wash text-text-link",
52
- children: /* @__PURE__ */ E(l, { className: "h-5 w-5" })
52
+ children: /* @__PURE__ */ E(u, { className: "h-5 w-5" })
53
53
  }),
54
54
  /* @__PURE__ */ D("div", {
55
55
  className: "min-w-0 flex-1",
@@ -68,7 +68,7 @@ function P({ asset: t, subscription: n }) {
68
68
  className: "rounded bg-bg-sunken px-1.5 py-0.5 text-text-secondary",
69
69
  children: i(t.type)
70
70
  }), t.expiresAt && /* @__PURE__ */ E("span", {
71
- className: e(d ? "text-status-warning-text" : "text-text-secondary"),
71
+ className: e(f ? "text-status-warning-text" : "text-text-secondary"),
72
72
  children: a("assetVault.expires", "Expires {{date}}", { date: r(t.expiresAt) })
73
73
  })]
74
74
  })
@@ -77,17 +77,17 @@ function P({ asset: t, subscription: n }) {
77
77
  t.file?.id && /* @__PURE__ */ E("button", {
78
78
  type: "button",
79
79
  onClick: async () => {
80
- if (!(!t.file?.id || s)) {
81
- c(!0);
80
+ if (!(!t.file?.id || c)) {
81
+ l(!0);
82
82
  try {
83
- let e = await o(t.file.id);
83
+ let e = await s(t.file.id);
84
84
  window.open(e, "_blank", "noopener,noreferrer");
85
85
  } finally {
86
- c(!1);
86
+ l(!1);
87
87
  }
88
88
  }
89
89
  },
90
- disabled: s,
90
+ disabled: c,
91
91
  "aria-label": a("assetVault.downloadAriaLabel", "Download {{name}}", { name: t.name }),
92
92
  className: "shrink-0 rounded-lg border border-border-subtle p-2 text-text-secondary hover:text-text-primary disabled:opacity-50",
93
93
  children: /* @__PURE__ */ E(_, { className: "h-4 w-4" })
@@ -96,11 +96,11 @@ function P({ asset: t, subscription: n }) {
96
96
  });
97
97
  }
98
98
  var F = () => {
99
- let u = l(), g = d({ pagination: { limit: 100 } }), _ = f(), [y, x] = m(""), [S, A] = m("ALL"), F = p(() => {
99
+ let d = u(), g = f({ pagination: { limit: 100 } }), _ = o(), [y, x] = m(""), [S, A] = m("ALL"), F = p(() => {
100
100
  let e = /* @__PURE__ */ new Map();
101
101
  for (let t of g.data?.items ?? []) e.set(t.id, t.label);
102
102
  return e;
103
- }, [g.data]), I = p(() => u.data ?? [], [u.data]), L = p(() => I.filter((e) => (S === "ALL" || e.type === S) && (!y || e.name.toLowerCase().includes(y.toLowerCase()))), [
103
+ }, [g.data]), I = p(() => d.data ?? [], [d.data]), L = p(() => I.filter((e) => (S === "ALL" || e.type === S) && (!y || e.name.toLowerCase().includes(y.toLowerCase()))), [
104
104
  I,
105
105
  S,
106
106
  y
@@ -109,9 +109,9 @@ var F = () => {
109
109
  for (let t of L) e.set(t.type, [...e.get(t.type) ?? [], t]);
110
110
  return j.filter((t) => e.has(t)).map((t) => [t, e.get(t)]);
111
111
  }, [L]), z = p(() => I.filter((e) => M(e.expiresAt)).sort((e, t) => N(e.expiresAt) - N(t.expiresAt)), [I]);
112
- return u.isLoading ? /* @__PURE__ */ E(s, { label: _("assetVault.loading", "Loading your asset vault…") }) : u.isError ? /* @__PURE__ */ E(o, {
112
+ return d.isLoading ? /* @__PURE__ */ E(c, { label: _("assetVault.loading", "Loading your asset vault…") }) : d.isError ? /* @__PURE__ */ E(s, {
113
113
  message: _("assetVault.error", "Could not load the asset vault."),
114
- onRetry: () => void u.refetch()
114
+ onRetry: () => void d.refetch()
115
115
  }) : /* @__PURE__ */ D(t, {
116
116
  title: _("assetVault.title", "Asset vault"),
117
117
  description: _("assetVault.description", "Every contract, receipt, license key and document attached to your subscriptions — in one secure place."),
@@ -172,7 +172,7 @@ var F = () => {
172
172
  icon: /* @__PURE__ */ E(T, { className: "h-8 w-8" }),
173
173
  title: I.length === 0 ? _("assetVault.empty.noDocumentsTitle", "No documents yet") : _("assetVault.empty.noMatchesTitle", "No matching documents"),
174
174
  description: I.length === 0 ? _("assetVault.empty.noDocumentsDescription", "Attach a contract, receipt or license key from any subscription’s detail page and it will appear here.") : _("assetVault.empty.noMatchesDescription", "Try a different search or type filter.")
175
- }) : R.map(([e, t]) => /* @__PURE__ */ E(c, {
175
+ }) : R.map(([e, t]) => /* @__PURE__ */ E(l, {
176
176
  title: `${i(e)} · ${t.length}`,
177
177
  children: /* @__PURE__ */ E("div", {
178
178
  className: "grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3",