@burdenoff/microfe-subscriberbot 2026.706.1 → 2026.706.3

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 (38) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.js +14 -6
  2. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  3. package/dist/subscriberbot/components/Modal.js +51 -0
  4. package/dist/subscriberbot/components/Modal.js.map +1 -0
  5. package/dist/subscriberbot/components/index.js +7 -0
  6. package/dist/subscriberbot/components/viz.js +196 -0
  7. package/dist/subscriberbot/components/viz.js.map +1 -0
  8. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +364 -161
  9. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  10. package/dist/subscriberbot/pages/AssetVaultPage.js +182 -0
  11. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -0
  12. package/dist/subscriberbot/pages/DashboardPage.js +272 -199
  13. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  14. package/dist/subscriberbot/pages/InboxPage.js +682 -126
  15. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  16. package/dist/subscriberbot/pages/InsightsPage.js +220 -0
  17. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -0
  18. package/dist/subscriberbot/pages/InvoicesPage.js +592 -81
  19. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  20. package/dist/subscriberbot/pages/WorkflowsPage.js +344 -169
  21. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  22. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +401 -116
  23. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  24. package/dist/subscriberbot/pages/agents/AgentsListPage.js +185 -93
  25. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  26. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +735 -135
  27. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  28. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +217 -153
  29. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +216 -111
  31. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +902 -250
  33. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  34. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +242 -192
  35. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  36. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +174 -131
  37. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  38. package/package.json +1 -1
@@ -1,179 +1,779 @@
1
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";
2
+ import { cn as t } from "../../utils/cn.js";
3
+ import { PageLayout as n } from "../../components/PageLayout.js";
4
+ import { formatCurrency as r, formatEnumLabel as i, formatIntervalSuffix as a } from "../../utils/formatters.js";
5
+ import { StatusBadge as o } from "../../components/StatusBadge.js";
6
+ import { EmptyState as s } from "../../components/EmptyState.js";
7
+ import { Modal as c } from "../../components/Modal.js";
8
+ import { ErrorView as l, LoadingView as u, Section as d } from "../../components/StateViews.js";
9
+ import { Gauge as f, MiniProgress as p } from "../../components/viz.js";
10
+ import "../../components/index.js";
11
+ import { useArchiveProvider as m, useCreatePlan as h, useProvider as g, useUpdateProvider as _ } from "../../hooks/useSubscriberBotApi.js";
12
+ import { useState as v } from "react";
13
+ import { Archive as y, ArrowLeft as b, Building2 as x, Check as S, Globe as C, Layers as w, Pencil as T, Plus as E, ShieldCheck as D, Sparkles as O, Tag as k, TrendingDown as A } from "lucide-react";
14
+ import { useParams as j } from "react-router-dom";
15
+ import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
16
+ import { GlassCard as F } from "@burdenoff/fe-libs/ui";
12
17
  //#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, {
18
+ var I = "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)]", L = "mb-1 block text-xs font-medium text-text-secondary", R = [
19
+ "SAAS",
20
+ "AI_SERVICE",
21
+ "STREAMING",
22
+ "NEWSLETTER",
23
+ "NEWS_DIGEST",
24
+ "MEMBERSHIP",
25
+ "COMMUNITY",
26
+ "EDUCATION",
27
+ "FINANCIAL",
28
+ "INSURANCE",
29
+ "TELECOM",
30
+ "UTILITY",
31
+ "ASSOCIATION",
32
+ "LICENSE",
33
+ "CONTRACT",
34
+ "OTHER"
35
+ ], z = [
36
+ "UNVERIFIED",
37
+ "VERIFIED",
38
+ "CLAIMED",
39
+ "DEPRECATED"
40
+ ], B = [
41
+ "MONTHLY",
42
+ "YEARLY",
43
+ "QUARTERLY",
44
+ "WEEKLY",
45
+ "DAILY",
46
+ "USAGE_BASED",
47
+ "LIFETIME",
48
+ "FREE"
49
+ ];
50
+ function V(e) {
51
+ return e >= 70 ? {
52
+ label: "Healthy",
53
+ cls: "bg-status-success-bg-subtle text-status-success-text"
54
+ } : e >= 45 ? {
55
+ label: "Fair",
56
+ cls: "bg-status-warning-bg-subtle text-status-warning-text"
57
+ } : {
58
+ label: "At risk",
59
+ cls: "bg-status-error-bg-subtle text-status-error-text"
60
+ };
61
+ }
62
+ function H(e) {
63
+ return e >= 67 ? {
64
+ label: "High",
65
+ chip: "bg-status-error-bg-subtle text-status-error-text",
66
+ tone: "negative"
67
+ } : e >= 34 ? {
68
+ label: "Moderate",
69
+ chip: "bg-status-warning-bg-subtle text-status-warning-text",
70
+ tone: "warning"
71
+ } : {
72
+ label: "Low",
73
+ chip: "bg-status-success-bg-subtle text-status-success-text",
74
+ tone: "positive"
75
+ };
76
+ }
77
+ function U({ provider: e, onClose: t }) {
78
+ let n = _(), [r, i] = v(e.name), [a, o] = v(e.category), [s, l] = v(e.status), [u, d] = v(e.description ?? ""), [f, p] = v(e.industry ?? ""), [m, h] = v(e.region ?? ""), [g, y] = v(e.language ?? ""), [b, x] = v(e.websiteUrl ?? ""), [S, C] = v(e.churnRiskScore == null ? "" : String(e.churnRiskScore)), [w, T] = v(e.vendorHealthScore == null ? "" : String(e.vendorHealthScore)), [E, D] = v(e.tags.join(", ")), [O, k] = v(null);
79
+ return /* @__PURE__ */ N(c, {
80
+ title: "Edit provider",
81
+ onClose: t,
82
+ maxWidthClassName: "max-w-2xl",
83
+ children: /* @__PURE__ */ P("form", {
84
+ onSubmit: (i) => {
85
+ if (i.preventDefault(), k(null), !r.trim()) {
86
+ k("A provider name is required.");
87
+ return;
88
+ }
89
+ let o = E.split(",").map((e) => e.trim()).filter(Boolean), c = {
90
+ name: r.trim(),
91
+ category: a,
92
+ status: s,
93
+ description: u.trim(),
94
+ tags: o,
95
+ ...f.trim() ? { industry: f.trim() } : {},
96
+ ...m.trim() ? { region: m.trim() } : {},
97
+ ...g.trim() ? { language: g.trim() } : {},
98
+ ...b.trim() ? { websiteUrl: b.trim() } : {},
99
+ ...S.trim() ? { churnRiskScore: Number(S) } : {},
100
+ ...w.trim() ? { vendorHealthScore: Number(w) } : {}
101
+ };
102
+ n.mutate({
103
+ id: e.id,
104
+ input: c
105
+ }, {
106
+ onSuccess: () => t(),
107
+ onError: (e) => k(e instanceof Error ? e.message : "Could not update provider.")
108
+ });
109
+ },
110
+ className: "space-y-4",
111
+ children: [
112
+ O && /* @__PURE__ */ N("div", {
113
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
114
+ children: O
115
+ }),
116
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
117
+ htmlFor: "prov-edit-name",
118
+ className: L,
119
+ children: ["Name ", /* @__PURE__ */ N("span", {
120
+ className: "text-status-error-text",
121
+ children: "*"
122
+ })]
123
+ }), /* @__PURE__ */ N("input", {
124
+ id: "prov-edit-name",
125
+ type: "text",
126
+ value: r,
127
+ onChange: (e) => i(e.target.value),
128
+ className: I,
129
+ required: !0
130
+ })] }),
131
+ /* @__PURE__ */ P("div", {
132
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
133
+ children: [/* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
134
+ htmlFor: "prov-edit-category",
135
+ className: L,
136
+ children: "Category"
137
+ }), /* @__PURE__ */ N("select", {
138
+ id: "prov-edit-category",
139
+ value: a,
140
+ onChange: (e) => o(e.target.value),
141
+ className: I,
142
+ children: R.map((e) => /* @__PURE__ */ N("option", {
143
+ value: e,
144
+ children: e.replace(/_/g, " ")
145
+ }, e))
146
+ })] }), /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
147
+ htmlFor: "prov-edit-status",
148
+ className: L,
149
+ children: "Status"
150
+ }), /* @__PURE__ */ N("select", {
151
+ id: "prov-edit-status",
152
+ value: s,
153
+ onChange: (e) => l(e.target.value),
154
+ className: I,
155
+ children: z.map((e) => /* @__PURE__ */ N("option", {
156
+ value: e,
157
+ children: e.replace(/_/g, " ")
158
+ }, e))
159
+ })] })]
160
+ }),
161
+ /* @__PURE__ */ P("div", {
162
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
163
+ children: [
164
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
165
+ htmlFor: "prov-edit-industry",
166
+ className: L,
167
+ children: "Industry"
168
+ }), /* @__PURE__ */ N("input", {
169
+ id: "prov-edit-industry",
170
+ type: "text",
171
+ value: f,
172
+ onChange: (e) => p(e.target.value),
173
+ className: I
174
+ })] }),
175
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
176
+ htmlFor: "prov-edit-region",
177
+ className: L,
178
+ children: "Region"
179
+ }), /* @__PURE__ */ N("input", {
180
+ id: "prov-edit-region",
181
+ type: "text",
182
+ value: m,
183
+ onChange: (e) => h(e.target.value),
184
+ className: I
185
+ })] }),
186
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
187
+ htmlFor: "prov-edit-language",
188
+ className: L,
189
+ children: "Language"
190
+ }), /* @__PURE__ */ N("input", {
191
+ id: "prov-edit-language",
192
+ type: "text",
193
+ value: g,
194
+ onChange: (e) => y(e.target.value),
195
+ className: I
196
+ })] })
197
+ ]
198
+ }),
199
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
200
+ htmlFor: "prov-edit-website",
201
+ className: L,
202
+ children: "Website"
203
+ }), /* @__PURE__ */ N("input", {
204
+ id: "prov-edit-website",
205
+ type: "url",
206
+ value: b,
207
+ onChange: (e) => x(e.target.value),
208
+ placeholder: "https://…",
209
+ className: I
210
+ })] }),
211
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
212
+ htmlFor: "prov-edit-desc",
213
+ className: L,
214
+ children: "Description"
215
+ }), /* @__PURE__ */ N("textarea", {
216
+ id: "prov-edit-desc",
217
+ value: u,
218
+ onChange: (e) => d(e.target.value),
219
+ rows: 3,
220
+ className: I
221
+ })] }),
222
+ /* @__PURE__ */ P("div", {
223
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
224
+ children: [/* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
225
+ htmlFor: "prov-edit-churn",
226
+ className: L,
227
+ children: "Churn risk (0–100)"
228
+ }), /* @__PURE__ */ N("input", {
229
+ id: "prov-edit-churn",
230
+ type: "number",
231
+ min: "0",
232
+ max: "100",
233
+ value: S,
234
+ onChange: (e) => C(e.target.value),
235
+ className: I
236
+ })] }), /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
237
+ htmlFor: "prov-edit-health",
238
+ className: L,
239
+ children: "Vendor health (0–100)"
240
+ }), /* @__PURE__ */ N("input", {
241
+ id: "prov-edit-health",
242
+ type: "number",
243
+ min: "0",
244
+ max: "100",
245
+ value: w,
246
+ onChange: (e) => T(e.target.value),
247
+ className: I
248
+ })] })]
249
+ }),
250
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
251
+ htmlFor: "prov-edit-tags",
252
+ className: L,
253
+ children: ["Tags ", /* @__PURE__ */ N("span", {
254
+ className: "text-text-secondary",
255
+ children: "(comma-separated)"
256
+ })]
257
+ }), /* @__PURE__ */ N("input", {
258
+ id: "prov-edit-tags",
259
+ type: "text",
260
+ value: E,
261
+ onChange: (e) => D(e.target.value),
262
+ className: I
263
+ })] }),
264
+ /* @__PURE__ */ P("div", {
265
+ className: "flex justify-end gap-3",
266
+ children: [/* @__PURE__ */ N("button", {
267
+ type: "button",
268
+ onClick: t,
269
+ className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
270
+ children: "Cancel"
271
+ }), /* @__PURE__ */ N("button", {
272
+ type: "submit",
273
+ disabled: n.isPending,
274
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
275
+ children: n.isPending ? "Saving…" : "Save changes"
276
+ })]
277
+ })
278
+ ]
279
+ })
280
+ });
281
+ }
282
+ function W({ providerId: e, onClose: t }) {
283
+ let n = h(), [r, i] = v(""), [a, o] = v(""), [s, l] = v("USD"), [u, d] = v("MONTHLY"), [f, p] = v(""), [m, g] = v(""), [_, y] = v(!0), [b, x] = v(null);
284
+ return /* @__PURE__ */ N(c, {
285
+ title: "Add plan",
286
+ onClose: t,
287
+ maxWidthClassName: "max-w-xl",
288
+ children: /* @__PURE__ */ P("form", {
289
+ onSubmit: (i) => {
290
+ if (i.preventDefault(), x(null), !r.trim()) {
291
+ x("A plan name is required.");
292
+ return;
293
+ }
294
+ let o = m.split("\n").map((e) => e.trim()).filter(Boolean);
295
+ n.mutate({
296
+ providerId: e,
297
+ name: r.trim(),
298
+ interval: u,
299
+ currency: s.trim() || "USD",
300
+ ...a.trim() ? { amount: Number(a) } : {},
301
+ ...f.trim() ? { description: f.trim() } : {},
302
+ ...o.length ? { features: o } : {}
303
+ }, {
304
+ onSuccess: () => t(),
305
+ onError: (e) => x(e instanceof Error ? e.message : "Could not add plan.")
306
+ });
307
+ },
308
+ className: "space-y-4",
309
+ children: [
310
+ b && /* @__PURE__ */ N("div", {
311
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
312
+ children: b
313
+ }),
314
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
315
+ htmlFor: "plan-name",
316
+ className: L,
317
+ children: ["Name ", /* @__PURE__ */ N("span", {
318
+ className: "text-status-error-text",
319
+ children: "*"
320
+ })]
321
+ }), /* @__PURE__ */ N("input", {
322
+ id: "plan-name",
323
+ type: "text",
324
+ value: r,
325
+ onChange: (e) => i(e.target.value),
326
+ placeholder: "e.g. Pro, Team, Enterprise",
327
+ className: I,
328
+ required: !0
329
+ })] }),
330
+ /* @__PURE__ */ P("div", {
331
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
332
+ children: [
333
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
334
+ htmlFor: "plan-amount",
335
+ className: L,
336
+ children: "Amount"
337
+ }), /* @__PURE__ */ N("input", {
338
+ id: "plan-amount",
339
+ type: "number",
340
+ min: "0",
341
+ step: "0.01",
342
+ value: a,
343
+ onChange: (e) => o(e.target.value),
344
+ placeholder: "0.00",
345
+ className: I
346
+ })] }),
347
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
348
+ htmlFor: "plan-currency",
349
+ className: L,
350
+ children: "Currency"
351
+ }), /* @__PURE__ */ N("input", {
352
+ id: "plan-currency",
353
+ type: "text",
354
+ value: s,
355
+ onChange: (e) => l(e.target.value.toUpperCase()),
356
+ maxLength: 3,
357
+ className: I
358
+ })] }),
359
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
360
+ htmlFor: "plan-interval",
361
+ className: L,
362
+ children: "Interval"
363
+ }), /* @__PURE__ */ N("select", {
364
+ id: "plan-interval",
365
+ value: u,
366
+ onChange: (e) => d(e.target.value),
367
+ className: I,
368
+ children: B.map((e) => /* @__PURE__ */ N("option", {
369
+ value: e,
370
+ children: e.replace(/_/g, " ")
371
+ }, e))
372
+ })] })
373
+ ]
374
+ }),
375
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
376
+ htmlFor: "plan-desc",
377
+ className: L,
378
+ children: "Description"
379
+ }), /* @__PURE__ */ N("textarea", {
380
+ id: "plan-desc",
381
+ value: f,
382
+ onChange: (e) => p(e.target.value),
383
+ rows: 2,
384
+ className: I
385
+ })] }),
386
+ /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
387
+ htmlFor: "plan-features",
388
+ className: L,
389
+ children: ["Features ", /* @__PURE__ */ N("span", {
390
+ className: "text-text-secondary",
391
+ children: "(one per line)"
392
+ })]
393
+ }), /* @__PURE__ */ N("textarea", {
394
+ id: "plan-features",
395
+ value: m,
396
+ onChange: (e) => g(e.target.value),
397
+ rows: 3,
398
+ placeholder: "Unlimited projects\nPriority support\nSSO",
399
+ className: I
400
+ })] }),
401
+ /* @__PURE__ */ P("label", {
402
+ className: "flex items-center gap-2 text-sm text-text-primary",
403
+ children: [/* @__PURE__ */ N("input", {
404
+ type: "checkbox",
405
+ checked: _,
406
+ onChange: (e) => y(e.target.checked),
407
+ className: "size-4 rounded border-border-subtle"
408
+ }), "Active"]
409
+ }),
410
+ /* @__PURE__ */ P("div", {
411
+ className: "flex justify-end gap-3",
412
+ children: [/* @__PURE__ */ N("button", {
413
+ type: "button",
414
+ onClick: t,
415
+ className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
416
+ children: "Cancel"
417
+ }), /* @__PURE__ */ N("button", {
418
+ type: "submit",
419
+ disabled: n.isPending,
420
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90 disabled:opacity-50",
421
+ children: n.isPending ? "Adding…" : "Add plan"
422
+ })]
423
+ })
424
+ ]
425
+ })
426
+ });
427
+ }
428
+ function G({ provider: t, onClose: n }) {
429
+ let { navigateTo: r } = e(), i = m(), [a, o] = v(null);
430
+ return /* @__PURE__ */ N(c, {
431
+ title: "Archive provider",
432
+ onClose: n,
433
+ children: /* @__PURE__ */ P("div", {
434
+ className: "space-y-4",
435
+ children: [
436
+ a && /* @__PURE__ */ N("div", {
437
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
438
+ children: a
439
+ }),
440
+ /* @__PURE__ */ P("p", {
441
+ className: "text-sm text-text-secondary",
442
+ children: [
443
+ "Archive ",
444
+ /* @__PURE__ */ N("span", {
445
+ className: "font-medium text-text-primary",
446
+ children: t.name
447
+ }),
448
+ "? It will be removed from the active registry. This can be reversed by an administrator."
449
+ ]
450
+ }),
451
+ /* @__PURE__ */ P("div", {
452
+ className: "flex justify-end gap-3",
453
+ children: [/* @__PURE__ */ N("button", {
454
+ type: "button",
455
+ onClick: n,
456
+ className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
457
+ children: "Cancel"
458
+ }), /* @__PURE__ */ N("button", {
459
+ type: "button",
460
+ onClick: () => {
461
+ o(null), i.mutate(t.id, {
462
+ onSuccess: () => r("/providers"),
463
+ onError: (e) => o(e instanceof Error ? e.message : "Could not archive this provider.")
464
+ });
465
+ },
466
+ disabled: i.isPending,
467
+ className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm font-medium text-status-error-text hover:opacity-90 disabled:opacity-50",
468
+ children: i.isPending ? "Archiving…" : "Archive provider"
469
+ })]
470
+ })
471
+ ]
472
+ })
473
+ });
474
+ }
475
+ function K() {
476
+ let { id: c } = j(), { navigateTo: m } = e(), { data: h, isLoading: _, isError: I, refetch: L } = g(c), [R, z] = v(!1), [B, K] = v(!1), [q, J] = v(!1);
477
+ if (_) return /* @__PURE__ */ N(n, {
16
478
  title: "Provider",
17
- children: /* @__PURE__ */ v(c, { label: "Loading provider…" })
479
+ children: /* @__PURE__ */ N(u, { label: "Loading provider…" })
18
480
  });
19
- if (T) return /* @__PURE__ */ v(t, {
481
+ if (I) return /* @__PURE__ */ N(n, {
20
482
  title: "Provider",
21
- children: /* @__PURE__ */ v(s, {
483
+ children: /* @__PURE__ */ N(l, {
22
484
  message: "Could not load this provider.",
23
- onRetry: () => void E()
485
+ onRetry: () => void L()
24
486
  })
25
487
  });
26
- if (!C) return /* @__PURE__ */ v(t, {
488
+ if (!h) return /* @__PURE__ */ N(n, {
27
489
  title: "Provider",
28
- children: /* @__PURE__ */ v(o, {
490
+ children: /* @__PURE__ */ N(s, {
29
491
  illustration: "empty-data",
30
492
  title: "Provider not found",
31
493
  description: "It may have been removed, or you may not have access to it.",
32
- action: /* @__PURE__ */ v("button", {
494
+ action: /* @__PURE__ */ N("button", {
33
495
  type: "button",
34
- onClick: () => S("/providers"),
496
+ onClick: () => m("/providers"),
35
497
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
36
498
  children: "Back to providers"
37
499
  })
38
500
  })
39
501
  });
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"]
502
+ let Y = h, X = Y.websiteUrl && /^https?:\/\//i.test(Y.websiteUrl) ? Y.websiteUrl : null, Z = Y.plans && Y.plans.length > 1 ? Y.plans.filter((e) => e.isActive && e.amount > 0).reduce((e, t) => e === null || t.amount < e.amount ? t : e, null)?.id ?? null : null;
503
+ return /* @__PURE__ */ P(n, {
504
+ title: Y.name,
505
+ description: i(Y.category),
506
+ actions: /* @__PURE__ */ P("div", {
507
+ className: "flex items-center gap-2",
508
+ children: [
509
+ /* @__PURE__ */ P("button", {
510
+ type: "button",
511
+ onClick: () => z(!0),
512
+ 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",
513
+ children: [/* @__PURE__ */ N(T, { className: "h-4 w-4" }), " Edit"]
514
+ }),
515
+ /* @__PURE__ */ P("button", {
516
+ type: "button",
517
+ onClick: () => J(!0),
518
+ className: "inline-flex items-center gap-2 rounded-lg border border-status-error-text/30 px-3 py-2 text-sm font-medium text-status-error-text hover:bg-status-error-bg-subtle",
519
+ children: [/* @__PURE__ */ N(y, { className: "h-4 w-4" }), " Archive"]
520
+ }),
521
+ /* @__PURE__ */ P("button", {
522
+ type: "button",
523
+ onClick: () => m("/providers"),
524
+ 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",
525
+ children: [/* @__PURE__ */ N(b, { className: "h-4 w-4" }), " Back"]
526
+ })
527
+ ]
49
528
  }),
50
529
  children: [
51
- /* @__PURE__ */ y("div", {
530
+ /* @__PURE__ */ P("div", {
52
531
  className: "flex flex-wrap items-center gap-3",
53
532
  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" })
533
+ /* @__PURE__ */ N("span", {
534
+ className: "flex size-11 items-center justify-center rounded-xl bg-[var(--color-accent-soft)] text-text-primary",
535
+ children: /* @__PURE__ */ N(x, { className: "h-5 w-5" })
536
+ }),
537
+ /* @__PURE__ */ N(o, { status: Y.status }),
538
+ Y.industry && /* @__PURE__ */ N("span", {
539
+ className: "text-sm text-text-secondary",
540
+ children: Y.industry
57
541
  }),
58
- /* @__PURE__ */ v(a, { status: D.status }),
59
- D.region && /* @__PURE__ */ v("span", {
542
+ Y.region && /* @__PURE__ */ P("span", {
60
543
  className: "text-sm text-text-secondary",
61
- children: D.region
544
+ children: ["· ", Y.region]
62
545
  }),
63
- D.websiteUrl && /* @__PURE__ */ y("a", {
64
- href: D.websiteUrl,
546
+ X && /* @__PURE__ */ P("a", {
547
+ href: X,
65
548
  target: "_blank",
66
- rel: "noreferrer",
549
+ rel: "noopener noreferrer",
67
550
  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"]
551
+ children: [/* @__PURE__ */ N(C, { className: "h-3.5 w-3.5" }), " Website"]
69
552
  })
70
553
  ]
71
554
  }),
72
- D.description && /* @__PURE__ */ v("p", {
73
- className: "mt-4 max-w-3xl text-sm text-text-secondary",
74
- children: D.description
555
+ Y.description && /* @__PURE__ */ N("p", {
556
+ className: "mt-4 max-w-3xl text-sm leading-relaxed text-text-secondary",
557
+ children: Y.description
75
558
  }),
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", {
559
+ Y.tags.length > 0 && /* @__PURE__ */ P("div", {
560
+ className: "mt-4 flex flex-wrap items-center gap-2",
561
+ children: [/* @__PURE__ */ N(k, { className: "h-3.5 w-3.5 text-text-secondary" }), Y.tags.map((e) => /* @__PURE__ */ N("span", {
128
562
  className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
129
563
  children: e
130
564
  }, e))]
131
565
  }),
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)
566
+ /* @__PURE__ */ P("div", {
567
+ className: "mt-6 grid grid-cols-1 gap-6 lg:grid-cols-3",
568
+ children: [/* @__PURE__ */ N("div", {
569
+ className: "lg:col-span-2",
570
+ children: /* @__PURE__ */ N(d, {
571
+ title: "Plans",
572
+ description: "Pricing this provider publishes",
573
+ action: /* @__PURE__ */ P("button", {
574
+ type: "button",
575
+ onClick: () => K(!0),
576
+ className: "inline-flex items-center gap-1.5 rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken",
577
+ children: [/* @__PURE__ */ N(E, { className: "h-3.5 w-3.5" }), " Add plan"]
578
+ }),
579
+ children: !Y.plans || Y.plans.length === 0 ? /* @__PURE__ */ N(s, {
580
+ illustration: "empty-data",
581
+ title: "No published plans",
582
+ description: "When this provider publishes plans, they'll appear here.",
583
+ action: /* @__PURE__ */ N("button", {
584
+ type: "button",
585
+ onClick: () => K(!0),
586
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
587
+ children: "Add plan"
588
+ })
589
+ }) : /* @__PURE__ */ N("div", {
590
+ className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
591
+ children: Y.plans.map((e) => {
592
+ let t = e.id === Z && Y.plans.length > 1;
593
+ return /* @__PURE__ */ P(F, {
594
+ treatment: t ? "insight" : "metric",
595
+ glow: t,
596
+ className: "flex flex-col p-5",
597
+ children: [
598
+ /* @__PURE__ */ P("div", {
599
+ className: "flex items-start justify-between gap-2",
600
+ children: [/* @__PURE__ */ N("p", {
601
+ className: "text-sm font-semibold text-text-primary",
602
+ children: e.name
603
+ }), t ? /* @__PURE__ */ P("span", {
604
+ className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-[11px] font-medium text-status-success-text",
605
+ children: [/* @__PURE__ */ N(O, { className: "h-3 w-3" }), " Best value"]
606
+ }) : /* @__PURE__ */ N(o, { status: e.isActive ? "ACTIVE" : "DISABLED" })]
607
+ }),
608
+ /* @__PURE__ */ P("p", {
609
+ className: "mt-3 text-2xl font-bold tabular-nums text-text-primary",
610
+ children: [r(e.amount, e.currency), /* @__PURE__ */ N("span", {
611
+ className: "text-sm font-normal text-text-secondary",
612
+ children: a(e.interval)
613
+ })]
614
+ }),
615
+ e.description && /* @__PURE__ */ N("p", {
616
+ className: "mt-2 text-xs leading-relaxed text-text-secondary",
617
+ children: e.description
618
+ }),
619
+ e.features.length > 0 && /* @__PURE__ */ P("ul", {
620
+ className: "mt-4 space-y-2 border-t border-border-subtle pt-4",
621
+ children: [e.features.slice(0, 6).map((e) => /* @__PURE__ */ P("li", {
622
+ className: "flex items-start gap-2 text-xs text-text-secondary",
623
+ children: [/* @__PURE__ */ N(S, { className: "mt-0.5 h-3.5 w-3.5 shrink-0 text-status-success-text" }), /* @__PURE__ */ N("span", { children: e })]
624
+ }, e)), e.features.length > 6 && /* @__PURE__ */ P("li", {
625
+ className: "pl-6 text-[11px] text-text-secondary",
626
+ children: [
627
+ "+",
628
+ e.features.length - 6,
629
+ " more"
630
+ ]
631
+ })]
632
+ })
633
+ ]
634
+ }, e.id);
635
+ })
636
+ })
637
+ })
638
+ }), /* @__PURE__ */ P("div", {
639
+ className: "space-y-4",
640
+ children: [
641
+ /* @__PURE__ */ P(F, {
642
+ treatment: "metric",
643
+ className: "p-5",
644
+ children: [/* @__PURE__ */ P("div", {
645
+ className: "flex items-center justify-between",
646
+ children: [/* @__PURE__ */ P("span", {
647
+ className: "inline-flex items-center gap-2 text-sm font-medium text-text-primary",
648
+ children: [/* @__PURE__ */ N(D, { className: "h-4 w-4 text-text-secondary" }), " Vendor health"]
649
+ }), Y.vendorHealthScore != null && /* @__PURE__ */ N("span", {
650
+ className: t("rounded-full px-2 py-0.5 text-[11px] font-medium", V(Y.vendorHealthScore).cls),
651
+ children: V(Y.vendorHealthScore).label
652
+ })]
653
+ }), Y.vendorHealthScore == null ? /* @__PURE__ */ N("p", {
654
+ className: "mt-4 text-sm text-text-secondary",
655
+ children: "No health score yet."
656
+ }) : /* @__PURE__ */ N("div", {
657
+ className: "mt-2 flex flex-col items-center",
658
+ children: /* @__PURE__ */ N(f, {
659
+ value: Y.vendorHealthScore,
660
+ max: 100,
661
+ size: 168,
662
+ label: "out of 100"
663
+ })
664
+ })]
665
+ }),
666
+ /* @__PURE__ */ P(F, {
667
+ treatment: "metric",
668
+ className: "p-5",
669
+ children: [/* @__PURE__ */ P("div", {
670
+ className: "flex items-center justify-between",
671
+ children: [/* @__PURE__ */ P("span", {
672
+ className: "inline-flex items-center gap-2 text-sm font-medium text-text-primary",
673
+ children: [/* @__PURE__ */ N(A, { className: "h-4 w-4 text-text-secondary" }), " Churn risk"]
674
+ }), Y.churnRiskScore != null && /* @__PURE__ */ N("span", {
675
+ className: t("rounded-full px-2 py-0.5 text-[11px] font-medium", H(Y.churnRiskScore).chip),
676
+ children: H(Y.churnRiskScore).label
156
677
  })]
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", {
678
+ }), Y.churnRiskScore == null ? /* @__PURE__ */ N("p", {
679
+ className: "mt-4 text-sm text-text-secondary",
680
+ children: "No churn signal yet."
681
+ }) : /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ P("div", {
682
+ className: "mt-3 flex items-baseline justify-between",
683
+ children: [/* @__PURE__ */ N("span", {
684
+ className: "text-2xl font-bold tabular-nums text-text-primary",
685
+ children: Y.churnRiskScore
686
+ }), /* @__PURE__ */ N("span", {
165
687
  className: "text-xs text-text-secondary",
166
- children: ["• ", e]
167
- }, e))
168
- })
169
- ]
170
- }, e.id))
171
- })
688
+ children: "/ 100"
689
+ })]
690
+ }), /* @__PURE__ */ N(p, {
691
+ value: Y.churnRiskScore,
692
+ tone: H(Y.churnRiskScore).tone,
693
+ className: "mt-2"
694
+ })] })]
695
+ }),
696
+ /* @__PURE__ */ P(F, {
697
+ treatment: "metric",
698
+ className: "p-5",
699
+ children: [/* @__PURE__ */ P("span", {
700
+ className: "inline-flex items-center gap-2 text-sm font-medium text-text-primary",
701
+ children: [/* @__PURE__ */ N(w, { className: "h-4 w-4 text-text-secondary" }), " At a glance"]
702
+ }), /* @__PURE__ */ P("dl", {
703
+ className: "mt-3 space-y-2.5 text-sm",
704
+ children: [
705
+ /* @__PURE__ */ P("div", {
706
+ className: "flex items-center justify-between gap-2",
707
+ children: [/* @__PURE__ */ N("dt", {
708
+ className: "text-text-secondary",
709
+ children: "Category"
710
+ }), /* @__PURE__ */ N("dd", {
711
+ className: "font-medium text-text-primary",
712
+ children: i(Y.category)
713
+ })]
714
+ }),
715
+ /* @__PURE__ */ P("div", {
716
+ className: "flex items-center justify-between gap-2",
717
+ children: [/* @__PURE__ */ N("dt", {
718
+ className: "text-text-secondary",
719
+ children: "Industry"
720
+ }), /* @__PURE__ */ N("dd", {
721
+ className: "font-medium text-text-primary",
722
+ children: Y.industry ?? "—"
723
+ })]
724
+ }),
725
+ /* @__PURE__ */ P("div", {
726
+ className: "flex items-center justify-between gap-2",
727
+ children: [/* @__PURE__ */ N("dt", {
728
+ className: "text-text-secondary",
729
+ children: "Region"
730
+ }), /* @__PURE__ */ N("dd", {
731
+ className: "font-medium text-text-primary",
732
+ children: Y.region ?? "—"
733
+ })]
734
+ }),
735
+ /* @__PURE__ */ P("div", {
736
+ className: "flex items-center justify-between gap-2",
737
+ children: [/* @__PURE__ */ N("dt", {
738
+ className: "text-text-secondary",
739
+ children: "Language"
740
+ }), /* @__PURE__ */ N("dd", {
741
+ className: "font-medium text-text-primary",
742
+ children: Y.language ?? "—"
743
+ })]
744
+ }),
745
+ /* @__PURE__ */ P("div", {
746
+ className: "flex items-center justify-between gap-2",
747
+ children: [/* @__PURE__ */ N("dt", {
748
+ className: "text-text-secondary",
749
+ children: "Published plans"
750
+ }), /* @__PURE__ */ N("dd", {
751
+ className: "font-medium tabular-nums text-text-primary",
752
+ children: Y.plans?.length ?? 0
753
+ })]
754
+ })
755
+ ]
756
+ })]
757
+ })
758
+ ]
759
+ })]
760
+ }),
761
+ R && /* @__PURE__ */ N(U, {
762
+ provider: Y,
763
+ onClose: () => z(!1)
764
+ }),
765
+ B && /* @__PURE__ */ N(W, {
766
+ providerId: Y.id,
767
+ onClose: () => K(!1)
768
+ }),
769
+ q && /* @__PURE__ */ N(G, {
770
+ provider: Y,
771
+ onClose: () => J(!1)
172
772
  })
173
773
  ]
174
774
  });
175
775
  }
176
776
  //#endregion
177
- export { x as ProviderDetailPage };
777
+ export { K as ProviderDetailPage };
178
778
 
179
779
  //# sourceMappingURL=ProviderDetailPage.js.map