@burdenoff/microfe-subscriberbot 2026.706.2 → 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 (36) hide show
  1. package/dist/subscriberbot/SubscriberBotRoutes.js +14 -6
  2. package/dist/subscriberbot/SubscriberBotRoutes.js.map +1 -1
  3. package/dist/subscriberbot/components/index.js +7 -0
  4. package/dist/subscriberbot/components/viz.js +196 -0
  5. package/dist/subscriberbot/components/viz.js.map +1 -0
  6. package/dist/subscriberbot/hooks/useSubscriberBotApi.js +38 -30
  7. package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
  8. package/dist/subscriberbot/pages/AssetVaultPage.js +182 -0
  9. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -0
  10. package/dist/subscriberbot/pages/DashboardPage.js +272 -199
  11. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  12. package/dist/subscriberbot/pages/InboxPage.js +517 -234
  13. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  14. package/dist/subscriberbot/pages/InsightsPage.js +220 -0
  15. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -0
  16. package/dist/subscriberbot/pages/InvoicesPage.js +325 -237
  17. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  18. package/dist/subscriberbot/pages/WorkflowsPage.js +301 -112
  19. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  20. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +311 -165
  21. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  22. package/dist/subscriberbot/pages/agents/AgentsListPage.js +183 -93
  23. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  24. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +426 -293
  25. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  26. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +217 -153
  27. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  28. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +215 -112
  29. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  30. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +542 -428
  31. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +242 -192
  33. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  34. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +174 -133
  35. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  36. package/package.json +1 -1
@@ -3,16 +3,18 @@ import { PageLayout as t } from "../../components/PageLayout.js";
3
3
  import { formatCurrency as n, formatDate as r, formatEnumLabel as i, formatIntervalSuffix as a } from "../../utils/formatters.js";
4
4
  import { StatusBadge as o } from "../../components/StatusBadge.js";
5
5
  import { EmptyState as s } from "../../components/EmptyState.js";
6
- import { ErrorView as c, LoadingView as l, Section as u } from "../../components/StateViews.js";
7
- import { useCancelRelationship as d, useCreateAsset as f, useCreateEntitlement as p, useFileDownloadUrl as m, usePlans as h, useProviders as g, useRelationship as _, useTransitionRelationship as v, useUpdateRelationship as y, useUploadFile as b } from "../../hooks/useSubscriberBotApi.js";
8
- import { Modal as x } from "../../components/Modal.js";
9
- import { useState as S } from "react";
10
- import { Activity as C, ArrowLeft as w, Building2 as T, CalendarClock as E, CreditCard as D, Download as O, Paperclip as k, Pencil as A, Plus as j, ShieldCheck as M, Tag as N } from "lucide-react";
11
- import { useParams as P } from "react-router-dom";
12
- import { jsx as F, jsxs as I } from "react/jsx-runtime";
13
- import { GlassCard as L } from "@burdenoff/fe-libs/ui";
6
+ import { Modal as c } from "../../components/Modal.js";
7
+ import { ErrorView as l, LoadingView as u, Section as d } from "../../components/StateViews.js";
8
+ import { Gauge as f, MiniProgress as p, Timeline as m } from "../../components/viz.js";
9
+ import "../../components/index.js";
10
+ import { useCancelRelationship as h, useCreateAsset as g, useCreateEntitlement as _, useFileDownloadUrl as v, usePlans as y, useProviders as b, useRelationship as x, useTransitionRelationship as S, useUpdateRelationship as C, useUploadFile as w } from "../../hooks/useSubscriberBotApi.js";
11
+ import { useState as T } from "react";
12
+ import { Activity as E, ArrowLeft as D, Ban as O, CalendarClock as k, CreditCard as A, Download as j, Paperclip as M, Pause as N, Pencil as P, Play as F, Plus as I, ShieldCheck as L, Tag as ee, Wallet as te } from "lucide-react";
13
+ import { useParams as ne } from "react-router-dom";
14
+ import { Fragment as R, jsx as z, jsxs as B } from "react/jsx-runtime";
15
+ import { GlassCard as V } from "@burdenoff/fe-libs/ui";
14
16
  //#region src/subscriberbot/pages/relationships/RelationshipDetailPage.tsx
15
- var R = "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)]", z = "mb-1 block text-xs font-medium text-text-secondary", B = [
17
+ var H = "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", W = [
16
18
  "MONTHLY",
17
19
  "YEARLY",
18
20
  "QUARTERLY",
@@ -21,14 +23,14 @@ var R = "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 t
21
23
  "USAGE_BASED",
22
24
  "LIFETIME",
23
25
  "FREE"
24
- ], V = [
26
+ ], G = [
25
27
  "FEATURE_ACCESS",
26
28
  "SEAT",
27
29
  "USAGE_QUOTA",
28
30
  "CONTENT",
29
31
  "DISCOUNT",
30
32
  "SUPPORT_TIER"
31
- ], H = [
33
+ ], K = [
32
34
  "RECEIPT",
33
35
  "INVOICE",
34
36
  "CONTRACT",
@@ -37,38 +39,56 @@ var R = "w-full rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 t
37
39
  "CERTIFICATE",
38
40
  "WARRANTY",
39
41
  "DOMAIN"
40
- ], U = [
42
+ ], q = [
41
43
  {
42
44
  status: "ACTIVE",
43
- label: "Activate"
45
+ label: "Activate",
46
+ icon: F
44
47
  },
45
48
  {
46
49
  status: "PAUSED",
47
- label: "Pause"
50
+ label: "Pause",
51
+ icon: N
48
52
  },
49
53
  {
50
54
  status: "EXPIRED",
51
- label: "Mark expired"
55
+ label: "Mark expired",
56
+ icon: O
52
57
  }
53
58
  ];
54
- function W(e) {
59
+ function J({ label: e, value: t }) {
60
+ return /* @__PURE__ */ B("div", {
61
+ className: "flex items-center justify-between gap-3 border-b border-border-subtle/60 py-2.5 last:border-0 last:pb-0",
62
+ children: [/* @__PURE__ */ z("span", {
63
+ className: "shrink-0 text-sm text-text-secondary",
64
+ children: e
65
+ }), /* @__PURE__ */ z("span", {
66
+ className: "min-w-0 truncate text-right text-sm font-medium text-text-primary",
67
+ children: t
68
+ })]
69
+ });
70
+ }
71
+ function re(e) {
72
+ return e == null ? "accent" : e >= 66 ? "positive" : e >= 33 ? "warning" : "negative";
73
+ }
74
+ function Y(e) {
55
75
  if (!e) return "";
56
76
  let t = new Date(e);
57
77
  return Number.isNaN(t.getTime()) ? "" : t.toISOString().slice(0, 10);
58
78
  }
59
- function G({ relationship: e, onClose: t }) {
60
- let n = y(), r = g({ pagination: {
79
+ function ie({ relationship: e, onClose: t }) {
80
+ let n = C(), r = b({ pagination: {
61
81
  limit: 100,
62
82
  offset: 0
63
- } }), [i, a] = S(e.label), [o, s] = S(e.providerId ?? ""), [c, l] = S(e.planId ?? ""), [u, d] = S(String(e.amount ?? "")), [f, p] = S(e.currency), [m, _] = S(e.interval), [v, b] = S(W(e.renewsAt)), [C, w] = S(e.autoRenew), [T, E] = S(e.healthScore == null ? "" : String(e.healthScore)), [D, O] = S(e.notes ?? ""), [k, A] = S(null), j = h(o || void 0), M = (() => {
83
+ } }), [i, a] = T(e.label), [o, s] = T(e.providerId ?? ""), [l, u] = T(e.planId ?? ""), [d, f] = T(String(e.amount ?? "")), [p, m] = T(e.currency), [h, g] = T(e.interval), [_, v] = T(Y(e.renewsAt)), [x, S] = T(e.autoRenew), [w, E] = T(e.healthScore == null ? "" : String(e.healthScore)), [D, O] = T(e.notes ?? ""), [k, A] = T(null), j = y(o || void 0), M = (() => {
64
84
  let t = r.data?.items ?? [];
65
85
  return e.provider && !t.some((t) => t.id === e.provider?.id) ? [e.provider, ...t] : t;
66
86
  })(), N = j.data ?? [];
67
- return /* @__PURE__ */ F(x, {
87
+ return /* @__PURE__ */ z(c, {
68
88
  title: "Edit relationship",
69
89
  onClose: t,
70
90
  maxWidthClassName: "max-w-2xl",
71
- children: /* @__PURE__ */ I("form", {
91
+ children: /* @__PURE__ */ B("form", {
72
92
  onSubmit: (r) => {
73
93
  if (r.preventDefault(), A(null), !i.trim()) {
74
94
  A("A label is required.");
@@ -76,15 +96,15 @@ function G({ relationship: e, onClose: t }) {
76
96
  }
77
97
  let a = {
78
98
  label: i.trim(),
79
- interval: m,
80
- autoRenew: C,
81
- currency: f.trim() || "USD",
99
+ interval: h,
100
+ autoRenew: x,
101
+ currency: p.trim() || "USD",
82
102
  notes: D.trim(),
83
103
  ...o ? { providerId: o } : {},
84
- ...c ? { planId: c } : {},
85
- ...u.trim() ? { amount: Number(u) } : {},
86
- ...T.trim() ? { healthScore: Number(T) } : {},
87
- ...v ? { renewsAt: new Date(v).toISOString() } : {}
104
+ ...l ? { planId: l } : {},
105
+ ...d.trim() ? { amount: Number(d) } : {},
106
+ ...w.trim() ? { healthScore: Number(w) } : {},
107
+ ..._ ? { renewsAt: new Date(_).toISOString() } : {}
88
108
  };
89
109
  n.mutate({
90
110
  id: e.id,
@@ -96,168 +116,168 @@ function G({ relationship: e, onClose: t }) {
96
116
  },
97
117
  className: "space-y-4",
98
118
  children: [
99
- k && /* @__PURE__ */ F("div", {
119
+ k && /* @__PURE__ */ z("div", {
100
120
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
101
121
  children: k
102
122
  }),
103
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ I("label", {
123
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ B("label", {
104
124
  htmlFor: "edit-label",
105
- className: z,
106
- children: ["Label ", /* @__PURE__ */ F("span", {
125
+ className: U,
126
+ children: ["Label ", /* @__PURE__ */ z("span", {
107
127
  className: "text-status-error-text",
108
128
  children: "*"
109
129
  })]
110
- }), /* @__PURE__ */ F("input", {
130
+ }), /* @__PURE__ */ z("input", {
111
131
  id: "edit-label",
112
132
  type: "text",
113
133
  value: i,
114
134
  onChange: (e) => a(e.target.value),
115
- className: R,
135
+ className: H,
116
136
  required: !0
117
137
  })] }),
118
- /* @__PURE__ */ I("div", {
138
+ /* @__PURE__ */ B("div", {
119
139
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
120
- children: [/* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
140
+ children: [/* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
121
141
  htmlFor: "edit-provider",
122
- className: z,
142
+ className: U,
123
143
  children: "Provider"
124
- }), /* @__PURE__ */ I("select", {
144
+ }), /* @__PURE__ */ B("select", {
125
145
  id: "edit-provider",
126
146
  value: o,
127
147
  onChange: (e) => {
128
- s(e.target.value), l("");
148
+ s(e.target.value), u("");
129
149
  },
130
- className: R,
131
- children: [/* @__PURE__ */ F("option", {
150
+ className: H,
151
+ children: [/* @__PURE__ */ z("option", {
132
152
  value: "",
133
153
  children: "— None —"
134
- }), M.map((e) => /* @__PURE__ */ F("option", {
154
+ }), M.map((e) => /* @__PURE__ */ z("option", {
135
155
  value: e.id,
136
156
  children: e.name
137
157
  }, e.id))]
138
- })] }), /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
158
+ })] }), /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
139
159
  htmlFor: "edit-plan",
140
- className: z,
160
+ className: U,
141
161
  children: "Plan"
142
- }), /* @__PURE__ */ I("select", {
162
+ }), /* @__PURE__ */ B("select", {
143
163
  id: "edit-plan",
144
- value: c,
145
- onChange: (e) => l(e.target.value),
146
- className: R,
164
+ value: l,
165
+ onChange: (e) => u(e.target.value),
166
+ className: H,
147
167
  disabled: !o || N.length === 0,
148
- children: [/* @__PURE__ */ F("option", {
168
+ children: [/* @__PURE__ */ z("option", {
149
169
  value: "",
150
170
  children: "— None —"
151
- }), N.map((e) => /* @__PURE__ */ F("option", {
171
+ }), N.map((e) => /* @__PURE__ */ z("option", {
152
172
  value: e.id,
153
173
  children: e.name
154
174
  }, e.id))]
155
175
  })] })]
156
176
  }),
157
- /* @__PURE__ */ I("div", {
177
+ /* @__PURE__ */ B("div", {
158
178
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
159
179
  children: [
160
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
180
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
161
181
  htmlFor: "edit-amount",
162
- className: z,
182
+ className: U,
163
183
  children: "Amount"
164
- }), /* @__PURE__ */ F("input", {
184
+ }), /* @__PURE__ */ z("input", {
165
185
  id: "edit-amount",
166
186
  type: "number",
167
187
  min: "0",
168
188
  step: "0.01",
169
- value: u,
170
- onChange: (e) => d(e.target.value),
171
- className: R
189
+ value: d,
190
+ onChange: (e) => f(e.target.value),
191
+ className: H
172
192
  })] }),
173
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
193
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
174
194
  htmlFor: "edit-currency",
175
- className: z,
195
+ className: U,
176
196
  children: "Currency"
177
- }), /* @__PURE__ */ F("input", {
197
+ }), /* @__PURE__ */ z("input", {
178
198
  id: "edit-currency",
179
199
  type: "text",
180
- value: f,
181
- onChange: (e) => p(e.target.value.toUpperCase()),
200
+ value: p,
201
+ onChange: (e) => m(e.target.value.toUpperCase()),
182
202
  maxLength: 3,
183
- className: R
203
+ className: H
184
204
  })] }),
185
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
205
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
186
206
  htmlFor: "edit-interval",
187
- className: z,
207
+ className: U,
188
208
  children: "Billing interval"
189
- }), /* @__PURE__ */ F("select", {
209
+ }), /* @__PURE__ */ z("select", {
190
210
  id: "edit-interval",
191
- value: m,
192
- onChange: (e) => _(e.target.value),
193
- className: R,
194
- children: B.map((e) => /* @__PURE__ */ F("option", {
211
+ value: h,
212
+ onChange: (e) => g(e.target.value),
213
+ className: H,
214
+ children: W.map((e) => /* @__PURE__ */ z("option", {
195
215
  value: e,
196
216
  children: e.replace(/_/g, " ")
197
217
  }, e))
198
218
  })] })
199
219
  ]
200
220
  }),
201
- /* @__PURE__ */ I("div", {
221
+ /* @__PURE__ */ B("div", {
202
222
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
203
223
  children: [
204
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
224
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
205
225
  htmlFor: "edit-renews",
206
- className: z,
226
+ className: U,
207
227
  children: "Renews on"
208
- }), /* @__PURE__ */ F("input", {
228
+ }), /* @__PURE__ */ z("input", {
209
229
  id: "edit-renews",
210
230
  type: "date",
211
- value: v,
212
- onChange: (e) => b(e.target.value),
213
- className: R
231
+ value: _,
232
+ onChange: (e) => v(e.target.value),
233
+ className: H
214
234
  })] }),
215
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
235
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
216
236
  htmlFor: "edit-health",
217
- className: z,
237
+ className: U,
218
238
  children: "Health score (0–100)"
219
- }), /* @__PURE__ */ F("input", {
239
+ }), /* @__PURE__ */ z("input", {
220
240
  id: "edit-health",
221
241
  type: "number",
222
242
  min: "0",
223
243
  max: "100",
224
- value: T,
244
+ value: w,
225
245
  onChange: (e) => E(e.target.value),
226
- className: R
246
+ className: H
227
247
  })] }),
228
- /* @__PURE__ */ F("div", {
248
+ /* @__PURE__ */ z("div", {
229
249
  className: "flex items-end",
230
- children: /* @__PURE__ */ I("label", {
250
+ children: /* @__PURE__ */ B("label", {
231
251
  className: "flex items-center gap-2 text-sm text-text-primary",
232
- children: [/* @__PURE__ */ F("input", {
252
+ children: [/* @__PURE__ */ z("input", {
233
253
  type: "checkbox",
234
- checked: C,
235
- onChange: (e) => w(e.target.checked),
254
+ checked: x,
255
+ onChange: (e) => S(e.target.checked),
236
256
  className: "size-4 rounded border-border-subtle"
237
257
  }), "Auto-renews"]
238
258
  })
239
259
  })
240
260
  ]
241
261
  }),
242
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
262
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
243
263
  htmlFor: "edit-notes",
244
- className: z,
264
+ className: U,
245
265
  children: "Notes"
246
- }), /* @__PURE__ */ F("textarea", {
266
+ }), /* @__PURE__ */ z("textarea", {
247
267
  id: "edit-notes",
248
268
  value: D,
249
269
  onChange: (e) => O(e.target.value),
250
270
  rows: 3,
251
- className: R
271
+ className: H
252
272
  })] }),
253
- /* @__PURE__ */ I("div", {
273
+ /* @__PURE__ */ B("div", {
254
274
  className: "flex justify-end gap-3",
255
- children: [/* @__PURE__ */ F("button", {
275
+ children: [/* @__PURE__ */ z("button", {
256
276
  type: "button",
257
277
  onClick: t,
258
278
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
259
279
  children: "Cancel"
260
- }), /* @__PURE__ */ F("button", {
280
+ }), /* @__PURE__ */ z("button", {
261
281
  type: "submit",
262
282
  disabled: n.isPending,
263
283
  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",
@@ -268,12 +288,12 @@ function G({ relationship: e, onClose: t }) {
268
288
  })
269
289
  });
270
290
  }
271
- function K({ relationshipId: e, onClose: t }) {
272
- let n = p(), [r, i] = S(""), [a, o] = S("FEATURE_ACCESS"), [s, c] = S(""), [l, u] = S(""), [d, f] = S(""), [m, h] = S(null);
273
- return /* @__PURE__ */ F(x, {
291
+ function ae({ relationshipId: e, onClose: t }) {
292
+ let n = _(), [r, i] = T(""), [a, o] = T("FEATURE_ACCESS"), [s, l] = T(""), [u, d] = T(""), [f, p] = T(""), [m, h] = T(null);
293
+ return /* @__PURE__ */ z(c, {
274
294
  title: "Add entitlement",
275
295
  onClose: t,
276
- children: /* @__PURE__ */ I("form", {
296
+ children: /* @__PURE__ */ B("form", {
277
297
  onSubmit: (i) => {
278
298
  if (i.preventDefault(), h(null), !r.trim()) {
279
299
  h("An entitlement name is required.");
@@ -284,8 +304,8 @@ function K({ relationshipId: e, onClose: t }) {
284
304
  name: r.trim(),
285
305
  type: a,
286
306
  ...s.trim() ? { quota: Number(s) } : {},
287
- ...l.trim() ? { unit: l.trim() } : {},
288
- ...d.trim() ? { description: d.trim() } : {}
307
+ ...u.trim() ? { unit: u.trim() } : {},
308
+ ...f.trim() ? { description: f.trim() } : {}
289
309
  }, {
290
310
  onSuccess: () => t(),
291
311
  onError: (e) => h(e instanceof Error ? e.message : "Could not add entitlement.")
@@ -293,89 +313,89 @@ function K({ relationshipId: e, onClose: t }) {
293
313
  },
294
314
  className: "space-y-4",
295
315
  children: [
296
- m && /* @__PURE__ */ F("div", {
316
+ m && /* @__PURE__ */ z("div", {
297
317
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
298
318
  children: m
299
319
  }),
300
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ I("label", {
320
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ B("label", {
301
321
  htmlFor: "ent-name",
302
- className: z,
303
- children: ["Name ", /* @__PURE__ */ F("span", {
322
+ className: U,
323
+ children: ["Name ", /* @__PURE__ */ z("span", {
304
324
  className: "text-status-error-text",
305
325
  children: "*"
306
326
  })]
307
- }), /* @__PURE__ */ F("input", {
327
+ }), /* @__PURE__ */ z("input", {
308
328
  id: "ent-name",
309
329
  type: "text",
310
330
  value: r,
311
331
  onChange: (e) => i(e.target.value),
312
332
  placeholder: "e.g. Seats, API calls, Priority support",
313
- className: R,
333
+ className: H,
314
334
  required: !0
315
335
  })] }),
316
- /* @__PURE__ */ I("div", {
336
+ /* @__PURE__ */ B("div", {
317
337
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
318
338
  children: [
319
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
339
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
320
340
  htmlFor: "ent-type",
321
- className: z,
341
+ className: U,
322
342
  children: "Type"
323
- }), /* @__PURE__ */ F("select", {
343
+ }), /* @__PURE__ */ z("select", {
324
344
  id: "ent-type",
325
345
  value: a,
326
346
  onChange: (e) => o(e.target.value),
327
- className: R,
328
- children: V.map((e) => /* @__PURE__ */ F("option", {
347
+ className: H,
348
+ children: G.map((e) => /* @__PURE__ */ z("option", {
329
349
  value: e,
330
350
  children: e.replace(/_/g, " ")
331
351
  }, e))
332
352
  })] }),
333
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
353
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
334
354
  htmlFor: "ent-quota",
335
- className: z,
355
+ className: U,
336
356
  children: "Quota"
337
- }), /* @__PURE__ */ F("input", {
357
+ }), /* @__PURE__ */ z("input", {
338
358
  id: "ent-quota",
339
359
  type: "number",
340
360
  min: "0",
341
361
  value: s,
342
- onChange: (e) => c(e.target.value),
362
+ onChange: (e) => l(e.target.value),
343
363
  placeholder: "e.g. 5",
344
- className: R
364
+ className: H
345
365
  })] }),
346
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
366
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
347
367
  htmlFor: "ent-unit",
348
- className: z,
368
+ className: U,
349
369
  children: "Unit"
350
- }), /* @__PURE__ */ F("input", {
370
+ }), /* @__PURE__ */ z("input", {
351
371
  id: "ent-unit",
352
372
  type: "text",
353
- value: l,
354
- onChange: (e) => u(e.target.value),
373
+ value: u,
374
+ onChange: (e) => d(e.target.value),
355
375
  placeholder: "e.g. seats, GB",
356
- className: R
376
+ className: H
357
377
  })] })
358
378
  ]
359
379
  }),
360
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
380
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
361
381
  htmlFor: "ent-desc",
362
- className: z,
382
+ className: U,
363
383
  children: "Description"
364
- }), /* @__PURE__ */ F("textarea", {
384
+ }), /* @__PURE__ */ z("textarea", {
365
385
  id: "ent-desc",
366
- value: d,
367
- onChange: (e) => f(e.target.value),
386
+ value: f,
387
+ onChange: (e) => p(e.target.value),
368
388
  rows: 2,
369
- className: R
389
+ className: H
370
390
  })] }),
371
- /* @__PURE__ */ I("div", {
391
+ /* @__PURE__ */ B("div", {
372
392
  className: "flex justify-end gap-3",
373
- children: [/* @__PURE__ */ F("button", {
393
+ children: [/* @__PURE__ */ z("button", {
374
394
  type: "button",
375
395
  onClick: t,
376
396
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
377
397
  children: "Cancel"
378
- }), /* @__PURE__ */ F("button", {
398
+ }), /* @__PURE__ */ z("button", {
379
399
  type: "submit",
380
400
  disabled: n.isPending,
381
401
  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",
@@ -386,99 +406,99 @@ function K({ relationshipId: e, onClose: t }) {
386
406
  })
387
407
  });
388
408
  }
389
- function q({ relationshipId: e, onClose: t }) {
390
- let n = f(), { uploadFile: r, progress: i, isUploading: a } = b(), [o, s] = S(""), [c, l] = S("RECEIPT"), [u, d] = S(null), [p, m] = S(""), [h, g] = S(null), _ = a || n.isPending;
391
- return /* @__PURE__ */ F(x, {
409
+ function oe({ relationshipId: e, onClose: t }) {
410
+ let n = g(), { uploadFile: r, progress: i, isUploading: a } = w(), [o, s] = T(""), [l, u] = T("RECEIPT"), [d, f] = T(null), [p, m] = T(""), [h, _] = T(null), v = a || n.isPending;
411
+ return /* @__PURE__ */ z(c, {
392
412
  title: "Attach asset",
393
413
  onClose: t,
394
- children: /* @__PURE__ */ I("form", {
414
+ children: /* @__PURE__ */ B("form", {
395
415
  onSubmit: async (i) => {
396
- if (i.preventDefault(), g(null), !u) {
397
- g("Choose a file to attach.");
416
+ if (i.preventDefault(), _(null), !d) {
417
+ _("Choose a file to attach.");
398
418
  return;
399
419
  }
400
420
  try {
401
- let { fileId: i, fileName: a } = await r(u);
421
+ let { fileId: i, fileName: a } = await r(d);
402
422
  await n.mutateAsync({
403
423
  relationshipId: e,
404
424
  name: o.trim() || a,
405
- type: c,
425
+ type: l,
406
426
  fileId: i,
407
427
  ...p ? { expiresAt: new Date(p).toISOString() } : {}
408
428
  }), t();
409
429
  } catch (e) {
410
- g(e instanceof Error ? e.message : "Could not attach the asset.");
430
+ _(e instanceof Error ? e.message : "Could not attach the asset.");
411
431
  }
412
432
  },
413
433
  className: "space-y-4",
414
434
  children: [
415
- h && /* @__PURE__ */ F("div", {
435
+ h && /* @__PURE__ */ z("div", {
416
436
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
417
437
  children: h
418
438
  }),
419
- /* @__PURE__ */ I("div", { children: [
420
- /* @__PURE__ */ I("label", {
439
+ /* @__PURE__ */ B("div", { children: [
440
+ /* @__PURE__ */ B("label", {
421
441
  htmlFor: "asset-file",
422
- className: z,
423
- children: ["File ", /* @__PURE__ */ F("span", {
442
+ className: U,
443
+ children: ["File ", /* @__PURE__ */ z("span", {
424
444
  className: "text-status-error-text",
425
445
  children: "*"
426
446
  })]
427
447
  }),
428
- /* @__PURE__ */ F("input", {
448
+ /* @__PURE__ */ z("input", {
429
449
  id: "asset-file",
430
450
  type: "file",
431
451
  onChange: (e) => {
432
452
  let t = e.target.files?.[0] ?? null;
433
- d(t), t && !o.trim() && s(t.name);
453
+ f(t), t && !o.trim() && s(t.name);
434
454
  },
435
455
  className: "w-full text-sm text-text-secondary file:mr-3 file:rounded-lg file:border file:border-border-subtle file:bg-bg-surface file:px-3 file:py-1.5 file:text-sm file:font-medium file:text-text-primary hover:file:bg-bg-sunken"
436
456
  }),
437
- /* @__PURE__ */ F("p", {
457
+ /* @__PURE__ */ z("p", {
438
458
  className: "mt-1 text-xs text-text-secondary",
439
459
  children: "Stored securely in files — only a reference is kept here."
440
460
  })
441
461
  ] }),
442
- /* @__PURE__ */ I("div", {
462
+ /* @__PURE__ */ B("div", {
443
463
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
444
- children: [/* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
464
+ children: [/* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
445
465
  htmlFor: "asset-name",
446
- className: z,
466
+ className: U,
447
467
  children: "Name"
448
- }), /* @__PURE__ */ F("input", {
468
+ }), /* @__PURE__ */ z("input", {
449
469
  id: "asset-name",
450
470
  type: "text",
451
471
  value: o,
452
472
  onChange: (e) => s(e.target.value),
453
473
  placeholder: "Defaults to the file name",
454
- className: R
455
- })] }), /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
474
+ className: H
475
+ })] }), /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
456
476
  htmlFor: "asset-type",
457
- className: z,
477
+ className: U,
458
478
  children: "Type"
459
- }), /* @__PURE__ */ F("select", {
479
+ }), /* @__PURE__ */ z("select", {
460
480
  id: "asset-type",
461
- value: c,
462
- onChange: (e) => l(e.target.value),
463
- className: R,
464
- children: H.map((e) => /* @__PURE__ */ F("option", {
481
+ value: l,
482
+ onChange: (e) => u(e.target.value),
483
+ className: H,
484
+ children: K.map((e) => /* @__PURE__ */ z("option", {
465
485
  value: e,
466
486
  children: e.replace(/_/g, " ")
467
487
  }, e))
468
488
  })] })]
469
489
  }),
470
- /* @__PURE__ */ I("div", { children: [/* @__PURE__ */ F("label", {
490
+ /* @__PURE__ */ B("div", { children: [/* @__PURE__ */ z("label", {
471
491
  htmlFor: "asset-expires",
472
- className: z,
492
+ className: U,
473
493
  children: "Expires on"
474
- }), /* @__PURE__ */ F("input", {
494
+ }), /* @__PURE__ */ z("input", {
475
495
  id: "asset-expires",
476
496
  type: "date",
477
497
  value: p,
478
498
  onChange: (e) => m(e.target.value),
479
- className: R
499
+ className: H
480
500
  })] }),
481
- a && /* @__PURE__ */ I("p", {
501
+ a && /* @__PURE__ */ B("p", {
482
502
  className: "text-xs text-text-secondary",
483
503
  children: [
484
504
  "Uploading… ",
@@ -486,46 +506,46 @@ function q({ relationshipId: e, onClose: t }) {
486
506
  "%"
487
507
  ]
488
508
  }),
489
- /* @__PURE__ */ I("div", {
509
+ /* @__PURE__ */ B("div", {
490
510
  className: "flex justify-end gap-3",
491
- children: [/* @__PURE__ */ F("button", {
511
+ children: [/* @__PURE__ */ z("button", {
492
512
  type: "button",
493
513
  onClick: t,
494
514
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
495
515
  children: "Cancel"
496
- }), /* @__PURE__ */ F("button", {
516
+ }), /* @__PURE__ */ z("button", {
497
517
  type: "submit",
498
- disabled: _,
518
+ disabled: v,
499
519
  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",
500
- children: _ ? "Attaching…" : "Attach asset"
520
+ children: v ? "Attaching…" : "Attach asset"
501
521
  })]
502
522
  })
503
523
  ]
504
524
  })
505
525
  });
506
526
  }
507
- function J({ asset: e }) {
508
- let t = m(), [n, a] = S(!1);
509
- return /* @__PURE__ */ I("div", {
527
+ function se({ asset: e }) {
528
+ let t = v(), [n, a] = T(!1);
529
+ return /* @__PURE__ */ B("div", {
510
530
  className: "flex items-center justify-between gap-3 p-3",
511
- children: [/* @__PURE__ */ I("div", {
531
+ children: [/* @__PURE__ */ B("div", {
512
532
  className: "flex min-w-0 items-center gap-2",
513
- children: [/* @__PURE__ */ F(k, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ I("div", {
533
+ children: [/* @__PURE__ */ z(M, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ B("div", {
514
534
  className: "min-w-0",
515
- children: [/* @__PURE__ */ F("p", {
535
+ children: [/* @__PURE__ */ z("p", {
516
536
  className: "truncate text-sm font-medium text-text-primary",
517
537
  children: e.name
518
- }), /* @__PURE__ */ F("p", {
538
+ }), /* @__PURE__ */ z("p", {
519
539
  className: "text-xs text-text-secondary",
520
540
  children: i(e.type)
521
541
  })]
522
542
  })]
523
- }), /* @__PURE__ */ I("div", {
543
+ }), /* @__PURE__ */ B("div", {
524
544
  className: "flex shrink-0 items-center gap-3",
525
- children: [e.expiresAt && /* @__PURE__ */ I("span", {
545
+ children: [e.expiresAt && /* @__PURE__ */ B("span", {
526
546
  className: "text-xs text-text-secondary",
527
547
  children: ["Expires ", r(e.expiresAt)]
528
- }), e.file?.id && /* @__PURE__ */ I("button", {
548
+ }), e.file?.id && /* @__PURE__ */ B("button", {
529
549
  type: "button",
530
550
  onClick: async () => {
531
551
  if (e.file?.id) {
@@ -541,7 +561,7 @@ function J({ asset: e }) {
541
561
  disabled: n,
542
562
  className: "inline-flex items-center gap-1 rounded-lg border border-border-subtle px-2.5 py-1 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50",
543
563
  children: [
544
- /* @__PURE__ */ F(O, { className: "h-3.5 w-3.5" }),
564
+ /* @__PURE__ */ z(j, { className: "h-3.5 w-3.5" }),
545
565
  " ",
546
566
  n ? "Opening…" : "Download"
547
567
  ]
@@ -549,296 +569,390 @@ function J({ asset: e }) {
549
569
  })]
550
570
  });
551
571
  }
552
- function Y() {
553
- let { id: f } = P(), { navigateTo: p } = e(), { data: m, isLoading: h, isError: g, refetch: y } = _(f), b = v(), x = d(), [O, k] = S(null), [R, z] = S(!1), [B, V] = S(!1), [H, W] = S(!1);
554
- if (h) return /* @__PURE__ */ F(t, {
572
+ function X() {
573
+ let { id: c } = ne(), { navigateTo: g } = e(), { data: _, isLoading: v, isError: y, refetch: b } = x(c), C = S(), w = h(), [j, M] = T(null), [N, F] = T(!1), [H, U] = T(!1), [W, G] = T(!1);
574
+ if (v) return /* @__PURE__ */ z(t, {
555
575
  title: "Relationship",
556
- children: /* @__PURE__ */ F(l, { label: "Loading relationship…" })
576
+ children: /* @__PURE__ */ z(u, { label: "Loading relationship…" })
557
577
  });
558
- if (g) return /* @__PURE__ */ F(t, {
578
+ if (y) return /* @__PURE__ */ z(t, {
559
579
  title: "Relationship",
560
- children: /* @__PURE__ */ F(c, {
580
+ children: /* @__PURE__ */ z(l, {
561
581
  message: "Could not load this relationship.",
562
- onRetry: () => void y()
582
+ onRetry: () => void b()
563
583
  })
564
584
  });
565
- if (!m) return /* @__PURE__ */ F(t, {
585
+ if (!_) return /* @__PURE__ */ z(t, {
566
586
  title: "Relationship",
567
- children: /* @__PURE__ */ F(s, {
587
+ children: /* @__PURE__ */ z(s, {
568
588
  illustration: "empty-data",
569
589
  title: "Relationship not found",
570
590
  description: "It may have been removed, or you may not have access to it.",
571
- action: /* @__PURE__ */ F("button", {
591
+ action: /* @__PURE__ */ z("button", {
572
592
  type: "button",
573
- onClick: () => p("/relationships"),
593
+ onClick: () => g("/relationships"),
574
594
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
575
595
  children: "Back to relationships"
576
596
  })
577
597
  })
578
598
  });
579
- let Y = m, X = b.isPending || x.isPending, Z = (e) => {
580
- k(null), b.mutate({
581
- id: Y.id,
599
+ let K = _, Y = C.isPending || w.isPending, X = (e) => {
600
+ M(null), C.mutate({
601
+ id: K.id,
582
602
  status: e
583
- }, { onError: (e) => k(e instanceof Error ? e.message : "Transition failed") });
584
- };
585
- return /* @__PURE__ */ I(t, {
586
- title: Y.label,
587
- description: Y.provider?.name ?? i(Y.kind),
588
- actions: /* @__PURE__ */ I("div", {
603
+ }, { onError: (e) => M(e instanceof Error ? e.message : "Transition failed") });
604
+ }, ce = () => {
605
+ M(null), w.mutate(K.id, { onError: (e) => M(e instanceof Error ? e.message : "Cancel failed") });
606
+ }, Z = [...K.renewalEvents ?? []].sort((e, t) => new Date(e.occursAt).getTime() - new Date(t.occursAt).getTime()).map((e) => {
607
+ let t = new Date(e.occursAt).getTime(), a = !Number.isNaN(t) && t > Date.now();
608
+ return {
609
+ title: i(e.eventType),
610
+ sub: `${r(e.occursAt)}${e.detail ? ` · ${e.detail}` : ""}`,
611
+ meta: e.amount == null ? void 0 : n(e.amount, e.currency ?? K.currency),
612
+ tone: a ? "warning" : "muted"
613
+ };
614
+ }), Q = K.autoRenew ? /* @__PURE__ */ z("span", {
615
+ className: "inline-flex items-center rounded-full bg-status-success-bg-subtle px-2 py-0.5 text-xs font-medium text-status-success-text",
616
+ children: "On"
617
+ }) : /* @__PURE__ */ z("span", {
618
+ className: "inline-flex items-center rounded-full bg-bg-sunken px-2 py-0.5 text-xs font-medium text-text-secondary",
619
+ children: "Off"
620
+ }), le = q.filter((e) => e.status !== K.status), $ = K.plan?.features ?? [];
621
+ return /* @__PURE__ */ B(t, {
622
+ title: K.label,
623
+ description: K.provider?.name ?? i(K.kind),
624
+ actions: /* @__PURE__ */ B("div", {
589
625
  className: "flex items-center gap-2",
590
- children: [/* @__PURE__ */ I("button", {
626
+ children: [/* @__PURE__ */ B("button", {
591
627
  type: "button",
592
- onClick: () => z(!0),
628
+ onClick: () => F(!0),
593
629
  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",
594
- children: [/* @__PURE__ */ F(A, { className: "h-4 w-4" }), " Edit"]
595
- }), /* @__PURE__ */ I("button", {
630
+ children: [/* @__PURE__ */ z(P, { className: "h-4 w-4" }), " Edit"]
631
+ }), /* @__PURE__ */ B("button", {
596
632
  type: "button",
597
- onClick: () => p("/relationships"),
633
+ onClick: () => g("/relationships"),
598
634
  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",
599
- children: [/* @__PURE__ */ F(w, { className: "h-4 w-4" }), " Back"]
635
+ children: [/* @__PURE__ */ z(D, { className: "h-4 w-4" }), " Back"]
600
636
  })]
601
637
  }),
602
638
  children: [
603
- /* @__PURE__ */ I("div", {
604
- className: "flex flex-wrap items-center gap-3",
605
- children: [
606
- /* @__PURE__ */ F(o, { status: Y.status }),
607
- /* @__PURE__ */ F("span", {
608
- className: "text-sm text-text-secondary",
609
- children: i(Y.kind)
610
- }),
611
- /* @__PURE__ */ F("span", {
612
- className: "text-sm text-text-secondary",
613
- children: "·"
614
- }),
615
- /* @__PURE__ */ I("span", {
616
- className: "text-sm font-semibold text-text-primary",
617
- children: [n(Y.amount, Y.currency), /* @__PURE__ */ F("span", {
618
- className: "text-xs font-normal text-text-secondary",
619
- children: a(Y.interval)
620
- })]
621
- }),
622
- Y.autoRenew && /* @__PURE__ */ F("span", {
623
- className: "text-xs text-text-secondary",
624
- children: "Auto-renews"
625
- })
626
- ]
627
- }),
628
- O && /* @__PURE__ */ F("div", {
629
- className: "mt-4 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
630
- children: O
631
- }),
632
- /* @__PURE__ */ I("div", {
633
- className: "mt-5 flex flex-wrap gap-2",
634
- children: [U.filter((e) => e.status !== Y.status).map((e) => /* @__PURE__ */ F("button", {
635
- type: "button",
636
- disabled: X,
637
- onClick: () => Z(e.status),
638
- className: "rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50",
639
- children: e.label
640
- }, e.status)), Y.status !== "CANCELLED" && /* @__PURE__ */ F("button", {
641
- type: "button",
642
- disabled: X,
643
- onClick: () => {
644
- k(null), x.mutate(Y.id, { onError: (e) => k(e instanceof Error ? e.message : "Cancel failed") });
645
- },
646
- className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:opacity-90 disabled:opacity-50",
647
- children: "Cancel relationship"
648
- })]
649
- }),
650
- /* @__PURE__ */ I("div", {
651
- className: "mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
652
- children: [
653
- /* @__PURE__ */ I(L, {
654
- treatment: "metric",
655
- className: "p-4",
656
- children: [/* @__PURE__ */ I("div", {
657
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
658
- children: [/* @__PURE__ */ F(T, { className: "h-3.5 w-3.5" }), " Provider"]
659
- }), /* @__PURE__ */ F("p", {
660
- className: "mt-1.5 text-sm text-text-primary",
661
- children: Y.provider?.name ?? "—"
662
- })]
663
- }),
664
- /* @__PURE__ */ I(L, {
665
- treatment: "metric",
666
- className: "p-4",
667
- children: [/* @__PURE__ */ I("div", {
668
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
669
- children: [/* @__PURE__ */ F(D, { className: "h-3.5 w-3.5" }), " Plan"]
670
- }), /* @__PURE__ */ F("p", {
671
- className: "mt-1.5 text-sm text-text-primary",
672
- children: Y.plan?.name ?? "—"
673
- })]
674
- }),
675
- /* @__PURE__ */ I(L, {
676
- treatment: "metric",
677
- className: "p-4",
678
- children: [/* @__PURE__ */ I("div", {
679
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
680
- children: [/* @__PURE__ */ F(E, { className: "h-3.5 w-3.5" }), " Next renewal"]
681
- }), /* @__PURE__ */ F("p", {
682
- className: "mt-1.5 text-sm text-text-primary",
683
- children: Y.renewsAt ? r(Y.renewsAt) : "—"
684
- })]
685
- }),
686
- /* @__PURE__ */ I(L, {
687
- treatment: "metric",
688
- className: "p-4",
689
- children: [/* @__PURE__ */ I("div", {
690
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
691
- children: [/* @__PURE__ */ F(C, { className: "h-3.5 w-3.5" }), " Health score"]
692
- }), /* @__PURE__ */ F("p", {
693
- className: "mt-1.5 text-sm text-text-primary",
694
- children: Y.healthScore == null ? "—" : `${Y.healthScore}/100`
695
- })]
696
- }),
697
- /* @__PURE__ */ I(L, {
698
- treatment: "metric",
699
- className: "p-4",
700
- children: [/* @__PURE__ */ I("div", {
701
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
702
- children: [/* @__PURE__ */ F(M, { className: "h-3.5 w-3.5" }), " Discovery"]
703
- }), /* @__PURE__ */ F("p", {
704
- className: "mt-1.5 text-sm text-text-primary",
705
- children: i(Y.discoverySource)
706
- })]
707
- }),
708
- /* @__PURE__ */ I(L, {
709
- treatment: "metric",
710
- className: "p-4",
711
- children: [/* @__PURE__ */ I("div", {
712
- className: "flex items-center gap-2 text-xs font-medium text-text-secondary",
713
- children: [/* @__PURE__ */ F(E, { className: "h-3.5 w-3.5" }), " Started"]
714
- }), /* @__PURE__ */ F("p", {
715
- className: "mt-1.5 text-sm text-text-primary",
716
- children: Y.startedAt ? r(Y.startedAt) : "—"
717
- })]
718
- })
719
- ]
720
- }),
721
- Y.tags.length > 0 && /* @__PURE__ */ I("div", {
722
- className: "mt-5 flex flex-wrap items-center gap-2",
723
- children: [/* @__PURE__ */ F(N, { className: "h-3.5 w-3.5 text-text-secondary" }), Y.tags.map((e) => /* @__PURE__ */ F("span", {
724
- className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
725
- children: e
726
- }, e))]
727
- }),
728
- Y.notes && /* @__PURE__ */ I("div", {
729
- className: "mt-5 rounded-lg border border-border-subtle bg-bg-surface p-4",
730
- children: [/* @__PURE__ */ F("p", {
731
- className: "text-xs font-medium text-text-secondary",
732
- children: "Notes"
733
- }), /* @__PURE__ */ F("p", {
734
- className: "mt-1 whitespace-pre-wrap text-sm text-text-primary",
735
- children: Y.notes
736
- })]
737
- }),
738
- /* @__PURE__ */ F(u, {
739
- title: "Entitlements",
740
- description: "What this relationship grants you",
741
- action: /* @__PURE__ */ I("button", {
742
- type: "button",
743
- onClick: () => V(!0),
744
- 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",
745
- children: [/* @__PURE__ */ F(j, { className: "h-3.5 w-3.5" }), " Add entitlement"]
746
- }),
747
- children: !Y.entitlements || Y.entitlements.length === 0 ? /* @__PURE__ */ F(s, {
748
- illustration: "empty-data",
749
- title: "No entitlements",
750
- description: "Entitlements (seats, quotas, feature access) will appear here."
751
- }) : /* @__PURE__ */ F("div", {
752
- className: "grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3",
753
- children: Y.entitlements.map((e) => /* @__PURE__ */ I("div", {
754
- className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
639
+ /* @__PURE__ */ z(V, {
640
+ treatment: "glass",
641
+ glow: !0,
642
+ className: "p-5 sm:p-6",
643
+ children: /* @__PURE__ */ B("div", {
644
+ className: "flex flex-col gap-5 lg:flex-row lg:items-start lg:justify-between",
645
+ children: [/* @__PURE__ */ B("div", {
646
+ className: "min-w-0",
755
647
  children: [
756
- /* @__PURE__ */ I("div", {
757
- className: "flex items-start justify-between gap-2",
758
- children: [/* @__PURE__ */ F("p", {
759
- className: "text-sm font-medium text-text-primary",
760
- children: e.name
761
- }), /* @__PURE__ */ F(o, { status: e.isActive ? "ACTIVE" : "DISABLED" })]
648
+ /* @__PURE__ */ z("p", {
649
+ className: "text-xs font-medium uppercase tracking-wide text-text-secondary",
650
+ children: i(K.kind)
762
651
  }),
763
- /* @__PURE__ */ F("p", {
764
- className: "mt-1 text-xs text-text-secondary",
765
- children: i(e.type)
652
+ /* @__PURE__ */ B("div", {
653
+ className: "mt-2 flex flex-wrap items-center gap-3",
654
+ children: [/* @__PURE__ */ B("span", {
655
+ className: "text-3xl font-bold tabular-nums text-text-primary",
656
+ children: [n(K.amount, K.currency), /* @__PURE__ */ z("span", {
657
+ className: "text-base font-normal text-text-secondary",
658
+ children: a(K.interval)
659
+ })]
660
+ }), /* @__PURE__ */ z(o, { status: K.status })]
766
661
  }),
767
- e.quota != null && /* @__PURE__ */ I("p", {
768
- className: "mt-2 text-xs text-text-secondary",
662
+ /* @__PURE__ */ B("div", {
663
+ className: "mt-2 flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-text-secondary",
769
664
  children: [
770
- "Used ",
771
- e.used,
772
- " of ",
773
- e.quota,
774
- e.unit ? ` ${e.unit}` : ""
665
+ /* @__PURE__ */ B("span", {
666
+ className: "inline-flex items-center gap-1.5",
667
+ children: [/* @__PURE__ */ z(k, { className: "h-3.5 w-3.5" }), K.renewsAt ? `Renews ${r(K.renewsAt)}` : "No renewal scheduled"]
668
+ }),
669
+ /* @__PURE__ */ B("span", {
670
+ className: "inline-flex items-center gap-1.5",
671
+ children: [/* @__PURE__ */ z(L, { className: "h-3.5 w-3.5" }), i(K.discoverySource)]
672
+ }),
673
+ /* @__PURE__ */ B("span", {
674
+ className: "inline-flex items-center gap-1.5",
675
+ children: ["Auto-renew ", Q]
676
+ })
775
677
  ]
678
+ }),
679
+ K.tags.length > 0 && /* @__PURE__ */ B("div", {
680
+ className: "mt-3 flex flex-wrap items-center gap-2",
681
+ children: [/* @__PURE__ */ z(ee, { className: "h-3.5 w-3.5 text-text-secondary" }), K.tags.map((e) => /* @__PURE__ */ z("span", {
682
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
683
+ children: e
684
+ }, e))]
776
685
  })
777
686
  ]
778
- }, e.id))
687
+ }), /* @__PURE__ */ B("div", {
688
+ className: "flex shrink-0 flex-wrap gap-2 lg:flex-col lg:items-stretch",
689
+ children: [le.map((e) => {
690
+ let t = e.icon;
691
+ return /* @__PURE__ */ B("button", {
692
+ type: "button",
693
+ disabled: Y,
694
+ onClick: () => X(e.status),
695
+ className: "inline-flex items-center justify-center gap-1.5 rounded-lg border border-border-subtle bg-bg-surface px-3 py-1.5 text-xs font-medium text-text-primary hover:bg-bg-sunken disabled:opacity-50",
696
+ children: [
697
+ /* @__PURE__ */ z(t, { className: "h-3.5 w-3.5" }),
698
+ " ",
699
+ e.label
700
+ ]
701
+ }, e.status);
702
+ }), K.status !== "CANCELLED" && /* @__PURE__ */ B("button", {
703
+ type: "button",
704
+ disabled: Y,
705
+ onClick: ce,
706
+ className: "inline-flex items-center justify-center gap-1.5 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-3 py-1.5 text-xs font-medium text-status-error-text hover:opacity-90 disabled:opacity-50",
707
+ children: [/* @__PURE__ */ z(O, { className: "h-3.5 w-3.5" }), " Cancel"]
708
+ })]
709
+ })]
779
710
  })
780
711
  }),
781
- /* @__PURE__ */ F(u, {
782
- title: "Assets",
783
- description: "Invoices, contracts, licenses and credentials",
784
- action: /* @__PURE__ */ I("button", {
785
- type: "button",
786
- onClick: () => W(!0),
787
- 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",
788
- children: [/* @__PURE__ */ F(j, { className: "h-3.5 w-3.5" }), " Attach asset"]
789
- }),
790
- children: !Y.assets || Y.assets.length === 0 ? /* @__PURE__ */ F(s, {
791
- illustration: "empty-data",
792
- title: "No assets attached",
793
- description: "Attach invoices, contracts, licenses or receipts to this relationship."
794
- }) : /* @__PURE__ */ F("div", {
795
- className: "divide-y divide-border-subtle rounded-lg border border-border-subtle bg-bg-surface",
796
- children: Y.assets.map((e) => /* @__PURE__ */ F(J, { asset: e }, e.id))
797
- })
712
+ j && /* @__PURE__ */ z("div", {
713
+ className: "mt-4 rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
714
+ children: j
798
715
  }),
799
- /* @__PURE__ */ F(u, {
800
- title: "Renewal timeline",
801
- description: "Detected renewals and price changes",
802
- children: !Y.renewalEvents || Y.renewalEvents.length === 0 ? /* @__PURE__ */ F(s, {
803
- illustration: "empty-calendar",
804
- title: "No renewal events",
805
- description: "Renewals and price changes detected for this relationship will appear here."
806
- }) : /* @__PURE__ */ F("div", {
807
- className: "divide-y divide-border-subtle rounded-lg border border-border-subtle bg-bg-surface",
808
- children: Y.renewalEvents.map((e) => /* @__PURE__ */ I("div", {
809
- className: "flex items-center justify-between gap-3 p-3",
810
- children: [/* @__PURE__ */ I("div", {
811
- className: "min-w-0",
812
- children: [/* @__PURE__ */ F("p", {
813
- className: "truncate text-sm font-medium text-text-primary",
814
- children: i(e.eventType)
815
- }), /* @__PURE__ */ I("p", {
816
- className: "text-xs text-text-secondary",
817
- children: [r(e.occursAt), e.detail ? ` · ${e.detail}` : ""]
716
+ /* @__PURE__ */ B("div", {
717
+ className: "mt-6 grid grid-cols-1 gap-4 lg:grid-cols-3",
718
+ children: [/* @__PURE__ */ B("div", {
719
+ className: "space-y-4 lg:col-span-2",
720
+ children: [
721
+ /* @__PURE__ */ B("div", {
722
+ className: "grid grid-cols-1 gap-4 md:grid-cols-2",
723
+ children: [/* @__PURE__ */ B(V, {
724
+ treatment: "metric",
725
+ className: "p-5",
726
+ children: [
727
+ /* @__PURE__ */ B("div", {
728
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
729
+ children: [/* @__PURE__ */ z(A, { className: "h-4 w-4 text-text-secondary" }), " Plan & pricing"]
730
+ }),
731
+ /* @__PURE__ */ B("div", {
732
+ className: "mt-3",
733
+ children: [
734
+ /* @__PURE__ */ z(J, {
735
+ label: "Plan",
736
+ value: K.plan?.name ?? "—"
737
+ }),
738
+ /* @__PURE__ */ z(J, {
739
+ label: "Price",
740
+ value: /* @__PURE__ */ B(R, { children: [n(K.amount, K.currency), /* @__PURE__ */ z("span", {
741
+ className: "font-normal text-text-secondary",
742
+ children: a(K.interval)
743
+ })] })
744
+ }),
745
+ /* @__PURE__ */ z(J, {
746
+ label: "Billing interval",
747
+ value: i(K.interval)
748
+ }),
749
+ /* @__PURE__ */ z(J, {
750
+ label: "Provider",
751
+ value: K.provider?.name ?? "—"
752
+ })
753
+ ]
754
+ }),
755
+ $.length > 0 && /* @__PURE__ */ z("div", {
756
+ className: "mt-3 flex flex-wrap gap-1.5",
757
+ children: $.map((e) => /* @__PURE__ */ z("span", {
758
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs text-text-secondary",
759
+ children: e
760
+ }, e))
761
+ })
762
+ ]
763
+ }), /* @__PURE__ */ B(V, {
764
+ treatment: "metric",
765
+ className: "p-5",
766
+ children: [/* @__PURE__ */ B("div", {
767
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
768
+ children: [/* @__PURE__ */ z(te, { className: "h-4 w-4 text-text-secondary" }), " Payment & billing"]
769
+ }), /* @__PURE__ */ B("div", {
770
+ className: "mt-3",
771
+ children: [
772
+ /* @__PURE__ */ z(J, {
773
+ label: "Currency",
774
+ value: K.currency
775
+ }),
776
+ /* @__PURE__ */ z(J, {
777
+ label: "Auto-renew",
778
+ value: Q
779
+ }),
780
+ /* @__PURE__ */ z(J, {
781
+ label: "Next renewal",
782
+ value: K.renewsAt ? r(K.renewsAt) : "—"
783
+ }),
784
+ /* @__PURE__ */ z(J, {
785
+ label: "Started",
786
+ value: K.startedAt ? r(K.startedAt) : "—"
787
+ }),
788
+ K.trialEndsAt && /* @__PURE__ */ z(J, {
789
+ label: "Trial ends",
790
+ value: r(K.trialEndsAt)
791
+ })
792
+ ]
793
+ })]
794
+ })]
795
+ }),
796
+ /* @__PURE__ */ z(d, {
797
+ className: "mt-0",
798
+ title: "Entitlements",
799
+ description: "What this relationship grants you",
800
+ action: /* @__PURE__ */ B("button", {
801
+ type: "button",
802
+ onClick: () => U(!0),
803
+ 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",
804
+ children: [/* @__PURE__ */ z(I, { className: "h-3.5 w-3.5" }), " Add entitlement"]
805
+ }),
806
+ children: !K.entitlements || K.entitlements.length === 0 ? /* @__PURE__ */ z(s, {
807
+ illustration: "empty-data",
808
+ title: "No entitlements",
809
+ description: "Entitlements (seats, quotas, feature access) will appear here."
810
+ }) : /* @__PURE__ */ z("div", {
811
+ className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
812
+ children: K.entitlements.map((e) => {
813
+ let t = e.quota != null && e.quota > 0;
814
+ return /* @__PURE__ */ B(V, {
815
+ treatment: "plain",
816
+ className: "p-4",
817
+ children: [
818
+ /* @__PURE__ */ B("div", {
819
+ className: "flex items-start justify-between gap-2",
820
+ children: [/* @__PURE__ */ z("p", {
821
+ className: "min-w-0 truncate text-sm font-medium text-text-primary",
822
+ children: e.name
823
+ }), /* @__PURE__ */ z(o, { status: e.isActive ? "ACTIVE" : "DISABLED" })]
824
+ }),
825
+ /* @__PURE__ */ z("p", {
826
+ className: "mt-1 text-xs text-text-secondary",
827
+ children: i(e.type)
828
+ }),
829
+ t && /* @__PURE__ */ B("div", {
830
+ className: "mt-3",
831
+ children: [/* @__PURE__ */ B("div", {
832
+ className: "flex items-center justify-between text-xs text-text-secondary",
833
+ children: [/* @__PURE__ */ B("span", { children: [
834
+ e.used,
835
+ " / ",
836
+ e.quota,
837
+ e.unit ? ` ${e.unit}` : ""
838
+ ] }), /* @__PURE__ */ B("span", {
839
+ className: "tabular-nums",
840
+ children: [Math.round(e.used / e.quota * 100), "%"]
841
+ })]
842
+ }), /* @__PURE__ */ z(p, {
843
+ value: e.used,
844
+ max: e.quota,
845
+ tone: e.used / e.quota >= .9 ? "negative" : e.used / e.quota >= .7 ? "warning" : "accent",
846
+ className: "mt-1.5"
847
+ })]
848
+ })
849
+ ]
850
+ }, e.id);
851
+ })
852
+ })
853
+ }),
854
+ /* @__PURE__ */ z(d, {
855
+ className: "mt-0",
856
+ title: "Assets",
857
+ description: "Invoices, contracts, licenses and credentials",
858
+ action: /* @__PURE__ */ B("button", {
859
+ type: "button",
860
+ onClick: () => G(!0),
861
+ 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",
862
+ children: [/* @__PURE__ */ z(I, { className: "h-3.5 w-3.5" }), " Attach asset"]
863
+ }),
864
+ children: !K.assets || K.assets.length === 0 ? /* @__PURE__ */ z(s, {
865
+ illustration: "empty-data",
866
+ title: "No assets attached",
867
+ description: "Attach invoices, contracts, licenses or receipts to this relationship."
868
+ }) : /* @__PURE__ */ z(V, {
869
+ treatment: "plain",
870
+ className: "divide-y divide-border-subtle p-0",
871
+ children: K.assets.map((e) => /* @__PURE__ */ z(se, { asset: e }, e.id))
872
+ })
873
+ }),
874
+ K.notes && /* @__PURE__ */ B(V, {
875
+ treatment: "plain",
876
+ className: "p-4",
877
+ children: [/* @__PURE__ */ z("p", {
878
+ className: "text-xs font-medium text-text-secondary",
879
+ children: "Notes"
880
+ }), /* @__PURE__ */ z("p", {
881
+ className: "mt-1 whitespace-pre-wrap text-sm text-text-primary",
882
+ children: K.notes
883
+ })]
884
+ })
885
+ ]
886
+ }), /* @__PURE__ */ B("div", {
887
+ className: "space-y-4",
888
+ children: [/* @__PURE__ */ B(V, {
889
+ treatment: "metric",
890
+ className: "p-5",
891
+ children: [/* @__PURE__ */ B("div", {
892
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
893
+ children: [/* @__PURE__ */ z(E, { className: "h-4 w-4 text-text-secondary" }), " Health score"]
894
+ }), K.healthScore == null ? /* @__PURE__ */ z("p", {
895
+ className: "mt-4 text-sm text-text-secondary",
896
+ children: "Not scored yet. A health score appears once Subscriber Bot has enough signal."
897
+ }) : /* @__PURE__ */ B("div", {
898
+ className: "mt-4 flex flex-col items-center",
899
+ children: [/* @__PURE__ */ z(f, {
900
+ value: K.healthScore,
901
+ max: 100,
902
+ size: 160,
903
+ label: "of 100"
904
+ }), /* @__PURE__ */ z("div", {
905
+ className: "mt-2 w-full",
906
+ children: /* @__PURE__ */ z(p, {
907
+ value: K.healthScore,
908
+ max: 100,
909
+ tone: re(K.healthScore)
910
+ })
818
911
  })]
819
- }), e.amount != null && /* @__PURE__ */ F("span", {
820
- className: "shrink-0 text-sm font-semibold tabular-nums text-text-primary",
821
- children: n(e.amount, e.currency ?? Y.currency)
822
912
  })]
823
- }, e.id))
824
- })
913
+ }), /* @__PURE__ */ B(V, {
914
+ treatment: "metric",
915
+ className: "p-5",
916
+ children: [
917
+ /* @__PURE__ */ B("div", {
918
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
919
+ children: [/* @__PURE__ */ z(k, { className: "h-4 w-4 text-text-secondary" }), " Renewal timeline"]
920
+ }),
921
+ /* @__PURE__ */ z("p", {
922
+ className: "mt-0.5 text-xs text-text-secondary",
923
+ children: "Detected renewals and price changes"
924
+ }),
925
+ Z.length === 0 ? /* @__PURE__ */ z("div", {
926
+ className: "mt-4",
927
+ children: /* @__PURE__ */ z(s, {
928
+ illustration: "empty-calendar",
929
+ title: "No renewal events",
930
+ description: "Renewals and price changes will appear here as they're detected."
931
+ })
932
+ }) : /* @__PURE__ */ z(m, {
933
+ items: Z,
934
+ className: "mt-4"
935
+ })
936
+ ]
937
+ })]
938
+ })]
825
939
  }),
826
- R && /* @__PURE__ */ F(G, {
827
- relationship: Y,
828
- onClose: () => z(!1)
940
+ N && /* @__PURE__ */ z(ie, {
941
+ relationship: K,
942
+ onClose: () => F(!1)
829
943
  }),
830
- B && /* @__PURE__ */ F(K, {
831
- relationshipId: Y.id,
832
- onClose: () => V(!1)
944
+ H && /* @__PURE__ */ z(ae, {
945
+ relationshipId: K.id,
946
+ onClose: () => U(!1)
833
947
  }),
834
- H && /* @__PURE__ */ F(q, {
835
- relationshipId: Y.id,
836
- onClose: () => W(!1)
948
+ W && /* @__PURE__ */ z(oe, {
949
+ relationshipId: K.id,
950
+ onClose: () => G(!1)
837
951
  })
838
952
  ]
839
953
  });
840
954
  }
841
955
  //#endregion
842
- export { Y as RelationshipDetailPage };
956
+ export { X as RelationshipDetailPage };
843
957
 
844
958
  //# sourceMappingURL=RelationshipDetailPage.js.map