@burdenoff/microfe-billing 2026.517.1 → 2026.517.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/billing/BillingUserRoutes.js +1 -1
- package/dist/billing/BillingUserRoutes.js.map +1 -1
- package/dist/billing/modules/billing/hooks/useInvoices.d.ts +1 -0
- package/dist/billing/modules/billing/hooks/useInvoices.d.ts.map +1 -1
- package/dist/billing/modules/billing/hooks/useInvoices.js +26 -20
- package/dist/billing/modules/billing/hooks/useInvoices.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoicesListPage.d.ts.map +1 -1
- package/dist/billing/modules/billing/pages/InvoicesListPage.js +170 -176
- package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/RefundsPage.js +1 -1
- package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
- package/dist/billing/modules/checkout/components/OrderSummary.js +4 -4
- package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.d.ts.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +2 -2
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.d.ts.map +1 -1
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +209 -178
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
- package/dist/billing/modules/dashboard/pages/OverviewPage.js +2 -2
- package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js +2 -2
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
- package/dist/billing/modules/earnings/api.d.ts +4 -0
- package/dist/billing/modules/earnings/api.d.ts.map +1 -1
- package/dist/billing/modules/earnings/api.js +14 -10
- package/dist/billing/modules/earnings/api.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.d.ts.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +523 -233
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaPage.js +1 -1
- package/dist/billing/modules/quota/pages/QuotaPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.d.ts.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +101 -44
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.d.ts.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +105 -46
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.d.ts +1 -1
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.d.ts.map +1 -1
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js +16 -15
- package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.d.ts.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +158 -165
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/usage/hooks/useUsage.d.ts +3 -0
- package/dist/billing/modules/usage/hooks/useUsage.d.ts.map +1 -1
- package/dist/billing/modules/usage/hooks/useUsage.js +4 -1
- package/dist/billing/modules/usage/hooks/useUsage.js.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.d.ts.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js +44 -22
- package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
- package/dist/billing/shared/types/graphql.d.ts +2 -0
- package/dist/billing/shared/types/graphql.d.ts.map +1 -1
- package/dist/billing/shared/types/graphql.js.map +1 -1
- package/dist/generated/global-operations.d.ts +51 -0
- package/dist/generated/global-operations.d.ts.map +1 -1
- package/dist/generated/global-operations.js +313 -293
- package/dist/generated/global-operations.js.map +1 -1
- package/dist/generated/global-types.d.ts +350 -1392
- package/dist/generated/global-types.d.ts.map +1 -1
- package/dist/generated/global-types.js.map +1 -1
- package/dist/generated/wspace-types.d.ts +2907 -11652
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -18,12 +18,14 @@ var h = () => {
|
|
|
18
18
|
let { t: h } = m(), g = (e, t) => {
|
|
19
19
|
let n = h(e);
|
|
20
20
|
return n === e ? t : n;
|
|
21
|
-
}, { quotaId: _ } = d(), v = o(), y = a(), { quota: b, isLoading: x, error: S, refetch: C } = s(_), { updateQuota: w, isUpdating: T } = c(), [E, D] = u(""), [O, k] = u("
|
|
21
|
+
}, { quotaId: _ } = d(), v = o(), y = a(), { quota: b, isLoading: x, error: S, refetch: C } = s(_), { updateQuota: w, isUpdating: T } = c(), [E, D] = u(""), [O, k] = u(""), [A, j] = u(""), [M, N] = u("numeric"), [P, F] = u(""), [I, L] = u(""), [R, z] = u(!1), [B, V] = u(r.NEVER), [H, U] = u(!0), [W, G] = u(null), [K, q] = u(!1);
|
|
22
22
|
return l(() => {
|
|
23
23
|
if (b) {
|
|
24
|
-
D(b.name ?? ""),
|
|
24
|
+
D(b.name ?? ""), z(b.reusable ?? !1), V(b.resetPeriod ?? r.NEVER), U(b.isActive ?? !0);
|
|
25
25
|
let e = b.limits;
|
|
26
|
-
|
|
26
|
+
N(e?.type ?? "numeric"), F(String(e?.value ?? "")), L(e?.unit ?? "");
|
|
27
|
+
let t = b.context;
|
|
28
|
+
k(t?.displayName ?? ""), j(t?.description ?? "");
|
|
27
29
|
}
|
|
28
30
|
}, [b]), y.canManageQuotas ? x ? /* @__PURE__ */ p("div", {
|
|
29
31
|
className: "space-y-6 p-6",
|
|
@@ -47,50 +49,54 @@ var h = () => {
|
|
|
47
49
|
}) : b ? /* @__PURE__ */ p("div", {
|
|
48
50
|
className: "space-y-6 p-6",
|
|
49
51
|
children: [/* @__PURE__ */ f(t, {
|
|
50
|
-
title: `Edit Quota: ${b.name}`,
|
|
52
|
+
title: `Edit Quota: ${b.context?.displayName ?? b.name}`,
|
|
51
53
|
description: "Update the quota template configuration"
|
|
52
54
|
}), /* @__PURE__ */ p("form", {
|
|
53
55
|
onSubmit: async (e) => {
|
|
54
|
-
if (e.preventDefault(),
|
|
55
|
-
|
|
56
|
+
if (e.preventDefault(), G(null), q(!1), !E.trim()) {
|
|
57
|
+
G("Quota name is required");
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
|
-
if (!
|
|
59
|
-
|
|
60
|
+
if (!P || isNaN(Number(P)) || Number(P) < 0) {
|
|
61
|
+
G("Valid limit value is required");
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
62
|
-
if (!
|
|
63
|
-
|
|
64
|
+
if (!I.trim()) {
|
|
65
|
+
G("Unit is required (e.g., bots, GB, seats)");
|
|
64
66
|
return;
|
|
65
67
|
}
|
|
66
68
|
let t = {
|
|
67
69
|
id: _,
|
|
68
70
|
name: E.trim(),
|
|
69
71
|
limits: {
|
|
70
|
-
type:
|
|
71
|
-
value: Number(
|
|
72
|
-
unit:
|
|
72
|
+
type: M,
|
|
73
|
+
value: Number(P),
|
|
74
|
+
unit: I.trim()
|
|
73
75
|
},
|
|
74
|
-
reusable:
|
|
75
|
-
isActive:
|
|
76
|
-
resetPeriod:
|
|
76
|
+
reusable: R,
|
|
77
|
+
isActive: H,
|
|
78
|
+
resetPeriod: B,
|
|
79
|
+
context: {
|
|
80
|
+
displayName: O.trim() || E.trim(),
|
|
81
|
+
description: A.trim()
|
|
82
|
+
}
|
|
77
83
|
};
|
|
78
84
|
try {
|
|
79
|
-
await w(t),
|
|
85
|
+
await w(t), q(!0), setTimeout(() => v(`/quotas/${_}`), 1500);
|
|
80
86
|
} catch (e) {
|
|
81
|
-
|
|
87
|
+
G(e instanceof Error ? e.message : "Failed to update quota");
|
|
82
88
|
}
|
|
83
89
|
},
|
|
84
90
|
className: "max-w-2xl space-y-6",
|
|
85
91
|
children: [
|
|
86
|
-
|
|
92
|
+
W && /* @__PURE__ */ f("div", {
|
|
87
93
|
className: "p-4 bg-status-error-bg-subtle border border-border-subtle rounded-lg",
|
|
88
94
|
children: /* @__PURE__ */ f("p", {
|
|
89
95
|
className: "text-sm text-status-error-text",
|
|
90
|
-
children:
|
|
96
|
+
children: W
|
|
91
97
|
})
|
|
92
98
|
}),
|
|
93
|
-
|
|
99
|
+
K && /* @__PURE__ */ f("div", {
|
|
94
100
|
className: "p-4 bg-status-success-bg-subtle border border-border-subtle rounded-lg",
|
|
95
101
|
children: /* @__PURE__ */ f("p", {
|
|
96
102
|
className: "text-sm text-status-success-text",
|
|
@@ -108,19 +114,72 @@ var h = () => {
|
|
|
108
114
|
}), /* @__PURE__ */ p("div", {
|
|
109
115
|
className: "p-4 space-y-4",
|
|
110
116
|
children: [
|
|
111
|
-
/* @__PURE__ */ p("div", { children: [
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
117
|
+
/* @__PURE__ */ p("div", { children: [
|
|
118
|
+
/* @__PURE__ */ f("label", {
|
|
119
|
+
htmlFor: "name",
|
|
120
|
+
className: "block text-sm font-medium text-foreground mb-1",
|
|
121
|
+
children: "Quota Key *"
|
|
122
|
+
}),
|
|
123
|
+
/* @__PURE__ */ f("input", {
|
|
124
|
+
id: "name",
|
|
125
|
+
type: "text",
|
|
126
|
+
value: E,
|
|
127
|
+
onChange: (e) => D(e.target.value),
|
|
128
|
+
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary font-mono text-sm",
|
|
129
|
+
placeholder: "e.g., sessions-started, tunnels-created",
|
|
130
|
+
required: !0
|
|
131
|
+
}),
|
|
132
|
+
/* @__PURE__ */ p("p", {
|
|
133
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
134
|
+
children: [
|
|
135
|
+
"Internal machine key — must match the ",
|
|
136
|
+
/* @__PURE__ */ f("code", { children: "quotaName" }),
|
|
137
|
+
" used in",
|
|
138
|
+
" ",
|
|
139
|
+
/* @__PURE__ */ f("code", { children: "@usage" }),
|
|
140
|
+
" directives. Never shown to users."
|
|
141
|
+
]
|
|
142
|
+
})
|
|
143
|
+
] }),
|
|
144
|
+
/* @__PURE__ */ p("div", { children: [
|
|
145
|
+
/* @__PURE__ */ f("label", {
|
|
146
|
+
htmlFor: "displayName",
|
|
147
|
+
className: "block text-sm font-medium text-foreground mb-1",
|
|
148
|
+
children: "Display Name *"
|
|
149
|
+
}),
|
|
150
|
+
/* @__PURE__ */ f("input", {
|
|
151
|
+
id: "displayName",
|
|
152
|
+
type: "text",
|
|
153
|
+
value: O,
|
|
154
|
+
onChange: (e) => k(e.target.value),
|
|
155
|
+
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
156
|
+
placeholder: "e.g., Tunnels, Session Starts, Webhooks",
|
|
157
|
+
required: !0
|
|
158
|
+
}),
|
|
159
|
+
/* @__PURE__ */ f("p", {
|
|
160
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
161
|
+
children: "Human-readable name shown to users in billing and usage UI."
|
|
162
|
+
})
|
|
163
|
+
] }),
|
|
164
|
+
/* @__PURE__ */ p("div", { children: [
|
|
165
|
+
/* @__PURE__ */ f("label", {
|
|
166
|
+
htmlFor: "description",
|
|
167
|
+
className: "block text-sm font-medium text-foreground mb-1",
|
|
168
|
+
children: "Description"
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ f("textarea", {
|
|
171
|
+
id: "description",
|
|
172
|
+
value: A,
|
|
173
|
+
onChange: (e) => j(e.target.value),
|
|
174
|
+
rows: 2,
|
|
175
|
+
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary resize-none",
|
|
176
|
+
placeholder: "e.g., Active tunnels created through VibeControls (slot freed on delete)"
|
|
177
|
+
}),
|
|
178
|
+
/* @__PURE__ */ f("p", {
|
|
179
|
+
className: "text-xs text-muted-foreground mt-1",
|
|
180
|
+
children: "Short explanation shown in billing and usage detail views."
|
|
181
|
+
})
|
|
182
|
+
] }),
|
|
124
183
|
/* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
125
184
|
className: "block text-sm font-medium text-foreground mb-1",
|
|
126
185
|
children: "Quota Type"
|
|
@@ -136,8 +195,8 @@ var h = () => {
|
|
|
136
195
|
children: [/* @__PURE__ */ f("input", {
|
|
137
196
|
id: "reusable",
|
|
138
197
|
type: "checkbox",
|
|
139
|
-
checked:
|
|
140
|
-
onChange: (e) =>
|
|
198
|
+
checked: R,
|
|
199
|
+
onChange: (e) => z(e.target.checked),
|
|
141
200
|
className: "w-4 h-4 rounded border-border text-primary focus:ring-primary"
|
|
142
201
|
}), /* @__PURE__ */ p("div", { children: [/* @__PURE__ */ f("label", {
|
|
143
202
|
htmlFor: "reusable",
|
|
@@ -156,8 +215,8 @@ var h = () => {
|
|
|
156
215
|
}),
|
|
157
216
|
/* @__PURE__ */ p("select", {
|
|
158
217
|
id: "resetPeriod",
|
|
159
|
-
value:
|
|
160
|
-
onChange: (e) =>
|
|
218
|
+
value: B,
|
|
219
|
+
onChange: (e) => V(e.target.value),
|
|
161
220
|
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
162
221
|
children: [
|
|
163
222
|
/* @__PURE__ */ f("option", {
|
|
@@ -184,8 +243,8 @@ var h = () => {
|
|
|
184
243
|
children: [/* @__PURE__ */ f("input", {
|
|
185
244
|
id: "isActive",
|
|
186
245
|
type: "checkbox",
|
|
187
|
-
checked:
|
|
188
|
-
onChange: (e) =>
|
|
246
|
+
checked: H,
|
|
247
|
+
onChange: (e) => U(e.target.checked),
|
|
189
248
|
className: "w-4 h-4 rounded border-border text-primary focus:ring-primary"
|
|
190
249
|
}), /* @__PURE__ */ f("label", {
|
|
191
250
|
htmlFor: "isActive",
|
|
@@ -213,8 +272,8 @@ var h = () => {
|
|
|
213
272
|
children: "Limit Type *"
|
|
214
273
|
}), /* @__PURE__ */ p("select", {
|
|
215
274
|
id: "limitType",
|
|
216
|
-
value:
|
|
217
|
-
onChange: (e) =>
|
|
275
|
+
value: M,
|
|
276
|
+
onChange: (e) => N(e.target.value),
|
|
218
277
|
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
219
278
|
children: [
|
|
220
279
|
/* @__PURE__ */ f("option", {
|
|
@@ -245,8 +304,8 @@ var h = () => {
|
|
|
245
304
|
id: "limitValue",
|
|
246
305
|
type: "number",
|
|
247
306
|
min: "0",
|
|
248
|
-
value:
|
|
249
|
-
onChange: (e) =>
|
|
307
|
+
value: P,
|
|
308
|
+
onChange: (e) => F(e.target.value),
|
|
250
309
|
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
251
310
|
placeholder: "1000",
|
|
252
311
|
required: !0
|
|
@@ -265,8 +324,8 @@ var h = () => {
|
|
|
265
324
|
/* @__PURE__ */ f("input", {
|
|
266
325
|
id: "unit",
|
|
267
326
|
type: "text",
|
|
268
|
-
value:
|
|
269
|
-
onChange: (e) =>
|
|
327
|
+
value: I,
|
|
328
|
+
onChange: (e) => L(e.target.value),
|
|
270
329
|
className: "w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary",
|
|
271
330
|
placeholder: "e.g., bots, GB, MB, seats, workflow runs",
|
|
272
331
|
required: !0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuotaTemplateEditPage.js","names":[],"sources":["../../../../../src/billing/modules/quota/pages/QuotaTemplateEditPage.tsx"],"sourcesContent":["/**\n * Quota Module - Quota Template Edit Page\n * Form to edit an existing quota template\n */\n\nimport { useState, useEffect, type FC, type FormEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useQuotaTemplate, useQuotaTemplateMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader, ServerError } from '../../../shared/components';\nimport { isServerError } from '../../../shared/utils';\nimport { QuotaResetPeriod, type UpdateQuotaInput } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const QuotaTemplateEditPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { quotaId } = useParams<{ quotaId: string }>();\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const {\n quota,\n isLoading: isQuotaLoading,\n error: quotaError,\n refetch,\n } = useQuotaTemplate(quotaId);\n const { updateQuota, isUpdating } = useQuotaTemplateMutations();\n\n // Form state\n const [name, setName] = useState('');\n const [limitType, setLimitType] = useState('numeric');\n const [limitValue, setLimitValue] = useState('');\n const [unit, setUnit] = useState('');\n const [reusable, setReusable] = useState(false);\n const [resetPeriod, setResetPeriod] = useState<QuotaResetPeriod>(QuotaResetPeriod.NEVER);\n const [isActive, setIsActive] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState(false);\n\n // Populate form when quota data loads\n useEffect(() => {\n if (quota) {\n setName(quota.name ?? '');\n setReusable(quota.reusable ?? false);\n setResetPeriod(quota.resetPeriod ?? QuotaResetPeriod.NEVER);\n setIsActive(quota.isActive ?? true);\n\n const limits = quota.limits as { type?: string; value?: number; unit?: string } | null;\n setLimitType(limits?.type ?? 'numeric');\n setLimitValue(String(limits?.value ?? ''));\n setUnit(limits?.unit ?? '');\n }\n }, [quota]);\n\n // Permission check\n if (!permissions.canManageQuotas) {\n return <AccessDenied message=\"You don't have permission to edit quotas.\" />;\n }\n\n // Loading state\n if (isQuotaLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"max-w-2xl space-y-4\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"h-16 bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (quotaError && isServerError(quotaError)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title=\"Server Unavailable\"\n message=\"Unable to load quota. The server might be down or experiencing issues.\"\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n if (!quota) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <h2 className=\"text-lg font-semibold text-foreground\">Quota not found</h2>\n <button\n onClick={() => navigateTo('/quotas')}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90\"\n >\n Back to Quotas\n </button>\n </div>\n </div>\n );\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError(null);\n setSuccess(false);\n\n // Validation\n if (!name.trim()) {\n setError('Quota name is required');\n return;\n }\n if (!limitValue || isNaN(Number(limitValue)) || Number(limitValue) < 0) {\n setError('Valid limit value is required');\n return;\n }\n if (!unit.trim()) {\n setError('Unit is required (e.g., bots, GB, seats)');\n return;\n }\n\n const input: UpdateQuotaInput = {\n id: quotaId!,\n name: name.trim(),\n limits: {\n type: limitType,\n value: Number(limitValue),\n unit: unit.trim(),\n },\n reusable,\n isActive,\n resetPeriod,\n };\n\n try {\n await updateQuota(input);\n setSuccess(true);\n // Navigate back after short delay\n setTimeout(() => navigateTo(`/quotas/${quotaId}`), 1500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update quota');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={`Edit Quota: ${quota.name}`}\n description=\"Update the quota template configuration\"\n />\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-6\">\n {/* Error/Success Messages */}\n {error && (\n <div className=\"p-4 bg-status-error-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n {success && (\n <div className=\"p-4 bg-status-success-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-success-text\">\n Quota updated successfully! Redirecting...\n </p>\n </div>\n )}\n\n {/* Basic Info */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Basic Information</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Name */}\n <div>\n <label htmlFor=\"name\" className=\"block text-sm font-medium text-foreground mb-1\">\n Quota Name *\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., API Calls, Storage, Seats\"\n required\n />\n </div>\n\n {/* Quota Type (read-only) */}\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1\">Quota Type</label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/50 text-muted-foreground\">\n {quota.quotaType === 'POOLED' ? 'Pooled' : 'Product Specific'}\n <span className=\"text-xs ml-2\">(cannot be changed)</span>\n </div>\n </div>\n\n {/* Reusable */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"reusable\"\n type=\"checkbox\"\n checked={reusable}\n onChange={(e) => setReusable(e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-primary focus:ring-primary\"\n />\n <div>\n <label htmlFor=\"reusable\" className=\"text-sm font-medium text-foreground\">\n Reusable Quota\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Enable for quotas like seats or bots that can be freed up\n </p>\n </div>\n </div>\n\n {/* Reset Period */}\n <div>\n <label\n htmlFor=\"resetPeriod\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Reset Period\n </label>\n <select\n id=\"resetPeriod\"\n value={resetPeriod}\n onChange={(e) => setResetPeriod(e.target.value as QuotaResetPeriod)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value={QuotaResetPeriod.NEVER}>Never (one-time limit)</option>\n <option value={QuotaResetPeriod.DAILY}>Daily (resets every day)</option>\n <option value={QuotaResetPeriod.MONTHLY}>Monthly (resets every month)</option>\n </select>\n <p className=\"text-xs text-muted-foreground mt-1\">\n How often the quota usage counter is reset to zero\n </p>\n </div>\n\n {/* Status */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"isActive\"\n type=\"checkbox\"\n checked={isActive}\n onChange={(e) => setIsActive(e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-primary focus:ring-primary\"\n />\n <label htmlFor=\"isActive\" className=\"text-sm font-medium text-foreground\">\n Quota is active\n </label>\n </div>\n </div>\n </div>\n\n {/* Limits Configuration */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Limits Configuration</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Limit Type */}\n <div>\n <label htmlFor=\"limitType\" className=\"block text-sm font-medium text-foreground mb-1\">\n Limit Type *\n </label>\n <select\n id=\"limitType\"\n value={limitType}\n onChange={(e) => setLimitType(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"numeric\">Numeric (count)</option>\n <option value=\"storage\">Storage (bytes)</option>\n <option value=\"duration\">Duration (seconds)</option>\n <option value=\"percentage\">Percentage</option>\n </select>\n </div>\n\n {/* Limit Value */}\n <div>\n <label\n htmlFor=\"limitValue\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Limit Value *\n </label>\n <input\n id=\"limitValue\"\n type=\"number\"\n min=\"0\"\n value={limitValue}\n onChange={(e) => setLimitValue(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"1000\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The maximum limit value for this quota\n </p>\n </div>\n\n {/* Unit */}\n <div>\n <label htmlFor=\"unit\" className=\"block text-sm font-medium text-foreground mb-1\">\n Unit *\n </label>\n <input\n id=\"unit\"\n type=\"text\"\n value={unit}\n onChange={(e) => setUnit(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., bots, GB, MB, seats, workflow runs\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The unit of measurement displayed with usage values (e.g., "2/6 bots")\n </p>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-3 pt-4\">\n <button\n type=\"submit\"\n disabled={isUpdating}\n className=\"px-6 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {isUpdating\n ? tr('billing.quota.saving', 'Saving...')\n : tr('billing.quota.saveChanges', 'Save Changes')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/quotas/${quotaId}`)}\n className=\"px-6 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QuotaTemplateEditPage.js","names":[],"sources":["../../../../../src/billing/modules/quota/pages/QuotaTemplateEditPage.tsx"],"sourcesContent":["/**\n * Quota Module - Quota Template Edit Page\n * Form to edit an existing quota template\n */\n\nimport { useState, useEffect, type FC, type FormEvent } from 'react';\nimport { useParams } from 'react-router-dom';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useQuotaTemplate, useQuotaTemplateMutations } from '../hooks';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader, ServerError } from '../../../shared/components';\nimport { isServerError } from '../../../shared/utils';\nimport { QuotaResetPeriod, type UpdateQuotaInput } from '../../../shared/types';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\nexport const QuotaTemplateEditPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const { quotaId } = useParams<{ quotaId: string }>();\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n const {\n quota,\n isLoading: isQuotaLoading,\n error: quotaError,\n refetch,\n } = useQuotaTemplate(quotaId);\n const { updateQuota, isUpdating } = useQuotaTemplateMutations();\n\n // Form state\n const [name, setName] = useState('');\n const [displayName, setDisplayName] = useState('');\n const [description, setDescription] = useState('');\n const [limitType, setLimitType] = useState('numeric');\n const [limitValue, setLimitValue] = useState('');\n const [unit, setUnit] = useState('');\n const [reusable, setReusable] = useState(false);\n const [resetPeriod, setResetPeriod] = useState<QuotaResetPeriod>(QuotaResetPeriod.NEVER);\n const [isActive, setIsActive] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [success, setSuccess] = useState(false);\n\n // Populate form when quota data loads\n useEffect(() => {\n if (quota) {\n setName(quota.name ?? '');\n setReusable(quota.reusable ?? false);\n setResetPeriod(quota.resetPeriod ?? QuotaResetPeriod.NEVER);\n setIsActive(quota.isActive ?? true);\n\n const limits = quota.limits as { type?: string; value?: number; unit?: string } | null;\n setLimitType(limits?.type ?? 'numeric');\n setLimitValue(String(limits?.value ?? ''));\n setUnit(limits?.unit ?? '');\n\n const ctx = quota.context as { displayName?: string; description?: string } | null;\n setDisplayName(ctx?.displayName ?? '');\n setDescription(ctx?.description ?? '');\n }\n }, [quota]);\n\n // Permission check\n if (!permissions.canManageQuotas) {\n return <AccessDenied message=\"You don't have permission to edit quotas.\" />;\n }\n\n // Loading state\n if (isQuotaLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"max-w-2xl space-y-4\">\n {[1, 2, 3, 4].map((i) => (\n <div key={i} className=\"h-16 bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n // Error state\n if (quotaError && isServerError(quotaError)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title=\"Server Unavailable\"\n message=\"Unable to load quota. The server might be down or experiencing issues.\"\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n if (!quota) {\n return (\n <div className=\"flex items-center justify-center h-full min-h-[400px]\">\n <div className=\"text-center space-y-4\">\n <h2 className=\"text-lg font-semibold text-foreground\">Quota not found</h2>\n <button\n onClick={() => navigateTo('/quotas')}\n className=\"px-4 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90\"\n >\n Back to Quotas\n </button>\n </div>\n </div>\n );\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setError(null);\n setSuccess(false);\n\n // Validation\n if (!name.trim()) {\n setError('Quota name is required');\n return;\n }\n if (!limitValue || isNaN(Number(limitValue)) || Number(limitValue) < 0) {\n setError('Valid limit value is required');\n return;\n }\n if (!unit.trim()) {\n setError('Unit is required (e.g., bots, GB, seats)');\n return;\n }\n\n const input: UpdateQuotaInput = {\n id: quotaId!,\n name: name.trim(),\n limits: {\n type: limitType,\n value: Number(limitValue),\n unit: unit.trim(),\n },\n reusable,\n isActive,\n resetPeriod,\n context: {\n displayName: displayName.trim() || name.trim(),\n description: description.trim(),\n },\n };\n\n try {\n await updateQuota(input);\n setSuccess(true);\n // Navigate back after short delay\n setTimeout(() => navigateTo(`/quotas/${quotaId}`), 1500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to update quota');\n }\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={`Edit Quota: ${(quota.context as { displayName?: string } | null)?.displayName ?? quota.name}`}\n description=\"Update the quota template configuration\"\n />\n\n <form onSubmit={handleSubmit} className=\"max-w-2xl space-y-6\">\n {/* Error/Success Messages */}\n {error && (\n <div className=\"p-4 bg-status-error-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n {success && (\n <div className=\"p-4 bg-status-success-bg-subtle border border-border-subtle rounded-lg\">\n <p className=\"text-sm text-status-success-text\">\n Quota updated successfully! Redirecting...\n </p>\n </div>\n )}\n\n {/* Basic Info */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Basic Information</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Machine Key (name) */}\n <div>\n <label htmlFor=\"name\" className=\"block text-sm font-medium text-foreground mb-1\">\n Quota Key *\n </label>\n <input\n id=\"name\"\n type=\"text\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary font-mono text-sm\"\n placeholder=\"e.g., sessions-started, tunnels-created\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Internal machine key — must match the <code>quotaName</code> used in{' '}\n <code>@usage</code> directives. Never shown to users.\n </p>\n </div>\n\n {/* Display Name */}\n <div>\n <label htmlFor=\"displayName\" className=\"block text-sm font-medium text-foreground mb-1\">\n Display Name *\n </label>\n <input\n id=\"displayName\"\n type=\"text\"\n value={displayName}\n onChange={(e) => setDisplayName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., Tunnels, Session Starts, Webhooks\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Human-readable name shown to users in billing and usage UI.\n </p>\n </div>\n\n {/* Description */}\n <div>\n <label htmlFor=\"description\" className=\"block text-sm font-medium text-foreground mb-1\">\n Description\n </label>\n <textarea\n id=\"description\"\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n rows={2}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary resize-none\"\n placeholder=\"e.g., Active tunnels created through VibeControls (slot freed on delete)\"\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n Short explanation shown in billing and usage detail views.\n </p>\n </div>\n\n {/* Quota Type (read-only) */}\n <div>\n <label className=\"block text-sm font-medium text-foreground mb-1\">Quota Type</label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/50 text-muted-foreground\">\n {quota.quotaType === 'POOLED' ? 'Pooled' : 'Product Specific'}\n <span className=\"text-xs ml-2\">(cannot be changed)</span>\n </div>\n </div>\n\n {/* Reusable */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"reusable\"\n type=\"checkbox\"\n checked={reusable}\n onChange={(e) => setReusable(e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-primary focus:ring-primary\"\n />\n <div>\n <label htmlFor=\"reusable\" className=\"text-sm font-medium text-foreground\">\n Reusable Quota\n </label>\n <p className=\"text-xs text-muted-foreground\">\n Enable for quotas like seats or bots that can be freed up\n </p>\n </div>\n </div>\n\n {/* Reset Period */}\n <div>\n <label\n htmlFor=\"resetPeriod\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Reset Period\n </label>\n <select\n id=\"resetPeriod\"\n value={resetPeriod}\n onChange={(e) => setResetPeriod(e.target.value as QuotaResetPeriod)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value={QuotaResetPeriod.NEVER}>Never (one-time limit)</option>\n <option value={QuotaResetPeriod.DAILY}>Daily (resets every day)</option>\n <option value={QuotaResetPeriod.MONTHLY}>Monthly (resets every month)</option>\n </select>\n <p className=\"text-xs text-muted-foreground mt-1\">\n How often the quota usage counter is reset to zero\n </p>\n </div>\n\n {/* Status */}\n <div className=\"flex items-center gap-3\">\n <input\n id=\"isActive\"\n type=\"checkbox\"\n checked={isActive}\n onChange={(e) => setIsActive(e.target.checked)}\n className=\"w-4 h-4 rounded border-border text-primary focus:ring-primary\"\n />\n <label htmlFor=\"isActive\" className=\"text-sm font-medium text-foreground\">\n Quota is active\n </label>\n </div>\n </div>\n </div>\n\n {/* Limits Configuration */}\n <div className=\"border border-border rounded-lg bg-card overflow-hidden\">\n <div className=\"p-4 border-b border-border bg-muted/30\">\n <h2 className=\"font-semibold text-foreground\">Limits Configuration</h2>\n </div>\n <div className=\"p-4 space-y-4\">\n {/* Limit Type */}\n <div>\n <label htmlFor=\"limitType\" className=\"block text-sm font-medium text-foreground mb-1\">\n Limit Type *\n </label>\n <select\n id=\"limitType\"\n value={limitType}\n onChange={(e) => setLimitType(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n >\n <option value=\"numeric\">Numeric (count)</option>\n <option value=\"storage\">Storage (bytes)</option>\n <option value=\"duration\">Duration (seconds)</option>\n <option value=\"percentage\">Percentage</option>\n </select>\n </div>\n\n {/* Limit Value */}\n <div>\n <label\n htmlFor=\"limitValue\"\n className=\"block text-sm font-medium text-foreground mb-1\"\n >\n Limit Value *\n </label>\n <input\n id=\"limitValue\"\n type=\"number\"\n min=\"0\"\n value={limitValue}\n onChange={(e) => setLimitValue(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"1000\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The maximum limit value for this quota\n </p>\n </div>\n\n {/* Unit */}\n <div>\n <label htmlFor=\"unit\" className=\"block text-sm font-medium text-foreground mb-1\">\n Unit *\n </label>\n <input\n id=\"unit\"\n type=\"text\"\n value={unit}\n onChange={(e) => setUnit(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"e.g., bots, GB, MB, seats, workflow runs\"\n required\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n The unit of measurement displayed with usage values (e.g., "2/6 bots")\n </p>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-3 pt-4\">\n <button\n type=\"submit\"\n disabled={isUpdating}\n className=\"px-6 py-2 text-sm font-medium bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {isUpdating\n ? tr('billing.quota.saving', 'Saving...')\n : tr('billing.quota.saveChanges', 'Save Changes')}\n </button>\n <button\n type=\"button\"\n onClick={() => navigateTo(`/quotas/${quotaId}`)}\n className=\"px-6 py-2 text-sm font-medium border border-border text-foreground rounded-md hover:bg-muted transition-colors\"\n >\n Cancel\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;AAeA,IAAa,UAAkC;CAC7C,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAa,EAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEnC,EAAE,eAAY,GAAgC,EAC9C,IAAa,GAAoB,EACjC,IAAc,GAAuB,EACrC,EACJ,UACA,WAAW,GACX,OAAO,GACP,eACE,EAAiB,EAAQ,EACvB,EAAE,gBAAa,kBAAe,GAA2B,EAGzD,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAa,KAAkB,EAAS,GAAG,EAC5C,CAAC,GAAW,KAAgB,EAAS,UAAU,EAC/C,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAa,KAAkB,EAA2B,EAAiB,MAAM,EAClF,CAAC,GAAU,KAAe,EAAS,GAAK,EACxC,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAS,KAAc,EAAS,GAAM;AAoH7C,QAjHA,QAAgB;AACd,MAAI,GAAO;AAIT,GAHA,EAAQ,EAAM,QAAQ,GAAG,EACzB,EAAY,EAAM,YAAY,GAAM,EACpC,EAAe,EAAM,eAAe,EAAiB,MAAM,EAC3D,EAAY,EAAM,YAAY,GAAK;GAEnC,IAAM,IAAS,EAAM;AAGrB,GAFA,EAAa,GAAQ,QAAQ,UAAU,EACvC,EAAc,OAAO,GAAQ,SAAS,GAAG,CAAC,EAC1C,EAAQ,GAAQ,QAAQ,GAAG;GAE3B,IAAM,IAAM,EAAM;AAElB,GADA,EAAe,GAAK,eAAe,GAAG,EACtC,EAAe,GAAK,eAAe,GAAG;;IAEvC,CAAC,EAAM,CAAC,EAGN,EAAY,kBAKb,IAEA,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAK,WAAU,2CAA4C,CAAA,EAC3D,kBAAC,OAAD;GAAK,WAAU;aACZ;IAAC;IAAG;IAAG;IAAG;IAAE,CAAC,KAAK,MACjB,kBAAC,OAAD,EAAa,WAAU,uCAAwC,EAArD,EAAqD,CAC/D;GACE,CAAA,CACF;MAKN,KAAc,EAAc,EAAW,GAEvC,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GACE,OAAM;GACN,SAAQ;GACR,eAAe,GAAS;GACxB,WAAA;GACA,CAAA;EACE,CAAA,GAIL,IA+DH,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,GAAD;GACE,OAAO,eAAgB,EAAM,SAA6C,eAAe,EAAM;GAC/F,aAAY;GACZ,CAAA,EAEF,kBAAC,QAAD;GAAM,UArDW,OAAO,MAAiB;AAM3C,QALA,EAAE,gBAAgB,EAClB,EAAS,KAAK,EACd,EAAW,GAAM,EAGb,CAAC,EAAK,MAAM,EAAE;AAChB,OAAS,yBAAyB;AAClC;;AAEF,QAAI,CAAC,KAAc,MAAM,OAAO,EAAW,CAAC,IAAI,OAAO,EAAW,GAAG,GAAG;AACtE,OAAS,gCAAgC;AACzC;;AAEF,QAAI,CAAC,EAAK,MAAM,EAAE;AAChB,OAAS,2CAA2C;AACpD;;IAGF,IAAM,IAA0B;KAC9B,IAAI;KACJ,MAAM,EAAK,MAAM;KACjB,QAAQ;MACN,MAAM;MACN,OAAO,OAAO,EAAW;MACzB,MAAM,EAAK,MAAM;MAClB;KACD;KACA;KACA;KACA,SAAS;MACP,aAAa,EAAY,MAAM,IAAI,EAAK,MAAM;MAC9C,aAAa,EAAY,MAAM;MAChC;KACF;AAED,QAAI;AAIF,KAHA,MAAM,EAAY,EAAM,EACxB,EAAW,GAAK,EAEhB,iBAAiB,EAAW,WAAW,IAAU,EAAE,KAAK;aACjD,GAAK;AACZ,OAAS,aAAe,QAAQ,EAAI,UAAU,yBAAyB;;;GAWzC,WAAU;aAAxC;IAEG,KACC,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,KAAD;MAAG,WAAU;gBAAkC;MAAU,CAAA;KACrD,CAAA;IAEP,KACC,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,KAAD;MAAG,WAAU;gBAAmC;MAE5C,CAAA;KACA,CAAA;IAIR,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,MAAD;OAAI,WAAU;iBAAgC;OAAsB,CAAA;MAChE,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OAEE,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,SAAQ;SAAO,WAAU;mBAAiD;SAEzE,CAAA;QACR,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,OAAO;SACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;SACxC,WAAU;SACV,aAAY;SACZ,UAAA;SACA,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAb;UAAkD;UACV,kBAAC,QAAD,EAAA,UAAM,aAAgB,CAAA;;UAAS;UACrE,kBAAC,QAAD,EAAA,UAAM,UAAa,CAAA;;UACjB;;QACA,EAAA,CAAA;OAGN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,SAAQ;SAAc,WAAU;mBAAiD;SAEhF,CAAA;QACR,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,OAAO;SACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;SAC/C,WAAU;SACV,aAAY;SACZ,UAAA;SACA,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAE9C,CAAA;QACA,EAAA,CAAA;OAGN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,SAAQ;SAAc,WAAU;mBAAiD;SAEhF,CAAA;QACR,kBAAC,YAAD;SACE,IAAG;SACH,OAAO;SACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAAM;SAC/C,MAAM;SACN,WAAU;SACV,aAAY;SACZ,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAE9C,CAAA;QACA,EAAA,CAAA;OAGN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QAAO,WAAU;kBAAiD;QAAkB,CAAA,EACpF,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACG,EAAM,cAAc,WAAW,WAAW,oBAC3C,kBAAC,QAAD;SAAM,WAAU;mBAAe;SAA0B,CAAA,CACrD;UACF,EAAA,CAAA;OAGN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,SAAS;SACT,WAAW,MAAM,EAAY,EAAE,OAAO,QAAQ;SAC9C,WAAU;SACV,CAAA,EACF,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SAAO,SAAQ;SAAW,WAAU;mBAAsC;SAElE,CAAA,EACR,kBAAC,KAAD;SAAG,WAAU;mBAAgC;SAEzC,CAAA,CACA,EAAA,CAAA,CACF;;OAGN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SACE,SAAQ;SACR,WAAU;mBACX;SAEO,CAAA;QACR,kBAAC,UAAD;SACE,IAAG;SACH,OAAO;SACP,WAAW,MAAM,EAAe,EAAE,OAAO,MAA0B;SACnE,WAAU;mBAJZ;UAME,kBAAC,UAAD;WAAQ,OAAO,EAAiB;qBAAO;WAA+B,CAAA;UACtE,kBAAC,UAAD;WAAQ,OAAO,EAAiB;qBAAO;WAAiC,CAAA;UACxE,kBAAC,UAAD;WAAQ,OAAO,EAAiB;qBAAS;WAAqC,CAAA;UACvE;;QACT,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAE9C,CAAA;QACA,EAAA,CAAA;OAGN,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,SAAS;SACT,WAAW,MAAM,EAAY,EAAE,OAAO,QAAQ;SAC9C,WAAU;SACV,CAAA,EACF,kBAAC,SAAD;SAAO,SAAQ;SAAW,WAAU;mBAAsC;SAElE,CAAA,CACJ;;OACF;QACF;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,MAAD;OAAI,WAAU;iBAAgC;OAAyB,CAAA;MACnE,CAAA,EACN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OAEE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;QAAO,SAAQ;QAAY,WAAU;kBAAiD;QAE9E,CAAA,EACR,kBAAC,UAAD;QACE,IAAG;QACH,OAAO;QACP,WAAW,MAAM,EAAa,EAAE,OAAO,MAAM;QAC7C,WAAU;kBAJZ;SAME,kBAAC,UAAD;UAAQ,OAAM;oBAAU;UAAwB,CAAA;SAChD,kBAAC,UAAD;UAAQ,OAAM;oBAAU;UAAwB,CAAA;SAChD,kBAAC,UAAD;UAAQ,OAAM;oBAAW;UAA2B,CAAA;SACpD,kBAAC,UAAD;UAAQ,OAAM;oBAAa;UAAmB,CAAA;SACvC;UACL,EAAA,CAAA;OAGN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SACE,SAAQ;SACR,WAAU;mBACX;SAEO,CAAA;QACR,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,KAAI;SACJ,OAAO;SACP,WAAW,MAAM,EAAc,EAAE,OAAO,MAAM;SAC9C,WAAU;SACV,aAAY;SACZ,UAAA;SACA,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAE9C,CAAA;QACA,EAAA,CAAA;OAGN,kBAAC,OAAD,EAAA,UAAA;QACE,kBAAC,SAAD;SAAO,SAAQ;SAAO,WAAU;mBAAiD;SAEzE,CAAA;QACR,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,OAAO;SACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;SACxC,WAAU;SACV,aAAY;SACZ,UAAA;SACA,CAAA;QACF,kBAAC,KAAD;SAAG,WAAU;mBAAqC;SAE9C,CAAA;QACA,EAAA,CAAA;OACF;QACF;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,UAAU;MACV,WAAU;gBAET,IACG,EAAG,wBAAwB,YAAY,GACvC,EAAG,6BAA6B,eAAe;MAC5C,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAW,WAAW,IAAU;MAC/C,WAAU;gBACX;MAEQ,CAAA,CACL;;IACD;KACH;MA5SJ,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,MAAD;IAAI,WAAU;cAAwC;IAAoB,CAAA,EAC1E,kBAAC,UAAD;IACE,eAAe,EAAW,UAAU;IACpC,WAAU;cACX;IAEQ,CAAA,CACL;;EACF,CAAA,GA3CD,kBAAC,GAAD,EAAc,SAAQ,6CAA8C,CAAA"}
|
|
@@ -77,7 +77,7 @@ export declare function useBillingAccounts(): {
|
|
|
77
77
|
/**
|
|
78
78
|
* Hook for fetching paginated subscriptions for a billing account
|
|
79
79
|
*/
|
|
80
|
-
export declare function usePaginatedSubscriptions(billingAccountId: string | undefined, page?: number, pageSize?: number): {
|
|
80
|
+
export declare function usePaginatedSubscriptions(billingAccountId: string | undefined, page?: number, pageSize?: number, search?: string): {
|
|
81
81
|
subscriptions: BillingSubscription[];
|
|
82
82
|
activeSubscriptions: BillingSubscription[];
|
|
83
83
|
totalCount: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSubscriptions.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/subscriptions/hooks/useSubscriptions.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"useSubscriptions.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/subscriptions/hooks/useSubscriptions.ts"],"names":[],"mappings":"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"}
|
|
@@ -106,28 +106,29 @@ function y() {
|
|
|
106
106
|
refetch: i
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
-
function b(e, t = 1, n = 10) {
|
|
110
|
-
let { data:
|
|
109
|
+
function b(e, t = 1, n = 10, r) {
|
|
110
|
+
let { data: i, loading: a, error: o, refetch: c } = s({
|
|
111
111
|
variables: {
|
|
112
112
|
billingAccountId: e,
|
|
113
113
|
page: t,
|
|
114
|
-
pageSize: n
|
|
114
|
+
pageSize: n,
|
|
115
|
+
search: r || void 0
|
|
115
116
|
},
|
|
116
117
|
skip: !e,
|
|
117
118
|
fetchPolicy: "cache-and-network"
|
|
118
|
-
}),
|
|
119
|
-
await
|
|
120
|
-
}, [
|
|
119
|
+
}), l = p(async () => {
|
|
120
|
+
await c();
|
|
121
|
+
}, [c]), u = i?.getPaginatedSubscriptions, d = m(() => u?.subscriptions || [], [u?.subscriptions]);
|
|
121
122
|
return {
|
|
122
|
-
subscriptions:
|
|
123
|
-
activeSubscriptions: m(() =>
|
|
124
|
-
totalCount:
|
|
125
|
-
page:
|
|
126
|
-
pageSize:
|
|
127
|
-
totalPages:
|
|
128
|
-
isLoading:
|
|
129
|
-
error:
|
|
130
|
-
refetch:
|
|
123
|
+
subscriptions: d,
|
|
124
|
+
activeSubscriptions: m(() => d.filter((e) => e.status === "active"), [d]),
|
|
125
|
+
totalCount: u?.totalCount || 0,
|
|
126
|
+
page: u?.page || t,
|
|
127
|
+
pageSize: u?.pageSize || n,
|
|
128
|
+
totalPages: u?.totalPages || 0,
|
|
129
|
+
isLoading: a,
|
|
130
|
+
error: o,
|
|
131
|
+
refetch: l
|
|
131
132
|
};
|
|
132
133
|
}
|
|
133
134
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSubscriptions.js","names":[],"sources":["../../../../../src/billing/modules/subscriptions/hooks/useSubscriptions.ts"],"sourcesContent":["/**\n * Subscriptions Module - useSubscriptions Hook\n * Provides access to subscription data and mutations\n */\n\nimport { useApolloClient } from '@apollo/client/react';\nimport { useCallback, useMemo } from 'react';\nimport {\n useGetSubscriptionQuery,\n useGetBillingAccountQuery,\n useGetDefaultBillingAccountQuery,\n useGetSubscriptionUsageOverviewQuery,\n useGetBillingAccountsForSubscriptionsQuery,\n useGetPaginatedSubscriptionsQuery,\n useCreateBillingAccountSubscriptionsMutation,\n useUpdateBillingAccountSubscriptionsMutation,\n useInitiatePaymentSubscriptionsMutation,\n useSpendCreditsSubscriptionsMutation,\n useCancelSubscriptionMutation,\n useUpdateSubscriptionSeatsMutation,\n GetSubscriptionDocument,\n GetBillingAccountDocument,\n GetDefaultBillingAccountDocument,\n} from '../../../../generated/global-operations';\nimport type {\n BillingSubscription,\n BillingAccount,\n SubscriptionStatus,\n CreateBillingAccountInput,\n UpdateBillingAccountInput,\n InitiatePaymentInput,\n InitiatePaymentResponse,\n SpendCreditsInput,\n CancelSubscriptionInput,\n UpdateSubscriptionSeatsInput,\n} from '../../../shared/types';\n\ninterface UseSubscriptionResult {\n subscription: BillingSubscription | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseBillingAccountResult {\n billingAccount: BillingAccount | null;\n subscriptions: BillingSubscription[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseSubscriptionsListResult {\n subscriptions: BillingSubscription[];\n activeSubscriptions: BillingSubscription[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseSubscriptionMutationsResult {\n createBillingAccount: (input: CreateBillingAccountInput) => Promise<BillingAccount>;\n updateBillingAccount: (input: UpdateBillingAccountInput) => Promise<BillingAccount>;\n initiatePayment: (input: InitiatePaymentInput) => Promise<InitiatePaymentResponse>;\n spendCredits: (input: SpendCreditsInput) => Promise<{ creditTransactionID: string }>;\n cancelSubscription: (input: CancelSubscriptionInput) => Promise<BillingSubscription>;\n updateSubscriptionSeats: (input: UpdateSubscriptionSeatsInput) => Promise<BillingSubscription>;\n isCreating: boolean;\n isUpdating: boolean;\n isInitiatingPayment: boolean;\n isSpendingCredits: boolean;\n isCanceling: boolean;\n isUpdatingSeats: boolean;\n}\n\n/**\n * Hook for fetching a single subscription by ID\n */\nexport function useSubscription(\n id: string | undefined,\n billingAccountId: string | undefined\n): UseSubscriptionResult {\n const { data, loading, error, refetch } = useGetSubscriptionQuery({\n variables: { id: id!, billingAccountId: billingAccountId! },\n skip: !id || !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n subscription: data?.getSubscription || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching billing account by ID\n */\nexport function useBillingAccount(id: string | undefined): UseBillingAccountResult {\n const { data, loading, error, refetch } = useGetBillingAccountQuery({\n variables: { id: id! },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccount = data?.getBillingAccount || null;\n const subscriptions = (billingAccount?.subscriptions || []).filter(\n Boolean\n ) as BillingSubscription[];\n\n return {\n billingAccount,\n subscriptions,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching default billing account for an org\n */\nexport function useDefaultBillingAccount(): UseBillingAccountResult {\n const { data, loading, error, refetch } = useGetDefaultBillingAccountQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccount = data?.getDefaultBillingAccount || null;\n const subscriptions = (billingAccount?.subscriptions || []).filter(\n Boolean\n ) as BillingSubscription[];\n\n return {\n billingAccount,\n subscriptions,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for listing subscriptions from a billing account\n */\nexport function useSubscriptionsList(\n billingAccountId: string | undefined\n): UseSubscriptionsListResult {\n const { subscriptions, isLoading, error, refetch } = useBillingAccount(billingAccountId);\n\n const activeSubscriptions = useMemo(() => {\n return subscriptions.filter((s) => s.status === ('active' as SubscriptionStatus));\n }, [subscriptions]);\n\n return {\n subscriptions,\n activeSubscriptions,\n isLoading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook for subscription usage overview\n */\nexport function useSubscriptionUsageOverview(\n billingAccountId: string | undefined,\n page = 1,\n pageSize = 10\n) {\n const { data, loading, error, refetch } = useGetSubscriptionUsageOverviewQuery({\n variables: { billingAccountId: billingAccountId!, page, pageSize },\n skip: !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n subscriptionsWithQuotas: data?.getSubscriptionUsageOverview || [],\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for subscription mutations\n */\nexport function useSubscriptionMutations(): UseSubscriptionMutationsResult {\n const client = useApolloClient();\n\n const [createBillingAccountMutation, { loading: isCreating }] =\n useCreateBillingAccountSubscriptionsMutation();\n const [updateBillingAccountMutation, { loading: isUpdating }] =\n useUpdateBillingAccountSubscriptionsMutation();\n const [initiatePaymentMutation, { loading: isInitiatingPayment }] =\n useInitiatePaymentSubscriptionsMutation();\n const [spendCreditsMutation, { loading: isSpendingCredits }] =\n useSpendCreditsSubscriptionsMutation();\n const [cancelSubscriptionMutation, { loading: isCanceling }] = useCancelSubscriptionMutation();\n const [updateSeatsMutation, { loading: isUpdatingSeats }] = useUpdateSubscriptionSeatsMutation();\n\n const createBillingAccount = useCallback(\n async (input: CreateBillingAccountInput): Promise<BillingAccount> => {\n try {\n const { data } = await createBillingAccountMutation({\n variables: { input },\n });\n return data.createBillingAccount;\n } catch (error) {\n console.error('Failed to create billing account:', error);\n throw error;\n }\n },\n [createBillingAccountMutation]\n );\n\n const updateBillingAccount = useCallback(\n async (input: UpdateBillingAccountInput): Promise<BillingAccount> => {\n try {\n const { data } = await updateBillingAccountMutation({\n variables: { input },\n });\n // Refetch billing account after update\n await client.refetchQueries({ include: [GetBillingAccountDocument] });\n return data.updateBillingAccount;\n } catch (error) {\n console.error('Failed to update billing account:', error);\n throw error;\n }\n },\n [updateBillingAccountMutation, client]\n );\n\n const initiatePayment = useCallback(\n async (input: InitiatePaymentInput): Promise<InitiatePaymentResponse> => {\n try {\n const { data } = await initiatePaymentMutation({\n variables: { input },\n });\n return data.initiatePayment;\n } catch (error) {\n console.error('Failed to initiate payment:', error);\n throw error;\n }\n },\n [initiatePaymentMutation]\n );\n\n const spendCredits = useCallback(\n async (input: SpendCreditsInput): Promise<{ creditTransactionID: string }> => {\n try {\n const { data } = await spendCreditsMutation({\n variables: { input },\n });\n // Refetch billing account after spending credits\n await client.refetchQueries({\n include: [GetBillingAccountDocument, GetDefaultBillingAccountDocument],\n });\n return data.spendCredits;\n } catch (error) {\n console.error('Failed to spend credits:', error);\n throw error;\n }\n },\n [spendCreditsMutation, client]\n );\n\n const cancelSubscription = useCallback(\n async (input: CancelSubscriptionInput): Promise<BillingSubscription> => {\n try {\n const { data } = await cancelSubscriptionMutation({\n variables: { input },\n });\n // Refetch subscription and billing account after cancellation\n await client.refetchQueries({\n include: [\n GetSubscriptionDocument,\n GetBillingAccountDocument,\n GetDefaultBillingAccountDocument,\n ],\n });\n return data.cancelSubscription;\n } catch (error) {\n console.error('Failed to cancel subscription:', error);\n throw error;\n }\n },\n [cancelSubscriptionMutation, client]\n );\n\n const updateSubscriptionSeats = useCallback(\n async (input: UpdateSubscriptionSeatsInput): Promise<BillingSubscription> => {\n try {\n const { data } = await updateSeatsMutation({ variables: { input } });\n await client.refetchQueries({ include: [GetSubscriptionDocument] });\n return data.updateSubscriptionSeats;\n } catch (error) {\n console.error('Failed to update subscription seats:', error);\n throw error;\n }\n },\n [updateSeatsMutation, client]\n );\n\n return {\n createBillingAccount,\n updateBillingAccount,\n initiatePayment,\n spendCredits,\n cancelSubscription,\n updateSubscriptionSeats,\n isCreating,\n isUpdating,\n isInitiatingPayment,\n isSpendingCredits,\n isCanceling,\n isUpdatingSeats,\n };\n}\n\n/**\n * Hook for fetching all billing accounts for an org\n */\nexport function useBillingAccounts() {\n const { data, loading, error, refetch } = useGetBillingAccountsForSubscriptionsQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccounts: BillingAccount[] = data?.getBillingAccountsByOrg || [];\n\n return {\n billingAccounts,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching paginated subscriptions for a billing account\n */\nexport function usePaginatedSubscriptions(\n billingAccountId: string | undefined,\n page: number = 1,\n pageSize: number = 10\n) {\n const { data, loading, error, refetch } = useGetPaginatedSubscriptionsQuery({\n variables: { billingAccountId: billingAccountId!, page, pageSize },\n skip: !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getPaginatedSubscriptions;\n const subscriptions = useMemo<BillingSubscription[]>(\n () => result?.subscriptions || [],\n [result?.subscriptions]\n );\n const activeSubscriptions = useMemo(() => {\n return subscriptions.filter((s) => s.status === ('active' as SubscriptionStatus));\n }, [subscriptions]);\n\n return {\n subscriptions,\n activeSubscriptions,\n totalCount: result?.totalCount || 0,\n page: result?.page || page,\n pageSize: result?.pageSize || pageSize,\n totalPages: result?.totalPages || 0,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useSubscriptions.js","names":[],"sources":["../../../../../src/billing/modules/subscriptions/hooks/useSubscriptions.ts"],"sourcesContent":["/**\n * Subscriptions Module - useSubscriptions Hook\n * Provides access to subscription data and mutations\n */\n\nimport { useApolloClient } from '@apollo/client/react';\nimport { useCallback, useMemo } from 'react';\nimport {\n useGetSubscriptionQuery,\n useGetBillingAccountQuery,\n useGetDefaultBillingAccountQuery,\n useGetSubscriptionUsageOverviewQuery,\n useGetBillingAccountsForSubscriptionsQuery,\n useGetPaginatedSubscriptionsQuery,\n useCreateBillingAccountSubscriptionsMutation,\n useUpdateBillingAccountSubscriptionsMutation,\n useInitiatePaymentSubscriptionsMutation,\n useSpendCreditsSubscriptionsMutation,\n useCancelSubscriptionMutation,\n useUpdateSubscriptionSeatsMutation,\n GetSubscriptionDocument,\n GetBillingAccountDocument,\n GetDefaultBillingAccountDocument,\n} from '../../../../generated/global-operations';\nimport type {\n BillingSubscription,\n BillingAccount,\n SubscriptionStatus,\n CreateBillingAccountInput,\n UpdateBillingAccountInput,\n InitiatePaymentInput,\n InitiatePaymentResponse,\n SpendCreditsInput,\n CancelSubscriptionInput,\n UpdateSubscriptionSeatsInput,\n} from '../../../shared/types';\n\ninterface UseSubscriptionResult {\n subscription: BillingSubscription | null;\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseBillingAccountResult {\n billingAccount: BillingAccount | null;\n subscriptions: BillingSubscription[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseSubscriptionsListResult {\n subscriptions: BillingSubscription[];\n activeSubscriptions: BillingSubscription[];\n isLoading: boolean;\n error: Error | undefined;\n refetch: () => Promise<void>;\n}\n\ninterface UseSubscriptionMutationsResult {\n createBillingAccount: (input: CreateBillingAccountInput) => Promise<BillingAccount>;\n updateBillingAccount: (input: UpdateBillingAccountInput) => Promise<BillingAccount>;\n initiatePayment: (input: InitiatePaymentInput) => Promise<InitiatePaymentResponse>;\n spendCredits: (input: SpendCreditsInput) => Promise<{ creditTransactionID: string }>;\n cancelSubscription: (input: CancelSubscriptionInput) => Promise<BillingSubscription>;\n updateSubscriptionSeats: (input: UpdateSubscriptionSeatsInput) => Promise<BillingSubscription>;\n isCreating: boolean;\n isUpdating: boolean;\n isInitiatingPayment: boolean;\n isSpendingCredits: boolean;\n isCanceling: boolean;\n isUpdatingSeats: boolean;\n}\n\n/**\n * Hook for fetching a single subscription by ID\n */\nexport function useSubscription(\n id: string | undefined,\n billingAccountId: string | undefined\n): UseSubscriptionResult {\n const { data, loading, error, refetch } = useGetSubscriptionQuery({\n variables: { id: id!, billingAccountId: billingAccountId! },\n skip: !id || !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n subscription: data?.getSubscription || null,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching billing account by ID\n */\nexport function useBillingAccount(id: string | undefined): UseBillingAccountResult {\n const { data, loading, error, refetch } = useGetBillingAccountQuery({\n variables: { id: id! },\n skip: !id,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccount = data?.getBillingAccount || null;\n const subscriptions = (billingAccount?.subscriptions || []).filter(\n Boolean\n ) as BillingSubscription[];\n\n return {\n billingAccount,\n subscriptions,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching default billing account for an org\n */\nexport function useDefaultBillingAccount(): UseBillingAccountResult {\n const { data, loading, error, refetch } = useGetDefaultBillingAccountQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccount = data?.getDefaultBillingAccount || null;\n const subscriptions = (billingAccount?.subscriptions || []).filter(\n Boolean\n ) as BillingSubscription[];\n\n return {\n billingAccount,\n subscriptions,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for listing subscriptions from a billing account\n */\nexport function useSubscriptionsList(\n billingAccountId: string | undefined\n): UseSubscriptionsListResult {\n const { subscriptions, isLoading, error, refetch } = useBillingAccount(billingAccountId);\n\n const activeSubscriptions = useMemo(() => {\n return subscriptions.filter((s) => s.status === ('active' as SubscriptionStatus));\n }, [subscriptions]);\n\n return {\n subscriptions,\n activeSubscriptions,\n isLoading,\n error,\n refetch,\n };\n}\n\n/**\n * Hook for subscription usage overview\n */\nexport function useSubscriptionUsageOverview(\n billingAccountId: string | undefined,\n page = 1,\n pageSize = 10\n) {\n const { data, loading, error, refetch } = useGetSubscriptionUsageOverviewQuery({\n variables: { billingAccountId: billingAccountId!, page, pageSize },\n skip: !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n return {\n subscriptionsWithQuotas: data?.getSubscriptionUsageOverview || [],\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for subscription mutations\n */\nexport function useSubscriptionMutations(): UseSubscriptionMutationsResult {\n const client = useApolloClient();\n\n const [createBillingAccountMutation, { loading: isCreating }] =\n useCreateBillingAccountSubscriptionsMutation();\n const [updateBillingAccountMutation, { loading: isUpdating }] =\n useUpdateBillingAccountSubscriptionsMutation();\n const [initiatePaymentMutation, { loading: isInitiatingPayment }] =\n useInitiatePaymentSubscriptionsMutation();\n const [spendCreditsMutation, { loading: isSpendingCredits }] =\n useSpendCreditsSubscriptionsMutation();\n const [cancelSubscriptionMutation, { loading: isCanceling }] = useCancelSubscriptionMutation();\n const [updateSeatsMutation, { loading: isUpdatingSeats }] = useUpdateSubscriptionSeatsMutation();\n\n const createBillingAccount = useCallback(\n async (input: CreateBillingAccountInput): Promise<BillingAccount> => {\n try {\n const { data } = await createBillingAccountMutation({\n variables: { input },\n });\n return data.createBillingAccount;\n } catch (error) {\n console.error('Failed to create billing account:', error);\n throw error;\n }\n },\n [createBillingAccountMutation]\n );\n\n const updateBillingAccount = useCallback(\n async (input: UpdateBillingAccountInput): Promise<BillingAccount> => {\n try {\n const { data } = await updateBillingAccountMutation({\n variables: { input },\n });\n // Refetch billing account after update\n await client.refetchQueries({ include: [GetBillingAccountDocument] });\n return data.updateBillingAccount;\n } catch (error) {\n console.error('Failed to update billing account:', error);\n throw error;\n }\n },\n [updateBillingAccountMutation, client]\n );\n\n const initiatePayment = useCallback(\n async (input: InitiatePaymentInput): Promise<InitiatePaymentResponse> => {\n try {\n const { data } = await initiatePaymentMutation({\n variables: { input },\n });\n return data.initiatePayment;\n } catch (error) {\n console.error('Failed to initiate payment:', error);\n throw error;\n }\n },\n [initiatePaymentMutation]\n );\n\n const spendCredits = useCallback(\n async (input: SpendCreditsInput): Promise<{ creditTransactionID: string }> => {\n try {\n const { data } = await spendCreditsMutation({\n variables: { input },\n });\n // Refetch billing account after spending credits\n await client.refetchQueries({\n include: [GetBillingAccountDocument, GetDefaultBillingAccountDocument],\n });\n return data.spendCredits;\n } catch (error) {\n console.error('Failed to spend credits:', error);\n throw error;\n }\n },\n [spendCreditsMutation, client]\n );\n\n const cancelSubscription = useCallback(\n async (input: CancelSubscriptionInput): Promise<BillingSubscription> => {\n try {\n const { data } = await cancelSubscriptionMutation({\n variables: { input },\n });\n // Refetch subscription and billing account after cancellation\n await client.refetchQueries({\n include: [\n GetSubscriptionDocument,\n GetBillingAccountDocument,\n GetDefaultBillingAccountDocument,\n ],\n });\n return data.cancelSubscription;\n } catch (error) {\n console.error('Failed to cancel subscription:', error);\n throw error;\n }\n },\n [cancelSubscriptionMutation, client]\n );\n\n const updateSubscriptionSeats = useCallback(\n async (input: UpdateSubscriptionSeatsInput): Promise<BillingSubscription> => {\n try {\n const { data } = await updateSeatsMutation({ variables: { input } });\n await client.refetchQueries({ include: [GetSubscriptionDocument] });\n return data.updateSubscriptionSeats;\n } catch (error) {\n console.error('Failed to update subscription seats:', error);\n throw error;\n }\n },\n [updateSeatsMutation, client]\n );\n\n return {\n createBillingAccount,\n updateBillingAccount,\n initiatePayment,\n spendCredits,\n cancelSubscription,\n updateSubscriptionSeats,\n isCreating,\n isUpdating,\n isInitiatingPayment,\n isSpendingCredits,\n isCanceling,\n isUpdatingSeats,\n };\n}\n\n/**\n * Hook for fetching all billing accounts for an org\n */\nexport function useBillingAccounts() {\n const { data, loading, error, refetch } = useGetBillingAccountsForSubscriptionsQuery({\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const billingAccounts: BillingAccount[] = data?.getBillingAccountsByOrg || [];\n\n return {\n billingAccounts,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n\n/**\n * Hook for fetching paginated subscriptions for a billing account\n */\nexport function usePaginatedSubscriptions(\n billingAccountId: string | undefined,\n page: number = 1,\n pageSize: number = 10,\n search?: string\n) {\n const { data, loading, error, refetch } = useGetPaginatedSubscriptionsQuery({\n variables: { billingAccountId: billingAccountId!, page, pageSize, search: search || undefined },\n skip: !billingAccountId,\n fetchPolicy: 'cache-and-network',\n });\n\n const handleRefetch = useCallback(async () => {\n await refetch();\n }, [refetch]);\n\n const result = data?.getPaginatedSubscriptions;\n const subscriptions = useMemo<BillingSubscription[]>(\n () => result?.subscriptions || [],\n [result?.subscriptions]\n );\n const activeSubscriptions = useMemo(() => {\n return subscriptions.filter((s) => s.status === ('active' as SubscriptionStatus));\n }, [subscriptions]);\n\n return {\n subscriptions,\n activeSubscriptions,\n totalCount: result?.totalCount || 0,\n page: result?.page || page,\n pageSize: result?.pageSize || pageSize,\n totalPages: result?.totalPages || 0,\n isLoading: loading,\n error: error as Error | undefined,\n refetch: handleRefetch,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionsListPage.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/subscriptions/pages/SubscriptionsListPage.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"SubscriptionsListPage.d.ts","sourceRoot":"","sources":["../../../../../src/billing/modules/subscriptions/pages/SubscriptionsListPage.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA+B,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAwB7D,eAAO,MAAM,qBAAqB,EAAE,EA6enC,CAAC"}
|