@burdenoff/microfe-subscriberbot 2026.626.2 → 2026.628.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 (141) hide show
  1. package/dist/index.js +4 -4
  2. package/dist/subscriberbot/SubscriberBotRoot.js +61 -133
  3. package/dist/subscriberbot/SubscriberBotRoot.js.map +1 -1
  4. package/dist/subscriberbot/SubscriberBotRoutes.js +56 -187
  5. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  6. package/dist/subscriberbot/components/StateViews.js +49 -0
  7. package/dist/subscriberbot/components/StateViews.js.map +1 -0
  8. package/dist/subscriberbot/components/StatusBadge.js +45 -47
  9. package/dist/subscriberbot/components/StatusBadge.js.map +1 -1
  10. package/dist/subscriberbot/context/SubscriberBotContext.js +22 -30
  11. package/dist/subscriberbot/context/SubscriberBotContext.js.map +1 -1
  12. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +342 -195
  13. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  14. package/dist/subscriberbot/index.js +1 -1
  15. package/dist/subscriberbot/pages/DashboardPage.js +269 -0
  16. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -0
  17. package/dist/subscriberbot/pages/InboxPage.js +186 -0
  18. package/dist/subscriberbot/pages/InboxPage.js.map +1 -0
  19. package/dist/subscriberbot/pages/InvoicesPage.js +211 -0
  20. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -0
  21. package/dist/subscriberbot/pages/WorkflowsPage.js +236 -0
  22. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -0
  23. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +160 -0
  24. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -0
  25. package/dist/subscriberbot/pages/agents/AgentNewPage.js +140 -0
  26. package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -0
  27. package/dist/subscriberbot/pages/agents/AgentsListPage.js +178 -0
  28. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -0
  29. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +179 -0
  30. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -0
  31. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +185 -0
  32. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -0
  33. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +254 -0
  34. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -0
  35. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +306 -0
  36. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -0
  37. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +253 -0
  38. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -0
  39. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +248 -0
  40. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -0
  41. package/dist/subscriberbot/utils/formatters.js +50 -32
  42. package/dist/subscriberbot/utils/formatters.js.map +1 -1
  43. package/package.json +1 -1
  44. package/dist/subscriberbot/components/InvestmentCard.js +0 -97
  45. package/dist/subscriberbot/components/InvestmentCard.js.map +0 -1
  46. package/dist/subscriberbot/components/RatingDisplay.js +0 -35
  47. package/dist/subscriberbot/components/RatingDisplay.js.map +0 -1
  48. package/dist/subscriberbot/mocks/data.js +0 -1517
  49. package/dist/subscriberbot/mocks/data.js.map +0 -1
  50. package/dist/subscriberbot/mocks/users.js +0 -34
  51. package/dist/subscriberbot/mocks/users.js.map +0 -1
  52. package/dist/subscriberbot/pages/HomePage.js +0 -930
  53. package/dist/subscriberbot/pages/HomePage.js.map +0 -1
  54. package/dist/subscriberbot/pages/admin/AdminAnalyticsPage.js +0 -651
  55. package/dist/subscriberbot/pages/admin/AdminAnalyticsPage.js.map +0 -1
  56. package/dist/subscriberbot/pages/admin/AdminDashboard.js +0 -679
  57. package/dist/subscriberbot/pages/admin/AdminDashboard.js.map +0 -1
  58. package/dist/subscriberbot/pages/admin/AdminFinancialPage.js +0 -427
  59. package/dist/subscriberbot/pages/admin/AdminFinancialPage.js.map +0 -1
  60. package/dist/subscriberbot/pages/admin/AdminOrdersPage.js +0 -665
  61. package/dist/subscriberbot/pages/admin/AdminOrdersPage.js.map +0 -1
  62. package/dist/subscriberbot/pages/admin/AdminProfilePage.js +0 -261
  63. package/dist/subscriberbot/pages/admin/AdminProfilePage.js.map +0 -1
  64. package/dist/subscriberbot/pages/admin/AdminSettingsPage.js +0 -654
  65. package/dist/subscriberbot/pages/admin/AdminSettingsPage.js.map +0 -1
  66. package/dist/subscriberbot/pages/admin/CartManagementPage.js +0 -874
  67. package/dist/subscriberbot/pages/admin/CartManagementPage.js.map +0 -1
  68. package/dist/subscriberbot/pages/admin/UserManagementPage.js +0 -898
  69. package/dist/subscriberbot/pages/admin/UserManagementPage.js.map +0 -1
  70. package/dist/subscriberbot/pages/cart-owner/AnalyticsDashboard.js +0 -839
  71. package/dist/subscriberbot/pages/cart-owner/AnalyticsDashboard.js.map +0 -1
  72. package/dist/subscriberbot/pages/cart-owner/BusinessSettingsPage.js +0 -705
  73. package/dist/subscriberbot/pages/cart-owner/BusinessSettingsPage.js.map +0 -1
  74. package/dist/subscriberbot/pages/cart-owner/CartOwnerDashboard.js +0 -802
  75. package/dist/subscriberbot/pages/cart-owner/CartOwnerDashboard.js.map +0 -1
  76. package/dist/subscriberbot/pages/cart-owner/CartOwnerProfilePage.js +0 -891
  77. package/dist/subscriberbot/pages/cart-owner/CartOwnerProfilePage.js.map +0 -1
  78. package/dist/subscriberbot/pages/cart-owner/CartServiceConfigPage.js +0 -633
  79. package/dist/subscriberbot/pages/cart-owner/CartServiceConfigPage.js.map +0 -1
  80. package/dist/subscriberbot/pages/cart-owner/InventoryManagementPage.js +0 -910
  81. package/dist/subscriberbot/pages/cart-owner/InventoryManagementPage.js.map +0 -1
  82. package/dist/subscriberbot/pages/cart-owner/OrderManagementPage.js +0 -879
  83. package/dist/subscriberbot/pages/cart-owner/OrderManagementPage.js.map +0 -1
  84. package/dist/subscriberbot/pages/cart-owner/StaffManagementPage.js +0 -838
  85. package/dist/subscriberbot/pages/cart-owner/StaffManagementPage.js.map +0 -1
  86. package/dist/subscriberbot/pages/common/HelpSupportPage.js +0 -1323
  87. package/dist/subscriberbot/pages/common/HelpSupportPage.js.map +0 -1
  88. package/dist/subscriberbot/pages/common/NotificationCenterPage.js +0 -672
  89. package/dist/subscriberbot/pages/common/NotificationCenterPage.js.map +0 -1
  90. package/dist/subscriberbot/pages/common/SettingsPage.js +0 -973
  91. package/dist/subscriberbot/pages/common/SettingsPage.js.map +0 -1
  92. package/dist/subscriberbot/pages/customer/BookingDetailsPage.js +0 -626
  93. package/dist/subscriberbot/pages/customer/BookingDetailsPage.js.map +0 -1
  94. package/dist/subscriberbot/pages/customer/CartDetailPage.js +0 -654
  95. package/dist/subscriberbot/pages/customer/CartDetailPage.js.map +0 -1
  96. package/dist/subscriberbot/pages/customer/CartDiscoveryPage.js +0 -555
  97. package/dist/subscriberbot/pages/customer/CartDiscoveryPage.js.map +0 -1
  98. package/dist/subscriberbot/pages/customer/CheckoutPage.js +0 -529
  99. package/dist/subscriberbot/pages/customer/CheckoutPage.js.map +0 -1
  100. package/dist/subscriberbot/pages/customer/CustomerDashboard.js +0 -532
  101. package/dist/subscriberbot/pages/customer/CustomerDashboard.js.map +0 -1
  102. package/dist/subscriberbot/pages/customer/CustomerProfilePage.js +0 -630
  103. package/dist/subscriberbot/pages/customer/CustomerProfilePage.js.map +0 -1
  104. package/dist/subscriberbot/pages/customer/DirectServiceBookingPage.js +0 -633
  105. package/dist/subscriberbot/pages/customer/DirectServiceBookingPage.js.map +0 -1
  106. package/dist/subscriberbot/pages/customer/FavoritesPage.js +0 -484
  107. package/dist/subscriberbot/pages/customer/FavoritesPage.js.map +0 -1
  108. package/dist/subscriberbot/pages/customer/OrderHistoryPage.js +0 -446
  109. package/dist/subscriberbot/pages/customer/OrderHistoryPage.js.map +0 -1
  110. package/dist/subscriberbot/pages/customer/OrderTrackingPage.js +0 -394
  111. package/dist/subscriberbot/pages/customer/OrderTrackingPage.js.map +0 -1
  112. package/dist/subscriberbot/pages/customer/PaymentMethodsPage.js +0 -495
  113. package/dist/subscriberbot/pages/customer/PaymentMethodsPage.js.map +0 -1
  114. package/dist/subscriberbot/pages/customer/ReviewsPage.js +0 -613
  115. package/dist/subscriberbot/pages/customer/ReviewsPage.js.map +0 -1
  116. package/dist/subscriberbot/pages/customer/SavedAddressesPage.js +0 -450
  117. package/dist/subscriberbot/pages/customer/SavedAddressesPage.js.map +0 -1
  118. package/dist/subscriberbot/pages/investor/InvestmentDetailsPage.js +0 -886
  119. package/dist/subscriberbot/pages/investor/InvestmentDetailsPage.js.map +0 -1
  120. package/dist/subscriberbot/pages/investor/InvestmentOpportunitiesPage.js +0 -947
  121. package/dist/subscriberbot/pages/investor/InvestmentOpportunitiesPage.js.map +0 -1
  122. package/dist/subscriberbot/pages/investor/InvestorAnalyticsPage.js +0 -687
  123. package/dist/subscriberbot/pages/investor/InvestorAnalyticsPage.js.map +0 -1
  124. package/dist/subscriberbot/pages/investor/InvestorDashboard.js +0 -451
  125. package/dist/subscriberbot/pages/investor/InvestorDashboard.js.map +0 -1
  126. package/dist/subscriberbot/pages/investor/InvestorInvestmentsPage.js +0 -406
  127. package/dist/subscriberbot/pages/investor/InvestorInvestmentsPage.js.map +0 -1
  128. package/dist/subscriberbot/pages/investor/InvestorPortfolioPage.js +0 -575
  129. package/dist/subscriberbot/pages/investor/InvestorPortfolioPage.js.map +0 -1
  130. package/dist/subscriberbot/pages/investor/InvestorProfilePage.js +0 -1070
  131. package/dist/subscriberbot/pages/investor/InvestorProfilePage.js.map +0 -1
  132. package/dist/subscriberbot/pages/worker/TaskDetailsPage.js +0 -535
  133. package/dist/subscriberbot/pages/worker/TaskDetailsPage.js.map +0 -1
  134. package/dist/subscriberbot/pages/worker/WorkerDashboard.js +0 -666
  135. package/dist/subscriberbot/pages/worker/WorkerDashboard.js.map +0 -1
  136. package/dist/subscriberbot/pages/worker/WorkerOrdersPage.js +0 -681
  137. package/dist/subscriberbot/pages/worker/WorkerOrdersPage.js.map +0 -1
  138. package/dist/subscriberbot/pages/worker/WorkerProfilePage.js +0 -692
  139. package/dist/subscriberbot/pages/worker/WorkerProfilePage.js.map +0 -1
  140. package/dist/subscriberbot/pages/worker/WorkerSchedulePage.js +0 -588
  141. package/dist/subscriberbot/pages/worker/WorkerSchedulePage.js.map +0 -1
@@ -0,0 +1,179 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { formatCurrency as n, formatEnumLabel as r, formatIntervalSuffix as i } from "../../utils/formatters.js";
4
+ import { StatusBadge as a } from "../../components/StatusBadge.js";
5
+ import { EmptyState as o } from "../../components/EmptyState.js";
6
+ import { ErrorView as s, LoadingView as c, Section as l } from "../../components/StateViews.js";
7
+ import { useProvider as u } from "../../hooks/useSubscriberBotApi.js";
8
+ import { ArrowLeft as d, Building2 as f, Globe as p, ShieldCheck as m, Tag as h, TrendingDown as g } from "lucide-react";
9
+ import { useParams as _ } from "react-router-dom";
10
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
11
+ import { GlassCard as b } from "@burdenoff/fe-libs/ui";
12
+ //#region src/subscriberbot/pages/providers/ProviderDetailPage.tsx
13
+ function x() {
14
+ let { id: x } = _(), { navigateTo: S } = e(), { data: C, isLoading: w, isError: T, refetch: E } = u(x);
15
+ if (w) return /* @__PURE__ */ v(t, {
16
+ title: "Provider",
17
+ children: /* @__PURE__ */ v(c, { label: "Loading provider…" })
18
+ });
19
+ if (T) return /* @__PURE__ */ v(t, {
20
+ title: "Provider",
21
+ children: /* @__PURE__ */ v(s, {
22
+ message: "Could not load this provider.",
23
+ onRetry: () => void E()
24
+ })
25
+ });
26
+ if (!C) return /* @__PURE__ */ v(t, {
27
+ title: "Provider",
28
+ children: /* @__PURE__ */ v(o, {
29
+ illustration: "empty-data",
30
+ title: "Provider not found",
31
+ description: "It may have been removed, or you may not have access to it.",
32
+ action: /* @__PURE__ */ v("button", {
33
+ type: "button",
34
+ onClick: () => S("/providers"),
35
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
36
+ children: "Back to providers"
37
+ })
38
+ })
39
+ });
40
+ let D = C;
41
+ return /* @__PURE__ */ y(t, {
42
+ title: D.name,
43
+ description: r(D.category),
44
+ actions: /* @__PURE__ */ y("button", {
45
+ type: "button",
46
+ onClick: () => S("/providers"),
47
+ className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
48
+ children: [/* @__PURE__ */ v(d, { className: "h-4 w-4" }), " Back"]
49
+ }),
50
+ children: [
51
+ /* @__PURE__ */ y("div", {
52
+ className: "flex flex-wrap items-center gap-3",
53
+ children: [
54
+ /* @__PURE__ */ v("span", {
55
+ className: "flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
56
+ children: /* @__PURE__ */ v(f, { className: "h-5 w-5" })
57
+ }),
58
+ /* @__PURE__ */ v(a, { status: D.status }),
59
+ D.region && /* @__PURE__ */ v("span", {
60
+ className: "text-sm text-text-secondary",
61
+ children: D.region
62
+ }),
63
+ D.websiteUrl && /* @__PURE__ */ y("a", {
64
+ href: D.websiteUrl,
65
+ target: "_blank",
66
+ rel: "noreferrer",
67
+ className: "inline-flex items-center gap-1 text-sm text-text-link hover:underline",
68
+ children: [/* @__PURE__ */ v(p, { className: "h-3.5 w-3.5" }), " Website"]
69
+ })
70
+ ]
71
+ }),
72
+ D.description && /* @__PURE__ */ v("p", {
73
+ className: "mt-4 max-w-3xl text-sm text-text-secondary",
74
+ children: D.description
75
+ }),
76
+ /* @__PURE__ */ y("div", {
77
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4",
78
+ children: [
79
+ /* @__PURE__ */ y(b, {
80
+ treatment: "metric",
81
+ className: "p-4",
82
+ children: [/* @__PURE__ */ y("div", {
83
+ className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
84
+ children: [/* @__PURE__ */ v(m, { className: "h-3.5 w-3.5" }), " Vendor health"]
85
+ }), /* @__PURE__ */ v("p", {
86
+ className: "mt-1.5 text-lg font-semibold tabular-nums text-text-primary",
87
+ children: D.vendorHealthScore == null ? "—" : `${D.vendorHealthScore}/100`
88
+ })]
89
+ }),
90
+ /* @__PURE__ */ y(b, {
91
+ treatment: "metric",
92
+ className: "p-4",
93
+ children: [/* @__PURE__ */ y("div", {
94
+ className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
95
+ children: [/* @__PURE__ */ v(g, { className: "h-3.5 w-3.5" }), " Churn risk"]
96
+ }), /* @__PURE__ */ v("p", {
97
+ className: "mt-1.5 text-lg font-semibold tabular-nums text-text-primary",
98
+ children: D.churnRiskScore == null ? "—" : `${D.churnRiskScore}/100`
99
+ })]
100
+ }),
101
+ /* @__PURE__ */ y(b, {
102
+ treatment: "metric",
103
+ className: "p-4",
104
+ children: [/* @__PURE__ */ v("div", {
105
+ className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
106
+ children: "Industry"
107
+ }), /* @__PURE__ */ v("p", {
108
+ className: "mt-1.5 text-sm text-text-primary",
109
+ children: D.industry ?? "—"
110
+ })]
111
+ }),
112
+ /* @__PURE__ */ y(b, {
113
+ treatment: "metric",
114
+ className: "p-4",
115
+ children: [/* @__PURE__ */ v("div", {
116
+ className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
117
+ children: "Language"
118
+ }), /* @__PURE__ */ v("p", {
119
+ className: "mt-1.5 text-sm text-text-primary",
120
+ children: D.language ?? "—"
121
+ })]
122
+ })
123
+ ]
124
+ }),
125
+ D.tags.length > 0 && /* @__PURE__ */ y("div", {
126
+ className: "mt-5 flex flex-wrap items-center gap-2",
127
+ children: [/* @__PURE__ */ v(h, { className: "h-3.5 w-3.5 text-text-secondary" }), D.tags.map((e) => /* @__PURE__ */ v("span", {
128
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
129
+ children: e
130
+ }, e))]
131
+ }),
132
+ /* @__PURE__ */ v(l, {
133
+ title: "Plans",
134
+ description: "Pricing this provider publishes",
135
+ children: !D.plans || D.plans.length === 0 ? /* @__PURE__ */ v(o, {
136
+ illustration: "empty-data",
137
+ title: "No published plans",
138
+ description: "When this provider publishes plans, they'll appear here."
139
+ }) : /* @__PURE__ */ v("div", {
140
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
141
+ children: D.plans.map((e) => /* @__PURE__ */ y("div", {
142
+ className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
143
+ children: [
144
+ /* @__PURE__ */ y("div", {
145
+ className: "flex items-start justify-between gap-2",
146
+ children: [/* @__PURE__ */ v("p", {
147
+ className: "text-sm font-semibold text-text-primary",
148
+ children: e.name
149
+ }), /* @__PURE__ */ v(a, { status: e.isActive ? "ACTIVE" : "DISABLED" })]
150
+ }),
151
+ /* @__PURE__ */ y("p", {
152
+ className: "mt-2 text-lg font-bold tabular-nums text-text-primary",
153
+ children: [n(e.amount, e.currency), /* @__PURE__ */ v("span", {
154
+ className: "text-xs font-normal text-text-secondary",
155
+ children: i(e.interval)
156
+ })]
157
+ }),
158
+ e.description && /* @__PURE__ */ v("p", {
159
+ className: "mt-1 text-xs text-text-secondary",
160
+ children: e.description
161
+ }),
162
+ e.features.length > 0 && /* @__PURE__ */ v("ul", {
163
+ className: "mt-3 space-y-1",
164
+ children: e.features.slice(0, 5).map((e) => /* @__PURE__ */ y("li", {
165
+ className: "text-xs text-text-secondary",
166
+ children: ["• ", e]
167
+ }, e))
168
+ })
169
+ ]
170
+ }, e.id))
171
+ })
172
+ })
173
+ ]
174
+ });
175
+ }
176
+ //#endregion
177
+ export { x as ProviderDetailPage };
178
+
179
+ //# sourceMappingURL=ProviderDetailPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderDetailPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProviderDetailPage.tsx"],"sourcesContent":["/**\n * Provider detail\n * @module subscriberbot/pages/providers\n *\n * A provider profile from the registry: category, status, region, scores,\n * tags and its published plans. Reads `subProvider(id)`.\n */\n\nimport { ArrowLeft, Building2, Globe, ShieldCheck, TrendingDown, Tag } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView, Section } from '../../components/StateViews';\nimport { useParams } from 'react-router-dom';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useProvider } from '../../hooks/useSubscriberBotApi';\nimport {\n formatCurrency,\n formatEnumLabel,\n formatIntervalSuffix,\n} from '../../utils/formatters';\n\nexport function ProviderDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useSubscriberBot();\n const { data: provider, isLoading, isError, refetch } = useProvider(id);\n\n if (isLoading) {\n return (\n <PageLayout title=\"Provider\">\n <LoadingView label=\"Loading provider…\" />\n </PageLayout>\n );\n }\n\n if (isError) {\n return (\n <PageLayout title=\"Provider\">\n <ErrorView message=\"Could not load this provider.\" onRetry={() => void refetch()} />\n </PageLayout>\n );\n }\n\n if (!provider) {\n return (\n <PageLayout title=\"Provider\">\n <EmptyState\n illustration=\"empty-data\"\n title=\"Provider not found\"\n description=\"It may have been removed, or you may not have access to it.\"\n action={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Back to providers\n </button>\n }\n />\n </PageLayout>\n );\n }\n\n const p = provider;\n\n return (\n <PageLayout\n title={p.name}\n description={formatEnumLabel(p.category)}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"flex size-10 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary\">\n <Building2 className=\"h-5 w-5\" />\n </span>\n <StatusBadge status={p.status} />\n {p.region && <span className=\"text-sm text-text-secondary\">{p.region}</span>}\n {p.websiteUrl && (\n <a\n href={p.websiteUrl}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-sm text-text-link hover:underline\"\n >\n <Globe className=\"h-3.5 w-3.5\" /> Website\n </a>\n )}\n </div>\n\n {p.description && (\n <p className=\"mt-4 max-w-3xl text-sm text-text-secondary\">{p.description}</p>\n )}\n\n <div className=\"mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4\">\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <ShieldCheck className=\"h-3.5 w-3.5\" /> Vendor health\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.vendorHealthScore != null ? `${p.vendorHealthScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n <TrendingDown className=\"h-3.5 w-3.5\" /> Churn risk\n </div>\n <p className=\"mt-1.5 text-lg font-semibold tabular-nums text-text-primary\">\n {p.churnRiskScore != null ? `${p.churnRiskScore}/100` : '—'}\n </p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Industry\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.industry ?? '—'}</p>\n </GlassCard>\n <GlassCard treatment=\"metric\" className=\"p-4\">\n <div className=\"flex items-center gap-2 text-xs font-medium text-text-secondary\">\n Language\n </div>\n <p className=\"mt-1.5 text-sm text-text-primary\">{p.language ?? '—'}</p>\n </GlassCard>\n </div>\n\n {p.tags.length > 0 && (\n <div className=\"mt-5 flex flex-wrap items-center gap-2\">\n <Tag className=\"h-3.5 w-3.5 text-text-secondary\" />\n {p.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n )}\n\n <Section title=\"Plans\" description=\"Pricing this provider publishes\">\n {!p.plans || p.plans.length === 0 ? (\n <EmptyState\n illustration=\"empty-data\"\n title=\"No published plans\"\n description=\"When this provider publishes plans, they'll appear here.\"\n />\n ) : (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3\">\n {p.plans.map((plan) => (\n <div key={plan.id} className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <p className=\"text-sm font-semibold text-text-primary\">{plan.name}</p>\n <StatusBadge status={plan.isActive ? 'ACTIVE' : 'DISABLED'} />\n </div>\n <p className=\"mt-2 text-lg font-bold tabular-nums text-text-primary\">\n {formatCurrency(plan.amount, plan.currency)}\n <span className=\"text-xs font-normal text-text-secondary\">\n {formatIntervalSuffix(plan.interval)}\n </span>\n </p>\n {plan.description && (\n <p className=\"mt-1 text-xs text-text-secondary\">{plan.description}</p>\n )}\n {plan.features.length > 0 && (\n <ul className=\"mt-3 space-y-1\">\n {plan.features.slice(0, 5).map((f) => (\n <li key={f} className=\"text-xs text-text-secondary\">\n • {f}\n </li>\n ))}\n </ul>\n )}\n </div>\n ))}\n </div>\n )}\n </Section>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,185 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { PageLayout as t } from "../../components/PageLayout.js";
3
+ import { useCreateProvider as n } from "../../hooks/useSubscriberBotApi.js";
4
+ import { useState as r } from "react";
5
+ import { ArrowLeft as i } from "lucide-react";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ import { PagePurpose as s } from "@burdenoff/fe-libs/ui";
8
+ //#region src/subscriberbot/pages/providers/ProviderNewPage.tsx
9
+ var c = [
10
+ "SAAS",
11
+ "AI_SERVICE",
12
+ "STREAMING",
13
+ "NEWSLETTER",
14
+ "NEWS_DIGEST",
15
+ "MEMBERSHIP",
16
+ "COMMUNITY",
17
+ "EDUCATION",
18
+ "FINANCIAL",
19
+ "INSURANCE",
20
+ "TELECOM",
21
+ "UTILITY",
22
+ "ASSOCIATION",
23
+ "LICENSE",
24
+ "CONTRACT",
25
+ "OTHER"
26
+ ], l = "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)]", u = "mb-1 block text-xs font-medium text-text-secondary";
27
+ function d() {
28
+ let { navigateTo: d } = e(), f = n(), [p, m] = r(""), [h, g] = r("SAAS"), [_, v] = r(""), [y, b] = r(""), [x, S] = r(""), [C, w] = r(""), [T, E] = r(""), [D, O] = r(null);
29
+ return /* @__PURE__ */ o(t, {
30
+ title: "Add provider",
31
+ description: "Register a new provider in the registry",
32
+ actions: /* @__PURE__ */ o("button", {
33
+ type: "button",
34
+ onClick: () => d("/providers"),
35
+ className: "inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
36
+ children: [/* @__PURE__ */ a(i, { className: "h-4 w-4" }), " Back"]
37
+ }),
38
+ children: [/* @__PURE__ */ a(s, {
39
+ className: "mb-6",
40
+ children: "Add a provider that isn't in the registry yet so you can attach relationships, plans and assets to it."
41
+ }), /* @__PURE__ */ o("form", {
42
+ onSubmit: (e) => {
43
+ if (e.preventDefault(), O(null), !p.trim()) {
44
+ O("A provider name is required.");
45
+ return;
46
+ }
47
+ let t = T.split(",").map((e) => e.trim()).filter(Boolean), n = {
48
+ name: p.trim(),
49
+ category: h,
50
+ ..._.trim() ? { description: _.trim() } : {},
51
+ ...y.trim() ? { websiteUrl: y.trim() } : {},
52
+ ...x.trim() ? { region: x.trim() } : {},
53
+ ...C.trim() ? { industry: C.trim() } : {},
54
+ ...t.length ? { tags: t } : {}
55
+ };
56
+ f.mutate(n, {
57
+ onSuccess: (e) => d(`/providers/${e.id}`),
58
+ onError: (e) => O(e instanceof Error ? e.message : "Could not create provider.")
59
+ });
60
+ },
61
+ className: "max-w-2xl space-y-5",
62
+ children: [
63
+ D && /* @__PURE__ */ a("div", {
64
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
65
+ children: D
66
+ }),
67
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ o("label", {
68
+ htmlFor: "prov-name",
69
+ className: u,
70
+ children: ["Name ", /* @__PURE__ */ a("span", {
71
+ className: "text-status-error-text",
72
+ children: "*"
73
+ })]
74
+ }), /* @__PURE__ */ a("input", {
75
+ id: "prov-name",
76
+ type: "text",
77
+ value: p,
78
+ onChange: (e) => m(e.target.value),
79
+ placeholder: "e.g. OpenAI, Netflix, AWS",
80
+ className: l,
81
+ required: !0
82
+ })] }),
83
+ /* @__PURE__ */ o("div", {
84
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
85
+ children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
86
+ htmlFor: "prov-category",
87
+ className: u,
88
+ children: "Category"
89
+ }), /* @__PURE__ */ a("select", {
90
+ id: "prov-category",
91
+ value: h,
92
+ onChange: (e) => g(e.target.value),
93
+ className: l,
94
+ children: c.map((e) => /* @__PURE__ */ a("option", {
95
+ value: e,
96
+ children: e.replace(/_/g, " ")
97
+ }, e))
98
+ })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
99
+ htmlFor: "prov-website",
100
+ className: u,
101
+ children: "Website"
102
+ }), /* @__PURE__ */ a("input", {
103
+ id: "prov-website",
104
+ type: "url",
105
+ value: y,
106
+ onChange: (e) => b(e.target.value),
107
+ placeholder: "https://…",
108
+ className: l
109
+ })] })]
110
+ }),
111
+ /* @__PURE__ */ o("div", {
112
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
113
+ children: [/* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
114
+ htmlFor: "prov-region",
115
+ className: u,
116
+ children: "Region"
117
+ }), /* @__PURE__ */ a("input", {
118
+ id: "prov-region",
119
+ type: "text",
120
+ value: x,
121
+ onChange: (e) => S(e.target.value),
122
+ placeholder: "e.g. Global, US, EU",
123
+ className: l
124
+ })] }), /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
125
+ htmlFor: "prov-industry",
126
+ className: u,
127
+ children: "Industry"
128
+ }), /* @__PURE__ */ a("input", {
129
+ id: "prov-industry",
130
+ type: "text",
131
+ value: C,
132
+ onChange: (e) => w(e.target.value),
133
+ placeholder: "e.g. Cloud, Media",
134
+ className: l
135
+ })] })]
136
+ }),
137
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ a("label", {
138
+ htmlFor: "prov-desc",
139
+ className: u,
140
+ children: "Description"
141
+ }), /* @__PURE__ */ a("textarea", {
142
+ id: "prov-desc",
143
+ value: _,
144
+ onChange: (e) => v(e.target.value),
145
+ rows: 3,
146
+ placeholder: "What does this provider offer?",
147
+ className: l
148
+ })] }),
149
+ /* @__PURE__ */ o("div", { children: [/* @__PURE__ */ o("label", {
150
+ htmlFor: "prov-tags",
151
+ className: u,
152
+ children: ["Tags ", /* @__PURE__ */ a("span", {
153
+ className: "text-text-secondary",
154
+ children: "(comma-separated)"
155
+ })]
156
+ }), /* @__PURE__ */ a("input", {
157
+ id: "prov-tags",
158
+ type: "text",
159
+ value: T,
160
+ onChange: (e) => E(e.target.value),
161
+ placeholder: "ai, productivity, enterprise",
162
+ className: l
163
+ })] }),
164
+ /* @__PURE__ */ o("div", {
165
+ className: "flex gap-3",
166
+ children: [/* @__PURE__ */ a("button", {
167
+ type: "submit",
168
+ disabled: f.isPending,
169
+ className: "rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
170
+ children: f.isPending ? "Creating…" : "Create provider"
171
+ }), /* @__PURE__ */ a("button", {
172
+ type: "button",
173
+ onClick: () => d("/providers"),
174
+ className: "rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken",
175
+ children: "Cancel"
176
+ })]
177
+ })
178
+ ]
179
+ })]
180
+ });
181
+ }
182
+ //#endregion
183
+ export { d as ProviderNewPage };
184
+
185
+ //# sourceMappingURL=ProviderNewPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProviderNewPage.js","names":[],"sources":["../../../../src/subscriberbot/pages/providers/ProviderNewPage.tsx"],"sourcesContent":["/**\n * Create provider\n * @module subscriberbot/pages/providers\n *\n * Add a provider to the registry. Writes `subCreateProvider`.\n */\n\nimport { useState } from 'react';\nimport { ArrowLeft } from 'lucide-react';\nimport { PagePurpose } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { useSubscriberBot } from '../../context/SubscriberBotContext';\nimport { useCreateProvider } from '../../hooks/useSubscriberBotApi';\nimport type { SubCreateProviderInput, SubProviderCategory } from '../../types';\n\nconst CATEGORIES: SubProviderCategory[] = [\n 'SAAS',\n 'AI_SERVICE',\n 'STREAMING',\n 'NEWSLETTER',\n 'NEWS_DIGEST',\n 'MEMBERSHIP',\n 'COMMUNITY',\n 'EDUCATION',\n 'FINANCIAL',\n 'INSURANCE',\n 'TELECOM',\n 'UTILITY',\n 'ASSOCIATION',\n 'LICENSE',\n 'CONTRACT',\n 'OTHER',\n];\n\nconst inputCls =\n '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)]';\nconst labelCls = 'mb-1 block text-xs font-medium text-text-secondary';\n\nexport function ProviderNewPage() {\n const { navigateTo } = useSubscriberBot();\n const create = useCreateProvider();\n\n const [name, setName] = useState('');\n const [category, setCategory] = useState<SubProviderCategory>('SAAS');\n const [description, setDescription] = useState('');\n const [websiteUrl, setWebsiteUrl] = useState('');\n const [region, setRegion] = useState('');\n const [industry, setIndustry] = useState('');\n const [tags, setTags] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n setFormError(null);\n if (!name.trim()) {\n setFormError('A provider name is required.');\n return;\n }\n const parsedTags = tags\n .split(',')\n .map((t) => t.trim())\n .filter(Boolean);\n const input: SubCreateProviderInput = {\n name: name.trim(),\n category,\n ...(description.trim() ? { description: description.trim() } : {}),\n ...(websiteUrl.trim() ? { websiteUrl: websiteUrl.trim() } : {}),\n ...(region.trim() ? { region: region.trim() } : {}),\n ...(industry.trim() ? { industry: industry.trim() } : {}),\n ...(parsedTags.length ? { tags: parsedTags } : {}),\n };\n create.mutate(input, {\n onSuccess: (provider) => navigateTo(`/providers/${provider.id}`),\n onError: (err) =>\n setFormError(err instanceof Error ? err.message : 'Could not create provider.'),\n });\n };\n\n return (\n <PageLayout\n title=\"Add provider\"\n description=\"Register a new provider in the registry\"\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"inline-flex items-center gap-2 rounded-lg border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" /> Back\n </button>\n }\n >\n <PagePurpose className=\"mb-6\">\n Add a provider that isn't in the registry yet so you can attach relationships, plans and\n assets to it.\n </PagePurpose>\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-5\">\n {formError && (\n <div className=\"rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text\">\n {formError}\n </div>\n )}\n\n <div>\n <label htmlFor=\"prov-name\" className={labelCls}>\n Name <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"prov-name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"e.g. OpenAI, Netflix, AWS\"\n className={inputCls}\n required\n />\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"prov-category\" className={labelCls}>\n Category\n </label>\n <select\n id=\"prov-category\"\n value={category}\n onChange={(e) => setCategory(e.target.value as SubProviderCategory)}\n className={inputCls}\n >\n {CATEGORIES.map((c) => (\n <option key={c} value={c}>\n {c.replace(/_/g, ' ')}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label htmlFor=\"prov-website\" className={labelCls}>\n Website\n </label>\n <input\n id=\"prov-website\"\n type=\"url\"\n value={websiteUrl}\n onChange={(e) => setWebsiteUrl(e.target.value)}\n placeholder=\"https://…\"\n className={inputCls}\n />\n </div>\n </div>\n\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2\">\n <div>\n <label htmlFor=\"prov-region\" className={labelCls}>\n Region\n </label>\n <input\n id=\"prov-region\"\n type=\"text\"\n value={region}\n onChange={(e) => setRegion(e.target.value)}\n placeholder=\"e.g. Global, US, EU\"\n className={inputCls}\n />\n </div>\n <div>\n <label htmlFor=\"prov-industry\" className={labelCls}>\n Industry\n </label>\n <input\n id=\"prov-industry\"\n type=\"text\"\n value={industry}\n onChange={(e) => setIndustry(e.target.value)}\n placeholder=\"e.g. Cloud, Media\"\n className={inputCls}\n />\n </div>\n </div>\n\n <div>\n <label htmlFor=\"prov-desc\" className={labelCls}>\n Description\n </label>\n <textarea\n id=\"prov-desc\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={3}\n placeholder=\"What does this provider offer?\"\n className={inputCls}\n />\n </div>\n\n <div>\n <label htmlFor=\"prov-tags\" className={labelCls}>\n Tags <span className=\"text-text-secondary\">(comma-separated)</span>\n </label>\n <input\n id=\"prov-tags\"\n type=\"text\"\n value={tags}\n onChange={(e) => setTags(e.target.value)}\n placeholder=\"ai, productivity, enterprise\"\n className={inputCls}\n />\n </div>\n\n <div className=\"flex gap-3\">\n <button\n type=\"submit\"\n disabled={create.isPending}\n className=\"rounded-lg bg-action-primary-bg px-5 py-2.5 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50\"\n >\n {create.isPending ? 'Creating…' : 'Create provider'}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo('/providers')}\n className=\"rounded-lg border border-border-subtle px-5 py-2.5 text-sm font-medium text-text-primary hover:bg-bg-sunken\"\n >\n Cancel\n </button>\n </div>\n </form>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,254 @@
1
+ import { useSubscriberBot as e } from "../../context/SubscriberBotContext.js";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { formatEnumLabel as r } from "../../utils/formatters.js";
5
+ import { StatusBadge as i } from "../../components/StatusBadge.js";
6
+ import { EmptyState as a } from "../../components/EmptyState.js";
7
+ import { ErrorView as o, LoadingView as s } from "../../components/StateViews.js";
8
+ import { useProviders as c } from "../../hooks/useSubscriberBotApi.js";
9
+ import { useState as l } from "react";
10
+ import { Building2 as u, Plus as d, Search as f, ShieldCheck as p } from "lucide-react";
11
+ import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
12
+ import { EmphasisPanel as _, PagePurpose as v } from "@burdenoff/fe-libs/ui";
13
+ //#region src/subscriberbot/pages/providers/ProvidersListPage.tsx
14
+ var y = 24, b = [
15
+ {
16
+ value: "",
17
+ label: "All categories"
18
+ },
19
+ {
20
+ value: "SAAS",
21
+ label: "SaaS"
22
+ },
23
+ {
24
+ value: "AI_SERVICE",
25
+ label: "AI service"
26
+ },
27
+ {
28
+ value: "STREAMING",
29
+ label: "Streaming"
30
+ },
31
+ {
32
+ value: "NEWSLETTER",
33
+ label: "Newsletter"
34
+ },
35
+ {
36
+ value: "NEWS_DIGEST",
37
+ label: "News digest"
38
+ },
39
+ {
40
+ value: "MEMBERSHIP",
41
+ label: "Membership"
42
+ },
43
+ {
44
+ value: "COMMUNITY",
45
+ label: "Community"
46
+ },
47
+ {
48
+ value: "EDUCATION",
49
+ label: "Education"
50
+ },
51
+ {
52
+ value: "FINANCIAL",
53
+ label: "Financial"
54
+ },
55
+ {
56
+ value: "INSURANCE",
57
+ label: "Insurance"
58
+ },
59
+ {
60
+ value: "TELECOM",
61
+ label: "Telecom"
62
+ },
63
+ {
64
+ value: "UTILITY",
65
+ label: "Utility"
66
+ },
67
+ {
68
+ value: "ASSOCIATION",
69
+ label: "Association"
70
+ },
71
+ {
72
+ value: "LICENSE",
73
+ label: "License"
74
+ },
75
+ {
76
+ value: "CONTRACT",
77
+ label: "Contract"
78
+ },
79
+ {
80
+ value: "OTHER",
81
+ label: "Other"
82
+ }
83
+ ], x = [
84
+ {
85
+ value: "",
86
+ label: "Any status"
87
+ },
88
+ {
89
+ value: "VERIFIED",
90
+ label: "Verified"
91
+ },
92
+ {
93
+ value: "CLAIMED",
94
+ label: "Claimed"
95
+ },
96
+ {
97
+ value: "UNVERIFIED",
98
+ label: "Unverified"
99
+ },
100
+ {
101
+ value: "DEPRECATED",
102
+ label: "Deprecated"
103
+ }
104
+ ];
105
+ function S() {
106
+ let { navigateTo: S } = e(), [C, w] = l(0), [T, E] = l(""), [D, O] = l(""), [k, A] = l(""), [j, M] = l(""), { data: N, isLoading: P, isError: F, refetch: I, isFetching: L } = c({
107
+ search: T || void 0,
108
+ category: k || void 0,
109
+ status: j || void 0,
110
+ pagination: {
111
+ limit: y,
112
+ offset: C * y
113
+ }
114
+ }), R = N?.items ?? [], z = N?.pageInfo.hasMore ?? !1;
115
+ return /* @__PURE__ */ g(n, {
116
+ title: "Providers",
117
+ description: "Discover and browse the global provider registry",
118
+ actions: /* @__PURE__ */ g("button", {
119
+ type: "button",
120
+ onClick: () => S("/providers/new"),
121
+ className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
122
+ children: [/* @__PURE__ */ h(d, { className: "h-4 w-4" }), " Add provider"]
123
+ }),
124
+ children: [
125
+ /* @__PURE__ */ h(v, {
126
+ className: "mb-4",
127
+ children: "The registry is the public face of the Subscription Knowledge Graph — every provider exists here whether or not it integrates. Search and filter to find the ones you have relationships with, or add a new one."
128
+ }),
129
+ /* @__PURE__ */ h(_, { children: /* @__PURE__ */ g("form", {
130
+ onSubmit: (e) => {
131
+ e.preventDefault(), E(D.trim()), w(0);
132
+ },
133
+ className: "relative",
134
+ children: [/* @__PURE__ */ h(f, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-text-secondary" }), /* @__PURE__ */ h("input", {
135
+ type: "text",
136
+ placeholder: "Search providers by name…",
137
+ value: D,
138
+ onChange: (e) => O(e.target.value),
139
+ className: "w-full rounded-lg border border-border-subtle bg-bg-surface py-2.5 pl-10 pr-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
140
+ })]
141
+ }) }),
142
+ /* @__PURE__ */ g("div", {
143
+ className: "mt-4 flex flex-wrap items-center gap-3",
144
+ children: [/* @__PURE__ */ h("select", {
145
+ value: k,
146
+ onChange: (e) => {
147
+ A(e.target.value), w(0);
148
+ },
149
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
150
+ children: b.map((e) => /* @__PURE__ */ h("option", {
151
+ value: e.value,
152
+ children: e.label
153
+ }, e.value))
154
+ }), /* @__PURE__ */ h("select", {
155
+ value: j,
156
+ onChange: (e) => {
157
+ M(e.target.value), w(0);
158
+ },
159
+ className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
160
+ children: x.map((e) => /* @__PURE__ */ h("option", {
161
+ value: e.value,
162
+ children: e.label
163
+ }, e.value))
164
+ })]
165
+ }),
166
+ P ? /* @__PURE__ */ h(s, { label: "Loading providers…" }) : F ? /* @__PURE__ */ h(o, {
167
+ message: "Could not load the provider registry.",
168
+ onRetry: () => void I()
169
+ }) : R.length === 0 ? /* @__PURE__ */ h("div", {
170
+ className: "mt-6",
171
+ children: /* @__PURE__ */ h(a, {
172
+ illustration: "empty-search",
173
+ icon: /* @__PURE__ */ h(u, { className: "h-12 w-12" }),
174
+ title: "No providers found",
175
+ description: T ? `No providers match "${T}".` : "No providers in the registry with these filters yet.",
176
+ action: /* @__PURE__ */ h("button", {
177
+ type: "button",
178
+ onClick: () => S("/providers/new"),
179
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
180
+ children: "Add provider"
181
+ })
182
+ })
183
+ }) : /* @__PURE__ */ g(m, { children: [/* @__PURE__ */ h("div", {
184
+ className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
185
+ children: R.map((e) => /* @__PURE__ */ g("button", {
186
+ type: "button",
187
+ onClick: () => S(`/providers/${e.id}`),
188
+ className: "flex flex-col rounded-lg border border-border-subtle bg-bg-surface p-4 text-left transition-shadow hover:shadow-md",
189
+ children: [
190
+ /* @__PURE__ */ g("div", {
191
+ className: "flex items-start justify-between gap-2",
192
+ children: [/* @__PURE__ */ h("span", {
193
+ className: "flex size-9 items-center justify-center rounded-lg bg-[var(--color-accent-soft)] text-text-primary",
194
+ children: /* @__PURE__ */ h(u, { className: "h-4 w-4" })
195
+ }), /* @__PURE__ */ h(i, { status: e.status })]
196
+ }),
197
+ /* @__PURE__ */ h("p", {
198
+ className: "mt-3 truncate text-sm font-semibold text-text-primary",
199
+ children: e.name
200
+ }),
201
+ /* @__PURE__ */ h("p", {
202
+ className: "text-xs text-text-secondary",
203
+ children: r(e.category)
204
+ }),
205
+ e.description && /* @__PURE__ */ h("p", {
206
+ className: "mt-2 line-clamp-2 text-xs text-text-secondary",
207
+ children: e.description
208
+ }),
209
+ /* @__PURE__ */ g("div", {
210
+ className: "mt-3 flex flex-wrap items-center gap-2 text-xs text-text-secondary",
211
+ children: [e.region && /* @__PURE__ */ h("span", { children: e.region }), e.vendorHealthScore != null && /* @__PURE__ */ g("span", {
212
+ className: "inline-flex items-center gap-1",
213
+ children: [
214
+ /* @__PURE__ */ h(p, { className: "h-3 w-3" }),
215
+ e.vendorHealthScore,
216
+ "/100"
217
+ ]
218
+ })]
219
+ })
220
+ ]
221
+ }, e.id))
222
+ }), /* @__PURE__ */ g("div", {
223
+ className: "mt-4 flex items-center justify-between",
224
+ children: [/* @__PURE__ */ g("p", {
225
+ className: "text-xs text-text-secondary",
226
+ children: [
227
+ "Page ",
228
+ C + 1,
229
+ L ? " · refreshing…" : ""
230
+ ]
231
+ }), /* @__PURE__ */ g("div", {
232
+ className: "flex gap-2",
233
+ children: [/* @__PURE__ */ h("button", {
234
+ type: "button",
235
+ disabled: C === 0,
236
+ onClick: () => w((e) => Math.max(0, e - 1)),
237
+ className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", C === 0 ? "cursor-not-allowed text-text-secondary opacity-50" : "text-text-primary hover:bg-bg-sunken"),
238
+ children: "Previous"
239
+ }), /* @__PURE__ */ h("button", {
240
+ type: "button",
241
+ disabled: !z,
242
+ onClick: () => w((e) => e + 1),
243
+ className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", z ? "text-text-primary hover:bg-bg-sunken" : "cursor-not-allowed text-text-secondary opacity-50"),
244
+ children: "Next"
245
+ })]
246
+ })]
247
+ })] })
248
+ ]
249
+ });
250
+ }
251
+ //#endregion
252
+ export { S as ProvidersListPage };
253
+
254
+ //# sourceMappingURL=ProvidersListPage.js.map