@burdenoff/microfe-subscriberbot 2026.827.1 → 2026.1014.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/dist/subscriberbot/admin/AdminDashboardPage.d.ts.map +1 -1
  2. package/dist/subscriberbot/admin/AdminDashboardPage.js +80 -83
  3. package/dist/subscriberbot/admin/AdminDashboardPage.js.map +1 -1
  4. package/dist/subscriberbot/hooks/index.d.ts +1 -0
  5. package/dist/subscriberbot/hooks/index.d.ts.map +1 -1
  6. package/dist/subscriberbot/hooks/index.js +1 -0
  7. package/dist/subscriberbot/hooks/useTr.d.ts +17 -0
  8. package/dist/subscriberbot/hooks/useTr.d.ts.map +1 -0
  9. package/dist/subscriberbot/hooks/useTr.js +14 -0
  10. package/dist/subscriberbot/hooks/useTr.js.map +1 -0
  11. package/dist/subscriberbot/pages/AssetVaultPage.d.ts.map +1 -1
  12. package/dist/subscriberbot/pages/AssetVaultPage.js +111 -109
  13. package/dist/subscriberbot/pages/AssetVaultPage.js.map +1 -1
  14. package/dist/subscriberbot/pages/DashboardPage.d.ts.map +1 -1
  15. package/dist/subscriberbot/pages/DashboardPage.js +113 -105
  16. package/dist/subscriberbot/pages/DashboardPage.js.map +1 -1
  17. package/dist/subscriberbot/pages/InboxPage.d.ts.map +1 -1
  18. package/dist/subscriberbot/pages/InboxPage.js +404 -369
  19. package/dist/subscriberbot/pages/InboxPage.js.map +1 -1
  20. package/dist/subscriberbot/pages/InsightsPage.d.ts.map +1 -1
  21. package/dist/subscriberbot/pages/InsightsPage.js +94 -93
  22. package/dist/subscriberbot/pages/InsightsPage.js.map +1 -1
  23. package/dist/subscriberbot/pages/InvoicesPage.d.ts.map +1 -1
  24. package/dist/subscriberbot/pages/InvoicesPage.js +360 -366
  25. package/dist/subscriberbot/pages/InvoicesPage.js.map +1 -1
  26. package/dist/subscriberbot/pages/WorkflowsPage.d.ts.map +1 -1
  27. package/dist/subscriberbot/pages/WorkflowsPage.js +209 -193
  28. package/dist/subscriberbot/pages/WorkflowsPage.js.map +1 -1
  29. package/dist/subscriberbot/pages/agents/AgentDetailPage.d.ts.map +1 -1
  30. package/dist/subscriberbot/pages/agents/AgentDetailPage.js +268 -236
  31. package/dist/subscriberbot/pages/agents/AgentDetailPage.js.map +1 -1
  32. package/dist/subscriberbot/pages/agents/AgentNewPage.d.ts.map +1 -1
  33. package/dist/subscriberbot/pages/agents/AgentNewPage.js +96 -76
  34. package/dist/subscriberbot/pages/agents/AgentNewPage.js.map +1 -1
  35. package/dist/subscriberbot/pages/agents/AgentsListPage.d.ts.map +1 -1
  36. package/dist/subscriberbot/pages/agents/AgentsListPage.js +145 -161
  37. package/dist/subscriberbot/pages/agents/AgentsListPage.js.map +1 -1
  38. package/dist/subscriberbot/pages/providers/ProviderDetailPage.d.ts.map +1 -1
  39. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js +514 -441
  40. package/dist/subscriberbot/pages/providers/ProviderDetailPage.js.map +1 -1
  41. package/dist/subscriberbot/pages/providers/ProviderNewPage.d.ts.map +1 -1
  42. package/dist/subscriberbot/pages/providers/ProviderNewPage.js +167 -129
  43. package/dist/subscriberbot/pages/providers/ProviderNewPage.js.map +1 -1
  44. package/dist/subscriberbot/pages/providers/ProvidersListPage.d.ts.map +1 -1
  45. package/dist/subscriberbot/pages/providers/ProvidersListPage.js +171 -218
  46. package/dist/subscriberbot/pages/providers/ProvidersListPage.js.map +1 -1
  47. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.d.ts.map +1 -1
  48. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js +340 -279
  49. package/dist/subscriberbot/pages/relationships/RelationshipDetailPage.js.map +1 -1
  50. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.d.ts.map +1 -1
  51. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js +185 -166
  52. package/dist/subscriberbot/pages/relationships/RelationshipNewPage.js.map +1 -1
  53. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.d.ts.map +1 -1
  54. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js +153 -182
  55. package/dist/subscriberbot/pages/relationships/RelationshipsListPage.js.map +1 -1
  56. package/package.json +1 -1
@@ -2,52 +2,28 @@ import { useSubscriberBot as e } from "../context/SubscriberBotContext.js";
2
2
  import { cn as t } from "../utils/cn.js";
3
3
  import { PageLayout as n } from "../components/PageLayout.js";
4
4
  import { MetricsCard as r } from "../components/MetricsCard.js";
5
- import { formatCurrency as i, formatDate as a } from "../utils/formatters.js";
6
- import { StatusBadge as o } from "../components/StatusBadge.js";
7
- import { EmptyState as s } from "../components/EmptyState.js";
8
- import { Modal as c } from "../components/Modal.js";
9
- import { ErrorView as l, LoadingView as u, Section as d } from "../components/StateViews.js";
10
- import { CHART_COLORS as f, Donut as p, Legend as m } from "../components/viz.js";
11
- import { useCreateInvoice as h, useCreatePaymentInstrument as g, useInvoices as _, useMarkInvoicePaid as v, usePaymentInstruments as y, useRelationships as b, useRemovePaymentInstrument as x } from "../hooks/useSubscriberBotApi.js";
12
- import { useMemo as S, useState as C } from "react";
13
- import { AlertTriangle as w, CheckCircle2 as T, CreditCard as E, FileText as D, Plus as O, Receipt as k, Star as A, Trash2 as j } from "lucide-react";
14
- import { Fragment as M, jsx as N, jsxs as P } from "react/jsx-runtime";
15
- import { GlassCard as F, PagePurpose as I } from "@burdenoff/fe-libs/ui";
5
+ import { formatCurrency as i, formatDate as a, formatEnumLabel as o } from "../utils/formatters.js";
6
+ import { StatusBadge as s } from "../components/StatusBadge.js";
7
+ import { EmptyState as c } from "../components/EmptyState.js";
8
+ import { Modal as l } from "../components/Modal.js";
9
+ import { ErrorView as u, LoadingView as d, Section as f } from "../components/StateViews.js";
10
+ import { CHART_COLORS as p, Donut as m, Legend as h } from "../components/viz.js";
11
+ import { useCreateInvoice as g, useCreatePaymentInstrument as _, useInvoices as v, useMarkInvoicePaid as y, usePaymentInstruments as b, useRelationships as x, useRemovePaymentInstrument as S } from "../hooks/useSubscriberBotApi.js";
12
+ import { useTr as C } from "../hooks/useTr.js";
13
+ import { useMemo as w, useState as T } from "react";
14
+ import { AlertTriangle as E, CheckCircle2 as D, CreditCard as O, FileText as ee, Plus as k, Receipt as A, Star as j, Trash2 as M } from "lucide-react";
15
+ import { Fragment as N, jsx as P, jsxs as F } from "react/jsx-runtime";
16
+ import { GlassCard as I, PagePurpose as te } from "@burdenoff/fe-libs/ui";
16
17
  //#region src/subscriberbot/pages/InvoicesPage.tsx
17
- var L = 25, 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 = [
18
- {
19
- value: "",
20
- label: "All statuses"
21
- },
22
- {
23
- value: "ISSUED",
24
- label: "Issued"
25
- },
26
- {
27
- value: "OVERDUE",
28
- label: "Overdue"
29
- },
30
- {
31
- value: "PAID",
32
- label: "Paid"
33
- },
34
- {
35
- value: "FAILED",
36
- label: "Failed"
37
- },
38
- {
39
- value: "DRAFT",
40
- label: "Draft"
41
- },
42
- {
43
- value: "CANCELLED",
44
- label: "Cancelled"
45
- },
46
- {
47
- value: "REFUNDED",
48
- label: "Refunded"
49
- }
50
- ], V = [
18
+ var L = 25, 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 = {
19
+ ISSUED: "invoices.filters.issued",
20
+ OVERDUE: "invoices.filters.overdue",
21
+ PAID: "invoices.filters.paid",
22
+ FAILED: "invoices.filters.failed",
23
+ DRAFT: "invoices.filters.draft",
24
+ CANCELLED: "invoices.filters.cancelled",
25
+ REFUNDED: "invoices.filters.refunded"
26
+ }, V = [
51
27
  "ISSUED",
52
28
  "DRAFT",
53
29
  "OVERDUE",
@@ -76,185 +52,189 @@ var L = 25, R = "w-full rounded-lg border border-border-subtle bg-bg-surface px-
76
52
  REFUNDED: "var(--color-status-warning-text)"
77
53
  };
78
54
  function G({ onClose: e }) {
79
- let t = h(), n = b({ pagination: {
55
+ let t = C(), n = g(), r = x({ pagination: {
80
56
  limit: 100,
81
57
  offset: 0
82
- } }).data?.items ?? [], [r, i] = C(""), [a, o] = C(""), [s, l] = C("ISSUED"), [u, d] = C("USD"), [f, p] = C(""), [m, g] = C(""), [_, v] = C(""), [y, x] = C(""), [S, w] = C(""), [T, E] = C(null);
83
- return /* @__PURE__ */ N(c, {
84
- title: "Create invoice",
58
+ } }).data?.items ?? [], [i, a] = T(""), [o, s] = T(""), [c, u] = T("ISSUED"), [d, f] = T("USD"), [p, m] = T(""), [h, _] = T(""), [v, y] = T(""), [b, S] = T(""), [w, E] = T(""), [D, O] = T(null);
59
+ return /* @__PURE__ */ P(l, {
60
+ title: t("invoices.createModal.title", "Create invoice"),
85
61
  onClose: e,
86
62
  maxWidthClassName: "max-w-xl",
87
- children: /* @__PURE__ */ P("form", {
88
- onSubmit: (n) => {
89
- if (n.preventDefault(), E(null), !r) {
90
- E("Select the relationship this invoice belongs to.");
63
+ children: /* @__PURE__ */ F("form", {
64
+ onSubmit: (r) => {
65
+ if (r.preventDefault(), O(null), !i) {
66
+ O(t("invoices.createModal.relationshipRequired", "Select the relationship this invoice belongs to."));
91
67
  return;
92
68
  }
93
- t.mutate({
94
- relationshipId: r,
95
- status: s,
96
- currency: u.trim() || "USD",
97
- ...a.trim() ? { number: a.trim() } : {},
98
- ...f.trim() ? { subtotal: Number(f) } : {},
99
- ...m.trim() ? { taxAmount: Number(m) } : {},
100
- ..._.trim() ? { total: Number(_) } : {},
101
- ...y ? { issueDate: new Date(y).toISOString() } : {},
102
- ...S ? { dueDate: new Date(S).toISOString() } : {}
69
+ n.mutate({
70
+ relationshipId: i,
71
+ status: c,
72
+ currency: d.trim() || "USD",
73
+ ...o.trim() ? { number: o.trim() } : {},
74
+ ...p.trim() ? { subtotal: Number(p) } : {},
75
+ ...h.trim() ? { taxAmount: Number(h) } : {},
76
+ ...v.trim() ? { total: Number(v) } : {},
77
+ ...b ? { issueDate: new Date(b).toISOString() } : {},
78
+ ...w ? { dueDate: new Date(w).toISOString() } : {}
103
79
  }, {
104
80
  onSuccess: () => e(),
105
- onError: (e) => E(e instanceof Error ? e.message : "Could not create invoice.")
81
+ onError: (e) => O(e instanceof Error ? e.message : t("invoices.createModal.error", "Could not create invoice."))
106
82
  });
107
83
  },
108
84
  className: "space-y-4",
109
85
  children: [
110
- T && /* @__PURE__ */ N("div", {
86
+ D && /* @__PURE__ */ P("div", {
111
87
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
112
- children: T
88
+ children: D
113
89
  }),
114
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
90
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ F("label", {
115
91
  htmlFor: "inv-relationship",
116
92
  className: z,
117
- children: ["Relationship ", /* @__PURE__ */ N("span", {
118
- className: "text-status-error-text",
119
- children: "*"
120
- })]
121
- }), /* @__PURE__ */ P("select", {
93
+ children: [
94
+ t("invoices.createModal.relationshipLabel", "Relationship"),
95
+ " ",
96
+ /* @__PURE__ */ P("span", {
97
+ className: "text-status-error-text",
98
+ children: "*"
99
+ })
100
+ ]
101
+ }), /* @__PURE__ */ F("select", {
122
102
  id: "inv-relationship",
123
- value: r,
124
- onChange: (e) => i(e.target.value),
103
+ value: i,
104
+ onChange: (e) => a(e.target.value),
125
105
  className: R,
126
106
  required: !0,
127
- children: [/* @__PURE__ */ N("option", {
107
+ children: [/* @__PURE__ */ P("option", {
128
108
  value: "",
129
- children: "— Select a relationship —"
130
- }), n.map((e) => /* @__PURE__ */ N("option", {
109
+ children: t("invoices.createModal.relationshipPlaceholder", "— Select a relationship —")
110
+ }), r.map((e) => /* @__PURE__ */ P("option", {
131
111
  value: e.id,
132
112
  children: e.label
133
113
  }, e.id))]
134
114
  })] }),
135
- /* @__PURE__ */ P("div", {
115
+ /* @__PURE__ */ F("div", {
136
116
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
137
117
  children: [
138
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
118
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
139
119
  htmlFor: "inv-number",
140
120
  className: z,
141
- children: "Number"
142
- }), /* @__PURE__ */ N("input", {
121
+ children: t("invoices.createModal.numberLabel", "Number")
122
+ }), /* @__PURE__ */ P("input", {
143
123
  id: "inv-number",
144
124
  type: "text",
145
- value: a,
146
- onChange: (e) => o(e.target.value),
147
- placeholder: "INV-0001",
125
+ value: o,
126
+ onChange: (e) => s(e.target.value),
127
+ placeholder: t("invoices.createModal.numberPlaceholder", "INV-0001"),
148
128
  className: R
149
129
  })] }),
150
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
130
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
151
131
  htmlFor: "inv-status",
152
132
  className: z,
153
- children: "Status"
154
- }), /* @__PURE__ */ N("select", {
133
+ children: t("invoices.createModal.statusLabel", "Status")
134
+ }), /* @__PURE__ */ P("select", {
155
135
  id: "inv-status",
156
- value: s,
157
- onChange: (e) => l(e.target.value),
136
+ value: c,
137
+ onChange: (e) => u(e.target.value),
158
138
  className: R,
159
- children: V.map((e) => /* @__PURE__ */ N("option", {
139
+ children: V.map((e) => /* @__PURE__ */ P("option", {
160
140
  value: e,
161
- children: e.replace(/_/g, " ")
141
+ children: t(B[e], e)
162
142
  }, e))
163
143
  })] }),
164
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
144
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
165
145
  htmlFor: "inv-currency",
166
146
  className: z,
167
- children: "Currency"
168
- }), /* @__PURE__ */ N("input", {
147
+ children: t("invoices.createModal.currencyLabel", "Currency")
148
+ }), /* @__PURE__ */ P("input", {
169
149
  id: "inv-currency",
170
150
  type: "text",
171
- value: u,
172
- onChange: (e) => d(e.target.value.toUpperCase()),
151
+ value: d,
152
+ onChange: (e) => f(e.target.value.toUpperCase()),
173
153
  maxLength: 3,
174
154
  className: R
175
155
  })] })
176
156
  ]
177
157
  }),
178
- /* @__PURE__ */ P("div", {
158
+ /* @__PURE__ */ F("div", {
179
159
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
180
160
  children: [
181
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
161
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
182
162
  htmlFor: "inv-subtotal",
183
163
  className: z,
184
- children: "Subtotal"
185
- }), /* @__PURE__ */ N("input", {
164
+ children: t("invoices.createModal.subtotalLabel", "Subtotal")
165
+ }), /* @__PURE__ */ P("input", {
186
166
  id: "inv-subtotal",
187
167
  type: "number",
188
168
  min: "0",
189
169
  step: "0.01",
190
- value: f,
191
- onChange: (e) => p(e.target.value),
170
+ value: p,
171
+ onChange: (e) => m(e.target.value),
192
172
  className: R
193
173
  })] }),
194
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
174
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
195
175
  htmlFor: "inv-tax",
196
176
  className: z,
197
- children: "Tax"
198
- }), /* @__PURE__ */ N("input", {
177
+ children: t("invoices.createModal.taxLabel", "Tax")
178
+ }), /* @__PURE__ */ P("input", {
199
179
  id: "inv-tax",
200
180
  type: "number",
201
181
  min: "0",
202
182
  step: "0.01",
203
- value: m,
204
- onChange: (e) => g(e.target.value),
183
+ value: h,
184
+ onChange: (e) => _(e.target.value),
205
185
  className: R
206
186
  })] }),
207
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
187
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
208
188
  htmlFor: "inv-total",
209
189
  className: z,
210
- children: "Total"
211
- }), /* @__PURE__ */ N("input", {
190
+ children: t("invoices.createModal.totalLabel", "Total")
191
+ }), /* @__PURE__ */ P("input", {
212
192
  id: "inv-total",
213
193
  type: "number",
214
194
  min: "0",
215
195
  step: "0.01",
216
- value: _,
217
- onChange: (e) => v(e.target.value),
196
+ value: v,
197
+ onChange: (e) => y(e.target.value),
218
198
  className: R
219
199
  })] })
220
200
  ]
221
201
  }),
222
- /* @__PURE__ */ P("div", {
202
+ /* @__PURE__ */ F("div", {
223
203
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
224
- children: [/* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
204
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
225
205
  htmlFor: "inv-issue",
226
206
  className: z,
227
- children: "Issue date"
228
- }), /* @__PURE__ */ N("input", {
207
+ children: t("invoices.createModal.issueDateLabel", "Issue date")
208
+ }), /* @__PURE__ */ P("input", {
229
209
  id: "inv-issue",
230
210
  type: "date",
231
- value: y,
232
- onChange: (e) => x(e.target.value),
211
+ value: b,
212
+ onChange: (e) => S(e.target.value),
233
213
  className: R
234
- })] }), /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
214
+ })] }), /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
235
215
  htmlFor: "inv-due",
236
216
  className: z,
237
- children: "Due date"
238
- }), /* @__PURE__ */ N("input", {
217
+ children: t("invoices.createModal.dueDateLabel", "Due date")
218
+ }), /* @__PURE__ */ P("input", {
239
219
  id: "inv-due",
240
220
  type: "date",
241
- value: S,
242
- onChange: (e) => w(e.target.value),
221
+ value: w,
222
+ onChange: (e) => E(e.target.value),
243
223
  className: R
244
224
  })] })]
245
225
  }),
246
- /* @__PURE__ */ P("div", {
226
+ /* @__PURE__ */ F("div", {
247
227
  className: "flex justify-end gap-3",
248
- children: [/* @__PURE__ */ N("button", {
228
+ children: [/* @__PURE__ */ P("button", {
249
229
  type: "button",
250
230
  onClick: e,
251
231
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
252
- children: "Cancel"
253
- }), /* @__PURE__ */ N("button", {
232
+ children: t("invoices.createModal.cancel", "Cancel")
233
+ }), /* @__PURE__ */ P("button", {
254
234
  type: "submit",
255
- disabled: t.isPending,
235
+ disabled: n.isPending,
256
236
  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",
257
- children: t.isPending ? "Creating…" : "Create invoice"
237
+ children: n.isPending ? t("invoices.creating", "Creating…") : t("invoices.createModal.submit", "Create invoice")
258
238
  })]
259
239
  })
260
240
  ]
@@ -262,151 +242,155 @@ function G({ onClose: e }) {
262
242
  });
263
243
  }
264
244
  function K({ onClose: e }) {
265
- let t = g(), [n, r] = C(""), [i, a] = C("CARD"), [o, s] = C(""), [l, u] = C(""), [d, f] = C(""), [p, m] = C(""), [h, _] = C(!1), [v, y] = C(null);
266
- return /* @__PURE__ */ N(c, {
267
- title: "Add payment method",
268
- description: "A passive annotation of which external card/account pays for a subscription — no full card numbers or CVV.",
245
+ let t = C(), n = _(), [r, i] = T(""), [a, s] = T("CARD"), [c, u] = T(""), [d, f] = T(""), [p, m] = T(""), [h, g] = T(""), [v, y] = T(!1), [b, x] = T(null);
246
+ return /* @__PURE__ */ P(l, {
247
+ title: t("invoices.addPaymentMethodModal.title", "Add payment method"),
248
+ description: t("invoices.addPaymentMethodModal.description", "A passive annotation of which external card/account pays for a subscription — no full card numbers or CVV."),
269
249
  onClose: e,
270
250
  maxWidthClassName: "max-w-xl",
271
- children: /* @__PURE__ */ P("form", {
272
- onSubmit: (r) => {
273
- if (r.preventDefault(), y(null), !n.trim()) {
274
- y("A label is required.");
251
+ children: /* @__PURE__ */ F("form", {
252
+ onSubmit: (i) => {
253
+ if (i.preventDefault(), x(null), !r.trim()) {
254
+ x(t("invoices.addPaymentMethodModal.labelRequired", "A label is required."));
275
255
  return;
276
256
  }
277
- t.mutate({
278
- label: n.trim(),
279
- type: i,
280
- isDefault: h,
281
- ...o.trim() ? { brand: o.trim() } : {},
282
- ...l.trim() ? { last4: l.trim() } : {},
283
- ...d.trim() ? { expiryMonth: Number(d) } : {},
284
- ...p.trim() ? { expiryYear: Number(p) } : {}
257
+ n.mutate({
258
+ label: r.trim(),
259
+ type: a,
260
+ isDefault: v,
261
+ ...c.trim() ? { brand: c.trim() } : {},
262
+ ...d.trim() ? { last4: d.trim() } : {},
263
+ ...p.trim() ? { expiryMonth: Number(p) } : {},
264
+ ...h.trim() ? { expiryYear: Number(h) } : {}
285
265
  }, {
286
266
  onSuccess: () => e(),
287
- onError: (e) => y(e instanceof Error ? e.message : "Could not add payment method.")
267
+ onError: (e) => x(e instanceof Error ? e.message : t("invoices.addPaymentMethodModal.error", "Could not add payment method."))
288
268
  });
289
269
  },
290
270
  className: "space-y-4",
291
271
  children: [
292
- v && /* @__PURE__ */ N("div", {
272
+ b && /* @__PURE__ */ P("div", {
293
273
  className: "rounded-lg border border-status-error-text/30 bg-status-error-bg-subtle px-4 py-2 text-sm text-status-error-text",
294
- children: v
274
+ children: b
295
275
  }),
296
- /* @__PURE__ */ P("div", {
276
+ /* @__PURE__ */ F("div", {
297
277
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2",
298
- children: [/* @__PURE__ */ P("div", { children: [/* @__PURE__ */ P("label", {
278
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ F("label", {
299
279
  htmlFor: "pm-label",
300
280
  className: z,
301
- children: ["Label ", /* @__PURE__ */ N("span", {
302
- className: "text-status-error-text",
303
- children: "*"
304
- })]
305
- }), /* @__PURE__ */ N("input", {
281
+ children: [
282
+ t("invoices.addPaymentMethodModal.labelLabel", "Label"),
283
+ " ",
284
+ /* @__PURE__ */ P("span", {
285
+ className: "text-status-error-text",
286
+ children: "*"
287
+ })
288
+ ]
289
+ }), /* @__PURE__ */ P("input", {
306
290
  id: "pm-label",
307
291
  type: "text",
308
- value: n,
309
- onChange: (e) => r(e.target.value),
310
- placeholder: "e.g. Personal Visa",
292
+ value: r,
293
+ onChange: (e) => i(e.target.value),
294
+ placeholder: t("invoices.addPaymentMethodModal.labelPlaceholder", "e.g. Personal Visa"),
311
295
  className: R,
312
296
  required: !0
313
- })] }), /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
297
+ })] }), /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
314
298
  htmlFor: "pm-type",
315
299
  className: z,
316
- children: "Type"
317
- }), /* @__PURE__ */ N("select", {
300
+ children: t("invoices.addPaymentMethodModal.typeLabel", "Type")
301
+ }), /* @__PURE__ */ P("select", {
318
302
  id: "pm-type",
319
- value: i,
320
- onChange: (e) => a(e.target.value),
303
+ value: a,
304
+ onChange: (e) => s(e.target.value),
321
305
  className: R,
322
- children: H.map((e) => /* @__PURE__ */ N("option", {
306
+ children: H.map((e) => /* @__PURE__ */ P("option", {
323
307
  value: e,
324
- children: e.replace(/_/g, " ")
308
+ children: o(e)
325
309
  }, e))
326
310
  })] })]
327
311
  }),
328
- /* @__PURE__ */ P("div", {
312
+ /* @__PURE__ */ F("div", {
329
313
  className: "grid grid-cols-1 gap-4 sm:grid-cols-3",
330
314
  children: [
331
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
315
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
332
316
  htmlFor: "pm-brand",
333
317
  className: z,
334
- children: "Brand"
335
- }), /* @__PURE__ */ N("input", {
318
+ children: t("invoices.addPaymentMethodModal.brandLabel", "Brand")
319
+ }), /* @__PURE__ */ P("input", {
336
320
  id: "pm-brand",
337
321
  type: "text",
338
- value: o,
339
- onChange: (e) => s(e.target.value),
340
- placeholder: "Visa, Amex…",
322
+ value: c,
323
+ onChange: (e) => u(e.target.value),
324
+ placeholder: t("invoices.addPaymentMethodModal.brandPlaceholder", "Visa, Amex…"),
341
325
  className: R
342
326
  })] }),
343
- /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
327
+ /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
344
328
  htmlFor: "pm-last4",
345
329
  className: z,
346
- children: "Last 4"
347
- }), /* @__PURE__ */ N("input", {
330
+ children: t("invoices.addPaymentMethodModal.last4Label", "Last 4")
331
+ }), /* @__PURE__ */ P("input", {
348
332
  id: "pm-last4",
349
333
  type: "text",
350
334
  inputMode: "numeric",
351
335
  maxLength: 4,
352
- value: l,
353
- onChange: (e) => u(e.target.value.replace(/\D/g, "")),
354
- placeholder: "4242",
336
+ value: d,
337
+ onChange: (e) => f(e.target.value.replace(/\D/g, "")),
338
+ placeholder: t("invoices.addPaymentMethodModal.last4Placeholder", "4242"),
355
339
  className: R
356
340
  })] }),
357
- /* @__PURE__ */ P("div", {
341
+ /* @__PURE__ */ F("div", {
358
342
  className: "grid grid-cols-2 gap-2",
359
- children: [/* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
343
+ children: [/* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
360
344
  htmlFor: "pm-exp-month",
361
345
  className: z,
362
- children: "Exp. mo."
363
- }), /* @__PURE__ */ N("input", {
346
+ children: t("invoices.addPaymentMethodModal.expMonthLabel", "Exp. mo.")
347
+ }), /* @__PURE__ */ P("input", {
364
348
  id: "pm-exp-month",
365
349
  type: "number",
366
350
  min: "1",
367
351
  max: "12",
368
- value: d,
369
- onChange: (e) => f(e.target.value),
370
- placeholder: "12",
352
+ value: p,
353
+ onChange: (e) => m(e.target.value),
354
+ placeholder: t("invoices.addPaymentMethodModal.expMonthPlaceholder", "12"),
371
355
  className: R
372
- })] }), /* @__PURE__ */ P("div", { children: [/* @__PURE__ */ N("label", {
356
+ })] }), /* @__PURE__ */ F("div", { children: [/* @__PURE__ */ P("label", {
373
357
  htmlFor: "pm-exp-year",
374
358
  className: z,
375
- children: "Exp. yr."
376
- }), /* @__PURE__ */ N("input", {
359
+ children: t("invoices.addPaymentMethodModal.expYearLabel", "Exp. yr.")
360
+ }), /* @__PURE__ */ P("input", {
377
361
  id: "pm-exp-year",
378
362
  type: "number",
379
363
  min: "2024",
380
364
  max: "2099",
381
- value: p,
382
- onChange: (e) => m(e.target.value),
383
- placeholder: "2028",
365
+ value: h,
366
+ onChange: (e) => g(e.target.value),
367
+ placeholder: t("invoices.addPaymentMethodModal.expYearPlaceholder", "2028"),
384
368
  className: R
385
369
  })] })]
386
370
  })
387
371
  ]
388
372
  }),
389
- /* @__PURE__ */ P("label", {
373
+ /* @__PURE__ */ F("label", {
390
374
  className: "flex items-center gap-2 text-sm text-text-primary",
391
- children: [/* @__PURE__ */ N("input", {
375
+ children: [/* @__PURE__ */ P("input", {
392
376
  type: "checkbox",
393
- checked: h,
394
- onChange: (e) => _(e.target.checked),
377
+ checked: v,
378
+ onChange: (e) => y(e.target.checked),
395
379
  className: "size-4 rounded border-border-subtle"
396
- }), "Set as default"]
380
+ }), t("invoices.addPaymentMethodModal.defaultLabel", "Set as default")]
397
381
  }),
398
- /* @__PURE__ */ P("div", {
382
+ /* @__PURE__ */ F("div", {
399
383
  className: "flex justify-end gap-3",
400
- children: [/* @__PURE__ */ N("button", {
384
+ children: [/* @__PURE__ */ P("button", {
401
385
  type: "button",
402
386
  onClick: e,
403
387
  className: "rounded-lg border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary hover:bg-bg-sunken",
404
- children: "Cancel"
405
- }), /* @__PURE__ */ N("button", {
388
+ children: t("invoices.addPaymentMethodModal.cancel", "Cancel")
389
+ }), /* @__PURE__ */ P("button", {
406
390
  type: "submit",
407
- disabled: t.isPending,
391
+ disabled: n.isPending,
408
392
  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",
409
- children: t.isPending ? "Adding…" : "Add payment method"
393
+ children: n.isPending ? t("invoices.addPaymentMethodModal.adding", "Adding…") : t("invoices.addPaymentMethodModal.submit", "Add payment method")
410
394
  })]
411
395
  })
412
396
  ]
@@ -414,177 +398,191 @@ function K({ onClose: e }) {
414
398
  });
415
399
  }
416
400
  function q() {
417
- let { data: e, isLoading: t, isError: n, refetch: r } = y(), i = x(), [a, c] = C(!1), f = e ?? [];
418
- return /* @__PURE__ */ P(d, {
419
- title: "Payment methods",
420
- description: "Which external cards and accounts pay for your subscriptions",
421
- action: /* @__PURE__ */ P("button", {
401
+ let e = C(), { data: t, isLoading: n, isError: r, refetch: i } = b(), a = S(), [l, p] = T(!1), m = t ?? [];
402
+ return /* @__PURE__ */ F(f, {
403
+ title: e("invoices.paymentMethods.title", "Payment methods"),
404
+ description: e("invoices.paymentMethods.description", "Which external cards and accounts pay for your subscriptions"),
405
+ action: /* @__PURE__ */ F("button", {
422
406
  type: "button",
423
- onClick: () => c(!0),
407
+ onClick: () => p(!0),
424
408
  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",
425
- children: [/* @__PURE__ */ N(O, { className: "h-3.5 w-3.5" }), " Add payment method"]
409
+ children: [
410
+ /* @__PURE__ */ P(k, { className: "h-3.5 w-3.5" }),
411
+ " ",
412
+ e("invoices.paymentMethods.add", "Add payment method")
413
+ ]
426
414
  }),
427
- children: [t ? /* @__PURE__ */ N(u, { label: "Loading payment methods…" }) : n ? /* @__PURE__ */ N(l, {
428
- message: "Could not load payment methods.",
429
- onRetry: () => void r()
430
- }) : f.length === 0 ? /* @__PURE__ */ N(s, {
415
+ children: [n ? /* @__PURE__ */ P(d, { label: e("invoices.paymentMethods.loading", "Loading payment methods…") }) : r ? /* @__PURE__ */ P(u, {
416
+ message: e("invoices.paymentMethods.error", "Could not load payment methods."),
417
+ onRetry: () => void i()
418
+ }) : m.length === 0 ? /* @__PURE__ */ P(c, {
431
419
  illustration: "empty-data",
432
- icon: /* @__PURE__ */ N(E, { className: "h-12 w-12" }),
433
- title: "No payment methods",
434
- description: "Annotate which card or account pays for each subscription. No full card numbers are stored."
435
- }) : /* @__PURE__ */ N("div", {
420
+ icon: /* @__PURE__ */ P(O, { className: "h-12 w-12" }),
421
+ title: e("invoices.paymentMethods.emptyTitle", "No payment methods"),
422
+ description: e("invoices.paymentMethods.emptyDescription", "Annotate which card or account pays for each subscription. No full card numbers are stored.")
423
+ }) : /* @__PURE__ */ P("div", {
436
424
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-3",
437
- children: f.map((e) => {
438
- let t = [e.expiryMonth && e.expiryYear ? `Exp ${String(e.expiryMonth).padStart(2, "0")}/${String(e.expiryYear).slice(-2)}` : null].filter(Boolean);
439
- return /* @__PURE__ */ P(F, {
425
+ children: m.map((t) => {
426
+ let n = [t.expiryMonth && t.expiryYear ? `Exp ${String(t.expiryMonth).padStart(2, "0")}/${String(t.expiryYear).slice(-2)}` : null].filter(Boolean);
427
+ return /* @__PURE__ */ F(I, {
440
428
  treatment: "metric",
441
429
  className: "flex flex-col gap-4 p-4",
442
- children: [/* @__PURE__ */ P("div", {
430
+ children: [/* @__PURE__ */ F("div", {
443
431
  className: "flex items-start justify-between gap-2",
444
- children: [/* @__PURE__ */ P("div", {
432
+ children: [/* @__PURE__ */ F("div", {
445
433
  className: "flex items-center gap-3",
446
- children: [/* @__PURE__ */ N("span", {
434
+ children: [/* @__PURE__ */ P("span", {
447
435
  className: "grid h-9 w-12 place-items-center rounded-md bg-[var(--color-accent-soft)] text-text-primary",
448
- children: /* @__PURE__ */ N(E, {
436
+ children: /* @__PURE__ */ P(O, {
449
437
  className: "h-4 w-4",
450
438
  "aria-hidden": !0
451
439
  })
452
- }), /* @__PURE__ */ P("div", {
440
+ }), /* @__PURE__ */ F("div", {
453
441
  className: "min-w-0",
454
- children: [/* @__PURE__ */ P("p", {
442
+ children: [/* @__PURE__ */ F("p", {
455
443
  className: "flex items-center gap-1.5 truncate text-sm font-semibold text-text-primary",
456
- children: [e.brand || e.label, e.isDefault && /* @__PURE__ */ P("span", {
444
+ children: [t.brand || t.label, t.isDefault && /* @__PURE__ */ F("span", {
457
445
  className: "inline-flex items-center gap-1 rounded-full bg-status-success-bg-subtle px-1.5 py-0.5 text-[10px] font-semibold uppercase tracking-wide text-status-success-text",
458
- children: [/* @__PURE__ */ N(A, {
446
+ children: [/* @__PURE__ */ P(j, {
459
447
  className: "h-2.5 w-2.5 fill-current",
460
448
  "aria-hidden": !0
461
- }), "Default"]
449
+ }), e("invoices.paymentMethods.default", "Default")]
462
450
  })]
463
- }), /* @__PURE__ */ N("p", {
451
+ }), /* @__PURE__ */ P("p", {
464
452
  className: "font-mono text-sm tracking-[0.15em] text-text-secondary",
465
- children: e.last4 ? `•••• ${e.last4}` : e.type.replace(/_/g, " ")
453
+ children: t.last4 ? `•••• ${t.last4}` : o(t.type)
466
454
  })]
467
455
  })]
468
- }), /* @__PURE__ */ N(o, { status: e.status })]
469
- }), /* @__PURE__ */ P("div", {
456
+ }), /* @__PURE__ */ P(s, { status: t.status })]
457
+ }), /* @__PURE__ */ F("div", {
470
458
  className: "mt-auto flex items-center justify-between border-t border-border-subtle pt-3",
471
- children: [/* @__PURE__ */ N("p", {
459
+ children: [/* @__PURE__ */ P("p", {
472
460
  className: "truncate text-xs text-text-secondary",
473
- children: [e.label, ...t].filter(Boolean).join(" · ")
474
- }), /* @__PURE__ */ P("button", {
461
+ children: [t.label, ...n].filter(Boolean).join(" · ")
462
+ }), /* @__PURE__ */ F("button", {
475
463
  type: "button",
476
- "aria-label": `Remove ${e.label}`,
477
- disabled: i.isPending,
478
- onClick: () => i.mutate(e.id),
464
+ "aria-label": e("invoices.paymentMethods.removeAria", "Remove {{label}}", { label: t.label }),
465
+ disabled: a.isPending,
466
+ onClick: () => a.mutate(t.id),
479
467
  className: "inline-flex shrink-0 items-center gap-1 rounded-lg border border-border-subtle px-2.5 py-1 text-xs font-medium text-text-secondary hover:border-status-error-text/40 hover:bg-status-error-bg-subtle hover:text-status-error-text disabled:opacity-50",
480
- children: [/* @__PURE__ */ N(j, {
468
+ children: [/* @__PURE__ */ P(M, {
481
469
  className: "h-3.5 w-3.5",
482
470
  "aria-hidden": !0
483
- }), "Remove"]
471
+ }), e("invoices.paymentMethods.remove", "Remove")]
484
472
  })]
485
473
  })]
486
- }, e.id);
474
+ }, t.id);
487
475
  })
488
- }), a && /* @__PURE__ */ N(K, { onClose: () => c(!1) })]
476
+ }), l && /* @__PURE__ */ P(K, { onClose: () => p(!1) })]
489
477
  });
490
478
  }
491
479
  function J() {
492
- let { navigateTo: c } = e(), [d, h] = C(0), [g, y] = C(""), [x, E] = C(!1), { data: A, isLoading: j, isError: R, refetch: z, isFetching: V } = _({
493
- status: g || void 0,
480
+ let o = C(), { navigateTo: l } = e(), [f, g] = T(0), [_, b] = T(""), [S, O] = T(!1), j = [{
481
+ value: "",
482
+ label: o("invoices.filters.allStatuses", "All statuses")
483
+ }, ...V.map((e) => ({
484
+ value: e,
485
+ label: o(B[e], e)
486
+ }))], { data: M, isLoading: R, isError: z, refetch: H, isFetching: K } = v({
487
+ status: _ || void 0,
494
488
  pagination: {
495
489
  limit: L,
496
- offset: d * L
490
+ offset: f * L
497
491
  }
498
- }), H = v(), K = b({ pagination: {
492
+ }), J = y(), Y = x({ pagination: {
499
493
  limit: 100,
500
494
  offset: 0
501
- } }), J = S(() => {
495
+ } }), X = w(() => {
502
496
  let e = /* @__PURE__ */ new Map();
503
- for (let t of K.data?.items ?? []) e.set(t.id, t.label);
497
+ for (let t of Y.data?.items ?? []) e.set(t.id, t.label);
504
498
  return e;
505
- }, [K.data]), Y = S(() => A?.items ?? [], [A]), X = A?.pageInfo.hasMore ?? !1, Z = S(() => {
506
- let e = Y.filter((e) => U.has(e.status)), t = Y[0]?.currency ?? "USD", n = /* @__PURE__ */ new Map();
507
- for (let e of Y) n.set(e.status, (n.get(e.status) ?? 0) + 1);
499
+ }, [Y.data]), Z = w(() => M?.items ?? [], [M]), Q = M?.pageInfo.hasMore ?? !1, $ = w(() => {
500
+ let e = Z.filter((e) => U.has(e.status)), t = Z[0]?.currency ?? "USD", n = /* @__PURE__ */ new Map();
501
+ for (let e of Z) n.set(e.status, (n.get(e.status) ?? 0) + 1);
508
502
  let r = Array.from(n.entries()).sort((e, t) => t[1] - e[1]).map(([e, t], n) => ({
509
- label: e.charAt(0) + e.slice(1).toLowerCase(),
503
+ label: o(B[e], e.charAt(0) + e.slice(1).toLowerCase()),
510
504
  value: t,
511
- color: W[e] ?? f[n % f.length]
505
+ color: W[e] ?? p[n % p.length]
512
506
  }));
513
507
  return {
514
508
  outstandingCount: e.length,
515
509
  outstandingTotal: e.reduce((e, t) => e + t.total, 0),
516
- paidCount: Y.filter((e) => e.status === "PAID").length,
517
- overdueCount: Y.filter((e) => e.status === "OVERDUE").length,
510
+ paidCount: Z.filter((e) => e.status === "PAID").length,
511
+ overdueCount: Z.filter((e) => e.status === "OVERDUE").length,
518
512
  distribution: r,
519
513
  currency: t
520
514
  };
521
- }, [Y]);
522
- return /* @__PURE__ */ P(n, {
523
- title: "Invoices",
524
- description: "Your billing ledger across every relationship",
525
- actions: /* @__PURE__ */ P("button", {
515
+ }, [Z, o]);
516
+ return /* @__PURE__ */ F(n, {
517
+ title: o("invoices.title", "Invoices"),
518
+ description: o("invoices.description", "Your billing ledger across every relationship"),
519
+ actions: /* @__PURE__ */ F("button", {
526
520
  type: "button",
527
- onClick: () => E(!0),
521
+ onClick: () => O(!0),
528
522
  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",
529
- children: [/* @__PURE__ */ N(O, { className: "h-4 w-4" }), " Create invoice"]
523
+ children: [
524
+ /* @__PURE__ */ P(k, { className: "h-4 w-4" }),
525
+ " ",
526
+ o("invoices.create", "Create invoice")
527
+ ]
530
528
  }),
531
529
  children: [
532
- /* @__PURE__ */ N(I, {
530
+ /* @__PURE__ */ P(te, {
533
531
  className: "mb-4",
534
- children: "Every invoice from your recurring relationships in one ledger. Filter by status and settle issued or overdue invoices directly."
532
+ children: o("invoices.purpose", "Every invoice from your recurring relationships in one ledger. Filter by status and settle issued or overdue invoices directly.")
535
533
  }),
536
- !j && !R && Y.length > 0 && /* @__PURE__ */ P("div", {
534
+ !R && !z && Z.length > 0 && /* @__PURE__ */ F("div", {
537
535
  className: "grid grid-cols-1 gap-4 lg:grid-cols-3",
538
- children: [/* @__PURE__ */ P("div", {
536
+ children: [/* @__PURE__ */ F("div", {
539
537
  className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:col-span-2",
540
538
  children: [
541
- /* @__PURE__ */ N(r, {
539
+ /* @__PURE__ */ P(r, {
542
540
  featured: !0,
543
- icon: /* @__PURE__ */ N(k, {}),
544
- value: i(Z.outstandingTotal, Z.currency, { maximumFractionDigits: 0 }),
545
- label: "Outstanding · this page"
541
+ icon: /* @__PURE__ */ P(A, {}),
542
+ value: i($.outstandingTotal, $.currency, { maximumFractionDigits: 0 }),
543
+ label: o("invoices.metrics.outstanding", "Outstanding · this page")
546
544
  }),
547
- /* @__PURE__ */ N(r, {
548
- icon: /* @__PURE__ */ N(D, {}),
549
- value: Z.outstandingCount,
550
- label: "Open invoices"
545
+ /* @__PURE__ */ P(r, {
546
+ icon: /* @__PURE__ */ P(ee, {}),
547
+ value: $.outstandingCount,
548
+ label: o("invoices.metrics.openInvoices", "Open invoices")
551
549
  }),
552
- /* @__PURE__ */ N(r, {
553
- icon: /* @__PURE__ */ N(w, {}),
554
- value: Z.overdueCount,
555
- label: "Overdue",
556
- ...Z.overdueCount > 0 ? { trend: "down" } : {}
550
+ /* @__PURE__ */ P(r, {
551
+ icon: /* @__PURE__ */ P(E, {}),
552
+ value: $.overdueCount,
553
+ label: o("invoices.metrics.overdue", "Overdue"),
554
+ ...$.overdueCount > 0 ? { trend: "down" } : {}
557
555
  }),
558
- /* @__PURE__ */ N(r, {
559
- icon: /* @__PURE__ */ N(T, {}),
560
- value: Z.paidCount,
561
- label: "Paid",
562
- ...Z.paidCount > 0 ? { trend: "up" } : {}
556
+ /* @__PURE__ */ P(r, {
557
+ icon: /* @__PURE__ */ P(D, {}),
558
+ value: $.paidCount,
559
+ label: o("invoices.metrics.paid", "Paid"),
560
+ ...$.paidCount > 0 ? { trend: "up" } : {}
563
561
  })
564
562
  ]
565
- }), /* @__PURE__ */ P(F, {
563
+ }), /* @__PURE__ */ F(I, {
566
564
  treatment: "insight",
567
565
  className: "p-6",
568
566
  children: [
569
- /* @__PURE__ */ N("p", {
567
+ /* @__PURE__ */ P("p", {
570
568
  className: "text-sm font-semibold text-text-primary",
571
- children: "Status breakdown"
569
+ children: o("invoices.metrics.statusBreakdown", "Status breakdown")
572
570
  }),
573
- /* @__PURE__ */ N("p", {
571
+ /* @__PURE__ */ P("p", {
574
572
  className: "text-xs text-text-secondary",
575
- children: "Across the invoices on this page"
573
+ children: o("invoices.metrics.statusBreakdownHint", "Across the invoices on this page")
576
574
  }),
577
- /* @__PURE__ */ P("div", {
575
+ /* @__PURE__ */ F("div", {
578
576
  className: "mt-4 flex flex-col items-center gap-5 sm:flex-row sm:items-center lg:flex-col xl:flex-row",
579
- children: [/* @__PURE__ */ N(p, {
580
- data: Z.distribution,
577
+ children: [/* @__PURE__ */ P(m, {
578
+ data: $.distribution,
581
579
  size: 132,
582
580
  thickness: 16,
583
- centerLabel: String(Y.length),
584
- centerSub: "invoices",
581
+ centerLabel: String(Z.length),
582
+ centerSub: o("invoices.metrics.invoices", "invoices"),
585
583
  className: "shrink-0"
586
- }), /* @__PURE__ */ N(m, {
587
- data: Z.distribution,
584
+ }), /* @__PURE__ */ P(h, {
585
+ data: $.distribution,
588
586
  className: "w-full min-w-0 flex-1",
589
587
  valueFormat: (e) => String(e)
590
588
  })]
@@ -592,104 +590,104 @@ function J() {
592
590
  ]
593
591
  })]
594
592
  }),
595
- /* @__PURE__ */ N("div", {
593
+ /* @__PURE__ */ P("div", {
596
594
  className: "mt-6 flex flex-wrap items-center gap-3",
597
- children: /* @__PURE__ */ N("select", {
598
- "aria-label": "Filter by status",
599
- value: g,
595
+ children: /* @__PURE__ */ P("select", {
596
+ "aria-label": o("invoices.filters.statusLabel", "Filter by status"),
597
+ value: _,
600
598
  onChange: (e) => {
601
- y(e.target.value), h(0);
599
+ b(e.target.value), g(0);
602
600
  },
603
601
  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)]",
604
- children: B.map((e) => /* @__PURE__ */ N("option", {
602
+ children: j.map((e) => /* @__PURE__ */ P("option", {
605
603
  value: e.value,
606
604
  children: e.label
607
605
  }, e.value))
608
606
  })
609
607
  }),
610
- j ? /* @__PURE__ */ N(u, { label: "Loading invoices…" }) : R ? /* @__PURE__ */ N(l, {
611
- message: "Could not load invoices.",
612
- onRetry: () => void z()
613
- }) : Y.length === 0 ? /* @__PURE__ */ N("div", {
608
+ R ? /* @__PURE__ */ P(d, { label: o("invoices.loading", "Loading invoices…") }) : z ? /* @__PURE__ */ P(u, {
609
+ message: o("invoices.error", "Could not load invoices."),
610
+ onRetry: () => void H()
611
+ }) : Z.length === 0 ? /* @__PURE__ */ P("div", {
614
612
  className: "mt-6",
615
- children: /* @__PURE__ */ N(s, {
613
+ children: /* @__PURE__ */ P(c, {
616
614
  illustration: "empty-data",
617
- icon: /* @__PURE__ */ N(k, { className: "h-12 w-12" }),
618
- title: "No invoices",
619
- description: g ? "No invoices match this status filter." : "Invoices from your relationships will appear here — or create one manually.",
620
- action: /* @__PURE__ */ N("button", {
615
+ icon: /* @__PURE__ */ P(A, { className: "h-12 w-12" }),
616
+ title: o("invoices.emptyTitle", "No invoices"),
617
+ description: _ ? o("invoices.emptyDescriptionFiltered", "No invoices match this status filter.") : o("invoices.emptyDescription", "Invoices from your relationships will appear here — or create one manually."),
618
+ action: /* @__PURE__ */ P("button", {
621
619
  type: "button",
622
- onClick: () => E(!0),
620
+ onClick: () => O(!0),
623
621
  className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
624
- children: "Create invoice"
622
+ children: o("invoices.create", "Create invoice")
625
623
  })
626
624
  })
627
- }) : /* @__PURE__ */ P(M, { children: [/* @__PURE__ */ P("div", {
625
+ }) : /* @__PURE__ */ F(N, { children: [/* @__PURE__ */ F("div", {
628
626
  className: "mt-6 overflow-hidden rounded-lg border border-border-subtle bg-bg-surface",
629
- children: [/* @__PURE__ */ P("div", {
627
+ children: [/* @__PURE__ */ F("div", {
630
628
  className: "hidden grid-cols-[1.3fr_1.2fr_0.8fr_0.8fr_0.8fr_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",
631
629
  children: [
632
- /* @__PURE__ */ N("span", { children: "Invoice" }),
633
- /* @__PURE__ */ N("span", { children: "Subscription" }),
634
- /* @__PURE__ */ N("span", { children: "Status" }),
635
- /* @__PURE__ */ N("span", {
630
+ /* @__PURE__ */ P("span", { children: o("invoices.table.invoice", "Invoice") }),
631
+ /* @__PURE__ */ P("span", { children: o("invoices.table.subscription", "Subscription") }),
632
+ /* @__PURE__ */ P("span", { children: o("invoices.table.status", "Status") }),
633
+ /* @__PURE__ */ P("span", {
636
634
  className: "text-right",
637
- children: "Total"
635
+ children: o("invoices.table.total", "Total")
638
636
  }),
639
- /* @__PURE__ */ N("span", {
637
+ /* @__PURE__ */ P("span", {
640
638
  className: "text-right",
641
- children: "Due"
639
+ children: o("invoices.table.due", "Due")
642
640
  }),
643
- /* @__PURE__ */ N("span", {
641
+ /* @__PURE__ */ P("span", {
644
642
  className: "text-right",
645
- children: "Action"
643
+ children: o("invoices.table.action", "Action")
646
644
  })
647
645
  ]
648
- }), /* @__PURE__ */ N("div", {
646
+ }), /* @__PURE__ */ P("div", {
649
647
  className: "divide-y divide-border-subtle",
650
- children: Y.map((e) => /* @__PURE__ */ P("div", {
648
+ children: Z.map((e) => /* @__PURE__ */ F("div", {
651
649
  className: "grid grid-cols-1 gap-2 px-4 py-3 transition-colors hover:bg-bg-sunken/50 sm:grid-cols-[1.3fr_1.2fr_0.8fr_0.8fr_0.8fr_auto] sm:items-center sm:gap-4",
652
650
  children: [
653
- /* @__PURE__ */ P("button", {
651
+ /* @__PURE__ */ F("button", {
654
652
  type: "button",
655
- onClick: () => c(`/relationships/${e.relationshipId}`),
653
+ onClick: () => l(`/relationships/${e.relationshipId}`),
656
654
  className: "min-w-0 text-left",
657
- children: [/* @__PURE__ */ N("p", {
655
+ children: [/* @__PURE__ */ P("p", {
658
656
  className: "truncate text-sm font-medium text-text-primary",
659
- children: e.number || `Invoice ${e.id.slice(0, 8)}`
660
- }), /* @__PURE__ */ N("p", {
657
+ children: e.number || `${o("invoices.table.invoice", "Invoice")} ${e.id.slice(0, 8)}`
658
+ }), /* @__PURE__ */ P("p", {
661
659
  className: "text-xs text-text-secondary",
662
- children: e.issueDate ? `Issued ${a(e.issueDate)}` : "—"
660
+ children: e.issueDate ? o("invoices.table.issued", "Issued {{date}}", { date: a(e.issueDate) }) : "—"
663
661
  })]
664
662
  }),
665
- /* @__PURE__ */ N("span", {
663
+ /* @__PURE__ */ P("span", {
666
664
  className: "min-w-0 truncate text-sm text-text-secondary",
667
- children: J.get(e.relationshipId) ?? "—"
665
+ children: X.get(e.relationshipId) ?? "—"
668
666
  }),
669
- /* @__PURE__ */ N("span", { children: /* @__PURE__ */ N(o, { status: e.status }) }),
670
- /* @__PURE__ */ N("span", {
667
+ /* @__PURE__ */ P("span", { children: /* @__PURE__ */ P(s, { status: e.status }) }),
668
+ /* @__PURE__ */ P("span", {
671
669
  className: "text-sm font-semibold tabular-nums text-text-primary sm:text-right",
672
670
  children: i(e.total, e.currency)
673
671
  }),
674
- /* @__PURE__ */ N("span", {
672
+ /* @__PURE__ */ P("span", {
675
673
  className: "text-xs text-text-secondary sm:text-right",
676
674
  children: e.dueDate ? a(e.dueDate) : "—"
677
675
  }),
678
- /* @__PURE__ */ N("span", {
676
+ /* @__PURE__ */ P("span", {
679
677
  className: "sm:text-right",
680
- children: U.has(e.status) ? /* @__PURE__ */ P("button", {
678
+ children: U.has(e.status) ? /* @__PURE__ */ F("button", {
681
679
  type: "button",
682
- disabled: H.isPending,
683
- onClick: () => H.mutate(e.id),
680
+ disabled: J.isPending,
681
+ onClick: () => J.mutate(e.id),
684
682
  className: "inline-flex items-center gap-1.5 rounded-lg border border-status-success-text/30 bg-status-success-bg-subtle px-3 py-1.5 text-xs font-medium text-status-success-text hover:opacity-90 disabled:opacity-50",
685
- children: [/* @__PURE__ */ N(T, {
683
+ children: [/* @__PURE__ */ P(D, {
686
684
  className: "h-3.5 w-3.5",
687
685
  "aria-hidden": !0
688
- }), "Mark paid"]
686
+ }), o("invoices.table.markPaid", "Mark paid")]
689
687
  }) : e.paidAt ? /* @__PURE__ */ P("span", {
690
688
  className: "text-xs text-text-secondary",
691
- children: ["Paid ", a(e.paidAt)]
692
- }) : /* @__PURE__ */ N("span", {
689
+ children: o("invoices.table.paidAt", "Paid {{date}}", { date: a(e.paidAt) })
690
+ }) : /* @__PURE__ */ P("span", {
693
691
  className: "text-xs text-text-secondary",
694
692
  children: "—"
695
693
  })
@@ -697,34 +695,30 @@ function J() {
697
695
  ]
698
696
  }, e.id))
699
697
  })]
700
- }), /* @__PURE__ */ P("div", {
698
+ }), /* @__PURE__ */ F("div", {
701
699
  className: "mt-4 flex items-center justify-between",
702
- children: [/* @__PURE__ */ P("p", {
700
+ children: [/* @__PURE__ */ F("p", {
703
701
  className: "text-xs text-text-secondary",
704
- children: [
705
- "Page ",
706
- d + 1,
707
- V ? " · refreshing…" : ""
708
- ]
709
- }), /* @__PURE__ */ P("div", {
702
+ children: [o("invoices.pagination.page", "Page {{page}}", { page: f + 1 }), K ? ` · ${o("invoices.pagination.refreshing", "refreshing…")}` : ""]
703
+ }), /* @__PURE__ */ F("div", {
710
704
  className: "flex gap-2",
711
- children: [/* @__PURE__ */ N("button", {
705
+ children: [/* @__PURE__ */ P("button", {
712
706
  type: "button",
713
- disabled: d === 0,
714
- onClick: () => h((e) => Math.max(0, e - 1)),
715
- 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"),
716
- children: "Previous"
717
- }), /* @__PURE__ */ N("button", {
707
+ disabled: f === 0,
708
+ onClick: () => g((e) => Math.max(0, e - 1)),
709
+ className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", f === 0 ? "cursor-not-allowed text-text-secondary opacity-50" : "text-text-primary hover:bg-bg-sunken"),
710
+ children: o("invoices.pagination.previous", "Previous")
711
+ }), /* @__PURE__ */ P("button", {
718
712
  type: "button",
719
- disabled: !X,
720
- onClick: () => h((e) => e + 1),
721
- className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", X ? "text-text-primary hover:bg-bg-sunken" : "cursor-not-allowed text-text-secondary opacity-50"),
722
- children: "Next"
713
+ disabled: !Q,
714
+ onClick: () => g((e) => e + 1),
715
+ className: t("rounded-lg border border-border-subtle px-3 py-1.5 text-xs font-medium", Q ? "text-text-primary hover:bg-bg-sunken" : "cursor-not-allowed text-text-secondary opacity-50"),
716
+ children: o("invoices.pagination.next", "Next")
723
717
  })]
724
718
  })]
725
719
  })] }),
726
- /* @__PURE__ */ N(q, {}),
727
- x && /* @__PURE__ */ N(G, { onClose: () => E(!1) })
720
+ /* @__PURE__ */ P(q, {}),
721
+ S && /* @__PURE__ */ P(G, { onClose: () => O(!1) })
728
722
  ]
729
723
  });
730
724
  }