@burdenoff/microfe-billing 2026.830.1 → 2026.830.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.
@@ -1,69 +1,66 @@
1
1
  import { useBilling as e } from "../../../providers/BillingProvider.js";
2
- import { StatusPill as t } from "../../../shared/ui/StatusPill.js";
2
+ import { useTr as t } from "../../../shared/hooks/useTr.js";
3
+ import { StatusPill as n } from "../../../shared/ui/StatusPill.js";
3
4
  import "../../../shared/ui/index.js";
4
- import { useBillingAccountSelection as n } from "../../../hooks/useBillingAccountSelection.js";
5
- import { formatCurrency as r, formatDate as i, formatPlanDuration as a, formatSubscriptionStatus as o } from "../../../shared/utils/format.js";
6
- import { getSubscriptionStatusColor as s } from "../../../shared/utils/status.js";
7
- import { useBillingPermissions as c } from "../../../hooks/useBillingPermissions.js";
8
- import { useBillingNavigate as l } from "../../../hooks/useBillingNavigate.js";
9
- import { withBillingAccountId as u } from "../../../shared/utils/navigation.js";
10
- import { useBillingAccounts as d, usePaginatedSubscriptions as f } from "../hooks/useSubscriptions.js";
5
+ import { useBillingAccountSelection as r } from "../../../hooks/useBillingAccountSelection.js";
6
+ import { formatCurrency as i, formatDate as a, formatPlanDuration as o, formatSubscriptionStatus as s } from "../../../shared/utils/format.js";
7
+ import { getSubscriptionStatusColor as c } from "../../../shared/utils/status.js";
8
+ import { useBillingPermissions as l } from "../../../hooks/useBillingPermissions.js";
9
+ import { useBillingNavigate as u } from "../../../hooks/useBillingNavigate.js";
10
+ import { withBillingAccountId as d } from "../../../shared/utils/navigation.js";
11
+ import { useBillingAccounts as f, usePaginatedSubscriptions as p } from "../hooks/useSubscriptions.js";
11
12
  import "../hooks/index.js";
12
- import { useEffect as p, useRef as m, useState as h } from "react";
13
- import { Fragment as g, jsx as _, jsxs as v } from "react/jsx-runtime";
14
- import { useI18n as y } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
13
+ import { useEffect as m, useRef as h, useState as g } from "react";
14
+ import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
15
15
  import { EmphasisPanel as b, IllustratedEmptyState as x, PagePurpose as S } from "@burdenoff/fe-libs/ui";
16
16
  //#region src/billing/modules/subscriptions/pages/SubscriptionsListPage.tsx
17
17
  var C = ["expired", "upgraded"], w = 10, T = () => {
18
- let { t } = y(), r = (e, n) => {
19
- let r = t(e);
20
- return r === e ? n : r;
21
- }, i = l(), a = c(), { orgId: o } = e(), { billingAccounts: s, isLoading: T } = d(), { selectedAccountId: D, setSelectedAccountId: O } = n({
18
+ let n = t(), i = u(), a = l(), { orgId: o } = e(), { billingAccounts: s, isLoading: c } = f(), { selectedAccountId: T, setSelectedAccountId: D } = r({
22
19
  orgId: o,
23
20
  billingAccounts: s,
24
21
  syncFromUrl: !0,
25
22
  urlParamName: "billingAccountId"
26
- }), [k, A] = h(!1), [j, M] = h("all"), [N, P] = h(""), [F, I] = h(""), [L, R] = h(1), z = m(void 0);
27
- p(() => (clearTimeout(z.current), z.current = setTimeout(() => {
28
- I(N), R(1);
29
- }, 400), () => clearTimeout(z.current)), [N]);
30
- let { subscriptions: B, activeSubscriptions: V, totalCount: H, totalPages: U, isLoading: W, error: G, refetch: K } = f(D ?? void 0, L, w, F || void 0), q = s.find((e) => e.id === D), J = (e) => {
31
- O(e.id), A(!1), R(1);
32
- }, Y = (e) => {
33
- R(e);
34
- }, X = B.filter((e) => j === "all" ? !0 : j === "inactive" ? C.includes(e.status) : e.status === j), Z = T || W;
35
- return a.canViewSubscriptions ? Z && !q ? /* @__PURE__ */ v("div", {
23
+ }), [O, k] = g(!1), [A, j] = g("all"), [M, N] = g(""), [P, F] = g(""), [I, L] = g(1), R = h(void 0);
24
+ m(() => (clearTimeout(R.current), R.current = setTimeout(() => {
25
+ F(M), L(1);
26
+ }, 400), () => clearTimeout(R.current)), [M]);
27
+ let { subscriptions: z, activeSubscriptions: B, totalCount: V, totalPages: H, isLoading: U, error: W, refetch: G } = p(T ?? void 0, I, w, P || void 0), K = s.find((e) => e.id === T), q = (e) => {
28
+ D(e.id), k(!1), L(1);
29
+ }, J = (e) => {
30
+ L(e);
31
+ }, Y = z.filter((e) => A === "all" ? !0 : A === "inactive" ? C.includes(e.status) : e.status === A), X = c || U;
32
+ return a.canViewSubscriptions ? X && !K ? /* @__PURE__ */ y("div", {
36
33
  className: "space-y-6 p-6",
37
- children: [/* @__PURE__ */ _("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ _("div", {
34
+ children: [/* @__PURE__ */ v("div", { className: "h-8 w-48 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ v("div", {
38
35
  className: "space-y-4",
39
36
  children: [
40
37
  1,
41
38
  2,
42
39
  3
43
- ].map((e) => /* @__PURE__ */ _("div", {
40
+ ].map((e) => /* @__PURE__ */ v("div", {
44
41
  className: "border border-border-subtle rounded-lg p-6",
45
- children: /* @__PURE__ */ v("div", {
42
+ children: /* @__PURE__ */ y("div", {
46
43
  className: "flex items-center gap-4",
47
- children: [/* @__PURE__ */ _("div", { className: "size-12 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ v("div", {
44
+ children: [/* @__PURE__ */ v("div", { className: "size-12 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ y("div", {
48
45
  className: "flex-1 space-y-2",
49
- children: [/* @__PURE__ */ _("div", { className: "h-5 w-32 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ _("div", { className: "h-4 w-48 bg-bg-sunken animate-pulse rounded" })]
46
+ children: [/* @__PURE__ */ v("div", { className: "h-5 w-32 bg-bg-sunken animate-pulse rounded" }), /* @__PURE__ */ v("div", { className: "h-4 w-48 bg-bg-sunken animate-pulse rounded" })]
50
47
  })]
51
48
  })
52
49
  }, e))
53
50
  })]
54
- }) : G ? /* @__PURE__ */ _("div", {
51
+ }) : W ? /* @__PURE__ */ v("div", {
55
52
  className: "flex items-center justify-center h-full min-h-[400px]",
56
- children: /* @__PURE__ */ v("div", {
53
+ children: /* @__PURE__ */ y("div", {
57
54
  className: "text-center space-y-4",
58
55
  children: [
59
- /* @__PURE__ */ _("div", {
56
+ /* @__PURE__ */ v("div", {
60
57
  className: "size-12 mx-auto rounded-full bg-status-error-bg-subtle flex items-center justify-center",
61
- children: /* @__PURE__ */ _("svg", {
58
+ children: /* @__PURE__ */ v("svg", {
62
59
  className: "size-6 text-status-error-text",
63
60
  fill: "none",
64
61
  viewBox: "0 0 24 24",
65
62
  stroke: "currentColor",
66
- children: /* @__PURE__ */ _("path", {
63
+ children: /* @__PURE__ */ v("path", {
67
64
  strokeLinecap: "round",
68
65
  strokeLinejoin: "round",
69
66
  strokeWidth: 2,
@@ -71,143 +68,143 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
71
68
  })
72
69
  })
73
70
  }),
74
- /* @__PURE__ */ _("h2", {
71
+ /* @__PURE__ */ v("h2", {
75
72
  className: "text-lg font-semibold text-text-primary",
76
- children: "Failed to load subscriptions"
73
+ children: n("billing.subscriptions.failedToLoad", "Failed to load subscriptions")
77
74
  }),
78
- /* @__PURE__ */ _("p", {
75
+ /* @__PURE__ */ v("p", {
79
76
  className: "text-sm text-text-secondary",
80
- children: G.message
77
+ children: W.message
81
78
  }),
82
- /* @__PURE__ */ _("button", {
79
+ /* @__PURE__ */ v("button", {
83
80
  type: "button",
84
- onClick: () => K(),
81
+ onClick: () => G(),
85
82
  className: "px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors",
86
- children: "Try Again"
83
+ children: n("billing.common.tryAgain", "Try Again")
87
84
  })
88
85
  ]
89
86
  })
90
- }) : /* @__PURE__ */ v("div", {
87
+ }) : /* @__PURE__ */ y("div", {
91
88
  className: "space-y-6 px-6 lg:px-8 py-6",
92
89
  children: [
93
- /* @__PURE__ */ v("div", {
90
+ /* @__PURE__ */ y("div", {
94
91
  className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
95
- children: [/* @__PURE__ */ v("div", { children: [
96
- /* @__PURE__ */ _("h1", {
92
+ children: [/* @__PURE__ */ y("div", { children: [
93
+ /* @__PURE__ */ v("h1", {
97
94
  className: "text-2xl md:text-3xl font-semibold tracking-tight text-text-primary",
98
- children: r("billing.subscriptions.title", "Subscriptions")
95
+ children: n("billing.subscriptions.title", "Subscriptions")
99
96
  }),
100
- /* @__PURE__ */ _("p", {
97
+ /* @__PURE__ */ v("p", {
101
98
  className: "text-sm text-text-secondary mt-1",
102
- children: r("billing.subscriptions.subtitle", "Manage your active and past subscriptions")
99
+ children: n("billing.subscriptions.subtitle", "Manage your active and past subscriptions")
103
100
  }),
104
- /* @__PURE__ */ _(S, {
101
+ /* @__PURE__ */ v(S, {
105
102
  className: "mt-3",
106
- children: r("billing.subscriptions.purpose", "See every plan a billing account is subscribed to — active, canceled and expired — in one place. Use it to review what you are paying for, when each plan renews or ends, upgrade or cancel a subscription, and start a new one by browsing plans.")
103
+ children: n("billing.subscriptions.purpose", "See every plan a billing account is subscribed to — active, canceled and expired — in one place. Use it to review what you are paying for, when each plan renews or ends, upgrade or cancel a subscription, and start a new one by browsing plans.")
107
104
  })
108
- ] }), a.canCreateSubscription && /* @__PURE__ */ v("button", {
105
+ ] }), a.canCreateSubscription && /* @__PURE__ */ y("button", {
109
106
  type: "button",
110
107
  onClick: () => i("/plans"),
111
108
  className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors duration-200",
112
- children: [/* @__PURE__ */ _("svg", {
109
+ children: [/* @__PURE__ */ v("svg", {
113
110
  className: "size-4",
114
111
  fill: "none",
115
112
  viewBox: "0 0 24 24",
116
113
  stroke: "currentColor",
117
- children: /* @__PURE__ */ _("path", {
114
+ children: /* @__PURE__ */ v("path", {
118
115
  strokeLinecap: "round",
119
116
  strokeLinejoin: "round",
120
117
  strokeWidth: 2,
121
118
  d: "M12 4v16m8-8H4"
122
119
  })
123
- }), "New Subscription"]
120
+ }), n("billing.subscriptions.newSubscription", "New Subscription")]
124
121
  })]
125
122
  }),
126
- s.length > 1 && /* @__PURE__ */ v("div", {
123
+ s.length > 1 && /* @__PURE__ */ y("div", {
127
124
  className: "relative",
128
- children: [/* @__PURE__ */ v("button", {
125
+ children: [/* @__PURE__ */ y("button", {
129
126
  type: "button",
130
- onClick: () => A(!k),
127
+ onClick: () => k(!O),
131
128
  className: "w-full sm:w-auto flex items-center justify-between gap-3 px-4 py-3 border border-border-seam rounded-card bg-bg-surface hover:bg-bg-sunken hover:border-border-strong transition-all duration-200",
132
- children: [/* @__PURE__ */ v("div", {
129
+ children: [/* @__PURE__ */ y("div", {
133
130
  className: "flex items-center gap-3",
134
- children: [/* @__PURE__ */ _("div", {
131
+ children: [/* @__PURE__ */ v("div", {
135
132
  className: "size-9 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center",
136
- children: /* @__PURE__ */ _("svg", {
133
+ children: /* @__PURE__ */ v("svg", {
137
134
  className: "size-4 text-text-link",
138
135
  fill: "none",
139
136
  viewBox: "0 0 24 24",
140
137
  stroke: "currentColor",
141
- children: /* @__PURE__ */ _("path", {
138
+ children: /* @__PURE__ */ v("path", {
142
139
  strokeLinecap: "round",
143
140
  strokeLinejoin: "round",
144
141
  strokeWidth: 2,
145
142
  d: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
146
143
  })
147
144
  })
148
- }), /* @__PURE__ */ v("div", {
145
+ }), /* @__PURE__ */ y("div", {
149
146
  className: "text-left",
150
- children: [/* @__PURE__ */ _("p", {
147
+ children: [/* @__PURE__ */ v("p", {
151
148
  className: "text-sm font-medium text-text-primary",
152
- children: q?.name || "Select Account"
153
- }), /* @__PURE__ */ _("p", {
149
+ children: K?.name || n("billing.subscriptions.selectAccount", "Select Account")
150
+ }), /* @__PURE__ */ v("p", {
154
151
  className: "text-xs text-text-secondary",
155
- children: q?.email
152
+ children: K?.email
156
153
  })]
157
154
  })]
158
- }), /* @__PURE__ */ _("svg", {
159
- className: `size-4 text-text-secondary transition-transform ${k ? "rotate-180" : ""}`,
155
+ }), /* @__PURE__ */ v("svg", {
156
+ className: `size-4 text-text-secondary transition-transform ${O ? "rotate-180" : ""}`,
160
157
  fill: "none",
161
158
  viewBox: "0 0 24 24",
162
159
  stroke: "currentColor",
163
- children: /* @__PURE__ */ _("path", {
160
+ children: /* @__PURE__ */ v("path", {
164
161
  strokeLinecap: "round",
165
162
  strokeLinejoin: "round",
166
163
  strokeWidth: 2,
167
164
  d: "M19 9l-7 7-7-7"
168
165
  })
169
166
  })]
170
- }), k && /* @__PURE__ */ v(g, { children: [/* @__PURE__ */ _("div", {
167
+ }), O && /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("div", {
171
168
  className: "fixed inset-0 z-10",
172
- onClick: () => A(!1)
173
- }), /* @__PURE__ */ _("div", {
169
+ onClick: () => k(!1)
170
+ }), /* @__PURE__ */ v("div", {
174
171
  className: "absolute top-full left-0 right-0 sm:right-auto mt-1 w-full sm:w-80 bg-bg-elevated border border-border-seam rounded-card shadow-elevation-3 z-20 py-1 max-h-60 overflow-y-auto",
175
- children: s.map((e) => /* @__PURE__ */ v("button", {
172
+ children: s.map((e) => /* @__PURE__ */ y("button", {
176
173
  type: "button",
177
- onClick: () => J(e),
174
+ onClick: () => q(e),
178
175
  className: "w-full flex items-center justify-between gap-3 px-4 py-3 hover:bg-bg-sunken transition-colors",
179
- children: [/* @__PURE__ */ v("div", {
176
+ children: [/* @__PURE__ */ y("div", {
180
177
  className: "flex items-center gap-3 min-w-0",
181
- children: [/* @__PURE__ */ _("div", {
178
+ children: [/* @__PURE__ */ v("div", {
182
179
  className: "size-9 rounded-lg bg-bg-sunken flex items-center justify-center flex-shrink-0",
183
- children: /* @__PURE__ */ _("svg", {
180
+ children: /* @__PURE__ */ v("svg", {
184
181
  className: "size-4 text-text-secondary",
185
182
  fill: "none",
186
183
  viewBox: "0 0 24 24",
187
184
  stroke: "currentColor",
188
- children: /* @__PURE__ */ _("path", {
185
+ children: /* @__PURE__ */ v("path", {
189
186
  strokeLinecap: "round",
190
187
  strokeLinejoin: "round",
191
188
  strokeWidth: 2,
192
189
  d: "M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4"
193
190
  })
194
191
  })
195
- }), /* @__PURE__ */ v("div", {
192
+ }), /* @__PURE__ */ y("div", {
196
193
  className: "text-left min-w-0",
197
- children: [/* @__PURE__ */ _("p", {
194
+ children: [/* @__PURE__ */ v("p", {
198
195
  className: "text-sm font-medium text-text-primary truncate",
199
196
  children: e.name
200
- }), /* @__PURE__ */ _("p", {
197
+ }), /* @__PURE__ */ v("p", {
201
198
  className: "text-xs text-text-secondary truncate",
202
199
  children: e.email
203
200
  })]
204
201
  })]
205
- }), q?.id === e.id && /* @__PURE__ */ _("svg", {
202
+ }), K?.id === e.id && /* @__PURE__ */ v("svg", {
206
203
  className: "size-4 text-text-link flex-shrink-0",
207
204
  fill: "none",
208
205
  viewBox: "0 0 24 24",
209
206
  stroke: "currentColor",
210
- children: /* @__PURE__ */ _("path", {
207
+ children: /* @__PURE__ */ v("path", {
211
208
  strokeLinecap: "round",
212
209
  strokeLinejoin: "round",
213
210
  strokeWidth: 2,
@@ -217,116 +214,118 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
217
214
  }, e.id))
218
215
  })] })]
219
216
  }),
220
- q && /* @__PURE__ */ _(b, {
217
+ K && /* @__PURE__ */ v(b, {
221
218
  className: "p-5",
222
- children: /* @__PURE__ */ v("div", {
219
+ children: /* @__PURE__ */ y("div", {
223
220
  className: "grid grid-cols-1 sm:grid-cols-3 gap-4",
224
221
  children: [
225
- /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
222
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
226
223
  className: "text-sm text-text-secondary",
227
- children: "Account"
228
- }), /* @__PURE__ */ _("p", {
224
+ children: n("billing.subscriptions.account", "Account")
225
+ }), /* @__PURE__ */ v("p", {
229
226
  className: "text-lg font-semibold text-text-primary mt-1",
230
- children: q.name
227
+ children: K.name
231
228
  })] }),
232
- /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
229
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
233
230
  className: "text-sm text-text-secondary",
234
- children: "Active Subscriptions"
235
- }), /* @__PURE__ */ _("p", {
231
+ children: n("billing.subscriptions.activeSubscriptions", "Active Subscriptions")
232
+ }), /* @__PURE__ */ v("p", {
236
233
  className: "text-lg font-semibold tabular-nums text-status-success-text mt-1",
237
- children: V.length
234
+ children: B.length
238
235
  })] }),
239
- /* @__PURE__ */ v("div", { children: [/* @__PURE__ */ _("p", {
236
+ /* @__PURE__ */ y("div", { children: [/* @__PURE__ */ v("p", {
240
237
  className: "text-sm text-text-secondary",
241
- children: "Credit Balance"
242
- }), /* @__PURE__ */ v("p", {
238
+ children: n("billing.subscriptions.creditBalance", "Credit Balance")
239
+ }), /* @__PURE__ */ y("p", {
243
240
  className: "text-lg font-semibold tabular-nums text-text-primary mt-1",
244
- children: [(q.creditAmount || 0).toLocaleString(), " Credits"]
241
+ children: [
242
+ (K.creditAmount || 0).toLocaleString(),
243
+ " ",
244
+ n("billing.common.credits", "Credits")
245
+ ]
245
246
  })] })
246
247
  ]
247
248
  })
248
249
  }),
249
- /* @__PURE__ */ v("div", {
250
+ /* @__PURE__ */ y("div", {
250
251
  className: "flex flex-col sm:flex-row flex-wrap items-stretch sm:items-center gap-3 sm:gap-4 pb-4 border-b border-border-subtle",
251
252
  children: [
252
- /* @__PURE__ */ _("div", {
253
+ /* @__PURE__ */ v("div", {
253
254
  className: "inline-flex rounded-lg border border-border-subtle p-1 bg-bg-sunken flex-wrap",
254
255
  children: [
255
256
  "all",
256
257
  "active",
257
258
  "canceled",
258
259
  "inactive"
259
- ].map((e) => /* @__PURE__ */ _("button", {
260
+ ].map((e) => /* @__PURE__ */ v("button", {
260
261
  type: "button",
261
- onClick: () => M(e),
262
- className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors capitalize ${j === e ? "bg-bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
263
- children: e === "inactive" ? "Inactive" : e
262
+ onClick: () => j(e),
263
+ className: `px-3 py-1.5 text-sm font-medium rounded-button transition-colors capitalize ${A === e ? "bg-bg-surface text-text-primary shadow-sm" : "text-text-secondary hover:text-text-primary"}`,
264
+ children: e === "all" ? n("billing.subscriptions.statusAll", "All") : e === "active" ? n("billing.subscriptions.statusActive", "Active") : e === "canceled" ? n("billing.subscriptions.statusCanceled", "Canceled") : n("billing.subscriptions.statusInactive", "Inactive")
264
265
  }, e))
265
266
  }),
266
- /* @__PURE__ */ v("div", {
267
+ /* @__PURE__ */ y("div", {
267
268
  className: "relative flex-1 min-w-0 w-full sm:max-w-md",
268
- children: [/* @__PURE__ */ _("svg", {
269
+ children: [/* @__PURE__ */ v("svg", {
269
270
  className: "absolute left-3 top-1/2 -translate-y-1/2 size-4 text-text-secondary",
270
271
  fill: "none",
271
272
  viewBox: "0 0 24 24",
272
273
  stroke: "currentColor",
273
- children: /* @__PURE__ */ _("path", {
274
+ children: /* @__PURE__ */ v("path", {
274
275
  strokeLinecap: "round",
275
276
  strokeLinejoin: "round",
276
277
  strokeWidth: 2,
277
278
  d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
278
279
  })
279
- }), /* @__PURE__ */ _("input", {
280
+ }), /* @__PURE__ */ v("input", {
280
281
  type: "text",
281
- placeholder: r("billing.subscriptions.searchPlaceholder", "Search subscriptions..."),
282
- value: N,
283
- onChange: (e) => P(e.target.value),
282
+ placeholder: n("billing.subscriptions.searchPlaceholder", "Search subscriptions..."),
283
+ value: M,
284
+ onChange: (e) => N(e.target.value),
284
285
  className: "w-full pl-[3.25rem] pr-4 py-2 text-sm border border-border-subtle rounded-button bg-bg-surface text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] focus:border-transparent"
285
286
  })]
286
287
  }),
287
288
  /* @__PURE__ */ v("div", {
288
289
  className: "text-sm text-text-secondary",
289
- children: [
290
- H,
291
- " subscription",
292
- H === 1 ? "" : "s",
293
- " total"
294
- ]
290
+ children: n("billing.subscriptions.totalCount", "{{count}} subscription{{plural}} total", {
291
+ count: V,
292
+ plural: V === 1 ? "" : "s"
293
+ })
295
294
  })
296
295
  ]
297
296
  }),
298
- X.length === 0 ? /* @__PURE__ */ _(x, {
299
- illustration: j !== "all" || F ? "empty-search" : "empty-data",
300
- title: r("billing.subscriptions.noSubscriptionsFound", "No subscriptions found"),
301
- description: j !== "all" || F ? "No subscriptions match your filters." : "You don't have any subscriptions yet.",
302
- action: a.canCreateSubscription && j === "all" && !F ? /* @__PURE__ */ _("button", {
297
+ Y.length === 0 ? /* @__PURE__ */ v(x, {
298
+ illustration: A !== "all" || P ? "empty-search" : "empty-data",
299
+ title: n("billing.subscriptions.noSubscriptionsFound", "No subscriptions found"),
300
+ description: A !== "all" || P ? n("billing.subscriptions.noSubscriptionsMatchFilters", "No subscriptions match your filters.") : n("billing.subscriptions.noSubscriptionsYet", "You don't have any subscriptions yet."),
301
+ action: a.canCreateSubscription && A === "all" && !P ? /* @__PURE__ */ v("button", {
303
302
  type: "button",
304
303
  onClick: () => i("/plans"),
305
304
  className: "px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors duration-200",
306
- children: "Browse Plans"
305
+ children: n("billing.subscriptions.browsePlans", "Browse Plans")
307
306
  }) : void 0
308
- }) : /* @__PURE__ */ _("div", {
307
+ }) : /* @__PURE__ */ v("div", {
309
308
  className: "space-y-4",
310
- children: X.map((e) => /* @__PURE__ */ _(E, {
309
+ children: Y.map((e) => /* @__PURE__ */ v(E, {
311
310
  subscription: e,
312
- onView: () => i(u(`/subscriptions/${e.id}`, e.billingAccountId)),
311
+ onView: () => i(d(`/subscriptions/${e.id}`, e.billingAccountId)),
313
312
  canCancel: a.canCancelSubscription
314
313
  }, e.id))
315
314
  }),
316
- U > 1 && /* @__PURE__ */ v("div", {
315
+ H > 1 && /* @__PURE__ */ y("div", {
317
316
  className: "flex items-center justify-center gap-2 pt-4",
318
317
  children: [
319
- /* @__PURE__ */ _("button", {
318
+ /* @__PURE__ */ v("button", {
320
319
  type: "button",
321
- onClick: () => Y(L - 1),
322
- disabled: L === 1,
320
+ onClick: () => J(I - 1),
321
+ disabled: I === 1,
323
322
  className: "px-3 py-1.5 text-sm border border-border-subtle rounded-button disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors",
324
- children: /* @__PURE__ */ _("svg", {
323
+ children: /* @__PURE__ */ v("svg", {
325
324
  className: "size-4",
326
325
  fill: "none",
327
326
  viewBox: "0 0 24 24",
328
327
  stroke: "currentColor",
329
- children: /* @__PURE__ */ _("path", {
328
+ children: /* @__PURE__ */ v("path", {
330
329
  strokeLinecap: "round",
331
330
  strokeLinejoin: "round",
332
331
  strokeWidth: 2,
@@ -334,32 +333,32 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
334
333
  })
335
334
  })
336
335
  }),
337
- /* @__PURE__ */ _("div", {
336
+ /* @__PURE__ */ v("div", {
338
337
  className: "flex items-center gap-1",
339
- children: Array.from({ length: U }, (e, t) => t + 1).map((e) => {
340
- let t = e === 1 || e === U || Math.abs(e - L) <= 1, n = e === L - 2 && L > 3, r = e === L + 2 && L < U - 2;
341
- return n || r ? /* @__PURE__ */ _("span", {
338
+ children: Array.from({ length: H }, (e, t) => t + 1).map((e) => {
339
+ let t = e === 1 || e === H || Math.abs(e - I) <= 1, n = e === I - 2 && I > 3, r = e === I + 2 && I < H - 2;
340
+ return n || r ? /* @__PURE__ */ v("span", {
342
341
  className: "px-2 text-text-secondary",
343
342
  children: "..."
344
- }, e) : t ? /* @__PURE__ */ _("button", {
343
+ }, e) : t ? /* @__PURE__ */ v("button", {
345
344
  type: "button",
346
- onClick: () => Y(e),
347
- className: `px-3 py-1.5 text-sm rounded-button transition-colors ${e === L ? "bg-action-primary-bg text-action-primary-text" : "border border-border-subtle hover:bg-bg-sunken"}`,
345
+ onClick: () => J(e),
346
+ className: `px-3 py-1.5 text-sm rounded-button transition-colors ${e === I ? "bg-action-primary-bg text-action-primary-text" : "border border-border-subtle hover:bg-bg-sunken"}`,
348
347
  children: e
349
348
  }, e) : null;
350
349
  })
351
350
  }),
352
- /* @__PURE__ */ _("button", {
351
+ /* @__PURE__ */ v("button", {
353
352
  type: "button",
354
- onClick: () => Y(L + 1),
355
- disabled: L === U,
353
+ onClick: () => J(I + 1),
354
+ disabled: I === H,
356
355
  className: "px-3 py-1.5 text-sm border border-border-subtle rounded-button disabled:opacity-50 disabled:cursor-not-allowed hover:bg-bg-sunken transition-colors",
357
- children: /* @__PURE__ */ _("svg", {
356
+ children: /* @__PURE__ */ v("svg", {
358
357
  className: "size-4",
359
358
  fill: "none",
360
359
  viewBox: "0 0 24 24",
361
360
  stroke: "currentColor",
362
- children: /* @__PURE__ */ _("path", {
361
+ children: /* @__PURE__ */ v("path", {
363
362
  strokeLinecap: "round",
364
363
  strokeLinejoin: "round",
365
364
  strokeWidth: 2,
@@ -370,19 +369,19 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
370
369
  ]
371
370
  })
372
371
  ]
373
- }) : /* @__PURE__ */ _("div", {
372
+ }) : /* @__PURE__ */ v("div", {
374
373
  className: "flex items-center justify-center h-full min-h-[400px]",
375
- children: /* @__PURE__ */ v("div", {
374
+ children: /* @__PURE__ */ y("div", {
376
375
  className: "text-center space-y-2",
377
376
  children: [
378
- /* @__PURE__ */ _("div", {
377
+ /* @__PURE__ */ v("div", {
379
378
  className: "size-12 mx-auto rounded-full bg-bg-sunken flex items-center justify-center",
380
- children: /* @__PURE__ */ _("svg", {
379
+ children: /* @__PURE__ */ v("svg", {
381
380
  className: "size-6 text-text-secondary",
382
381
  fill: "none",
383
382
  viewBox: "0 0 24 24",
384
383
  stroke: "currentColor",
385
- children: /* @__PURE__ */ _("path", {
384
+ children: /* @__PURE__ */ v("path", {
386
385
  strokeLinecap: "round",
387
386
  strokeLinejoin: "round",
388
387
  strokeWidth: 2,
@@ -390,36 +389,36 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
390
389
  })
391
390
  })
392
391
  }),
393
- /* @__PURE__ */ _("h2", {
392
+ /* @__PURE__ */ v("h2", {
394
393
  className: "text-lg font-semibold text-text-primary",
395
- children: "Access Denied"
394
+ children: n("billing.accessDenied.title", "Access Denied")
396
395
  }),
397
- /* @__PURE__ */ _("p", {
396
+ /* @__PURE__ */ v("p", {
398
397
  className: "text-sm text-text-secondary max-w-sm",
399
- children: "You don't have permission to view subscriptions."
398
+ children: n("billing.subscriptions.noViewPermission", "You don't have permission to view subscriptions.")
400
399
  })
401
400
  ]
402
401
  })
403
402
  });
404
- }, E = ({ subscription: e, onView: n, canCancel: c }) => {
405
- let l = e.plan, u = s(e.status), d = e.status === "active", f = new Date(e.endDate), p = /* @__PURE__ */ new Date(), m = Math.max(0, Math.ceil((f.getTime() - p.getTime()) / (1e3 * 60 * 60 * 24)));
406
- return /* @__PURE__ */ _("div", {
403
+ }, E = ({ subscription: e, onView: r, canCancel: l }) => {
404
+ let u = t(), d = e.plan, f = c(e.status), p = e.status === "active", m = new Date(e.endDate), h = /* @__PURE__ */ new Date(), g = Math.max(0, Math.ceil((m.getTime() - h.getTime()) / (1e3 * 60 * 60 * 24)));
405
+ return /* @__PURE__ */ v("div", {
407
406
  className: "border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 hover:border-border-strong hover:shadow-elevation-2 transition-all duration-200 cursor-pointer",
408
- onClick: n,
409
- children: /* @__PURE__ */ v("div", {
407
+ onClick: r,
408
+ children: /* @__PURE__ */ y("div", {
410
409
  className: "p-5",
411
410
  children: [
412
- /* @__PURE__ */ v("div", {
411
+ /* @__PURE__ */ y("div", {
413
412
  className: "flex flex-col sm:flex-row sm:items-center gap-4",
414
413
  children: [
415
- /* @__PURE__ */ _("div", {
414
+ /* @__PURE__ */ v("div", {
416
415
  className: "size-12 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center shrink-0",
417
- children: /* @__PURE__ */ _("svg", {
416
+ children: /* @__PURE__ */ v("svg", {
418
417
  className: "size-6 text-text-link",
419
418
  fill: "none",
420
419
  viewBox: "0 0 24 24",
421
420
  stroke: "currentColor",
422
- children: /* @__PURE__ */ _("path", {
421
+ children: /* @__PURE__ */ v("path", {
423
422
  strokeLinecap: "round",
424
423
  strokeLinejoin: "round",
425
424
  strokeWidth: 2,
@@ -427,82 +426,76 @@ var C = ["expired", "upgraded"], w = 10, T = () => {
427
426
  })
428
427
  })
429
428
  }),
430
- /* @__PURE__ */ v("div", {
429
+ /* @__PURE__ */ y("div", {
431
430
  className: "flex-1 min-w-0",
432
- children: [/* @__PURE__ */ v("div", {
431
+ children: [/* @__PURE__ */ y("div", {
433
432
  className: "flex items-center gap-2 flex-wrap",
434
- children: [/* @__PURE__ */ _("h3", {
433
+ children: [/* @__PURE__ */ v("h3", {
435
434
  className: "font-semibold text-text-primary",
436
- children: l?.name || "Unknown Plan"
437
- }), /* @__PURE__ */ _(t, {
438
- status: u,
435
+ children: d?.name || u("billing.common.unknownPlan", "Unknown Plan")
436
+ }), /* @__PURE__ */ v(n, {
437
+ status: f,
439
438
  dot: !0,
440
- pulse: d,
441
- children: o(e.status)
439
+ pulse: p,
440
+ children: s(e.status)
442
441
  })]
443
- }), /* @__PURE__ */ v("div", {
442
+ }), /* @__PURE__ */ y("div", {
444
443
  className: "flex items-center gap-4 mt-1 text-sm text-text-secondary",
445
444
  children: [
446
- /* @__PURE__ */ v("span", { children: [
447
- l ? r(l.price, l.currency) : "—",
445
+ /* @__PURE__ */ y("span", { children: [
446
+ d ? i(d.price, d.currency) : "—",
448
447
  " /",
449
448
  " ",
450
- l ? a(l.duration) : "—"
449
+ d ? o(d.duration) : "—"
451
450
  ] }),
452
- /* @__PURE__ */ _("span", {
451
+ /* @__PURE__ */ v("span", {
453
452
  className: "hidden sm:inline",
454
453
  children: "•"
455
454
  }),
456
455
  /* @__PURE__ */ v("span", {
457
456
  className: "hidden sm:inline",
458
- children: ["Started ", i(e.startDate, "short")]
457
+ children: u("billing.subscriptions.started", "Started {{date}}", { date: a(e.startDate, "short") })
459
458
  })
460
459
  ]
461
460
  })]
462
461
  }),
463
- /* @__PURE__ */ v("div", {
462
+ /* @__PURE__ */ y("div", {
464
463
  className: "flex items-center gap-4",
465
- children: [d && /* @__PURE__ */ v("div", {
464
+ children: [p && /* @__PURE__ */ y("div", {
466
465
  className: "text-right",
467
466
  children: [/* @__PURE__ */ v("p", {
468
467
  className: "text-sm font-medium text-text-primary",
469
- children: [m, " days"]
470
- }), /* @__PURE__ */ _("p", {
468
+ children: u("billing.subscriptions.daysRemaining", "{{count}} days", { count: g })
469
+ }), /* @__PURE__ */ v("p", {
471
470
  className: "text-xs text-text-secondary",
472
- children: "remaining"
471
+ children: u("billing.subscriptions.remaining", "remaining")
473
472
  })]
474
- }), /* @__PURE__ */ _("button", {
473
+ }), /* @__PURE__ */ v("button", {
475
474
  type: "button",
476
475
  onClick: (e) => {
477
- e.stopPropagation(), n();
476
+ e.stopPropagation(), r();
478
477
  },
479
478
  className: "px-3 py-1.5 text-sm font-medium border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken hover:border-border-strong transition-all duration-200",
480
- children: "View"
479
+ children: u("billing.common.view", "View")
481
480
  })]
482
481
  })
483
482
  ]
484
483
  }),
485
- e.addonSubscriptions && e.addonSubscriptions.length > 0 && /* @__PURE__ */ _("div", {
484
+ e.addonSubscriptions && e.addonSubscriptions.length > 0 && /* @__PURE__ */ v("div", {
486
485
  className: "mt-4 pt-4 border-t border-border-subtle",
487
486
  children: /* @__PURE__ */ v("p", {
488
487
  className: "text-sm text-text-secondary",
489
- children: [
490
- e.addonSubscriptions.length,
491
- " addon",
492
- e.addonSubscriptions.length === 1 ? "" : "s",
493
- " attached"
494
- ]
488
+ children: u("billing.subscriptions.addonsAttached", "{{count}} addon{{plural}} attached", {
489
+ count: e.addonSubscriptions.length,
490
+ plural: e.addonSubscriptions.length === 1 ? "" : "s"
491
+ })
495
492
  })
496
493
  }),
497
- e.canceledAt && /* @__PURE__ */ _("div", {
494
+ e.canceledAt && /* @__PURE__ */ v("div", {
498
495
  className: "mt-4 pt-4 border-t border-border-subtle",
499
- children: /* @__PURE__ */ v("p", {
496
+ children: /* @__PURE__ */ y("p", {
500
497
  className: "text-sm text-text-secondary",
501
- children: [
502
- "Canceled on ",
503
- i(e.canceledAt),
504
- e.cancellationReason && /* @__PURE__ */ v("span", { children: [": ", e.cancellationReason] })
505
- ]
498
+ children: [u("billing.subscriptions.canceledOn", "Canceled on {{date}}", { date: a(e.canceledAt) }), e.cancellationReason && /* @__PURE__ */ y("span", { children: [": ", e.cancellationReason] })]
506
499
  })
507
500
  })
508
501
  ]