@burdenoff/microfe-subscriberbot 2026.1029.1 → 2026.1030.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -1
  2. package/dist/subscriberbot/SubscriberBotRoutes.js +18 -10
  3. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  4. package/dist/subscriberbot/components/StatusBadge.d.ts.map +1 -1
  5. package/dist/subscriberbot/components/StatusBadge.js +6 -1
  6. package/dist/subscriberbot/components/StatusBadge.js.map +1 -1
  7. package/dist/subscriberbot/components/decisions/DecisionBanners.d.ts +11 -0
  8. package/dist/subscriberbot/components/decisions/DecisionBanners.d.ts.map +1 -0
  9. package/dist/subscriberbot/components/decisions/DecisionBanners.js +62 -0
  10. package/dist/subscriberbot/components/decisions/DecisionBanners.js.map +1 -0
  11. package/dist/subscriberbot/components/decisions/DecisionCard.d.ts +22 -0
  12. package/dist/subscriberbot/components/decisions/DecisionCard.d.ts.map +1 -0
  13. package/dist/subscriberbot/components/decisions/DecisionCard.js +316 -0
  14. package/dist/subscriberbot/components/decisions/DecisionCard.js.map +1 -0
  15. package/dist/subscriberbot/components/decisions/decisionModel.d.ts +51 -0
  16. package/dist/subscriberbot/components/decisions/decisionModel.d.ts.map +1 -0
  17. package/dist/subscriberbot/components/decisions/decisionModel.js +139 -0
  18. package/dist/subscriberbot/components/decisions/decisionModel.js.map +1 -0
  19. package/dist/subscriberbot/components/decisions/index.d.ts +9 -0
  20. package/dist/subscriberbot/components/decisions/index.d.ts.map +1 -0
  21. package/dist/subscriberbot/components/decisions/index.js +3 -0
  22. package/dist/subscriberbot/hooks/index.d.ts +3 -1
  23. package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
  24. package/dist/subscriberbot/hooks/index.js +1 -0
  25. package/dist/subscriberbot/hooks/useRouteSelection.d.ts +15 -0
  26. package/dist/subscriberbot/hooks/useRouteSelection.d.ts.map +1 -0
  27. package/dist/subscriberbot/hooks/useRouteSelection.js +18 -0
  28. package/dist/subscriberbot/hooks/useRouteSelection.js.map +1 -0
  29. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +16 -1
  30. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
  31. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +99 -26
  32. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  33. package/dist/subscriberbot/pages/InboxPage.d.ts.map +1 -1
  34. package/dist/subscriberbot/pages/InboxPage.js +211 -210
  35. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  36. package/dist/subscriberbot/pages/WorkflowsPage.d.ts.map +1 -1
  37. package/dist/subscriberbot/pages/WorkflowsPage.js +166 -165
  38. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  39. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts +7 -0
  40. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
  41. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +280 -175
  42. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  43. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.d.ts +12 -0
  44. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.d.ts.map +1 -0
  45. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.js +180 -0
  46. package/dist/subscriberbot/pages/decisions/DecisionDetailPage.js.map +1 -0
  47. package/dist/subscriberbot/pages/decisions/DecisionsPage.d.ts +13 -0
  48. package/dist/subscriberbot/pages/decisions/DecisionsPage.d.ts.map +1 -0
  49. package/dist/subscriberbot/pages/decisions/DecisionsPage.js +154 -0
  50. package/dist/subscriberbot/pages/decisions/DecisionsPage.js.map +1 -0
  51. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
  52. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +330 -314
  53. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  54. package/dist/subscriberbot/types/index.d.ts +66 -0
  55. package/dist/subscriberbot/types/index.d.ts.map +1 -1
  56. package/dist/subscriberbot/utils/pageContext.d.ts +44 -11
  57. package/dist/subscriberbot/utils/pageContext.d.ts.map +1 -1
  58. package/dist/subscriberbot/utils/pageContext.js +44 -37
  59. package/dist/subscriberbot/utils/pageContext.js.map +1 -1
  60. 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;AA8EhD,eAAO,MAAM,mBAAmB,EAAE,EAiEjC,CAAC"}
@@ -5,15 +5,15 @@ import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-
5
5
  import { jsx as c, jsxs as l } from "react/jsx-runtime";
6
6
  import { Spinner as u } from "@burdenoff/fe-libs/ui";
7
7
  //#region src/subscriberbot/SubscriberBotRoutes.tsx
8
- var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e) => ({ default: e.RelationshipsListPage }))), f = r(() => import("./pages/relationships/RelationshipNewPage.js").then((e) => ({ default: e.RelationshipNewPage }))), p = r(() => import("./pages/relationships/RelationshipDetailPage.js").then((e) => ({ default: e.RelationshipDetailPage }))), m = r(() => import("./pages/providers/ProvidersListPage.js").then((e) => ({ default: e.ProvidersListPage }))), h = r(() => import("./pages/providers/ProviderNewPage.js").then((e) => ({ default: e.ProviderNewPage }))), g = r(() => import("./pages/providers/ProviderDetailPage.js").then((e) => ({ default: e.ProviderDetailPage }))), _ = r(() => import("./pages/InboxPage.js").then((e) => ({ default: e.InboxPage }))), v = r(() => import("./pages/InvoicesPage.js").then((e) => ({ default: e.InvoicesPage }))), y = r(() => import("./pages/WorkflowsPage.js").then((e) => ({ default: e.WorkflowsPage }))), b = r(() => import("./pages/agents/AgentsListPage.js").then((e) => ({ default: e.AgentsListPage }))), x = r(() => import("./pages/agents/AgentNewPage.js").then((e) => ({ default: e.AgentNewPage }))), S = r(() => import("./pages/agents/AgentDetailPage.js").then((e) => ({ default: e.AgentDetailPage }))), C = r(() => import("./pages/InsightsPage.js").then((e) => ({ default: e.InsightsPage }))), w = r(() => import("./pages/AssetVaultPage.js").then((e) => ({ default: e.AssetVaultPage }))), T = () => /* @__PURE__ */ c("div", {
8
+ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e) => ({ default: e.RelationshipsListPage }))), f = r(() => import("./pages/relationships/RelationshipNewPage.js").then((e) => ({ default: e.RelationshipNewPage }))), p = r(() => import("./pages/relationships/RelationshipDetailPage.js").then((e) => ({ default: e.RelationshipDetailPage }))), m = r(() => import("./pages/providers/ProvidersListPage.js").then((e) => ({ default: e.ProvidersListPage }))), h = r(() => import("./pages/providers/ProviderNewPage.js").then((e) => ({ default: e.ProviderNewPage }))), g = r(() => import("./pages/providers/ProviderDetailPage.js").then((e) => ({ default: e.ProviderDetailPage }))), _ = r(() => import("./pages/InboxPage.js").then((e) => ({ default: e.InboxPage }))), v = r(() => import("./pages/InvoicesPage.js").then((e) => ({ default: e.InvoicesPage }))), y = r(() => import("./pages/WorkflowsPage.js").then((e) => ({ default: e.WorkflowsPage }))), b = r(() => import("./pages/agents/AgentsListPage.js").then((e) => ({ default: e.AgentsListPage }))), x = r(() => import("./pages/agents/AgentNewPage.js").then((e) => ({ default: e.AgentNewPage }))), S = r(() => import("./pages/agents/AgentDetailPage.js").then((e) => ({ default: e.AgentDetailPage }))), C = r(() => import("./pages/decisions/DecisionsPage.js").then((e) => ({ default: e.DecisionsPage }))), w = r(() => import("./pages/decisions/DecisionDetailPage.js").then((e) => ({ default: e.DecisionDetailPage }))), T = r(() => import("./pages/InsightsPage.js").then((e) => ({ default: e.InsightsPage }))), E = r(() => import("./pages/AssetVaultPage.js").then((e) => ({ default: e.AssetVaultPage }))), D = () => /* @__PURE__ */ c("div", {
9
9
  className: "flex min-h-[400px] items-center justify-center",
10
10
  children: /* @__PURE__ */ c(u, { size: "lg" })
11
- }), E = () => {
12
- let { basePath: r, isStandalone: u } = e(), E = s(), D = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
13
- return D && !u && !(E.pathname === D || E.pathname.startsWith(D + "/")) ? null : /* @__PURE__ */ c("div", {
11
+ }), O = () => {
12
+ let { basePath: r, isStandalone: u } = e(), O = s(), k = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
13
+ return k && !u && !(O.pathname === k || O.pathname.startsWith(k + "/")) ? null : /* @__PURE__ */ c("div", {
14
14
  className: "flex min-h-full flex-col",
15
15
  children: /* @__PURE__ */ c(n, {
16
- fallback: /* @__PURE__ */ c(T, {}),
16
+ fallback: /* @__PURE__ */ c(D, {}),
17
17
  children: /* @__PURE__ */ l(o, { children: [
18
18
  /* @__PURE__ */ c(a, {
19
19
  index: !0,
@@ -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, {
@@ -53,11 +53,11 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
53
53
  }),
54
54
  /* @__PURE__ */ c(a, {
55
55
  path: "insights",
56
- element: /* @__PURE__ */ c(C, {})
56
+ element: /* @__PURE__ */ c(T, {})
57
57
  }),
58
58
  /* @__PURE__ */ c(a, {
59
59
  path: "vault",
60
- element: /* @__PURE__ */ c(w, {})
60
+ element: /* @__PURE__ */ c(E, {})
61
61
  }),
62
62
  /* @__PURE__ */ c(a, {
63
63
  path: "agents",
@@ -72,7 +72,15 @@ 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: "decisions",
76
+ element: /* @__PURE__ */ c(C, {})
77
+ }),
78
+ /* @__PURE__ */ c(a, {
79
+ path: "decisions/:id",
80
+ element: /* @__PURE__ */ c(w, {})
81
+ }),
82
+ /* @__PURE__ */ c(a, {
83
+ path: "workflows/:selectedId?",
76
84
  element: /* @__PURE__ */ c(y, {})
77
85
  }),
78
86
  /* @__PURE__ */ c(a, {
@@ -87,6 +95,6 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
87
95
  });
88
96
  };
89
97
  //#endregion
90
- export { E as SubscriberBotRoutes };
98
+ export { O as SubscriberBotRoutes };
91
99
 
92
100
  //# sourceMappingURL=SubscriberBotRoutes.js.map
@@ -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// AI decision queue (BOFF-3663)\nconst DecisionsPage = lazy(() =>\n import('./pages/decisions/DecisionsPage').then((m) => ({ default: m.DecisionsPage }))\n);\nconst DecisionDetailPage = lazy(() =>\n import('./pages/decisions/DecisionDetailPage').then((m) => ({ default: m.DecisionDetailPage }))\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 {/* AI decision queue */}\n <Route path=\"decisions\" element={<DecisionsPage />} />\n <Route path=\"decisions/:id\" element={<DecisionDetailPage />} />\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 +1 @@
1
- {"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA6DD,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAsB5C,CAAC"}
1
+ {"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/components/StatusBadge.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAIhC,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoED,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAsB5C,CAAC"}
@@ -42,7 +42,12 @@ var i = {
42
42
  APPROVED: "success",
43
43
  REJECTED: "destructive",
44
44
  DISMISSED: "outline",
45
- RESOLVED: "success"
45
+ RESOLVED: "success",
46
+ PROPOSED: "info",
47
+ APPLYING: "warning",
48
+ APPLIED: "success",
49
+ STALE: "secondary",
50
+ FLAGGED: "warning"
46
51
  }, s = ({ status: s, className: c }) => {
47
52
  let l = s.toUpperCase(), u = o[l] ?? "secondary", d = a.has(l);
48
53
  return /* @__PURE__ */ r("span", {
@@ -1 +1 @@
1
- {"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/subscriberbot/components/StatusBadge.tsx"],"sourcesContent":["/**\n * Status Badge Component\n * @module subscriberbot/components\n *\n * A colored badge for Subscriber Bot domain statuses (relationship lifecycle,\n * invoice status, agent posture, channel verification, provider status,\n * workflow state) with semantic color mapping. Accepts the raw server enum\n * value (e.g. \"ACTIVE\", \"PAST_DUE\", \"SUGGEST_ONLY\").\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatEnumLabel } from '../utils/formatters';\n\ninterface StatusBadgeProps {\n status: string;\n className?: string;\n}\n\ntype BadgeVariant = 'success' | 'warning' | 'destructive' | 'secondary' | 'info' | 'outline';\n\nconst variantStyles: Record<BadgeVariant, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n destructive: 'bg-status-error-bg-subtle text-status-error-text',\n secondary: 'bg-bg-sunken text-text-secondary',\n info: 'bg-[var(--color-accent-soft)] text-text-primary',\n outline: 'border border-border-seam text-text-primary',\n};\n\n// Statuses that represent a \"live\" / in-progress condition get a subtle,\n// opacity-only glow pulse (reduced-motion safe via motion-safe:).\nconst liveStatuses = new Set(['ACTIVE', 'AUTONOMOUS', 'TRIAL', 'EXPIRING']);\n\nconst statusVariantMap: Record<string, BadgeVariant> = {\n // Relationship lifecycle\n ACTIVE: 'success',\n TRIAL: 'info',\n PAUSED: 'warning',\n PAST_DUE: 'destructive',\n LAPSED: 'warning',\n EXPIRED: 'secondary',\n CANCELLED: 'destructive',\n\n // Invoice status\n DRAFT: 'secondary',\n ISSUED: 'info',\n PAID: 'success',\n OVERDUE: 'destructive',\n FAILED: 'destructive',\n REFUNDED: 'outline',\n\n // Agent posture\n AUTONOMOUS: 'success',\n SUGGEST_ONLY: 'info',\n DISABLED: 'secondary',\n\n // Channel verification / payment instrument\n VERIFIED: 'success',\n PENDING: 'warning',\n EXPIRING: 'warning',\n REMOVED: 'outline',\n\n // Provider status\n CLAIMED: 'success',\n UNVERIFIED: 'secondary',\n DEPRECATED: 'outline',\n\n // Workflow status\n ARCHIVED: 'outline',\n\n // Adapter submission / marketplace report moderation status\n APPROVED: 'success',\n REJECTED: 'destructive',\n DISMISSED: 'outline',\n RESOLVED: 'success',\n};\n\nexport const StatusBadge: FC<StatusBadgeProps> = ({ status, className }) => {\n const key = status.toUpperCase();\n const variant = statusVariantMap[key] ?? 'secondary';\n const isLive = liveStatuses.has(key);\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium',\n variantStyles[variant],\n className\n )}\n >\n {isLive && (\n <span\n aria-hidden=\"true\"\n className=\"size-1.5 rounded-full bg-current motion-safe:animate-vc-glow-pulse\"\n />\n )}\n {formatEnumLabel(status)}\n </span>\n );\n};\n"],"mappings":";;;;AAqBA,IAAM,IAA8C;CAClD,SAAS;CACT,SAAS;CACT,aAAa;CACb,WAAW;CACX,MAAM;CACN,SAAS;AACX,GAIM,IAAe,IAAI,IAAI;CAAC;CAAU;CAAc;CAAS;AAAU,CAAC,GAEpE,IAAiD;CAErD,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,SAAS;CACT,WAAW;CAGX,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,QAAQ;CACR,UAAU;CAGV,YAAY;CACZ,cAAc;CACd,UAAU;CAGV,UAAU;CACV,SAAS;CACT,UAAU;CACV,SAAS;CAGT,SAAS;CACT,YAAY;CACZ,YAAY;CAGZ,UAAU;CAGV,UAAU;CACV,UAAU;CACV,WAAW;CACX,UAAU;AACZ,GAEa,KAAqC,EAAE,WAAQ,mBAAgB;CAC1E,IAAM,IAAM,EAAO,YAAY,GACzB,IAAU,EAAiB,MAAQ,aACnC,IAAS,EAAa,IAAI,CAAG;CAEnC,OACE,kBAAC,QAAD;EACE,WAAW,EACT,mFACA,EAAc,IACd,CACF;YALF,CAOG,KACC,kBAAC,QAAD;GACE,eAAY;GACZ,WAAU;EACX,CAAA,GAEF,EAAgB,CAAM,CACnB;;AAEV"}
1
+ {"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/subscriberbot/components/StatusBadge.tsx"],"sourcesContent":["/**\n * Status Badge Component\n * @module subscriberbot/components\n *\n * A colored badge for Subscriber Bot domain statuses (relationship lifecycle,\n * invoice status, agent posture, channel verification, provider status,\n * workflow state) with semantic color mapping. Accepts the raw server enum\n * value (e.g. \"ACTIVE\", \"PAST_DUE\", \"SUGGEST_ONLY\").\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatEnumLabel } from '../utils/formatters';\n\ninterface StatusBadgeProps {\n status: string;\n className?: string;\n}\n\ntype BadgeVariant = 'success' | 'warning' | 'destructive' | 'secondary' | 'info' | 'outline';\n\nconst variantStyles: Record<BadgeVariant, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n destructive: 'bg-status-error-bg-subtle text-status-error-text',\n secondary: 'bg-bg-sunken text-text-secondary',\n info: 'bg-[var(--color-accent-soft)] text-text-primary',\n outline: 'border border-border-seam text-text-primary',\n};\n\n// Statuses that represent a \"live\" / in-progress condition get a subtle,\n// opacity-only glow pulse (reduced-motion safe via motion-safe:).\nconst liveStatuses = new Set(['ACTIVE', 'AUTONOMOUS', 'TRIAL', 'EXPIRING']);\n\nconst statusVariantMap: Record<string, BadgeVariant> = {\n // Relationship lifecycle\n ACTIVE: 'success',\n TRIAL: 'info',\n PAUSED: 'warning',\n PAST_DUE: 'destructive',\n LAPSED: 'warning',\n EXPIRED: 'secondary',\n CANCELLED: 'destructive',\n\n // Invoice status\n DRAFT: 'secondary',\n ISSUED: 'info',\n PAID: 'success',\n OVERDUE: 'destructive',\n FAILED: 'destructive',\n REFUNDED: 'outline',\n\n // Agent posture\n AUTONOMOUS: 'success',\n SUGGEST_ONLY: 'info',\n DISABLED: 'secondary',\n\n // Channel verification / payment instrument\n VERIFIED: 'success',\n PENDING: 'warning',\n EXPIRING: 'warning',\n REMOVED: 'outline',\n\n // Provider status\n CLAIMED: 'success',\n UNVERIFIED: 'secondary',\n DEPRECATED: 'outline',\n\n // Workflow status\n ARCHIVED: 'outline',\n\n // Adapter submission / marketplace report moderation status\n APPROVED: 'success',\n REJECTED: 'destructive',\n DISMISSED: 'outline',\n RESOLVED: 'success',\n\n // AI decision status (DISMISSED shared with moderation above)\n PROPOSED: 'info',\n APPLYING: 'warning',\n APPLIED: 'success',\n STALE: 'secondary',\n FLAGGED: 'warning',\n};\n\nexport const StatusBadge: FC<StatusBadgeProps> = ({ status, className }) => {\n const key = status.toUpperCase();\n const variant = statusVariantMap[key] ?? 'secondary';\n const isLive = liveStatuses.has(key);\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium',\n variantStyles[variant],\n className\n )}\n >\n {isLive && (\n <span\n aria-hidden=\"true\"\n className=\"size-1.5 rounded-full bg-current motion-safe:animate-vc-glow-pulse\"\n />\n )}\n {formatEnumLabel(status)}\n </span>\n );\n};\n"],"mappings":";;;;AAqBA,IAAM,IAA8C;CAClD,SAAS;CACT,SAAS;CACT,aAAa;CACb,WAAW;CACX,MAAM;CACN,SAAS;AACX,GAIM,IAAe,IAAI,IAAI;CAAC;CAAU;CAAc;CAAS;AAAU,CAAC,GAEpE,IAAiD;CAErD,QAAQ;CACR,OAAO;CACP,QAAQ;CACR,UAAU;CACV,QAAQ;CACR,SAAS;CACT,WAAW;CAGX,OAAO;CACP,QAAQ;CACR,MAAM;CACN,SAAS;CACT,QAAQ;CACR,UAAU;CAGV,YAAY;CACZ,cAAc;CACd,UAAU;CAGV,UAAU;CACV,SAAS;CACT,UAAU;CACV,SAAS;CAGT,SAAS;CACT,YAAY;CACZ,YAAY;CAGZ,UAAU;CAGV,UAAU;CACV,UAAU;CACV,WAAW;CACX,UAAU;CAGV,UAAU;CACV,UAAU;CACV,SAAS;CACT,OAAO;CACP,SAAS;AACX,GAEa,KAAqC,EAAE,WAAQ,mBAAgB;CAC1E,IAAM,IAAM,EAAO,YAAY,GACzB,IAAU,EAAiB,MAAQ,aACnC,IAAS,EAAa,IAAI,CAAG;CAEnC,OACE,kBAAC,QAAD;EACE,WAAW,EACT,mFACA,EAAc,IACd,CACF;YALF,CAOG,KACC,kBAAC,QAAD;GACE,eAAY;GACZ,WAAU;EACX,CAAA,GAEF,EAAgB,CAAM,CACnB;;AAEV"}
@@ -0,0 +1,11 @@
1
+ import { FC } from 'react';
2
+
3
+ export declare const AiDisclaimer: FC<{
4
+ className?: string;
5
+ }>;
6
+ export declare const DecisionsUnavailableBanner: FC<{
7
+ message?: string;
8
+ onRetry?: () => void;
9
+ className?: string;
10
+ }>;
11
+ //# sourceMappingURL=DecisionBanners.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionBanners.d.ts","sourceRoot":"","sources":["../../../../src/subscriberbot/components/decisions/DecisionBanners.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAMhC,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAuBnD,CAAC;AAEF,eAAO,MAAM,0BAA0B,EAAE,EAAE,CAAC;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CA+CA,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { useTr as n } from "../../hooks/useTr.js";
4
+ import { AlertTriangle as r, Info as i } from "lucide-react";
5
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
+ //#region src/subscriberbot/components/decisions/DecisionBanners.tsx
7
+ var s = ({ className: e }) => {
8
+ let r = n();
9
+ return /* @__PURE__ */ o("div", {
10
+ role: "note",
11
+ "data-testid": "ai-disclaimer",
12
+ className: t("flex items-start gap-2.5 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-2.5 text-xs text-text-secondary", e),
13
+ children: [/* @__PURE__ */ a(i, {
14
+ className: "mt-0.5 h-4 w-4 shrink-0 text-text-secondary",
15
+ "aria-hidden": !0
16
+ }), /* @__PURE__ */ o("p", { children: [
17
+ /* @__PURE__ */ a("span", {
18
+ className: "font-medium text-text-primary",
19
+ children: r("decisions.disclaimer.title", "AI-generated recommendations.")
20
+ }),
21
+ " ",
22
+ r("decisions.disclaimer.body", "They are produced automatically from your subscription data and may be wrong. Check the linked source records before you apply one. Nothing changes until you apply it.")
23
+ ] })]
24
+ });
25
+ }, c = ({ message: i, onRetry: s, className: c }) => {
26
+ let l = n(), { navigateTo: u } = e();
27
+ return /* @__PURE__ */ o("div", {
28
+ role: "status",
29
+ "data-testid": "decisions-unavailable",
30
+ className: t("flex flex-col gap-3 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text sm:flex-row sm:items-center sm:justify-between", c),
31
+ children: [/* @__PURE__ */ o("div", {
32
+ className: "flex items-start gap-2.5",
33
+ children: [/* @__PURE__ */ a(r, {
34
+ className: "mt-0.5 h-4 w-4 shrink-0",
35
+ "aria-hidden": !0
36
+ }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("p", {
37
+ className: "font-medium",
38
+ children: l("decisions.unavailable.title", "AI recommendations are unavailable right now.")
39
+ }), /* @__PURE__ */ o("p", {
40
+ className: "mt-0.5 text-xs",
41
+ children: [l("decisions.unavailable.body", "Agents and policies still work, and every change can be made by hand from the relationship page."), i ? ` (${i})` : ""]
42
+ })] })]
43
+ }), /* @__PURE__ */ o("div", {
44
+ className: "flex shrink-0 gap-2",
45
+ children: [s && /* @__PURE__ */ a("button", {
46
+ type: "button",
47
+ onClick: s,
48
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
49
+ children: l("decisions.unavailable.retry", "Retry")
50
+ }), /* @__PURE__ */ a("button", {
51
+ type: "button",
52
+ onClick: () => u("/relationships"),
53
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
54
+ children: l("decisions.unavailable.manual", "Manage relationships")
55
+ })]
56
+ })]
57
+ });
58
+ };
59
+ //#endregion
60
+ export { s as AiDisclaimer, c as DecisionsUnavailableBanner };
61
+
62
+ //# sourceMappingURL=DecisionBanners.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionBanners.js","names":[],"sources":["../../../../src/subscriberbot/components/decisions/DecisionBanners.tsx"],"sourcesContent":["/**\n * Decision surface banners\n * @module subscriberbot/components/decisions\n *\n * - {@link AiDisclaimer}: the persistent, non-dismissable notice that every\n * recommendation is machine-generated and may be wrong. It has no close\n * control on purpose and must render on every surface that shows decisions.\n * - {@link DecisionsUnavailableBanner}: shown in place of the decision feed\n * when the decision engine cannot be reached, so the rest of the page (agent\n * and policy management, relationships) keeps working.\n */\n\nimport type { FC } from 'react';\nimport { AlertTriangle, Info } from 'lucide-react';\nimport { useTr } from '../../hooks/useTr';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { cn } from '../../utils/cn';\n\nexport const AiDisclaimer: FC<{ className?: string }> = ({ className }) => {\n const tr = useTr();\n return (\n <div\n role=\"note\"\n data-testid=\"ai-disclaimer\"\n className={cn(\n 'flex items-start gap-2.5 rounded-lg border border-border-subtle bg-bg-sunken px-4 py-2.5 text-xs text-text-secondary',\n className\n )}\n >\n <Info className=\"mt-0.5 h-4 w-4 shrink-0 text-text-secondary\" aria-hidden />\n <p>\n <span className=\"font-medium text-text-primary\">\n {tr('decisions.disclaimer.title', 'AI-generated recommendations.')}\n </span>{' '}\n {tr(\n 'decisions.disclaimer.body',\n 'They are produced automatically from your subscription data and may be wrong. Check the linked source records before you apply one. Nothing changes until you apply it.'\n )}\n </p>\n </div>\n );\n};\n\nexport const DecisionsUnavailableBanner: FC<{\n message?: string;\n onRetry?: () => void;\n className?: string;\n}> = ({ message, onRetry, className }) => {\n const tr = useTr();\n const { navigateTo } = useSubscriberBot();\n return (\n <div\n role=\"status\"\n data-testid=\"decisions-unavailable\"\n className={cn(\n 'flex flex-col gap-3 rounded-lg border border-status-warning-text/30 bg-status-warning-bg-subtle px-4 py-3 text-sm text-status-warning-text sm:flex-row sm:items-center sm:justify-between',\n className\n )}\n >\n <div className=\"flex items-start gap-2.5\">\n <AlertTriangle className=\"mt-0.5 h-4 w-4 shrink-0\" aria-hidden />\n <div>\n <p className=\"font-medium\">\n {tr('decisions.unavailable.title', 'AI recommendations are unavailable right now.')}\n </p>\n <p className=\"mt-0.5 text-xs\">\n {tr(\n 'decisions.unavailable.body',\n 'Agents and policies still work, and every change can be made by hand from the relationship page.'\n )}\n {message ? ` (${message})` : ''}\n </p>\n </div>\n </div>\n <div className=\"flex shrink-0 gap-2\">\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken\"\n >\n {tr('decisions.unavailable.retry', 'Retry')}\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => navigateTo('/relationships')}\n className=\"rounded-lg border border-border-subtle bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken\"\n >\n {tr('decisions.unavailable.manual', 'Manage relationships')}\n </button>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;AAkBA,IAAa,KAA4C,EAAE,mBAAgB;CACzE,IAAM,IAAK,EAAM;CACjB,OACE,kBAAC,OAAD;EACE,MAAK;EACL,eAAY;EACZ,WAAW,EACT,wHACA,CACF;YANF,CAQE,kBAAC,GAAD;GAAM,WAAU;GAA8C,eAAA;EAAa,CAAA,GAC3E,kBAAC,KAAD,EAAA,UAAA;GACE,kBAAC,QAAD;IAAM,WAAU;cACb,EAAG,8BAA8B,+BAA+B;GAC7D,CAAA;GAAE;GACP,EACC,6BACA,yKACF;EACC,EAAA,CAAA,CACA;;AAET,GAEa,KAIP,EAAE,YAAS,YAAS,mBAAgB;CACxC,IAAM,IAAK,EAAM,GACX,EAAE,kBAAe,EAAiB;CACxC,OACE,kBAAC,OAAD;EACE,MAAK;EACL,eAAY;EACZ,WAAW,EACT,6LACA,CACF;YANF,CAQE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAe,WAAU;IAA0B,eAAA;GAAa,CAAA,GAChE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;IAAG,WAAU;cACV,EAAG,+BAA+B,+CAA+C;GACjF,CAAA,GACH,kBAAC,KAAD;IAAG,WAAU;cAAb,CACG,EACC,8BACA,kGACF,GACC,IAAU,KAAK,EAAQ,KAAK,EAC5B;KACA,EAAA,CAAA,CACF;MACL,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KACC,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAET,EAAG,+BAA+B,OAAO;GACpC,CAAA,GAEV,kBAAC,UAAD;IACE,MAAK;IACL,eAAe,EAAW,gBAAgB;IAC1C,WAAU;cAET,EAAG,gCAAgC,sBAAsB;GACpD,CAAA,CACL;IACF;;AAET"}
@@ -0,0 +1,22 @@
1
+ import { FC } from 'react';
2
+ import { SubDecision } from '../../types';
3
+
4
+ export declare const ApplyDecisionDialog: FC<{
5
+ decision: SubDecision;
6
+ onClose: () => void;
7
+ onApplied?: (decision: SubDecision) => void;
8
+ }>;
9
+ export declare const DismissDecisionDialog: FC<{
10
+ decision: SubDecision;
11
+ onClose: () => void;
12
+ }>;
13
+ export declare const DecisionSources: FC<{
14
+ decision: SubDecision;
15
+ limit?: number;
16
+ }>;
17
+ export declare const DecisionCard: FC<{
18
+ decision: SubDecision;
19
+ /** Hide the agent name (e.g. on the agent's own page). */
20
+ hideAgent?: boolean;
21
+ }>;
22
+ //# sourceMappingURL=DecisionCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecisionCard.d.ts","sourceRoot":"","sources":["../../../../src/subscriberbot/components/decisions/DecisionCard.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAY,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAU1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AA6B/C,eAAO,MAAM,mBAAmB,EAAE,EAAE,CAAC;IACnC,QAAQ,EAAE,WAAW,CAAC;IACtB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC7C,CA0GA,CAAC;AAMF,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CA4EpF,CAAC;AAMF,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC;IAAE,QAAQ,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CA4CzE,CAAC;AAMF,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC;IAC5B,QAAQ,EAAE,WAAW,CAAC;IACtB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAoHA,CAAC"}
@@ -0,0 +1,316 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { formatCurrency as n, formatEnumLabel as r, formatRelativeTime as i } from "../../utils/formatters.js";
4
+ import { StatusBadge as a } from "../StatusBadge.js";
5
+ import { Modal as o } from "../Modal.js";
6
+ import { useTr as s } from "../../hooks/useTr.js";
7
+ import { useApplyDecision as c, useDismissDecision as l } from "../../hooks/useSubscriberBotApi.js";
8
+ import { DECISION_KIND_LABEL as u, RECOMMENDATION_LABEL as d, confidencePercent as f, evidenceSources as p, isActionable as m, isDestructive as h, relationshipSnapshot as g } from "./decisionModel.js";
9
+ import { useState as _ } from "react";
10
+ import { CheckCircle2 as v, ExternalLink as y, Gauge as b, PiggyBank as x, ShieldAlert as S, XCircle as C } from "lucide-react";
11
+ import { jsx as w, jsxs as T } from "react/jsx-runtime";
12
+ import { GlassCard as E } from "@burdenoff/fe-libs/ui";
13
+ //#region src/subscriberbot/components/decisions/DecisionCard.tsx
14
+ function D(e, t) {
15
+ return e instanceof Error && e.message ? e.message : t;
16
+ }
17
+ function O(e) {
18
+ let t = g(e), i = t.amount === null ? null : `${n(t.amount, t.currency ?? e.currency)}${t.interval ? ` / ${r(t.interval).toLowerCase()}` : ""}`;
19
+ return {
20
+ label: t.label ?? e.relationshipId,
21
+ amount: i
22
+ };
23
+ }
24
+ var k = ({ decision: e, onClose: n, onApplied: r }) => {
25
+ let i = s(), a = c(), [l, u] = _(!1), [f, p] = _(null), m = h(e.recommendation), g = O(e), v = d[e.recommendation], y = !a.isPending && (!m || l);
26
+ return /* @__PURE__ */ w(o, {
27
+ title: i("decisions.apply.title", "Apply: {{action}}", { action: i(v.key, v.fallback) }),
28
+ description: i("decisions.apply.description", "This runs the same change you could make by hand on the relationship page."),
29
+ onClose: n,
30
+ children: /* @__PURE__ */ T("div", {
31
+ className: "space-y-4",
32
+ "data-testid": "apply-decision-dialog",
33
+ children: [
34
+ /* @__PURE__ */ T("div", {
35
+ className: "rounded-lg border border-border-subtle bg-bg-sunken px-4 py-3",
36
+ children: [
37
+ /* @__PURE__ */ w("p", {
38
+ className: "text-xs text-text-secondary",
39
+ children: i("decisions.apply.relationship", "Subscription")
40
+ }),
41
+ /* @__PURE__ */ w("p", {
42
+ className: "text-sm font-semibold text-text-primary",
43
+ "data-testid": "confirm-label",
44
+ children: g.label
45
+ }),
46
+ g.amount && /* @__PURE__ */ w("p", {
47
+ className: "text-sm tabular-nums text-text-primary",
48
+ "data-testid": "confirm-amount",
49
+ children: g.amount
50
+ })
51
+ ]
52
+ }),
53
+ /* @__PURE__ */ w("p", {
54
+ className: "text-sm text-text-secondary",
55
+ children: e.rationale
56
+ }),
57
+ m && /* @__PURE__ */ T("label", {
58
+ className: "flex items-start gap-2.5 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-3 text-sm text-status-error-text",
59
+ children: [/* @__PURE__ */ w("input", {
60
+ type: "checkbox",
61
+ checked: l,
62
+ onChange: (e) => u(e.target.checked),
63
+ className: "mt-0.5 size-4 shrink-0 rounded border-border-subtle",
64
+ "data-testid": "confirm-destructive"
65
+ }), /* @__PURE__ */ w("span", { children: i("decisions.apply.acknowledgeCancel", "I want to cancel \"{{label}}\"{{amount}}. I understand the subscription will stop.", {
66
+ label: g.label,
67
+ amount: g.amount ? ` (${g.amount})` : ""
68
+ }) })]
69
+ }),
70
+ f && /* @__PURE__ */ w("div", {
71
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
72
+ children: f
73
+ }),
74
+ /* @__PURE__ */ T("div", {
75
+ className: "flex justify-end gap-3",
76
+ children: [/* @__PURE__ */ w("button", {
77
+ type: "button",
78
+ onClick: n,
79
+ className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
80
+ children: i("decisions.apply.back", "Not now")
81
+ }), /* @__PURE__ */ w("button", {
82
+ type: "button",
83
+ onClick: () => {
84
+ y && (p(null), a.mutate(e.id, {
85
+ onSuccess: (e) => {
86
+ r?.(e.decision), n();
87
+ },
88
+ onError: (e) => p(D(e, i("decisions.apply.error", "Could not apply this decision.")))
89
+ }));
90
+ },
91
+ disabled: !y,
92
+ "data-testid": "confirm-apply",
93
+ className: t("rounded-lg px-4 py-2 text-sm font-medium hover:opacity-90 disabled:cursor-not-allowed disabled:opacity-50", m ? "bg-action-danger-bg text-action-danger-text hover:bg-action-danger-bg-hover" : "bg-action-primary-bg text-action-primary-text"),
94
+ children: a.isPending ? i("decisions.apply.applying", "Applying…") : i("decisions.apply.submit", "Apply")
95
+ })]
96
+ })
97
+ ]
98
+ })
99
+ });
100
+ }, A = ({ decision: e, onClose: t }) => {
101
+ let n = s(), r = l(), [i, a] = _(""), [c, u] = _(null), d = O(e);
102
+ return /* @__PURE__ */ w(o, {
103
+ title: n("decisions.dismiss.title", "Dismiss recommendation"),
104
+ description: d.label,
105
+ onClose: t,
106
+ children: /* @__PURE__ */ T("form", {
107
+ onSubmit: (a) => {
108
+ a.preventDefault(), u(null), r.mutate({
109
+ id: e.id,
110
+ reason: i
111
+ }, {
112
+ onSuccess: () => t(),
113
+ onError: (e) => u(D(e, n("decisions.dismiss.error", "Could not dismiss this decision.")))
114
+ });
115
+ },
116
+ className: "space-y-4",
117
+ "data-testid": "dismiss-decision-dialog",
118
+ children: [
119
+ /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("label", {
120
+ htmlFor: `dismiss-reason-${e.id}`,
121
+ className: "mb-1 block text-xs font-medium text-text-secondary",
122
+ children: n("decisions.dismiss.reason", "Reason (optional)")
123
+ }), /* @__PURE__ */ w("textarea", {
124
+ id: `dismiss-reason-${e.id}`,
125
+ value: i,
126
+ onChange: (e) => a(e.target.value),
127
+ rows: 3,
128
+ maxLength: 500,
129
+ placeholder: n("decisions.dismiss.placeholder", "e.g. We still use this every week"),
130
+ className: "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
131
+ })] }),
132
+ c && /* @__PURE__ */ w("div", {
133
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
134
+ children: c
135
+ }),
136
+ /* @__PURE__ */ T("div", {
137
+ className: "flex justify-end gap-3",
138
+ children: [/* @__PURE__ */ w("button", {
139
+ type: "button",
140
+ onClick: t,
141
+ className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
142
+ children: n("decisions.dismiss.back", "Back")
143
+ }), /* @__PURE__ */ w("button", {
144
+ type: "submit",
145
+ disabled: r.isPending,
146
+ "data-testid": "confirm-dismiss",
147
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
148
+ children: r.isPending ? n("decisions.dismiss.dismissing", "Dismissing…") : n("decisions.dismiss.submit", "Dismiss")
149
+ })]
150
+ })
151
+ ]
152
+ })
153
+ });
154
+ }, j = ({ decision: t, limit: n }) => {
155
+ let r = s(), { navigateTo: i } = e(), a = p(t), o = n ? a.slice(0, n) : a, c = {
156
+ relationship: r("decisions.sources.relationship", "Subscription"),
157
+ plan: r("decisions.sources.plan", "Current plan"),
158
+ alternativePlan: r("decisions.sources.alternativePlan", "Suggested plan"),
159
+ renewalEvent: r("decisions.sources.renewalEvent", "Renewal event"),
160
+ entitlement: r("decisions.sources.entitlement", "Entitlement usage")
161
+ };
162
+ return /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ w("p", {
163
+ className: "text-[10px] font-medium uppercase tracking-wide text-text-secondary",
164
+ children: r("decisions.sources.title", "Based on")
165
+ }), /* @__PURE__ */ T("ul", {
166
+ className: "mt-1.5 flex flex-wrap gap-1.5",
167
+ "data-testid": "decision-sources",
168
+ children: [o.map((e) => /* @__PURE__ */ w("li", { children: /* @__PURE__ */ T("button", {
169
+ type: "button",
170
+ onClick: () => i(e.path),
171
+ "data-source-kind": e.kind,
172
+ className: "inline-flex max-w-full items-center gap-1.5 rounded-md border border-border-subtle bg-bg-sunken px-2 py-0.5 text-left text-[11px] text-text-secondary hover:text-text-primary",
173
+ children: [
174
+ /* @__PURE__ */ w("span", {
175
+ className: "font-medium text-text-primary",
176
+ children: c[e.kind]
177
+ }),
178
+ /* @__PURE__ */ w("span", {
179
+ className: "truncate",
180
+ children: e.title
181
+ }),
182
+ e.detail && /* @__PURE__ */ w("span", {
183
+ className: "tabular-nums",
184
+ children: e.detail
185
+ }),
186
+ /* @__PURE__ */ w(y, {
187
+ className: "h-3 w-3 shrink-0",
188
+ "aria-hidden": !0
189
+ })
190
+ ]
191
+ }) }, `${e.kind}-${e.id}`)), n && a.length > n && /* @__PURE__ */ w("li", {
192
+ className: "px-1 py-0.5 text-[11px] text-text-secondary",
193
+ children: r("decisions.sources.more", "+{{count}} more", { count: a.length - n })
194
+ })]
195
+ })] });
196
+ }, M = ({ decision: r, hideAgent: o = !1 }) => {
197
+ let c = s(), { navigateTo: l } = e(), [p, g] = _(null), y = u[r.kind], D = d[r.recommendation], M = h(r.recommendation), N = m(r), P = O(r);
198
+ return /* @__PURE__ */ T(E, {
199
+ treatment: "metric",
200
+ className: "flex flex-col gap-3 p-4",
201
+ "data-testid": "decision-card",
202
+ "data-decision-id": r.id,
203
+ "data-recommendation": r.recommendation,
204
+ "data-status": r.status,
205
+ children: [
206
+ /* @__PURE__ */ T("div", {
207
+ className: "flex flex-wrap items-start justify-between gap-2",
208
+ children: [/* @__PURE__ */ T("div", {
209
+ className: "min-w-0",
210
+ children: [
211
+ /* @__PURE__ */ T("p", {
212
+ className: "text-[11px] font-medium uppercase tracking-wide text-text-secondary",
213
+ children: [c(y.key, y.fallback), !o && r.agent ? ` · ${r.agent.name}` : ""]
214
+ }),
215
+ /* @__PURE__ */ T("button", {
216
+ type: "button",
217
+ onClick: () => l(`/decisions/${r.id}`),
218
+ className: "mt-0.5 flex items-center gap-1.5 text-left text-sm font-semibold text-text-primary hover:underline",
219
+ children: [
220
+ M && /* @__PURE__ */ w(S, {
221
+ className: "h-4 w-4 shrink-0 text-status-error-text",
222
+ "aria-hidden": !0
223
+ }),
224
+ c(D.key, D.fallback),
225
+ ": ",
226
+ P.label
227
+ ]
228
+ }),
229
+ P.amount && /* @__PURE__ */ w("p", {
230
+ className: "text-xs tabular-nums text-text-secondary",
231
+ children: P.amount
232
+ })
233
+ ]
234
+ }), /* @__PURE__ */ w(a, { status: r.status })]
235
+ }),
236
+ /* @__PURE__ */ w("p", {
237
+ className: "text-sm text-text-secondary",
238
+ children: r.rationale
239
+ }),
240
+ /* @__PURE__ */ T("div", {
241
+ className: "flex flex-wrap gap-2 text-xs",
242
+ children: [
243
+ /* @__PURE__ */ T("span", {
244
+ className: "inline-flex items-center gap-1.5 rounded-md bg-bg-sunken px-2 py-0.5 text-text-secondary",
245
+ children: [/* @__PURE__ */ w(b, {
246
+ className: "h-3.5 w-3.5",
247
+ "aria-hidden": !0
248
+ }), c("decisions.card.confidence", "Confidence {{pct}}%", { pct: f(r.confidence) })]
249
+ }),
250
+ r.estimatedSavings > 0 && /* @__PURE__ */ T("span", {
251
+ className: "inline-flex items-center gap-1.5 rounded-md bg-status-success-bg-subtle px-2 py-0.5 font-medium text-status-success-text tabular-nums",
252
+ children: [/* @__PURE__ */ w(x, {
253
+ className: "h-3.5 w-3.5",
254
+ "aria-hidden": !0
255
+ }), c("decisions.card.savings", "Saves {{amount}} a year", { amount: n(r.estimatedSavings, r.currency) })]
256
+ }),
257
+ /* @__PURE__ */ w("span", {
258
+ className: "inline-flex items-center rounded-md bg-bg-sunken px-2 py-0.5 text-text-secondary",
259
+ children: i(r.createdAt)
260
+ })
261
+ ]
262
+ }),
263
+ /* @__PURE__ */ w(j, {
264
+ decision: r,
265
+ limit: 4
266
+ }),
267
+ r.status === "FLAGGED" && r.validationErrors.length > 0 && /* @__PURE__ */ T("p", {
268
+ className: "rounded-md bg-status-warning-bg-subtle px-3 py-2 text-xs text-status-warning-text",
269
+ children: [
270
+ c("decisions.card.flagged", "Held back: failed validation"),
271
+ " —",
272
+ " ",
273
+ r.validationErrors.join("; ")
274
+ ]
275
+ }),
276
+ r.status === "DISMISSED" && r.dismissedReason && /* @__PURE__ */ w("p", {
277
+ className: "text-xs text-text-secondary",
278
+ children: c("decisions.card.dismissedReason", "Dismissed: {{reason}}", { reason: r.dismissedReason })
279
+ }),
280
+ N && /* @__PURE__ */ T("div", {
281
+ className: "flex flex-wrap justify-end gap-2 border-t border-border-subtle pt-3",
282
+ children: [/* @__PURE__ */ T("button", {
283
+ type: "button",
284
+ onClick: () => g("dismiss"),
285
+ "data-testid": "dismiss-decision",
286
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
287
+ children: [/* @__PURE__ */ w(C, {
288
+ className: "h-3.5 w-3.5",
289
+ "aria-hidden": !0
290
+ }), c("decisions.card.dismiss", "Dismiss")]
291
+ }), /* @__PURE__ */ T("button", {
292
+ type: "button",
293
+ onClick: () => g("apply"),
294
+ "data-testid": "apply-decision",
295
+ className: t("inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium hover:opacity-90", M ? "border border-status-error-text/40 bg-status-error-bg-subtle text-status-error-text" : "bg-action-primary-bg text-action-primary-text"),
296
+ children: [/* @__PURE__ */ w(v, {
297
+ className: "h-3.5 w-3.5",
298
+ "aria-hidden": !0
299
+ }), c("decisions.card.apply", "Review and apply")]
300
+ })]
301
+ }),
302
+ p === "apply" && /* @__PURE__ */ w(k, {
303
+ decision: r,
304
+ onClose: () => g(null)
305
+ }),
306
+ p === "dismiss" && /* @__PURE__ */ w(A, {
307
+ decision: r,
308
+ onClose: () => g(null)
309
+ })
310
+ ]
311
+ });
312
+ };
313
+ //#endregion
314
+ export { k as ApplyDecisionDialog, M as DecisionCard, j as DecisionSources, A as DismissDecisionDialog };
315
+
316
+ //# sourceMappingURL=DecisionCard.js.map