@burdenoff/microfe-subscriberbot 2026.1030.7 → 2026.1102.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 (128) hide show
  1. package/README.md +26 -0
  2. package/dist/stories/pages/AgentDetailPage.stories.d.ts +16 -0
  3. package/dist/stories/pages/AgentDetailPage.stories.d.ts.map +1 -0
  4. package/dist/stories/pages/AgentNewPage.stories.d.ts +12 -0
  5. package/dist/stories/pages/AgentNewPage.stories.d.ts.map +1 -0
  6. package/dist/stories/pages/AgentsListPage.stories.d.ts +16 -0
  7. package/dist/stories/pages/AgentsListPage.stories.d.ts.map +1 -0
  8. package/dist/stories/pages/AssetVaultPage.stories.d.ts +14 -0
  9. package/dist/stories/pages/AssetVaultPage.stories.d.ts.map +1 -0
  10. package/dist/stories/pages/DashboardPage.stories.d.ts +12 -0
  11. package/dist/stories/pages/DashboardPage.stories.d.ts.map +1 -0
  12. package/dist/stories/pages/DecisionDetailPage.stories.d.ts +13 -0
  13. package/dist/stories/pages/DecisionDetailPage.stories.d.ts.map +1 -0
  14. package/dist/stories/pages/DecisionsPage.stories.d.ts +14 -0
  15. package/dist/stories/pages/DecisionsPage.stories.d.ts.map +1 -0
  16. package/dist/stories/pages/EnterpriseSpendPage.stories.d.ts +13 -0
  17. package/dist/stories/pages/EnterpriseSpendPage.stories.d.ts.map +1 -0
  18. package/dist/stories/pages/InboxPage.stories.d.ts +20 -0
  19. package/dist/stories/pages/InboxPage.stories.d.ts.map +1 -0
  20. package/dist/stories/pages/InsightsPage.stories.d.ts +12 -0
  21. package/dist/stories/pages/InsightsPage.stories.d.ts.map +1 -0
  22. package/dist/stories/pages/InvoicesPage.stories.d.ts +16 -0
  23. package/dist/stories/pages/InvoicesPage.stories.d.ts.map +1 -0
  24. package/dist/stories/pages/NegotiationDetailPage.stories.d.ts +11 -0
  25. package/dist/stories/pages/NegotiationDetailPage.stories.d.ts.map +1 -0
  26. package/dist/stories/pages/NegotiationNewPage.stories.d.ts +9 -0
  27. package/dist/stories/pages/NegotiationNewPage.stories.d.ts.map +1 -0
  28. package/dist/stories/pages/NegotiationsPage.stories.d.ts +11 -0
  29. package/dist/stories/pages/NegotiationsPage.stories.d.ts.map +1 -0
  30. package/dist/stories/pages/ProviderDetailPage.stories.d.ts +15 -0
  31. package/dist/stories/pages/ProviderDetailPage.stories.d.ts.map +1 -0
  32. package/dist/stories/pages/ProviderNewPage.stories.d.ts +12 -0
  33. package/dist/stories/pages/ProviderNewPage.stories.d.ts.map +1 -0
  34. package/dist/stories/pages/ProvidersListPage.stories.d.ts +17 -0
  35. package/dist/stories/pages/ProvidersListPage.stories.d.ts.map +1 -0
  36. package/dist/stories/pages/RelationshipDetailPage.stories.d.ts +15 -0
  37. package/dist/stories/pages/RelationshipDetailPage.stories.d.ts.map +1 -0
  38. package/dist/stories/pages/RelationshipNewPage.stories.d.ts +12 -0
  39. package/dist/stories/pages/RelationshipNewPage.stories.d.ts.map +1 -0
  40. package/dist/stories/pages/RelationshipsListPage.stories.d.ts +14 -0
  41. package/dist/stories/pages/RelationshipsListPage.stories.d.ts.map +1 -0
  42. package/dist/stories/pages/SavingsPage.stories.d.ts +13 -0
  43. package/dist/stories/pages/SavingsPage.stories.d.ts.map +1 -0
  44. package/dist/stories/pages/WorkflowsPage.stories.d.ts +16 -0
  45. package/dist/stories/pages/WorkflowsPage.stories.d.ts.map +1 -0
  46. package/dist/stories/support/PageHarness.d.ts +28 -0
  47. package/dist/stories/support/PageHarness.d.ts.map +1 -0
  48. package/dist/stories/support/fixtures.d.ts +28 -0
  49. package/dist/stories/support/fixtures.d.ts.map +1 -0
  50. package/dist/stories/support/graphqlMock.d.ts +34 -0
  51. package/dist/stories/support/graphqlMock.d.ts.map +1 -0
  52. package/dist/stories/support/handlers.d.ts +8 -0
  53. package/dist/stories/support/handlers.d.ts.map +1 -0
  54. package/dist/stories/support/negotiationFixtures.d.ts +14 -0
  55. package/dist/stories/support/negotiationFixtures.d.ts.map +1 -0
  56. package/dist/stories/support/play.d.ts +7 -0
  57. package/dist/stories/support/play.d.ts.map +1 -0
  58. package/dist/subscriberbot/SubscriberBotRoutes.d.ts.map +1 -1
  59. package/dist/subscriberbot/SubscriberBotRoutes.js +18 -6
  60. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  61. package/dist/subscriberbot/admin/AdminDashboardPage.d.ts.map +1 -1
  62. package/dist/subscriberbot/admin/AdminDashboardPage.js +61 -51
  63. package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
  64. package/dist/subscriberbot/admin/NegotiationDeskPanel.d.ts +4 -0
  65. package/dist/subscriberbot/admin/NegotiationDeskPanel.d.ts.map +1 -0
  66. package/dist/subscriberbot/admin/NegotiationDeskPanel.js +210 -0
  67. package/dist/subscriberbot/admin/NegotiationDeskPanel.js.map +1 -0
  68. package/dist/subscriberbot/components/Modal.d.ts.map +1 -1
  69. package/dist/subscriberbot/components/Modal.js +9 -6
  70. package/dist/subscriberbot/components/Modal.js.map +1 -1
  71. package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.d.ts +8 -0
  72. package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.d.ts.map +1 -0
  73. package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.js +18 -0
  74. package/dist/subscriberbot/components/negotiations/NegotiationStatusPill.js.map +1 -0
  75. package/dist/subscriberbot/components/negotiations/NegotiationTimeline.d.ts +8 -0
  76. package/dist/subscriberbot/components/negotiations/NegotiationTimeline.d.ts.map +1 -0
  77. package/dist/subscriberbot/components/negotiations/NegotiationTimeline.js +49 -0
  78. package/dist/subscriberbot/components/negotiations/NegotiationTimeline.js.map +1 -0
  79. package/dist/subscriberbot/components/negotiations/OutcomeForm.d.ts +13 -0
  80. package/dist/subscriberbot/components/negotiations/OutcomeForm.d.ts.map +1 -0
  81. package/dist/subscriberbot/components/negotiations/OutcomeForm.js +112 -0
  82. package/dist/subscriberbot/components/negotiations/OutcomeForm.js.map +1 -0
  83. package/dist/subscriberbot/components/negotiations/index.d.ts +5 -0
  84. package/dist/subscriberbot/components/negotiations/index.d.ts.map +1 -0
  85. package/dist/subscriberbot/components/negotiations/index.js +4 -0
  86. package/dist/subscriberbot/components/negotiations/labels.d.ts +16 -0
  87. package/dist/subscriberbot/components/negotiations/labels.d.ts.map +1 -0
  88. package/dist/subscriberbot/components/negotiations/labels.js +179 -0
  89. package/dist/subscriberbot/components/negotiations/labels.js.map +1 -0
  90. package/dist/subscriberbot/hooks/useNegotiationApi.d.ts +51 -0
  91. package/dist/subscriberbot/hooks/useNegotiationApi.d.ts.map +1 -0
  92. package/dist/subscriberbot/hooks/useNegotiationApi.js +106 -0
  93. package/dist/subscriberbot/hooks/useNegotiationApi.js.map +1 -0
  94. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts +1 -0
  95. package/dist/subscriberbot/hooks/useSubscriberBotApi.d.ts.map +1 -1
  96. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +1 -1
  97. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  98. package/dist/subscriberbot/pages/InvoicesPage.d.ts.map +1 -1
  99. package/dist/subscriberbot/pages/InvoicesPage.js +1 -0
  100. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  101. package/dist/subscriberbot/pages/enterprise/EnterpriseSpendPage.d.ts.map +1 -1
  102. package/dist/subscriberbot/pages/enterprise/EnterpriseSpendPage.js +1 -0
  103. package/dist/subscriberbot/pages/enterprise/EnterpriseSpendPage.js.map +1 -1
  104. package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.d.ts +11 -0
  105. package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.d.ts.map +1 -0
  106. package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.js +312 -0
  107. package/dist/subscriberbot/pages/negotiations/NegotiationDetailPage.js.map +1 -0
  108. package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.d.ts +11 -0
  109. package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.d.ts.map +1 -0
  110. package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.js +375 -0
  111. package/dist/subscriberbot/pages/negotiations/NegotiationNewPage.js.map +1 -0
  112. package/dist/subscriberbot/pages/negotiations/NegotiationsPage.d.ts +10 -0
  113. package/dist/subscriberbot/pages/negotiations/NegotiationsPage.d.ts.map +1 -0
  114. package/dist/subscriberbot/pages/negotiations/NegotiationsPage.js +155 -0
  115. package/dist/subscriberbot/pages/negotiations/NegotiationsPage.js.map +1 -0
  116. package/dist/subscriberbot/pages/providers/ProvidersListPage.d.ts.map +1 -1
  117. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +1 -0
  118. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  119. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
  120. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +321 -307
  121. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  122. package/dist/subscriberbot/types/negotiation.d.ts +101 -0
  123. package/dist/subscriberbot/types/negotiation.d.ts.map +1 -0
  124. package/dist/subscriberbot/utils/formatters.d.ts +1 -0
  125. package/dist/subscriberbot/utils/formatters.d.ts.map +1 -1
  126. package/dist/subscriberbot/utils/formatters.js +4 -3
  127. package/dist/subscriberbot/utils/formatters.js.map +1 -1
  128. package/package.json +2 -1
@@ -0,0 +1,14 @@
1
+ import { SubNegotiation, SubNegotiationSummary, SubNegotiationTerms } from '../../subscriberbot/types/negotiation';
2
+ import { GraphqlMockHandlers } from './graphqlMock';
3
+
4
+ export declare const negotiationTerms: SubNegotiationTerms;
5
+ export declare const draftSelfServe: SubNegotiation;
6
+ export declare const draftManaged: SubNegotiation;
7
+ export declare const submittedSelfServe: SubNegotiation;
8
+ export declare const succeededManaged: SubNegotiation;
9
+ export declare const negotiations: SubNegotiation[];
10
+ export declare const negotiationSummary: SubNegotiationSummary;
11
+ /** Populated SubscriberBot handlers plus every negotiation operation. */
12
+ export declare function negotiationHandlers(): GraphqlMockHandlers;
13
+ export declare function emptyNegotiationHandlers(): GraphqlMockHandlers;
14
+ //# sourceMappingURL=negotiationFixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"negotiationFixtures.d.ts","sourceRoot":"","sources":["../../../src/stories/support/negotiationFixtures.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,uCAAuC,CAAC;AAC/C,OAAO,KAAK,EAAE,mBAAmB,EAAoB,MAAM,eAAe,CAAC;AAI3E,eAAO,MAAM,gBAAgB,EAAE,mBAO9B,CAAC;AAyDF,eAAO,MAAM,cAAc,gBAAkB,CAAC;AAE9C,eAAO,MAAM,YAAY,gBAOvB,CAAC;AAEH,eAAO,MAAM,kBAAkB,gBAI7B,CAAC;AAEH,eAAO,MAAM,gBAAgB,gBAgB3B,CAAC;AAEH,eAAO,MAAM,YAAY,kBAAuE,CAAC;AAEjG,eAAO,MAAM,kBAAkB,EAAE,qBAMhC,CAAC;AAMF,yEAAyE;AACzE,wBAAgB,mBAAmB,IAAI,mBAAmB,CA0BzD;AAED,wBAAgB,wBAAwB,IAAI,mBAAmB,CAc9D"}
@@ -0,0 +1,7 @@
1
+ import { GraphqlCall } from './graphqlMock';
2
+
3
+ /** Wait until the in-story router reports `pathname` (from the PageHarness probe). */
4
+ export declare function expectLocation(canvasElement: HTMLElement, pathname: string): Promise<void>;
5
+ /** Wait for an operation to be sent and return its most recent call. */
6
+ export declare function expectGraphqlCall(operationName: string): Promise<GraphqlCall>;
7
+ //# sourceMappingURL=play.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"play.d.ts","sourceRoot":"","sources":["../../../src/stories/support/play.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAmB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAElE,sFAAsF;AACtF,wBAAsB,cAAc,CAAC,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhG;AAED,wEAAwE;AACxE,wBAAsB,iBAAiB,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAWnF"}
@@ -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;AA0FhD,eAAO,MAAM,mBAAmB,EAAE,EAqEjC,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;AAyGhD,eAAO,MAAM,mBAAmB,EAAE,EA0EjC,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/decisions/DecisionsPage.js").then((e) => ({ default: e.DecisionsPage }))), w = r(() => import("./pages/decisions/DecisionDetailPage.js").then((e) => ({ default: e.DecisionDetailPage }))), T = r(() => import("./pages/SavingsPage.js").then((e) => ({ default: e.SavingsPage }))), E = r(() => import("./pages/InsightsPage.js").then((e) => ({ default: e.InsightsPage }))), D = r(() => import("./pages/AssetVaultPage.js").then((e) => ({ default: e.AssetVaultPage }))), O = r(() => import("./pages/enterprise/EnterpriseSpendPage.js").then((e) => ({ default: e.EnterpriseSpendPage }))), k = () => /* @__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/SavingsPage.js").then((e) => ({ default: e.SavingsPage }))), E = r(() => import("./pages/InsightsPage.js").then((e) => ({ default: e.InsightsPage }))), D = r(() => import("./pages/AssetVaultPage.js").then((e) => ({ default: e.AssetVaultPage }))), O = r(() => import("./pages/enterprise/EnterpriseSpendPage.js").then((e) => ({ default: e.EnterpriseSpendPage }))), k = r(() => import("./pages/negotiations/NegotiationsPage.js").then((e) => ({ default: e.NegotiationsPage }))), A = r(() => import("./pages/negotiations/NegotiationNewPage.js").then((e) => ({ default: e.NegotiationNewPage }))), j = r(() => import("./pages/negotiations/NegotiationDetailPage.js").then((e) => ({ default: e.NegotiationDetailPage }))), M = () => /* @__PURE__ */ c("div", {
9
9
  className: "flex min-h-[400px] items-center justify-center",
10
10
  children: /* @__PURE__ */ c(u, { size: "lg" })
11
- }), A = () => {
12
- let { basePath: r, isStandalone: u } = e(), A = s(), j = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
13
- return j && !u && !(A.pathname === j || A.pathname.startsWith(j + "/")) ? null : /* @__PURE__ */ c("div", {
11
+ }), N = () => {
12
+ let { basePath: r, isStandalone: u } = e(), N = s(), P = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
13
+ return P && !u && !(N.pathname === P || N.pathname.startsWith(P + "/")) ? null : /* @__PURE__ */ c("div", {
14
14
  className: "flex min-h-full flex-col",
15
15
  children: /* @__PURE__ */ c(n, {
16
- fallback: /* @__PURE__ */ c(k, {}),
16
+ fallback: /* @__PURE__ */ c(M, {}),
17
17
  children: /* @__PURE__ */ l(o, { children: [
18
18
  /* @__PURE__ */ c(a, {
19
19
  index: !0,
@@ -87,6 +87,18 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
87
87
  path: "decisions/:id",
88
88
  element: /* @__PURE__ */ c(w, {})
89
89
  }),
90
+ /* @__PURE__ */ c(a, {
91
+ path: "negotiations",
92
+ element: /* @__PURE__ */ c(k, {})
93
+ }),
94
+ /* @__PURE__ */ c(a, {
95
+ path: "negotiations/new",
96
+ element: /* @__PURE__ */ c(A, {})
97
+ }),
98
+ /* @__PURE__ */ c(a, {
99
+ path: "negotiations/:id",
100
+ element: /* @__PURE__ */ c(j, {})
101
+ }),
90
102
  /* @__PURE__ */ c(a, {
91
103
  path: "workflows/:selectedId?",
92
104
  element: /* @__PURE__ */ c(y, {})
@@ -103,6 +115,6 @@ var d = r(() => import("./pages/relationships/RelationshipsListPage.js").then((e
103
115
  });
104
116
  };
105
117
  //#endregion
106
- export { A as SubscriberBotRoutes };
118
+ export { N as SubscriberBotRoutes };
107
119
 
108
120
  //# 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// 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// Cost optimization dashboard (BOFF-4001)\nconst SavingsPage = lazy(() =>\n import('./pages/SavingsPage').then((m) => ({ default: m.SavingsPage }))\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\n// Enterprise SaaS spend management (BOFF-4008)\nconst EnterpriseSpendPage = lazy(() =>\n import('./pages/enterprise/EnterpriseSpendPage').then((m) => ({\n default: m.EnterpriseSpendPage,\n }))\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 {/* Enterprise SaaS spend management */}\n <Route path=\"enterprise/spend\" element={<EnterpriseSpendPage />} />\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=\"savings\" element={<SavingsPage />} />\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
+ {"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// Cost optimization dashboard (BOFF-4001)\nconst SavingsPage = lazy(() =>\n import('./pages/SavingsPage').then((m) => ({ default: m.SavingsPage }))\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\n// Enterprise SaaS spend management (BOFF-4008)\nconst EnterpriseSpendPage = lazy(() =>\n import('./pages/enterprise/EnterpriseSpendPage').then((m) => ({\n default: m.EnterpriseSpendPage,\n }))\n);\n\n// Bill negotiation (BOFF-4154)\nconst NegotiationsPage = lazy(() =>\n import('./pages/negotiations/NegotiationsPage').then((m) => ({ default: m.NegotiationsPage }))\n);\nconst NegotiationNewPage = lazy(() =>\n import('./pages/negotiations/NegotiationNewPage').then((m) => ({\n default: m.NegotiationNewPage,\n }))\n);\nconst NegotiationDetailPage = lazy(() =>\n import('./pages/negotiations/NegotiationDetailPage').then((m) => ({\n default: m.NegotiationDetailPage,\n }))\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 {/* Enterprise SaaS spend management */}\n <Route path=\"enterprise/spend\" element={<EnterpriseSpendPage />} />\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=\"savings\" element={<SavingsPage />} />\n <Route path=\"decisions/:id\" element={<DecisionDetailPage />} />\n\n {/* Bill negotiation */}\n <Route path=\"negotiations\" element={<NegotiationsPage />} />\n <Route path=\"negotiations/new\" element={<NegotiationNewPage />} />\n <Route path=\"negotiations/:id\" element={<NegotiationDetailPage />} />\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":"AdminDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAuCpD,eAAO,MAAM,kBAAkB,EAAE,EA0dhC,CAAC"}
1
+ {"version":3,"file":"AdminDashboardPage.d.ts","sourceRoot":"","sources":["../../../src/subscriberbot/admin/AdminDashboardPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAwCpD,eAAO,MAAM,kBAAkB,EAAE,EAgfhC,CAAC"}
@@ -1,39 +1,40 @@
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 { 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";
4
+ import { useTr as ee } from "../hooks/useTr.js";
5
+ import { useAdapterSubmissions as te, useApproveAdapter as ne, useMarketplaceReports as re, useModerateListing as r, useProviders as i, useRejectAdapter as ie, useUpdateProvider as ae } from "../hooks/useSubscriberBotApi.js";
6
+ import { NegotiationDeskPanel as oe } from "./NegotiationDeskPanel.js";
6
7
  import "../hooks/index.js";
7
- import { Fragment as s, useState as c } from "react";
8
- import { CheckCircle2 as l, Plug as u, Settings2 as ie, Store as d, XCircle as ae } from "lucide-react";
8
+ import { Fragment as a, useState as o } from "react";
9
+ import { CheckCircle2 as s, Handshake as se, Plug as c, Settings2 as l, Store as u, XCircle as d } from "lucide-react";
9
10
  import { jsx as f, jsxs as p } from "react/jsx-runtime";
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
+ 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 ce, TabsContent as O, TabsList as le, TabsTrigger as k, Textarea as A } from "@burdenoff/fe-libs/ui";
11
12
  //#region src/subscriberbot/admin/AdminDashboardPage.tsx
12
13
  var j = () => {
13
- let j = r(), [M, ce] = c("providers"), { data: le, isLoading: ue } = ne({ pagination: { limit: 50 } }), N = o(), P = (e) => {
14
- N.mutate({
14
+ let j = ee(), [ue, M] = o("providers"), { data: de, isLoading: N } = i({ pagination: { limit: 50 } }), P = ae(), F = (e) => {
15
+ P.mutate({
15
16
  id: e,
16
17
  input: { status: "VERIFIED" }
17
18
  });
18
- }, F = (e) => {
19
- N.mutate({
19
+ }, I = (e) => {
20
+ P.mutate({
20
21
  id: e,
21
22
  input: { status: "DEPRECATED" }
22
23
  });
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
- z.mutate({ id: e });
25
- }, fe = (e) => {
24
+ }, L = de?.items ?? [], { data: R, isLoading: z } = te({ pagination: { limit: 50 } }), B = ne(), V = ie(), [fe, H] = o(null), [U, W] = o(""), G = R?.items ?? [], pe = (e) => {
25
+ B.mutate({ id: e });
26
+ }, me = (e) => {
26
27
  H(e), W("");
27
- }, pe = (e) => {
28
- U.trim() && B.mutate({
28
+ }, he = (e) => {
29
+ U.trim() && V.mutate({
29
30
  id: e,
30
31
  reason: U.trim()
31
32
  }, { onSuccess: () => {
32
33
  H(null), W("");
33
34
  } });
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
+ }, { data: ge, isLoading: _e } = re({ pagination: { limit: 50 } }), K = r(), [ve, q] = o(null), [J, Y] = o(null), [X, Z] = o(""), Q = ge?.items ?? [], $ = (e, t) => {
35
36
  q(e), Y(t), Z("");
36
- }, _e = (e) => {
37
+ }, ye = (e) => {
37
38
  !J || !X.trim() || K.mutate({
38
39
  id: e,
39
40
  action: J,
@@ -45,38 +46,43 @@ var j = () => {
45
46
  return /* @__PURE__ */ f(e, {
46
47
  title: j("admin.title", "SubscriberBot Admin"),
47
48
  description: j("admin.description", "Provider registry curation, adapter approvals, and marketplace moderation."),
48
- children: /* @__PURE__ */ p(oe, {
49
- value: M,
50
- onValueChange: ce,
49
+ children: /* @__PURE__ */ p(ce, {
50
+ value: ue,
51
+ onValueChange: M,
51
52
  className: "w-full",
52
53
  children: [
53
- /* @__PURE__ */ p(se, {
54
- className: "mb-4 grid w-full grid-cols-3 sm:w-auto sm:inline-flex",
54
+ /* @__PURE__ */ p(le, {
55
+ className: "mb-4 grid w-full grid-cols-2 sm:w-auto sm:inline-flex",
55
56
  children: [
56
57
  /* @__PURE__ */ p(k, {
57
58
  value: "providers",
58
59
  className: "gap-2",
59
- children: [/* @__PURE__ */ f(ie, { size: 16 }), j("admin.tabs.providers", "Provider Registry")]
60
+ children: [/* @__PURE__ */ f(l, { size: 16 }), j("admin.tabs.providers", "Provider Registry")]
60
61
  }),
61
62
  /* @__PURE__ */ p(k, {
62
63
  value: "adapters",
63
64
  className: "gap-2",
64
- children: [/* @__PURE__ */ f(u, { size: 16 }), j("admin.tabs.adapters", "Adapter Approvals")]
65
+ children: [/* @__PURE__ */ f(c, { size: 16 }), j("admin.tabs.adapters", "Adapter Approvals")]
65
66
  }),
66
67
  /* @__PURE__ */ p(k, {
67
68
  value: "marketplace",
68
69
  className: "gap-2",
69
- children: [/* @__PURE__ */ f(d, { size: 16 }), j("admin.tabs.marketplace", "Marketplace Moderation")]
70
+ children: [/* @__PURE__ */ f(u, { size: 16 }), j("admin.tabs.marketplace", "Marketplace Moderation")]
71
+ }),
72
+ /* @__PURE__ */ p(k, {
73
+ value: "negotiations",
74
+ className: "gap-2",
75
+ children: [/* @__PURE__ */ f(se, { size: 16 }), j("admin.tabs.negotiations", "Negotiation Desk")]
70
76
  })
71
77
  ]
72
78
  }),
73
79
  /* @__PURE__ */ f(O, {
74
80
  value: "providers",
75
- children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.providers.title", "Provider registry") }), /* @__PURE__ */ f(_, { children: j("admin.providers.description", "Curate the global provider catalog. Verify submitted providers or deprecate stale entries.") })] }), /* @__PURE__ */ f(g, { children: ue ? /* @__PURE__ */ f("div", {
81
+ children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.providers.title", "Provider registry") }), /* @__PURE__ */ f(_, { children: j("admin.providers.description", "Curate the global provider catalog. Verify submitted providers or deprecate stale entries.") })] }), /* @__PURE__ */ f(g, { children: N ? /* @__PURE__ */ f("div", {
76
82
  className: "flex min-h-[200px] items-center justify-center",
77
83
  children: /* @__PURE__ */ f(x, { size: "lg" })
78
- }) : I.length === 0 ? /* @__PURE__ */ f(b, {
79
- icon: /* @__PURE__ */ f(d, { className: "size-6 text-action-primary-bg" }),
84
+ }) : L.length === 0 ? /* @__PURE__ */ f(b, {
85
+ icon: /* @__PURE__ */ f(u, { className: "size-6 text-action-primary-bg" }),
80
86
  title: j("admin.providers.emptyTitle", "No providers yet"),
81
87
  description: j("admin.providers.emptyDescription", "Once providers are created or claimed they will appear here for curation.")
82
88
  }) : /* @__PURE__ */ f("div", {
@@ -90,7 +96,7 @@ var j = () => {
90
96
  className: "text-right",
91
97
  children: j("admin.providers.table.actions", "Actions")
92
98
  })
93
- ] }) }), /* @__PURE__ */ f(C, { children: I.map((e) => /* @__PURE__ */ p(D, { children: [
99
+ ] }) }), /* @__PURE__ */ f(C, { children: L.map((e) => /* @__PURE__ */ p(D, { children: [
94
100
  /* @__PURE__ */ f(w, {
95
101
  className: "font-medium text-text-primary",
96
102
  children: e.name
@@ -111,17 +117,17 @@ var j = () => {
111
117
  children: [e.status !== "VERIFIED" && /* @__PURE__ */ p(m, {
112
118
  size: "sm",
113
119
  variant: "outline",
114
- onClick: () => P(e.id),
115
- disabled: N.isPending,
116
- children: [/* @__PURE__ */ f(l, {
120
+ onClick: () => F(e.id),
121
+ disabled: P.isPending,
122
+ children: [/* @__PURE__ */ f(s, {
117
123
  size: 14,
118
124
  className: "mr-1"
119
125
  }), j("admin.providers.verify", "Verify")]
120
126
  }), e.status !== "DEPRECATED" && /* @__PURE__ */ f(m, {
121
127
  size: "sm",
122
128
  variant: "secondary",
123
- onClick: () => F(e.id),
124
- disabled: N.isPending,
129
+ onClick: () => I(e.id),
130
+ disabled: P.isPending,
125
131
  children: j("admin.providers.deprecate", "Deprecate")
126
132
  })]
127
133
  })
@@ -131,11 +137,11 @@ var j = () => {
131
137
  }),
132
138
  /* @__PURE__ */ f(O, {
133
139
  value: "adapters",
134
- children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.adapters.title", "Adapter approvals") }), /* @__PURE__ */ f(_, { children: j("admin.adapters.description", "Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.") })] }), /* @__PURE__ */ f(g, { children: R ? /* @__PURE__ */ f("div", {
140
+ children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.adapters.title", "Adapter approvals") }), /* @__PURE__ */ f(_, { children: j("admin.adapters.description", "Review submitted integration adapters before they are published to the SubscriberBot adapter marketplace.") })] }), /* @__PURE__ */ f(g, { children: z ? /* @__PURE__ */ f("div", {
135
141
  className: "flex min-h-[200px] items-center justify-center",
136
142
  children: /* @__PURE__ */ f(x, { size: "lg" })
137
143
  }) : G.length === 0 ? /* @__PURE__ */ f(b, {
138
- icon: /* @__PURE__ */ f(u, { className: "size-6 text-action-primary-bg" }),
144
+ icon: /* @__PURE__ */ f(c, { className: "size-6 text-action-primary-bg" }),
139
145
  title: j("admin.adapters.emptyTitle", "No adapter submissions"),
140
146
  description: j("admin.adapters.emptyDescription", "Submitted integration adapters will appear here for review.")
141
147
  }) : /* @__PURE__ */ f("div", {
@@ -149,7 +155,7 @@ var j = () => {
149
155
  className: "text-right",
150
156
  children: j("admin.adapters.table.actions", "Actions")
151
157
  })
152
- ] }) }), /* @__PURE__ */ f(C, { children: G.map((e) => /* @__PURE__ */ p(s, { children: [/* @__PURE__ */ p(D, { children: [
158
+ ] }) }), /* @__PURE__ */ f(C, { children: G.map((e) => /* @__PURE__ */ p(a, { children: [/* @__PURE__ */ p(D, { children: [
153
159
  /* @__PURE__ */ f(w, {
154
160
  className: "font-medium text-text-primary",
155
161
  children: e.adapterId
@@ -170,25 +176,25 @@ var j = () => {
170
176
  children: [/* @__PURE__ */ p(m, {
171
177
  size: "sm",
172
178
  variant: "outline",
173
- onClick: () => de(e.id),
174
- disabled: z.isPending || B.isPending,
175
- children: [/* @__PURE__ */ f(l, {
179
+ onClick: () => pe(e.id),
180
+ disabled: B.isPending || V.isPending,
181
+ children: [/* @__PURE__ */ f(s, {
176
182
  size: 14,
177
183
  className: "mr-1"
178
184
  }), j("admin.adapters.approve", "Approve")]
179
185
  }), /* @__PURE__ */ p(m, {
180
186
  size: "sm",
181
187
  variant: "secondary",
182
- onClick: () => fe(e.id),
183
- disabled: z.isPending || B.isPending,
184
- children: [/* @__PURE__ */ f(ae, {
188
+ onClick: () => me(e.id),
189
+ disabled: B.isPending || V.isPending,
190
+ children: [/* @__PURE__ */ f(d, {
185
191
  size: 14,
186
192
  className: "mr-1"
187
193
  }), j("admin.adapters.reject", "Reject")]
188
194
  })]
189
195
  })
190
196
  })
191
- ] }), V === e.id && /* @__PURE__ */ f(D, { children: /* @__PURE__ */ f(w, {
197
+ ] }), fe === e.id && /* @__PURE__ */ f(D, { children: /* @__PURE__ */ f(w, {
192
198
  colSpan: 5,
193
199
  className: "bg-bg-sunken",
194
200
  children: /* @__PURE__ */ p("div", {
@@ -204,14 +210,14 @@ var j = () => {
204
210
  children: [/* @__PURE__ */ f(m, {
205
211
  size: "sm",
206
212
  variant: "destructive",
207
- onClick: () => pe(e.id),
208
- disabled: !U.trim() || B.isPending,
213
+ onClick: () => he(e.id),
214
+ disabled: !U.trim() || V.isPending,
209
215
  children: j("admin.adapters.confirmReject", "Confirm reject")
210
216
  }), /* @__PURE__ */ f(m, {
211
217
  size: "sm",
212
218
  variant: "outline",
213
219
  onClick: () => H(null),
214
- disabled: B.isPending,
220
+ disabled: V.isPending,
215
221
  children: j("admin.adapters.cancel", "Cancel")
216
222
  })]
217
223
  })]
@@ -221,11 +227,11 @@ var j = () => {
221
227
  }),
222
228
  /* @__PURE__ */ f(O, {
223
229
  value: "marketplace",
224
- children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.marketplace.title", "Marketplace moderation") }), /* @__PURE__ */ f(_, { children: j("admin.marketplace.description", "Review reported marketplace listings and take moderation actions.") })] }), /* @__PURE__ */ f(g, { children: he ? /* @__PURE__ */ f("div", {
230
+ children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.marketplace.title", "Marketplace moderation") }), /* @__PURE__ */ f(_, { children: j("admin.marketplace.description", "Review reported marketplace listings and take moderation actions.") })] }), /* @__PURE__ */ f(g, { children: _e ? /* @__PURE__ */ f("div", {
225
231
  className: "flex min-h-[200px] items-center justify-center",
226
232
  children: /* @__PURE__ */ f(x, { size: "lg" })
227
233
  }) : Q.length === 0 ? /* @__PURE__ */ f(b, {
228
- icon: /* @__PURE__ */ f(d, { className: "size-6 text-action-primary-bg" }),
234
+ icon: /* @__PURE__ */ f(u, { className: "size-6 text-action-primary-bg" }),
229
235
  title: j("admin.marketplace.emptyTitle", "No reported listings"),
230
236
  description: j("admin.marketplace.emptyDescription", "Reported marketplace listings will appear here for moderation.")
231
237
  }) : /* @__PURE__ */ f("div", {
@@ -240,7 +246,7 @@ var j = () => {
240
246
  className: "text-right",
241
247
  children: j("admin.marketplace.table.actions", "Actions")
242
248
  })
243
- ] }) }), /* @__PURE__ */ f(C, { children: Q.map((e) => /* @__PURE__ */ p(s, { children: [/* @__PURE__ */ p(D, { children: [
249
+ ] }) }), /* @__PURE__ */ f(C, { children: Q.map((e) => /* @__PURE__ */ p(a, { children: [/* @__PURE__ */ p(D, { children: [
244
250
  /* @__PURE__ */ f(w, {
245
251
  className: "font-medium text-text-primary",
246
252
  children: e.listingId
@@ -277,7 +283,7 @@ var j = () => {
277
283
  })]
278
284
  })
279
285
  })
280
- ] }), ge === e.id && /* @__PURE__ */ f(D, { children: /* @__PURE__ */ f(w, {
286
+ ] }), ve === e.id && /* @__PURE__ */ f(D, { children: /* @__PURE__ */ f(w, {
281
287
  colSpan: 6,
282
288
  className: "bg-bg-sunken",
283
289
  children: /* @__PURE__ */ p("div", {
@@ -293,7 +299,7 @@ var j = () => {
293
299
  children: [/* @__PURE__ */ f(m, {
294
300
  size: "sm",
295
301
  variant: J === "REMOVE_LISTING" ? "destructive" : "outline",
296
- onClick: () => _e(e.id),
302
+ onClick: () => ye(e.id),
297
303
  disabled: !X.trim() || K.isPending,
298
304
  children: J === "REMOVE_LISTING" ? j("admin.marketplace.confirmRemoval", "Confirm removal") : j("admin.marketplace.confirmDismissal", "Confirm dismissal")
299
305
  }), /* @__PURE__ */ f(m, {
@@ -307,6 +313,10 @@ var j = () => {
307
313
  })
308
314
  }) }, `${e.id}-moderate`)] }, e.id)) })] })
309
315
  }) })] })
316
+ }),
317
+ /* @__PURE__ */ f(O, {
318
+ value: "negotiations",
319
+ children: /* @__PURE__ */ p(h, { children: [/* @__PURE__ */ p(v, { children: [/* @__PURE__ */ f(y, { children: j("admin.desk.title", "Negotiation desk") }), /* @__PURE__ */ f(_, { children: j("admin.desk.description", "Managed bill negotiations customers authorised, across all workspaces. Recording a successful outcome bills the success fee in global billing.") })] }), /* @__PURE__ */ f(g, { children: /* @__PURE__ */ f(oe, {}) })] })
310
320
  })
311
321
  ]
312
322
  })
@@ -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, Handshake, Plug, Settings2, Store, XCircle } from 'lucide-react';\n\nimport { PageLayout } from '../components/PageLayout';\nimport { StatusBadge } from '../components/StatusBadge';\nimport { NegotiationDeskPanel } from './NegotiationDeskPanel';\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-2 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 <TabsTrigger value=\"negotiations\" className=\"gap-2\">\n <Handshake size={16} />\n {tr('admin.tabs.negotiations', 'Negotiation Desk')}\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\n {/* Bill negotiation desk (BOFF-4154). */}\n <TabsContent value=\"negotiations\">\n <Card>\n <CardHeader>\n <CardTitle>{tr('admin.desk.title', 'Negotiation desk')}</CardTitle>\n <CardDescription>\n {tr(\n 'admin.desk.description',\n 'Managed bill negotiations customers authorised, across all workspaces. Recording a successful outcome bills the success fee in global billing.'\n )}\n </CardDescription>\n </CardHeader>\n <CardContent>\n <NegotiationDeskPanel />\n </CardContent>\n </Card>\n </TabsContent>\n </Tabs>\n </PageLayout>\n );\n};\n"],"mappings":"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"}