@burdenoff/microfe-subscriberbot 2026.629.1 → 2026.706.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/subscriberbot/components/Modal.js +51 -0
- package/dist/subscriberbot/components/Modal.js.map +1 -0
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js +355 -159
- package/dist/subscriberbot/hooks/useSubscriberBotApi.js.map +1 -1
- package/dist/subscriberbot/pages/InboxPage.js +339 -66
- package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
- package/dist/subscriberbot/pages/InvoicesPage.js +496 -73
- package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
- package/dist/subscriberbot/pages/WorkflowsPage.js +136 -150
- package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js +197 -58
- package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/agents/AgentsListPage.js +2 -0
- package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +538 -71
- package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/providers/ProvidersListPage.js +2 -0
- package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +664 -126
- package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
- package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +18 -16
- package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,14 +5,15 @@ import { MetricsCard as r } from "../components/MetricsCard.js";
|
|
|
5
5
|
import { formatCurrency as i, formatDate as a } from "../utils/formatters.js";
|
|
6
6
|
import { StatusBadge as o } from "../components/StatusBadge.js";
|
|
7
7
|
import { EmptyState as s } from "../components/EmptyState.js";
|
|
8
|
-
import { ErrorView as c, LoadingView as l } from "../components/StateViews.js";
|
|
9
|
-
import { useInvoices as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
8
|
+
import { ErrorView as c, LoadingView as l, Section as u } from "../components/StateViews.js";
|
|
9
|
+
import { useCreateInvoice as d, useCreatePaymentInstrument as f, useInvoices as p, useMarkInvoicePaid as m, usePaymentInstruments as h, useRelationships as g, useRemovePaymentInstrument as _ } from "../hooks/useSubscriberBotApi.js";
|
|
10
|
+
import { Modal as v } from "../components/Modal.js";
|
|
11
|
+
import { useMemo as y, useState as b } from "react";
|
|
12
|
+
import { CreditCard as x, FileText as S, Plus as C, Receipt as w, Star as T, Trash2 as E } from "lucide-react";
|
|
13
|
+
import { Fragment as D, jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
14
|
+
import { PagePurpose as A } from "@burdenoff/fe-libs/ui";
|
|
14
15
|
//#region src/subscriberbot/pages/InvoicesPage.tsx
|
|
15
|
-
var
|
|
16
|
+
var j = 25, M = "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)]", N = "mb-1 block text-xs font-medium text-text-secondary", P = [
|
|
16
17
|
{
|
|
17
18
|
value: "",
|
|
18
19
|
label: "All statuses"
|
|
@@ -45,130 +46,550 @@ var b = 25, x = [
|
|
|
45
46
|
value: "REFUNDED",
|
|
46
47
|
label: "Refunded"
|
|
47
48
|
}
|
|
48
|
-
],
|
|
49
|
+
], F = [
|
|
50
|
+
"ISSUED",
|
|
51
|
+
"DRAFT",
|
|
52
|
+
"OVERDUE",
|
|
53
|
+
"PAID",
|
|
54
|
+
"FAILED",
|
|
55
|
+
"CANCELLED",
|
|
56
|
+
"REFUNDED"
|
|
57
|
+
], I = [
|
|
58
|
+
"CARD",
|
|
59
|
+
"BANK_ACCOUNT",
|
|
60
|
+
"PAYPAL",
|
|
61
|
+
"UPI",
|
|
62
|
+
"WALLET",
|
|
63
|
+
"OTHER"
|
|
64
|
+
], L = new Set([
|
|
49
65
|
"ISSUED",
|
|
50
66
|
"OVERDUE",
|
|
51
67
|
"FAILED"
|
|
52
68
|
]);
|
|
53
|
-
function
|
|
54
|
-
let
|
|
55
|
-
|
|
69
|
+
function R({ onClose: e }) {
|
|
70
|
+
let t = d(), n = g({ pagination: {
|
|
71
|
+
limit: 100,
|
|
72
|
+
offset: 0
|
|
73
|
+
} }).data?.items ?? [], [r, i] = b(""), [a, o] = b(""), [s, c] = b("ISSUED"), [l, u] = b("USD"), [f, p] = b(""), [m, h] = b(""), [_, y] = b(""), [x, S] = b(""), [C, w] = b(""), [T, E] = b(null);
|
|
74
|
+
return /* @__PURE__ */ O(v, {
|
|
75
|
+
title: "Create invoice",
|
|
76
|
+
onClose: e,
|
|
77
|
+
maxWidthClassName: "max-w-xl",
|
|
78
|
+
children: /* @__PURE__ */ k("form", {
|
|
79
|
+
onSubmit: (n) => {
|
|
80
|
+
if (n.preventDefault(), E(null), !r) {
|
|
81
|
+
E("Select the relationship this invoice belongs to.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
t.mutate({
|
|
85
|
+
relationshipId: r,
|
|
86
|
+
status: s,
|
|
87
|
+
currency: l.trim() || "USD",
|
|
88
|
+
...a.trim() ? { number: a.trim() } : {},
|
|
89
|
+
...f.trim() ? { subtotal: Number(f) } : {},
|
|
90
|
+
...m.trim() ? { taxAmount: Number(m) } : {},
|
|
91
|
+
..._.trim() ? { total: Number(_) } : {},
|
|
92
|
+
...x ? { issueDate: new Date(x).toISOString() } : {},
|
|
93
|
+
...C ? { dueDate: new Date(C).toISOString() } : {}
|
|
94
|
+
}, {
|
|
95
|
+
onSuccess: () => e(),
|
|
96
|
+
onError: (e) => E(e instanceof Error ? e.message : "Could not create invoice.")
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
className: "space-y-4",
|
|
100
|
+
children: [
|
|
101
|
+
T && /* @__PURE__ */ O("div", {
|
|
102
|
+
className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
|
|
103
|
+
children: T
|
|
104
|
+
}),
|
|
105
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ k("label", {
|
|
106
|
+
htmlFor: "inv-relationship",
|
|
107
|
+
className: N,
|
|
108
|
+
children: ["Relationship ", /* @__PURE__ */ O("span", {
|
|
109
|
+
className: "text-status-error-text",
|
|
110
|
+
children: "*"
|
|
111
|
+
})]
|
|
112
|
+
}), /* @__PURE__ */ k("select", {
|
|
113
|
+
id: "inv-relationship",
|
|
114
|
+
value: r,
|
|
115
|
+
onChange: (e) => i(e.target.value),
|
|
116
|
+
className: M,
|
|
117
|
+
required: !0,
|
|
118
|
+
children: [/* @__PURE__ */ O("option", {
|
|
119
|
+
value: "",
|
|
120
|
+
children: "— Select a relationship —"
|
|
121
|
+
}), n.map((e) => /* @__PURE__ */ O("option", {
|
|
122
|
+
value: e.id,
|
|
123
|
+
children: e.label
|
|
124
|
+
}, e.id))]
|
|
125
|
+
})] }),
|
|
126
|
+
/* @__PURE__ */ k("div", {
|
|
127
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
130
|
+
htmlFor: "inv-number",
|
|
131
|
+
className: N,
|
|
132
|
+
children: "Number"
|
|
133
|
+
}), /* @__PURE__ */ O("input", {
|
|
134
|
+
id: "inv-number",
|
|
135
|
+
type: "text",
|
|
136
|
+
value: a,
|
|
137
|
+
onChange: (e) => o(e.target.value),
|
|
138
|
+
placeholder: "INV-0001",
|
|
139
|
+
className: M
|
|
140
|
+
})] }),
|
|
141
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
142
|
+
htmlFor: "inv-status",
|
|
143
|
+
className: N,
|
|
144
|
+
children: "Status"
|
|
145
|
+
}), /* @__PURE__ */ O("select", {
|
|
146
|
+
id: "inv-status",
|
|
147
|
+
value: s,
|
|
148
|
+
onChange: (e) => c(e.target.value),
|
|
149
|
+
className: M,
|
|
150
|
+
children: F.map((e) => /* @__PURE__ */ O("option", {
|
|
151
|
+
value: e,
|
|
152
|
+
children: e.replace(/_/g, " ")
|
|
153
|
+
}, e))
|
|
154
|
+
})] }),
|
|
155
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
156
|
+
htmlFor: "inv-currency",
|
|
157
|
+
className: N,
|
|
158
|
+
children: "Currency"
|
|
159
|
+
}), /* @__PURE__ */ O("input", {
|
|
160
|
+
id: "inv-currency",
|
|
161
|
+
type: "text",
|
|
162
|
+
value: l,
|
|
163
|
+
onChange: (e) => u(e.target.value.toUpperCase()),
|
|
164
|
+
maxLength: 3,
|
|
165
|
+
className: M
|
|
166
|
+
})] })
|
|
167
|
+
]
|
|
168
|
+
}),
|
|
169
|
+
/* @__PURE__ */ k("div", {
|
|
170
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
|
|
171
|
+
children: [
|
|
172
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
173
|
+
htmlFor: "inv-subtotal",
|
|
174
|
+
className: N,
|
|
175
|
+
children: "Subtotal"
|
|
176
|
+
}), /* @__PURE__ */ O("input", {
|
|
177
|
+
id: "inv-subtotal",
|
|
178
|
+
type: "number",
|
|
179
|
+
min: "0",
|
|
180
|
+
step: "0.01",
|
|
181
|
+
value: f,
|
|
182
|
+
onChange: (e) => p(e.target.value),
|
|
183
|
+
className: M
|
|
184
|
+
})] }),
|
|
185
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
186
|
+
htmlFor: "inv-tax",
|
|
187
|
+
className: N,
|
|
188
|
+
children: "Tax"
|
|
189
|
+
}), /* @__PURE__ */ O("input", {
|
|
190
|
+
id: "inv-tax",
|
|
191
|
+
type: "number",
|
|
192
|
+
min: "0",
|
|
193
|
+
step: "0.01",
|
|
194
|
+
value: m,
|
|
195
|
+
onChange: (e) => h(e.target.value),
|
|
196
|
+
className: M
|
|
197
|
+
})] }),
|
|
198
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
199
|
+
htmlFor: "inv-total",
|
|
200
|
+
className: N,
|
|
201
|
+
children: "Total"
|
|
202
|
+
}), /* @__PURE__ */ O("input", {
|
|
203
|
+
id: "inv-total",
|
|
204
|
+
type: "number",
|
|
205
|
+
min: "0",
|
|
206
|
+
step: "0.01",
|
|
207
|
+
value: _,
|
|
208
|
+
onChange: (e) => y(e.target.value),
|
|
209
|
+
className: M
|
|
210
|
+
})] })
|
|
211
|
+
]
|
|
212
|
+
}),
|
|
213
|
+
/* @__PURE__ */ k("div", {
|
|
214
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
215
|
+
children: [/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
216
|
+
htmlFor: "inv-issue",
|
|
217
|
+
className: N,
|
|
218
|
+
children: "Issue date"
|
|
219
|
+
}), /* @__PURE__ */ O("input", {
|
|
220
|
+
id: "inv-issue",
|
|
221
|
+
type: "date",
|
|
222
|
+
value: x,
|
|
223
|
+
onChange: (e) => S(e.target.value),
|
|
224
|
+
className: M
|
|
225
|
+
})] }), /* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
226
|
+
htmlFor: "inv-due",
|
|
227
|
+
className: N,
|
|
228
|
+
children: "Due date"
|
|
229
|
+
}), /* @__PURE__ */ O("input", {
|
|
230
|
+
id: "inv-due",
|
|
231
|
+
type: "date",
|
|
232
|
+
value: C,
|
|
233
|
+
onChange: (e) => w(e.target.value),
|
|
234
|
+
className: M
|
|
235
|
+
})] })]
|
|
236
|
+
}),
|
|
237
|
+
/* @__PURE__ */ k("div", {
|
|
238
|
+
className: "flex justify-end gap-3",
|
|
239
|
+
children: [/* @__PURE__ */ O("button", {
|
|
240
|
+
type: "button",
|
|
241
|
+
onClick: e,
|
|
242
|
+
className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
|
|
243
|
+
children: "Cancel"
|
|
244
|
+
}), /* @__PURE__ */ O("button", {
|
|
245
|
+
type: "submit",
|
|
246
|
+
disabled: t.isPending,
|
|
247
|
+
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",
|
|
248
|
+
children: t.isPending ? "Creating…" : "Create invoice"
|
|
249
|
+
})]
|
|
250
|
+
})
|
|
251
|
+
]
|
|
252
|
+
})
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function z({ onClose: e }) {
|
|
256
|
+
let t = f(), [n, r] = b(""), [i, a] = b("CARD"), [o, s] = b(""), [c, l] = b(""), [u, d] = b(""), [p, m] = b(""), [h, g] = b(!1), [_, y] = b(null);
|
|
257
|
+
return /* @__PURE__ */ O(v, {
|
|
258
|
+
title: "Add payment method",
|
|
259
|
+
description: "A passive annotation of which external card/account pays for a subscription — no full card numbers or CVV.",
|
|
260
|
+
onClose: e,
|
|
261
|
+
maxWidthClassName: "max-w-xl",
|
|
262
|
+
children: /* @__PURE__ */ k("form", {
|
|
263
|
+
onSubmit: (r) => {
|
|
264
|
+
if (r.preventDefault(), y(null), !n.trim()) {
|
|
265
|
+
y("A label is required.");
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
t.mutate({
|
|
269
|
+
label: n.trim(),
|
|
270
|
+
type: i,
|
|
271
|
+
isDefault: h,
|
|
272
|
+
...o.trim() ? { brand: o.trim() } : {},
|
|
273
|
+
...c.trim() ? { last4: c.trim() } : {},
|
|
274
|
+
...u.trim() ? { expiryMonth: Number(u) } : {},
|
|
275
|
+
...p.trim() ? { expiryYear: Number(p) } : {}
|
|
276
|
+
}, {
|
|
277
|
+
onSuccess: () => e(),
|
|
278
|
+
onError: (e) => y(e instanceof Error ? e.message : "Could not add payment method.")
|
|
279
|
+
});
|
|
280
|
+
},
|
|
281
|
+
className: "space-y-4",
|
|
282
|
+
children: [
|
|
283
|
+
_ && /* @__PURE__ */ O("div", {
|
|
284
|
+
className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
|
|
285
|
+
children: _
|
|
286
|
+
}),
|
|
287
|
+
/* @__PURE__ */ k("div", {
|
|
288
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
|
|
289
|
+
children: [/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ k("label", {
|
|
290
|
+
htmlFor: "pm-label",
|
|
291
|
+
className: N,
|
|
292
|
+
children: ["Label ", /* @__PURE__ */ O("span", {
|
|
293
|
+
className: "text-status-error-text",
|
|
294
|
+
children: "*"
|
|
295
|
+
})]
|
|
296
|
+
}), /* @__PURE__ */ O("input", {
|
|
297
|
+
id: "pm-label",
|
|
298
|
+
type: "text",
|
|
299
|
+
value: n,
|
|
300
|
+
onChange: (e) => r(e.target.value),
|
|
301
|
+
placeholder: "e.g. Personal Visa",
|
|
302
|
+
className: M,
|
|
303
|
+
required: !0
|
|
304
|
+
})] }), /* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
305
|
+
htmlFor: "pm-type",
|
|
306
|
+
className: N,
|
|
307
|
+
children: "Type"
|
|
308
|
+
}), /* @__PURE__ */ O("select", {
|
|
309
|
+
id: "pm-type",
|
|
310
|
+
value: i,
|
|
311
|
+
onChange: (e) => a(e.target.value),
|
|
312
|
+
className: M,
|
|
313
|
+
children: I.map((e) => /* @__PURE__ */ O("option", {
|
|
314
|
+
value: e,
|
|
315
|
+
children: e.replace(/_/g, " ")
|
|
316
|
+
}, e))
|
|
317
|
+
})] })]
|
|
318
|
+
}),
|
|
319
|
+
/* @__PURE__ */ k("div", {
|
|
320
|
+
className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
|
|
321
|
+
children: [
|
|
322
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
323
|
+
htmlFor: "pm-brand",
|
|
324
|
+
className: N,
|
|
325
|
+
children: "Brand"
|
|
326
|
+
}), /* @__PURE__ */ O("input", {
|
|
327
|
+
id: "pm-brand",
|
|
328
|
+
type: "text",
|
|
329
|
+
value: o,
|
|
330
|
+
onChange: (e) => s(e.target.value),
|
|
331
|
+
placeholder: "Visa, Amex…",
|
|
332
|
+
className: M
|
|
333
|
+
})] }),
|
|
334
|
+
/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
335
|
+
htmlFor: "pm-last4",
|
|
336
|
+
className: N,
|
|
337
|
+
children: "Last 4"
|
|
338
|
+
}), /* @__PURE__ */ O("input", {
|
|
339
|
+
id: "pm-last4",
|
|
340
|
+
type: "text",
|
|
341
|
+
inputMode: "numeric",
|
|
342
|
+
maxLength: 4,
|
|
343
|
+
value: c,
|
|
344
|
+
onChange: (e) => l(e.target.value.replace(/\D/g, "")),
|
|
345
|
+
placeholder: "4242",
|
|
346
|
+
className: M
|
|
347
|
+
})] }),
|
|
348
|
+
/* @__PURE__ */ k("div", {
|
|
349
|
+
className: "grid grid-cols-2 gap-2",
|
|
350
|
+
children: [/* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
351
|
+
htmlFor: "pm-exp-month",
|
|
352
|
+
className: N,
|
|
353
|
+
children: "Exp. mo."
|
|
354
|
+
}), /* @__PURE__ */ O("input", {
|
|
355
|
+
id: "pm-exp-month",
|
|
356
|
+
type: "number",
|
|
357
|
+
min: "1",
|
|
358
|
+
max: "12",
|
|
359
|
+
value: u,
|
|
360
|
+
onChange: (e) => d(e.target.value),
|
|
361
|
+
placeholder: "12",
|
|
362
|
+
className: M
|
|
363
|
+
})] }), /* @__PURE__ */ k("div", { children: [/* @__PURE__ */ O("label", {
|
|
364
|
+
htmlFor: "pm-exp-year",
|
|
365
|
+
className: N,
|
|
366
|
+
children: "Exp. yr."
|
|
367
|
+
}), /* @__PURE__ */ O("input", {
|
|
368
|
+
id: "pm-exp-year",
|
|
369
|
+
type: "number",
|
|
370
|
+
min: "2024",
|
|
371
|
+
max: "2099",
|
|
372
|
+
value: p,
|
|
373
|
+
onChange: (e) => m(e.target.value),
|
|
374
|
+
placeholder: "2028",
|
|
375
|
+
className: M
|
|
376
|
+
})] })]
|
|
377
|
+
})
|
|
378
|
+
]
|
|
379
|
+
}),
|
|
380
|
+
/* @__PURE__ */ k("label", {
|
|
381
|
+
className: "flex items-center gap-2 text-sm text-text-primary",
|
|
382
|
+
children: [/* @__PURE__ */ O("input", {
|
|
383
|
+
type: "checkbox",
|
|
384
|
+
checked: h,
|
|
385
|
+
onChange: (e) => g(e.target.checked),
|
|
386
|
+
className: "size-4 rounded border-border-subtle"
|
|
387
|
+
}), "Set as default"]
|
|
388
|
+
}),
|
|
389
|
+
/* @__PURE__ */ k("div", {
|
|
390
|
+
className: "flex justify-end gap-3",
|
|
391
|
+
children: [/* @__PURE__ */ O("button", {
|
|
392
|
+
type: "button",
|
|
393
|
+
onClick: e,
|
|
394
|
+
className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
|
|
395
|
+
children: "Cancel"
|
|
396
|
+
}), /* @__PURE__ */ O("button", {
|
|
397
|
+
type: "submit",
|
|
398
|
+
disabled: t.isPending,
|
|
399
|
+
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",
|
|
400
|
+
children: t.isPending ? "Adding…" : "Add payment method"
|
|
401
|
+
})]
|
|
402
|
+
})
|
|
403
|
+
]
|
|
404
|
+
})
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
function B() {
|
|
408
|
+
let { data: e, isLoading: t, isError: n, refetch: r } = h(), i = _(), [a, d] = b(!1), f = e ?? [];
|
|
409
|
+
return /* @__PURE__ */ k(u, {
|
|
410
|
+
title: "Payment methods",
|
|
411
|
+
description: "Which external cards and accounts pay for your subscriptions",
|
|
412
|
+
action: /* @__PURE__ */ k("button", {
|
|
413
|
+
type: "button",
|
|
414
|
+
onClick: () => d(!0),
|
|
415
|
+
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",
|
|
416
|
+
children: [/* @__PURE__ */ O(C, { className: "h-3.5 w-3.5" }), " Add payment method"]
|
|
417
|
+
}),
|
|
418
|
+
children: [t ? /* @__PURE__ */ O(l, { label: "Loading payment methods…" }) : n ? /* @__PURE__ */ O(c, {
|
|
419
|
+
message: "Could not load payment methods.",
|
|
420
|
+
onRetry: () => void r()
|
|
421
|
+
}) : f.length === 0 ? /* @__PURE__ */ O(s, {
|
|
422
|
+
illustration: "empty-data",
|
|
423
|
+
icon: /* @__PURE__ */ O(x, { className: "h-12 w-12" }),
|
|
424
|
+
title: "No payment methods",
|
|
425
|
+
description: "Annotate which card or account pays for each subscription. No full card numbers are stored."
|
|
426
|
+
}) : /* @__PURE__ */ O("div", {
|
|
427
|
+
className: "divide-y divide-border-subtle rounded-lg border border-border-subtle bg-bg-surface",
|
|
428
|
+
children: f.map((e) => /* @__PURE__ */ k("div", {
|
|
429
|
+
className: "flex items-center justify-between gap-3 p-3",
|
|
430
|
+
children: [/* @__PURE__ */ k("div", {
|
|
431
|
+
className: "flex min-w-0 items-center gap-2",
|
|
432
|
+
children: [/* @__PURE__ */ O(x, { className: "h-4 w-4 shrink-0 text-text-secondary" }), /* @__PURE__ */ k("div", {
|
|
433
|
+
className: "min-w-0",
|
|
434
|
+
children: [/* @__PURE__ */ k("p", {
|
|
435
|
+
className: "flex items-center gap-1.5 truncate text-sm font-medium text-text-primary",
|
|
436
|
+
children: [e.label, e.isDefault && /* @__PURE__ */ O(T, { className: "h-3 w-3 fill-current text-status-warning-text" })]
|
|
437
|
+
}), /* @__PURE__ */ O("p", {
|
|
438
|
+
className: "text-xs text-text-secondary",
|
|
439
|
+
children: [
|
|
440
|
+
e.brand,
|
|
441
|
+
e.last4 ? `•••• ${e.last4}` : null,
|
|
442
|
+
e.expiryMonth && e.expiryYear ? `${e.expiryMonth}/${e.expiryYear}` : null
|
|
443
|
+
].filter(Boolean).join(" · ") || e.type.replace(/_/g, " ")
|
|
444
|
+
})]
|
|
445
|
+
})]
|
|
446
|
+
}), /* @__PURE__ */ k("div", {
|
|
447
|
+
className: "flex shrink-0 items-center gap-2",
|
|
448
|
+
children: [/* @__PURE__ */ O(o, { status: e.status }), /* @__PURE__ */ O("button", {
|
|
449
|
+
type: "button",
|
|
450
|
+
"aria-label": `Remove ${e.label}`,
|
|
451
|
+
disabled: i.isPending,
|
|
452
|
+
onClick: () => i.mutate(e.id),
|
|
453
|
+
className: "rounded-lg border border-border-subtle p-1.5 text-text-secondary hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-50",
|
|
454
|
+
children: /* @__PURE__ */ O(E, { className: "h-4 w-4" })
|
|
455
|
+
})]
|
|
456
|
+
})]
|
|
457
|
+
}, e.id))
|
|
458
|
+
}), a && /* @__PURE__ */ O(z, { onClose: () => d(!1) })]
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
function V() {
|
|
462
|
+
let { navigateTo: u } = e(), [d, f] = b(0), [h, g] = b(""), [_, v] = b(!1), { data: x, isLoading: T, isError: E, refetch: M, isFetching: N } = p({
|
|
463
|
+
status: h || void 0,
|
|
56
464
|
pagination: {
|
|
57
|
-
limit:
|
|
58
|
-
offset:
|
|
465
|
+
limit: j,
|
|
466
|
+
offset: d * j
|
|
59
467
|
}
|
|
60
|
-
}),
|
|
61
|
-
let e =
|
|
468
|
+
}), F = m(), I = y(() => x?.items ?? [], [x]), z = x?.pageInfo.hasMore ?? !1, V = y(() => {
|
|
469
|
+
let e = I.filter((e) => L.has(e.status)), t = I[0]?.currency ?? "USD";
|
|
62
470
|
return {
|
|
63
471
|
outstandingCount: e.length,
|
|
64
472
|
outstandingTotal: e.reduce((e, t) => e + t.total, 0),
|
|
65
473
|
currency: t
|
|
66
474
|
};
|
|
67
|
-
}, [
|
|
68
|
-
return /* @__PURE__ */
|
|
475
|
+
}, [I]);
|
|
476
|
+
return /* @__PURE__ */ k(n, {
|
|
69
477
|
title: "Invoices",
|
|
70
478
|
description: "Your billing ledger across every relationship",
|
|
479
|
+
actions: /* @__PURE__ */ k("button", {
|
|
480
|
+
type: "button",
|
|
481
|
+
onClick: () => v(!0),
|
|
482
|
+
className: "inline-flex items-center gap-2 rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
|
|
483
|
+
children: [/* @__PURE__ */ O(C, { className: "h-4 w-4" }), " Create invoice"]
|
|
484
|
+
}),
|
|
71
485
|
children: [
|
|
72
|
-
/* @__PURE__ */
|
|
486
|
+
/* @__PURE__ */ O(A, {
|
|
73
487
|
className: "mb-4",
|
|
74
488
|
children: "Every invoice from your recurring relationships in one ledger. Filter by status and settle issued or overdue invoices directly."
|
|
75
489
|
}),
|
|
76
|
-
!
|
|
490
|
+
!T && !E && I.length > 0 && /* @__PURE__ */ k("div", {
|
|
77
491
|
className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3",
|
|
78
|
-
children: [/* @__PURE__ */
|
|
492
|
+
children: [/* @__PURE__ */ O(r, {
|
|
79
493
|
featured: !0,
|
|
80
|
-
icon: /* @__PURE__ */
|
|
81
|
-
value: i(
|
|
494
|
+
icon: /* @__PURE__ */ O(w, {}),
|
|
495
|
+
value: i(V.outstandingTotal, V.currency, { maximumFractionDigits: 0 }),
|
|
82
496
|
label: "Outstanding (this page)"
|
|
83
|
-
}), /* @__PURE__ */
|
|
84
|
-
icon: /* @__PURE__ */
|
|
85
|
-
value:
|
|
497
|
+
}), /* @__PURE__ */ O(r, {
|
|
498
|
+
icon: /* @__PURE__ */ O(S, {}),
|
|
499
|
+
value: V.outstandingCount,
|
|
86
500
|
label: "Open invoices (this page)"
|
|
87
501
|
})]
|
|
88
502
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
503
|
+
/* @__PURE__ */ O("div", {
|
|
90
504
|
className: "mt-6 flex flex-wrap items-center gap-3",
|
|
91
|
-
children: /* @__PURE__ */
|
|
92
|
-
|
|
505
|
+
children: /* @__PURE__ */ O("select", {
|
|
506
|
+
"aria-label": "Filter by status",
|
|
507
|
+
value: h,
|
|
93
508
|
onChange: (e) => {
|
|
94
|
-
|
|
509
|
+
g(e.target.value), f(0);
|
|
95
510
|
},
|
|
96
511
|
className: "rounded-lg border border-border-subtle bg-bg-surface px-3 py-2 text-xs text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]",
|
|
97
|
-
children:
|
|
512
|
+
children: P.map((e) => /* @__PURE__ */ O("option", {
|
|
98
513
|
value: e.value,
|
|
99
514
|
children: e.label
|
|
100
515
|
}, e.value))
|
|
101
516
|
})
|
|
102
517
|
}),
|
|
103
|
-
|
|
518
|
+
T ? /* @__PURE__ */ O(l, { label: "Loading invoices…" }) : E ? /* @__PURE__ */ O(c, {
|
|
104
519
|
message: "Could not load invoices.",
|
|
105
|
-
onRetry: () => void
|
|
106
|
-
}) :
|
|
520
|
+
onRetry: () => void M()
|
|
521
|
+
}) : I.length === 0 ? /* @__PURE__ */ O("div", {
|
|
107
522
|
className: "mt-6",
|
|
108
|
-
children: /* @__PURE__ */
|
|
523
|
+
children: /* @__PURE__ */ O(s, {
|
|
109
524
|
illustration: "empty-data",
|
|
110
|
-
icon: /* @__PURE__ */
|
|
525
|
+
icon: /* @__PURE__ */ O(w, { className: "h-12 w-12" }),
|
|
111
526
|
title: "No invoices",
|
|
112
|
-
description:
|
|
527
|
+
description: h ? "No invoices match this status filter." : "Invoices from your relationships will appear here — or create one manually.",
|
|
528
|
+
action: /* @__PURE__ */ O("button", {
|
|
529
|
+
type: "button",
|
|
530
|
+
onClick: () => v(!0),
|
|
531
|
+
className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
|
|
532
|
+
children: "Create invoice"
|
|
533
|
+
})
|
|
113
534
|
})
|
|
114
|
-
}) : /* @__PURE__ */
|
|
535
|
+
}) : /* @__PURE__ */ k(D, { children: [/* @__PURE__ */ k("div", {
|
|
115
536
|
className: "mt-6 overflow-hidden rounded-lg border border-border-subtle bg-bg-surface",
|
|
116
|
-
children: [/* @__PURE__ */
|
|
537
|
+
children: [/* @__PURE__ */ k("div", {
|
|
117
538
|
className: "hidden grid-cols-[1.5fr_1fr_1fr_1fr_auto] gap-4 border-b border-border-subtle bg-bg-sunken px-4 py-2.5 text-xs font-medium text-text-secondary sm:grid",
|
|
118
539
|
children: [
|
|
119
|
-
/* @__PURE__ */
|
|
120
|
-
/* @__PURE__ */
|
|
121
|
-
/* @__PURE__ */
|
|
540
|
+
/* @__PURE__ */ O("span", { children: "Invoice" }),
|
|
541
|
+
/* @__PURE__ */ O("span", { children: "Status" }),
|
|
542
|
+
/* @__PURE__ */ O("span", {
|
|
122
543
|
className: "text-right",
|
|
123
544
|
children: "Total"
|
|
124
545
|
}),
|
|
125
|
-
/* @__PURE__ */
|
|
546
|
+
/* @__PURE__ */ O("span", {
|
|
126
547
|
className: "text-right",
|
|
127
548
|
children: "Due"
|
|
128
549
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
550
|
+
/* @__PURE__ */ O("span", {
|
|
130
551
|
className: "text-right",
|
|
131
552
|
children: "Action"
|
|
132
553
|
})
|
|
133
554
|
]
|
|
134
|
-
}), /* @__PURE__ */
|
|
555
|
+
}), /* @__PURE__ */ O("div", {
|
|
135
556
|
className: "divide-y divide-border-subtle",
|
|
136
|
-
children:
|
|
557
|
+
children: I.map((e) => /* @__PURE__ */ k("div", {
|
|
137
558
|
className: "grid grid-cols-1 gap-2 px-4 py-3 sm:grid-cols-[1.5fr_1fr_1fr_1fr_auto] sm:items-center sm:gap-4",
|
|
138
559
|
children: [
|
|
139
|
-
/* @__PURE__ */
|
|
560
|
+
/* @__PURE__ */ k("button", {
|
|
140
561
|
type: "button",
|
|
141
|
-
onClick: () =>
|
|
562
|
+
onClick: () => u(`/relationships/${e.relationshipId}`),
|
|
142
563
|
className: "min-w-0 text-left",
|
|
143
|
-
children: [/* @__PURE__ */
|
|
564
|
+
children: [/* @__PURE__ */ O("p", {
|
|
144
565
|
className: "truncate text-sm font-medium text-text-primary",
|
|
145
566
|
children: e.number || `Invoice ${e.id.slice(0, 8)}`
|
|
146
|
-
}), /* @__PURE__ */
|
|
567
|
+
}), /* @__PURE__ */ O("p", {
|
|
147
568
|
className: "text-xs text-text-secondary",
|
|
148
569
|
children: e.issueDate ? `Issued ${a(e.issueDate)}` : "—"
|
|
149
570
|
})]
|
|
150
571
|
}),
|
|
151
|
-
/* @__PURE__ */
|
|
152
|
-
/* @__PURE__ */
|
|
572
|
+
/* @__PURE__ */ O("span", { children: /* @__PURE__ */ O(o, { status: e.status }) }),
|
|
573
|
+
/* @__PURE__ */ O("span", {
|
|
153
574
|
className: "text-sm font-semibold tabular-nums text-text-primary sm:text-right",
|
|
154
575
|
children: i(e.total, e.currency)
|
|
155
576
|
}),
|
|
156
|
-
/* @__PURE__ */
|
|
577
|
+
/* @__PURE__ */ O("span", {
|
|
157
578
|
className: "text-xs text-text-secondary sm:text-right",
|
|
158
579
|
children: e.dueDate ? a(e.dueDate) : "—"
|
|
159
580
|
}),
|
|
160
|
-
/* @__PURE__ */
|
|
581
|
+
/* @__PURE__ */ O("span", {
|
|
161
582
|
className: "sm:text-right",
|
|
162
|
-
children:
|
|
583
|
+
children: L.has(e.status) ? /* @__PURE__ */ O("button", {
|
|
163
584
|
type: "button",
|
|
164
|
-
disabled:
|
|
165
|
-
onClick: () =>
|
|
585
|
+
disabled: F.isPending,
|
|
586
|
+
onClick: () => F.mutate(e.id),
|
|
166
587
|
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",
|
|
167
588
|
children: "Mark paid"
|
|
168
|
-
}) : e.paidAt ? /* @__PURE__ */
|
|
589
|
+
}) : e.paidAt ? /* @__PURE__ */ k("span", {
|
|
169
590
|
className: "text-xs text-text-secondary",
|
|
170
591
|
children: ["Paid ", a(e.paidAt)]
|
|
171
|
-
}) : /* @__PURE__ */
|
|
592
|
+
}) : /* @__PURE__ */ O("span", {
|
|
172
593
|
className: "text-xs text-text-secondary",
|
|
173
594
|
children: "—"
|
|
174
595
|
})
|
|
@@ -176,36 +597,38 @@ function C() {
|
|
|
176
597
|
]
|
|
177
598
|
}, e.id))
|
|
178
599
|
})]
|
|
179
|
-
}), /* @__PURE__ */
|
|
600
|
+
}), /* @__PURE__ */ k("div", {
|
|
180
601
|
className: "mt-4 flex items-center justify-between",
|
|
181
|
-
children: [/* @__PURE__ */
|
|
602
|
+
children: [/* @__PURE__ */ k("p", {
|
|
182
603
|
className: "text-xs text-text-secondary",
|
|
183
604
|
children: [
|
|
184
605
|
"Page ",
|
|
185
|
-
|
|
186
|
-
|
|
606
|
+
d + 1,
|
|
607
|
+
N ? " · refreshing…" : ""
|
|
187
608
|
]
|
|
188
|
-
}), /* @__PURE__ */
|
|
609
|
+
}), /* @__PURE__ */ k("div", {
|
|
189
610
|
className: "flex gap-2",
|
|
190
|
-
children: [/* @__PURE__ */
|
|
611
|
+
children: [/* @__PURE__ */ O("button", {
|
|
191
612
|
type: "button",
|
|
192
|
-
disabled:
|
|
193
|
-
onClick: () =>
|
|
194
|
-
className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium",
|
|
613
|
+
disabled: d === 0,
|
|
614
|
+
onClick: () => f((e) => Math.max(0, e - 1)),
|
|
615
|
+
className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", d === 0 ? "cursor-not-allowed text-text-secondary opacity-50" : "text-text-primary hover:bg-bg-sunken"),
|
|
195
616
|
children: "Previous"
|
|
196
|
-
}), /* @__PURE__ */
|
|
617
|
+
}), /* @__PURE__ */ O("button", {
|
|
197
618
|
type: "button",
|
|
198
|
-
disabled: !
|
|
199
|
-
onClick: () =>
|
|
200
|
-
className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium",
|
|
619
|
+
disabled: !z,
|
|
620
|
+
onClick: () => f((e) => e + 1),
|
|
621
|
+
className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", z ? "text-text-primary hover:bg-bg-sunken" : "cursor-not-allowed text-text-secondary opacity-50"),
|
|
201
622
|
children: "Next"
|
|
202
623
|
})]
|
|
203
624
|
})]
|
|
204
|
-
})] })
|
|
625
|
+
})] }),
|
|
626
|
+
/* @__PURE__ */ O(B, {}),
|
|
627
|
+
_ && /* @__PURE__ */ O(R, { onClose: () => v(!1) })
|
|
205
628
|
]
|
|
206
629
|
});
|
|
207
630
|
}
|
|
208
631
|
//#endregion
|
|
209
|
-
export {
|
|
632
|
+
export { V as InvoicesPage };
|
|
210
633
|
|
|
211
634
|
//# sourceMappingURL=InvoicesPage.js.map
|