@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.
Files changed (65) hide show
  1. package/dist/billing/BillingUserRoutes.js +1 -1
  2. package/dist/billing/BillingUserRoutes.js.map +1 -1
  3. package/dist/billing/modules/billing/hooks/useInvoices.d.ts +1 -0
  4. package/dist/billing/modules/billing/hooks/useInvoices.d.ts.map +1 -1
  5. package/dist/billing/modules/billing/hooks/useInvoices.js +26 -20
  6. package/dist/billing/modules/billing/hooks/useInvoices.js.map +1 -1
  7. package/dist/billing/modules/billing/pages/InvoicesListPage.d.ts.map +1 -1
  8. package/dist/billing/modules/billing/pages/InvoicesListPage.js +170 -176
  9. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  10. package/dist/billing/modules/billing/pages/RefundsPage.js +1 -1
  11. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  12. package/dist/billing/modules/checkout/components/OrderSummary.js +4 -4
  13. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  14. package/dist/billing/modules/checkout/pages/CheckoutPage.d.ts.map +1 -1
  15. package/dist/billing/modules/checkout/pages/CheckoutPage.js +2 -2
  16. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  17. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.d.ts.map +1 -1
  18. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +209 -178
  19. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  20. package/dist/billing/modules/dashboard/pages/OverviewPage.js +2 -2
  21. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  22. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +2 -2
  23. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  24. package/dist/billing/modules/earnings/api.d.ts +4 -0
  25. package/dist/billing/modules/earnings/api.d.ts.map +1 -1
  26. package/dist/billing/modules/earnings/api.js +14 -10
  27. package/dist/billing/modules/earnings/api.js.map +1 -1
  28. package/dist/billing/modules/earnings/pages/PayoutAdminPage.d.ts.map +1 -1
  29. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +523 -233
  30. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  31. package/dist/billing/modules/quota/pages/QuotaPage.js +1 -1
  32. package/dist/billing/modules/quota/pages/QuotaPage.js.map +1 -1
  33. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.d.ts.map +1 -1
  34. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +101 -44
  35. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  36. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.d.ts.map +1 -1
  37. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +105 -46
  38. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  39. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.d.ts +1 -1
  40. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.d.ts.map +1 -1
  41. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js +16 -15
  42. package/dist/billing/modules/subscriptions/hooks/useSubscriptions.js.map +1 -1
  43. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.d.ts.map +1 -1
  44. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +158 -165
  45. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  46. package/dist/billing/modules/usage/hooks/useUsage.d.ts +3 -0
  47. package/dist/billing/modules/usage/hooks/useUsage.d.ts.map +1 -1
  48. package/dist/billing/modules/usage/hooks/useUsage.js +4 -1
  49. package/dist/billing/modules/usage/hooks/useUsage.js.map +1 -1
  50. package/dist/billing/modules/usage/pages/UsagePage.d.ts.map +1 -1
  51. package/dist/billing/modules/usage/pages/UsagePage.js +44 -22
  52. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  53. package/dist/billing/shared/types/graphql.d.ts +2 -0
  54. package/dist/billing/shared/types/graphql.d.ts.map +1 -1
  55. package/dist/billing/shared/types/graphql.js.map +1 -1
  56. package/dist/generated/global-operations.d.ts +51 -0
  57. package/dist/generated/global-operations.d.ts.map +1 -1
  58. package/dist/generated/global-operations.js +313 -293
  59. package/dist/generated/global-operations.js.map +1 -1
  60. package/dist/generated/global-types.d.ts +350 -1392
  61. package/dist/generated/global-types.d.ts.map +1 -1
  62. package/dist/generated/global-types.js.map +1 -1
  63. package/dist/generated/wspace-types.d.ts +2907 -11652
  64. package/dist/generated/wspace-types.d.ts.map +1 -1
  65. 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("numeric"), [A, j] = u(""), [M, N] = u(""), [P, F] = u(!1), [I, L] = u(r.NEVER), [R, z] = u(!0), [B, V] = u(null), [H, U] = u(!1);
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 ?? ""), F(b.reusable ?? !1), L(b.resetPeriod ?? r.NEVER), z(b.isActive ?? !0);
24
+ D(b.name ?? ""), z(b.reusable ?? !1), V(b.resetPeriod ?? r.NEVER), U(b.isActive ?? !0);
25
25
  let e = b.limits;
26
- k(e?.type ?? "numeric"), j(String(e?.value ?? "")), N(e?.unit ?? "");
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(), V(null), U(!1), !E.trim()) {
55
- V("Quota name is required");
56
+ if (e.preventDefault(), G(null), q(!1), !E.trim()) {
57
+ G("Quota name is required");
56
58
  return;
57
59
  }
58
- if (!A || isNaN(Number(A)) || Number(A) < 0) {
59
- V("Valid limit value is required");
60
+ if (!P || isNaN(Number(P)) || Number(P) < 0) {
61
+ G("Valid limit value is required");
60
62
  return;
61
63
  }
62
- if (!M.trim()) {
63
- V("Unit is required (e.g., bots, GB, seats)");
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: O,
71
- value: Number(A),
72
- unit: M.trim()
72
+ type: M,
73
+ value: Number(P),
74
+ unit: I.trim()
73
75
  },
74
- reusable: P,
75
- isActive: R,
76
- resetPeriod: I
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), U(!0), setTimeout(() => v(`/quotas/${_}`), 1500);
85
+ await w(t), q(!0), setTimeout(() => v(`/quotas/${_}`), 1500);
80
86
  } catch (e) {
81
- V(e instanceof Error ? e.message : "Failed to update quota");
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
- B && /* @__PURE__ */ f("div", {
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: B
96
+ children: W
91
97
  })
92
98
  }),
93
- H && /* @__PURE__ */ f("div", {
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: [/* @__PURE__ */ f("label", {
112
- htmlFor: "name",
113
- className: "block text-sm font-medium text-foreground mb-1",
114
- children: "Quota Name *"
115
- }), /* @__PURE__ */ f("input", {
116
- id: "name",
117
- type: "text",
118
- value: E,
119
- onChange: (e) => D(e.target.value),
120
- 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",
121
- placeholder: "e.g., API Calls, Storage, Seats",
122
- required: !0
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: P,
140
- onChange: (e) => F(e.target.checked),
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: I,
160
- onChange: (e) => L(e.target.value),
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: R,
188
- onChange: (e) => z(e.target.checked),
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: O,
217
- onChange: (e) => k(e.target.value),
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: A,
249
- onChange: (e) => j(e.target.value),
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: M,
269
- onChange: (e) => N(e.target.value),
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., &quot;2/6 bots&quot;)\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., &quot;2/6 bots&quot;)\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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"}
@@ -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: r, loading: i, error: a, refetch: o } = s({
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
- }), c = p(async () => {
119
- await o();
120
- }, [o]), l = r?.getPaginatedSubscriptions, u = m(() => l?.subscriptions || [], [l?.subscriptions]);
119
+ }), l = p(async () => {
120
+ await c();
121
+ }, [c]), u = i?.getPaginatedSubscriptions, d = m(() => u?.subscriptions || [], [u?.subscriptions]);
121
122
  return {
122
- subscriptions: u,
123
- activeSubscriptions: m(() => u.filter((e) => e.status === "active"), [u]),
124
- totalCount: l?.totalCount || 0,
125
- page: l?.page || t,
126
- pageSize: l?.pageSize || n,
127
- totalPages: l?.totalPages || 0,
128
- isLoading: i,
129
- error: a,
130
- refetch: c
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,EAAY,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAwB1C,eAAO,MAAM,qBAAqB,EAAE,EA6enC,CAAC"}
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"}