@burdenoff/microfe-billing 2026.623.2 → 2026.624.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/billing/BillingUserRoutes.js +3 -3
- package/dist/billing/BillingUserRoutes.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +34 -34
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +94 -94
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +40 -40
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +10 -10
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/TransactionsPage.js +62 -62
- package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +7 -7
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
- package/dist/billing/modules/earnings/pages/EarningsPage.js +21 -21
- package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +4 -4
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutsPage.js +33 -33
- package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +4 -4
- package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js +146 -142
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +4 -4
- package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/SettingsPage.js +57 -57
- package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +33 -33
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
- package/dist/billing/shared/components/AccessDenied.js +4 -4
- package/dist/billing/shared/components/AccessDenied.js.map +1 -1
- package/dist/billing/shared/components/ActorIdentity.js +8 -8
- package/dist/billing/shared/components/ActorIdentity.js.map +1 -1
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js +11 -11
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js.map +1 -1
- package/dist/billing/shared/ui/Card.js +1 -1
- package/dist/billing/shared/ui/Card.js.map +1 -1
- package/dist/billing/shared/ui/MetricCard.js +1 -1
- package/dist/billing/shared/ui/MetricCard.js.map +1 -1
- package/package.json +1 -1
|
@@ -130,16 +130,16 @@ var D = () => {
|
|
|
130
130
|
description: "Register payout accounts, request withdrawals, and track disbursement status."
|
|
131
131
|
}),
|
|
132
132
|
B && !c(B) ? /* @__PURE__ */ T("div", {
|
|
133
|
-
className: "rounded-lg border border-border bg-
|
|
133
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4 text-sm text-status-error-text",
|
|
134
134
|
children: B.message
|
|
135
135
|
}) : null,
|
|
136
136
|
/* @__PURE__ */ E("div", {
|
|
137
137
|
className: "grid gap-6 xl:grid-cols-[1.05fr,1.95fr]",
|
|
138
138
|
children: [/* @__PURE__ */ E("section", {
|
|
139
|
-
className: "rounded-lg border border-border bg-
|
|
139
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
140
140
|
children: [
|
|
141
141
|
/* @__PURE__ */ T("h2", {
|
|
142
|
-
className: "mb-4 text-lg font-semibold text-
|
|
142
|
+
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
143
143
|
children: J ? "Edit payout account" : "Add payout account"
|
|
144
144
|
}),
|
|
145
145
|
/* @__PURE__ */ E("div", {
|
|
@@ -152,7 +152,7 @@ var D = () => {
|
|
|
152
152
|
label: e.target.value
|
|
153
153
|
})),
|
|
154
154
|
placeholder: "Label",
|
|
155
|
-
className: "w-full rounded-md border border-border bg-
|
|
155
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
156
156
|
}),
|
|
157
157
|
/* @__PURE__ */ E("div", {
|
|
158
158
|
className: "grid gap-3 md:grid-cols-2",
|
|
@@ -162,7 +162,7 @@ var D = () => {
|
|
|
162
162
|
...t,
|
|
163
163
|
type: e.target.value
|
|
164
164
|
})),
|
|
165
|
-
className: "rounded-md border border-border bg-
|
|
165
|
+
className: "rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary",
|
|
166
166
|
children: [
|
|
167
167
|
/* @__PURE__ */ T("option", {
|
|
168
168
|
value: "BANK_ACCOUNT",
|
|
@@ -183,7 +183,7 @@ var D = () => {
|
|
|
183
183
|
...t,
|
|
184
184
|
providerPreference: e.target.value
|
|
185
185
|
})),
|
|
186
|
-
className: "rounded-md border border-border bg-
|
|
186
|
+
className: "rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary",
|
|
187
187
|
children: [
|
|
188
188
|
/* @__PURE__ */ T("option", {
|
|
189
189
|
value: "AUTO",
|
|
@@ -213,7 +213,7 @@ var D = () => {
|
|
|
213
213
|
country: e.target.value.toUpperCase()
|
|
214
214
|
})),
|
|
215
215
|
placeholder: "Country",
|
|
216
|
-
className: "rounded-md border border-border bg-
|
|
216
|
+
className: "rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
217
217
|
}), /* @__PURE__ */ T("input", {
|
|
218
218
|
value: H.currency,
|
|
219
219
|
onChange: (e) => U((t) => ({
|
|
@@ -221,7 +221,7 @@ var D = () => {
|
|
|
221
221
|
currency: e.target.value.toUpperCase()
|
|
222
222
|
})),
|
|
223
223
|
placeholder: "Currency",
|
|
224
|
-
className: "rounded-md border border-border bg-
|
|
224
|
+
className: "rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
225
225
|
})]
|
|
226
226
|
}),
|
|
227
227
|
/* @__PURE__ */ T("input", {
|
|
@@ -231,7 +231,7 @@ var D = () => {
|
|
|
231
231
|
accountHolderName: e.target.value
|
|
232
232
|
})),
|
|
233
233
|
placeholder: "Account holder name",
|
|
234
|
-
className: "w-full rounded-md border border-border bg-
|
|
234
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
235
235
|
}),
|
|
236
236
|
H.type === "BANK_ACCOUNT" ? /* @__PURE__ */ E(w, { children: [
|
|
237
237
|
/* @__PURE__ */ T("input", {
|
|
@@ -241,7 +241,7 @@ var D = () => {
|
|
|
241
241
|
bankName: e.target.value
|
|
242
242
|
})),
|
|
243
243
|
placeholder: "Bank name",
|
|
244
|
-
className: "w-full rounded-md border border-border bg-
|
|
244
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
245
245
|
}),
|
|
246
246
|
/* @__PURE__ */ T("input", {
|
|
247
247
|
value: H.accountNumber,
|
|
@@ -250,7 +250,7 @@ var D = () => {
|
|
|
250
250
|
accountNumber: e.target.value
|
|
251
251
|
})),
|
|
252
252
|
placeholder: "Account number",
|
|
253
|
-
className: "w-full rounded-md border border-border bg-
|
|
253
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
254
254
|
}),
|
|
255
255
|
/* @__PURE__ */ T("input", {
|
|
256
256
|
value: H.country === "IN" ? H.ifsc : H.routingNumber,
|
|
@@ -262,7 +262,7 @@ var D = () => {
|
|
|
262
262
|
routingNumber: e.target.value
|
|
263
263
|
}),
|
|
264
264
|
placeholder: H.country === "IN" ? "IFSC" : "Routing number",
|
|
265
|
-
className: "w-full rounded-md border border-border bg-
|
|
265
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
266
266
|
})
|
|
267
267
|
] }) : H.type === "UPI" ? /* @__PURE__ */ T("input", {
|
|
268
268
|
value: H.upiId,
|
|
@@ -271,14 +271,14 @@ var D = () => {
|
|
|
271
271
|
upiId: e.target.value
|
|
272
272
|
})),
|
|
273
273
|
placeholder: "UPI ID",
|
|
274
|
-
className: "w-full rounded-md border border-border bg-
|
|
274
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
275
275
|
}) : null
|
|
276
276
|
]
|
|
277
277
|
}),
|
|
278
278
|
/* @__PURE__ */ E("button", {
|
|
279
279
|
type: "button",
|
|
280
280
|
onClick: () => void Q(),
|
|
281
|
-
className: "mt-4 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-
|
|
281
|
+
className: "mt-4 inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
|
|
282
282
|
children: [/* @__PURE__ */ T(x, { className: "size-4" }), J ? "Update payout account" : "Save payout account"]
|
|
283
283
|
}),
|
|
284
284
|
J ? /* @__PURE__ */ T("button", {
|
|
@@ -298,24 +298,24 @@ var D = () => {
|
|
|
298
298
|
upiId: ""
|
|
299
299
|
});
|
|
300
300
|
},
|
|
301
|
-
className: "mt-4 ml-3 inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-
|
|
301
|
+
className: "mt-4 ml-3 inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary",
|
|
302
302
|
children: "Cancel edit"
|
|
303
303
|
}) : null
|
|
304
304
|
]
|
|
305
305
|
}), /* @__PURE__ */ E("section", {
|
|
306
306
|
className: "space-y-4",
|
|
307
307
|
children: [/* @__PURE__ */ E("div", {
|
|
308
|
-
className: "rounded-lg border border-border bg-
|
|
308
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
309
309
|
children: [
|
|
310
310
|
/* @__PURE__ */ E("div", {
|
|
311
311
|
className: "mb-4 flex items-center justify-between",
|
|
312
312
|
children: [/* @__PURE__ */ T("h2", {
|
|
313
|
-
className: "text-lg font-semibold text-
|
|
313
|
+
className: "text-lg font-semibold text-text-primary",
|
|
314
314
|
children: "Request payout"
|
|
315
315
|
}), /* @__PURE__ */ E("button", {
|
|
316
316
|
type: "button",
|
|
317
317
|
onClick: () => void Z(),
|
|
318
|
-
className: "inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-
|
|
318
|
+
className: "inline-flex items-center gap-2 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary",
|
|
319
319
|
children: [/* @__PURE__ */ T(S, { className: "size-4" }), "Refresh"]
|
|
320
320
|
})]
|
|
321
321
|
}),
|
|
@@ -329,7 +329,7 @@ var D = () => {
|
|
|
329
329
|
/* @__PURE__ */ T("select", {
|
|
330
330
|
value: K,
|
|
331
331
|
onChange: (e) => q(e.target.value),
|
|
332
|
-
className: "w-full rounded-md border border-border bg-
|
|
332
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary",
|
|
333
333
|
children: P.map((e) => /* @__PURE__ */ E("option", {
|
|
334
334
|
value: e.id,
|
|
335
335
|
children: [
|
|
@@ -345,32 +345,32 @@ var D = () => {
|
|
|
345
345
|
value: W,
|
|
346
346
|
onChange: (e) => G(e.target.value),
|
|
347
347
|
placeholder: "Amount",
|
|
348
|
-
className: "w-full rounded-md border border-border bg-
|
|
348
|
+
className: "w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary"
|
|
349
349
|
}),
|
|
350
350
|
/* @__PURE__ */ E("button", {
|
|
351
351
|
type: "button",
|
|
352
352
|
onClick: () => void ne(),
|
|
353
|
-
className: "inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-
|
|
353
|
+
className: "inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text",
|
|
354
354
|
children: [/* @__PURE__ */ T(C, { className: "size-4" }), "Request payout"]
|
|
355
355
|
})
|
|
356
356
|
]
|
|
357
357
|
}),
|
|
358
358
|
P.length > 0 ? /* @__PURE__ */ E("div", {
|
|
359
|
-
className: "mt-4 space-y-3 rounded-md border border-border bg-
|
|
359
|
+
className: "mt-4 space-y-3 rounded-md border border-border-subtle bg-bg-surface/60 p-3",
|
|
360
360
|
children: [/* @__PURE__ */ T("h3", {
|
|
361
|
-
className: "text-sm font-semibold text-
|
|
361
|
+
className: "text-sm font-semibold text-text-primary",
|
|
362
362
|
children: "Saved payout accounts"
|
|
363
363
|
}), P.map((e) => /* @__PURE__ */ E("div", {
|
|
364
|
-
className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-border/70 bg-
|
|
364
|
+
className: "flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-subtle/70 bg-bg-surface px-3 py-2 text-sm",
|
|
365
365
|
children: [/* @__PURE__ */ E("div", { children: [/* @__PURE__ */ E("p", {
|
|
366
|
-
className: "font-medium text-
|
|
366
|
+
className: "font-medium text-text-primary",
|
|
367
367
|
children: [
|
|
368
368
|
e.label,
|
|
369
369
|
" ",
|
|
370
370
|
e.isDefault ? "• Default" : ""
|
|
371
371
|
]
|
|
372
372
|
}), /* @__PURE__ */ E("p", {
|
|
373
|
-
className: "text-
|
|
373
|
+
className: "text-text-secondary",
|
|
374
374
|
children: [
|
|
375
375
|
e.providerPreference,
|
|
376
376
|
" · ",
|
|
@@ -384,19 +384,19 @@ var D = () => {
|
|
|
384
384
|
/* @__PURE__ */ T("button", {
|
|
385
385
|
type: "button",
|
|
386
386
|
onClick: () => te(e),
|
|
387
|
-
className: "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-
|
|
387
|
+
className: "rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary",
|
|
388
388
|
children: "Edit"
|
|
389
389
|
}),
|
|
390
390
|
e.isDefault ? null : /* @__PURE__ */ T("button", {
|
|
391
391
|
type: "button",
|
|
392
392
|
onClick: () => void $(e.id),
|
|
393
|
-
className: "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-
|
|
393
|
+
className: "rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary",
|
|
394
394
|
children: "Make default"
|
|
395
395
|
}),
|
|
396
396
|
/* @__PURE__ */ T("button", {
|
|
397
397
|
type: "button",
|
|
398
398
|
onClick: () => void ee(e.id),
|
|
399
|
-
className: "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-
|
|
399
|
+
className: "rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text",
|
|
400
400
|
children: "Archive"
|
|
401
401
|
})
|
|
402
402
|
]
|
|
@@ -405,9 +405,9 @@ var D = () => {
|
|
|
405
405
|
}) : null
|
|
406
406
|
]
|
|
407
407
|
}), /* @__PURE__ */ E("div", {
|
|
408
|
-
className: "rounded-lg border border-border bg-
|
|
408
|
+
className: "rounded-lg border border-border-subtle bg-bg-surface p-4",
|
|
409
409
|
children: [/* @__PURE__ */ T("h2", {
|
|
410
|
-
className: "mb-4 text-lg font-semibold text-
|
|
410
|
+
className: "mb-4 text-lg font-semibold text-text-primary",
|
|
411
411
|
children: "Payout requests"
|
|
412
412
|
}), I.length === 0 && !R ? /* @__PURE__ */ T(r, {
|
|
413
413
|
icon: /* @__PURE__ */ T(C, { className: "size-8" }),
|
|
@@ -418,7 +418,7 @@ var D = () => {
|
|
|
418
418
|
children: /* @__PURE__ */ E("table", {
|
|
419
419
|
className: "min-w-full text-sm",
|
|
420
420
|
children: [/* @__PURE__ */ T("thead", { children: /* @__PURE__ */ E("tr", {
|
|
421
|
-
className: "border-b border-border text-left text-
|
|
421
|
+
className: "border-b border-border-subtle text-left text-text-secondary",
|
|
422
422
|
children: [
|
|
423
423
|
/* @__PURE__ */ T("th", {
|
|
424
424
|
className: "px-3 py-2",
|
|
@@ -442,7 +442,7 @@ var D = () => {
|
|
|
442
442
|
})
|
|
443
443
|
]
|
|
444
444
|
}) }), /* @__PURE__ */ T("tbody", { children: I.map((e) => /* @__PURE__ */ E("tr", {
|
|
445
|
-
className: "border-b border-border/70 text-
|
|
445
|
+
className: "border-b border-border-subtle/70 text-text-primary",
|
|
446
446
|
children: [
|
|
447
447
|
/* @__PURE__ */ T("td", {
|
|
448
448
|
className: "px-3 py-2 font-medium",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PayoutsPage.js","names":[],"sources":["../../../../../src/billing/modules/earnings/pages/PayoutsPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type FC } from 'react';\nimport { Landmark, RefreshCw, Send } from 'lucide-react';\n\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useBillingEventEmitter } from '../../../hooks/useBillingEventEmitter';\nimport { useBilling } from '../../../providers/BillingProvider';\nimport { AccessDenied, EmptyState, PageHeader, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { useGetDefaultBillingAccountSettingsQuery } from '../../../../generated/global-operations';\nimport {\n addPayoutAccount,\n archivePayoutAccount,\n fetchPayoutAccounts,\n fetchPayoutRequests,\n requestPayout,\n setDefaultPayoutAccount,\n updatePayoutAccount,\n type PayoutAccount,\n type PayoutRequest,\n} from '../api';\n\nexport const PayoutsPage: FC = () => {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const { apiGatewayUrl, authToken, orgId } = useBilling();\n const { data: billingAccountData } = useGetDefaultBillingAccountSettingsQuery({});\n const billingAccountId = billingAccountData?.getDefaultBillingAccount?.id;\n\n const [accounts, setAccounts] = useState<PayoutAccount[]>([]);\n const [requests, setRequests] = useState<PayoutRequest[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [accountForm, setAccountForm] = useState({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n const [requestAmount, setRequestAmount] = useState('');\n const [selectedAccountId, setSelectedAccountId] = useState<string>('');\n const [editingAccountId, setEditingAccountId] = useState<string | null>(null);\n\n const requestContext = useMemo(\n () => ({\n apiGatewayUrl,\n authToken,\n orgId,\n }),\n [apiGatewayUrl, authToken, orgId]\n );\n\n const loadData = async () => {\n if (!billingAccountId) return;\n setLoading(true);\n setError(null);\n try {\n const [loadedAccounts, loadedRequests] = await Promise.all([\n fetchPayoutAccounts(billingAccountId, requestContext),\n fetchPayoutRequests(billingAccountId, requestContext),\n ]);\n setAccounts(loadedAccounts);\n setRequests(loadedRequests);\n if (!selectedAccountId && loadedAccounts[0]?.id) {\n setSelectedAccountId(loadedAccounts[0].id);\n }\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError : new Error('Failed to load payout data'));\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void loadData();\n }, [billingAccountId, requestContext]);\n\n if (!permissions.canManagePaymentMethods) {\n return <AccessDenied message=\"You don't have permission to manage payout accounts.\" />;\n }\n\n if (error && isServerError(error)) {\n return (\n <ServerError\n title=\"Payout data unavailable\"\n message={error.message}\n onRetry={() => void loadData()}\n showRetry\n />\n );\n }\n\n const handleAddAccount = async () => {\n if (!billingAccountId) return;\n const payload = {\n billingAccountId,\n ...accountForm,\n };\n\n if (editingAccountId) {\n await updatePayoutAccount(editingAccountId, payload, requestContext);\n emit('billing.payout_account.updated', {\n route: '/billing/payouts',\n entityId: editingAccountId,\n source: 'payouts',\n });\n } else {\n await addPayoutAccount(payload, requestContext);\n emit('billing.payout_account.added', {\n route: '/billing/payouts',\n entityId: billingAccountId,\n source: 'payouts',\n });\n }\n\n setAccountForm({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n setEditingAccountId(null);\n await loadData();\n };\n\n const handleSetDefault = async (accountId: string) => {\n await setDefaultPayoutAccount(accountId, requestContext);\n await loadData();\n };\n\n const handleArchive = async (accountId: string) => {\n if (!window.confirm('Archive this payout account?')) return;\n await archivePayoutAccount(accountId, requestContext);\n emit('billing.payout_account.archived', {\n route: '/billing/payouts',\n entityId: accountId,\n source: 'payouts',\n });\n await loadData();\n };\n\n const handleEditAccount = (account: PayoutAccount) => {\n setEditingAccountId(account.id);\n setAccountForm((current) => ({\n ...current,\n label: account.label,\n type: account.type,\n providerPreference: account.providerPreference,\n country: account.country || current.country,\n currency: account.currency,\n accountHolderName: account.displayName || current.accountHolderName,\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n }));\n };\n\n const handleRequestPayout = async () => {\n if (!billingAccountId || !selectedAccountId || !requestAmount) return;\n await requestPayout(\n {\n billingAccountId,\n payoutAccountId: selectedAccountId,\n amount: Number(requestAmount),\n currency: accounts.find((account) => account.id === selectedAccountId)?.currency || 'USD',\n },\n requestContext\n );\n emit('billing.payout.requested', {\n route: '/billing/payouts',\n entityId: selectedAccountId,\n source: 'payouts',\n amount: Number(requestAmount),\n currency: accounts.find((account) => account.id === selectedAccountId)?.currency || 'USD',\n });\n setRequestAmount('');\n await loadData();\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title=\"Payouts\"\n description=\"Register payout accounts, request withdrawals, and track disbursement status.\"\n />\n\n {error && !isServerError(error) ? (\n <div className=\"rounded-lg border border-border bg-card p-4 text-sm text-destructive\">\n {error.message}\n </div>\n ) : null}\n\n <div className=\"grid gap-6 xl:grid-cols-[1.05fr,1.95fr]\">\n <section className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-4 text-lg font-semibold text-foreground\">\n {editingAccountId ? 'Edit payout account' : 'Add payout account'}\n </h2>\n <div className=\"space-y-3\">\n <input\n value={accountForm.label}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, label: event.target.value }))\n }\n placeholder=\"Label\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <div className=\"grid gap-3 md:grid-cols-2\">\n <select\n value={accountForm.type}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, type: event.target.value }))\n }\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n >\n <option value=\"BANK_ACCOUNT\">Bank account</option>\n <option value=\"UPI\">UPI</option>\n <option value=\"WALLET\">Wallet</option>\n </select>\n <select\n value={accountForm.providerPreference}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n providerPreference: event.target.value,\n }))\n }\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n >\n <option value=\"AUTO\">Auto</option>\n <option value=\"STRIPE\">Stripe</option>\n <option value=\"RAZORPAY\">Razorpay</option>\n <option value=\"MANUAL\">Manual</option>\n </select>\n </div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <input\n value={accountForm.country}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n country: event.target.value.toUpperCase(),\n }))\n }\n placeholder=\"Country\"\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <input\n value={accountForm.currency}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n currency: event.target.value.toUpperCase(),\n }))\n }\n placeholder=\"Currency\"\n className=\"rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n </div>\n <input\n value={accountForm.accountHolderName}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, accountHolderName: event.target.value }))\n }\n placeholder=\"Account holder name\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n {accountForm.type === 'BANK_ACCOUNT' ? (\n <>\n <input\n value={accountForm.bankName}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, bankName: event.target.value }))\n }\n placeholder=\"Bank name\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <input\n value={accountForm.accountNumber}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, accountNumber: event.target.value }))\n }\n placeholder=\"Account number\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <input\n value={\n accountForm.country === 'IN' ? accountForm.ifsc : accountForm.routingNumber\n }\n onChange={(event) =>\n setAccountForm((current) =>\n current.country === 'IN'\n ? { ...current, ifsc: event.target.value }\n : { ...current, routingNumber: event.target.value }\n )\n }\n placeholder={accountForm.country === 'IN' ? 'IFSC' : 'Routing number'}\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n </>\n ) : accountForm.type === 'UPI' ? (\n <input\n value={accountForm.upiId}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, upiId: event.target.value }))\n }\n placeholder=\"UPI ID\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n ) : null}\n </div>\n <button\n type=\"button\"\n onClick={() => void handleAddAccount()}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground\"\n >\n <Landmark className=\"size-4\" />\n {editingAccountId ? 'Update payout account' : 'Save payout account'}\n </button>\n {editingAccountId ? (\n <button\n type=\"button\"\n onClick={() => {\n setEditingAccountId(null);\n setAccountForm({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n }}\n className=\"mt-4 ml-3 inline-flex items-center gap-2 rounded-md border border-border px-4 py-2 text-sm font-medium text-foreground\"\n >\n Cancel edit\n </button>\n ) : null}\n </section>\n\n <section className=\"space-y-4\">\n <div className=\"rounded-lg border border-border bg-card p-4\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-foreground\">Request payout</h2>\n <button\n type=\"button\"\n onClick={() => void loadData()}\n className=\"inline-flex items-center gap-2 rounded-md border border-border px-3 py-2 text-sm font-medium text-foreground\"\n >\n <RefreshCw className=\"size-4\" />\n Refresh\n </button>\n </div>\n {accounts.length === 0 && !loading ? (\n <EmptyState\n icon={<Landmark className=\"size-8\" />}\n title=\"No payout accounts yet\"\n description=\"Add a payout account before requesting a withdrawal.\"\n />\n ) : (\n <div className=\"space-y-3\">\n <select\n value={selectedAccountId}\n onChange={(event) => setSelectedAccountId(event.target.value)}\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n >\n {accounts.map((account) => (\n <option key={account.id} value={account.id}>\n {account.label} · {account.currency} · {account.status}\n </option>\n ))}\n </select>\n <input\n value={requestAmount}\n onChange={(event) => setRequestAmount(event.target.value)}\n placeholder=\"Amount\"\n className=\"w-full rounded-md border border-border bg-background px-3 py-2 text-sm text-foreground\"\n />\n <button\n type=\"button\"\n onClick={() => void handleRequestPayout()}\n className=\"inline-flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground\"\n >\n <Send className=\"size-4\" />\n Request payout\n </button>\n </div>\n )}\n\n {accounts.length > 0 ? (\n <div className=\"mt-4 space-y-3 rounded-md border border-border bg-background/60 p-3\">\n <h3 className=\"text-sm font-semibold text-foreground\">Saved payout accounts</h3>\n {accounts.map((account) => (\n <div\n key={account.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-md border border-border/70 bg-card px-3 py-2 text-sm\"\n >\n <div>\n <p className=\"font-medium text-foreground\">\n {account.label} {account.isDefault ? '• Default' : ''}\n </p>\n <p className=\"text-muted-foreground\">\n {account.providerPreference} · {account.currency} · {account.status}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => handleEditAccount(account)}\n className=\"rounded-md border border-border px-3 py-1.5 text-xs font-medium text-foreground\"\n >\n Edit\n </button>\n {!account.isDefault ? (\n <button\n type=\"button\"\n onClick={() => void handleSetDefault(account.id)}\n className=\"rounded-md border border-border px-3 py-1.5 text-xs font-medium text-foreground\"\n >\n Make default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => void handleArchive(account.id)}\n className=\"rounded-md border border-border px-3 py-1.5 text-xs font-medium text-destructive\"\n >\n Archive\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n\n <div className=\"rounded-lg border border-border bg-card p-4\">\n <h2 className=\"mb-4 text-lg font-semibold text-foreground\">Payout requests</h2>\n {requests.length === 0 && !loading ? (\n <EmptyState\n icon={<Send className=\"size-8\" />}\n title=\"No payout requests yet\"\n description=\"Your payout requests and processing updates will appear here.\"\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border text-left text-muted-foreground\">\n <th className=\"px-3 py-2\">Amount</th>\n <th className=\"px-3 py-2\">Provider</th>\n <th className=\"px-3 py-2\">Status</th>\n <th className=\"px-3 py-2\">Account</th>\n <th className=\"px-3 py-2\">Created</th>\n </tr>\n </thead>\n <tbody>\n {requests.map((request) => (\n <tr key={request.id} className=\"border-b border-border/70 text-foreground\">\n <td className=\"px-3 py-2 font-medium\">\n {formatCurrency(request.requestedAmount, request.currency)}\n </td>\n <td className=\"px-3 py-2\">{request.provider}</td>\n <td className=\"px-3 py-2\">{request.status}</td>\n <td className=\"px-3 py-2\">{request.payoutAccount?.label || '-'}</td>\n <td className=\"px-3 py-2\">{formatDateTime(request.createdAt)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </section>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PayoutsPage.js","names":[],"sources":["../../../../../src/billing/modules/earnings/pages/PayoutsPage.tsx"],"sourcesContent":["import { useEffect, useMemo, useState, type FC } from 'react';\nimport { Landmark, RefreshCw, Send } from 'lucide-react';\n\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { useBillingEventEmitter } from '../../../hooks/useBillingEventEmitter';\nimport { useBilling } from '../../../providers/BillingProvider';\nimport { AccessDenied, EmptyState, PageHeader, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { useGetDefaultBillingAccountSettingsQuery } from '../../../../generated/global-operations';\nimport {\n addPayoutAccount,\n archivePayoutAccount,\n fetchPayoutAccounts,\n fetchPayoutRequests,\n requestPayout,\n setDefaultPayoutAccount,\n updatePayoutAccount,\n type PayoutAccount,\n type PayoutRequest,\n} from '../api';\n\nexport const PayoutsPage: FC = () => {\n const permissions = useBillingPermissions();\n const { emit } = useBillingEventEmitter();\n const { apiGatewayUrl, authToken, orgId } = useBilling();\n const { data: billingAccountData } = useGetDefaultBillingAccountSettingsQuery({});\n const billingAccountId = billingAccountData?.getDefaultBillingAccount?.id;\n\n const [accounts, setAccounts] = useState<PayoutAccount[]>([]);\n const [requests, setRequests] = useState<PayoutRequest[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<Error | null>(null);\n const [accountForm, setAccountForm] = useState({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n const [requestAmount, setRequestAmount] = useState('');\n const [selectedAccountId, setSelectedAccountId] = useState<string>('');\n const [editingAccountId, setEditingAccountId] = useState<string | null>(null);\n\n const requestContext = useMemo(\n () => ({\n apiGatewayUrl,\n authToken,\n orgId,\n }),\n [apiGatewayUrl, authToken, orgId]\n );\n\n const loadData = async () => {\n if (!billingAccountId) return;\n setLoading(true);\n setError(null);\n try {\n const [loadedAccounts, loadedRequests] = await Promise.all([\n fetchPayoutAccounts(billingAccountId, requestContext),\n fetchPayoutRequests(billingAccountId, requestContext),\n ]);\n setAccounts(loadedAccounts);\n setRequests(loadedRequests);\n if (!selectedAccountId && loadedAccounts[0]?.id) {\n setSelectedAccountId(loadedAccounts[0].id);\n }\n } catch (loadError) {\n setError(loadError instanceof Error ? loadError : new Error('Failed to load payout data'));\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void loadData();\n }, [billingAccountId, requestContext]);\n\n if (!permissions.canManagePaymentMethods) {\n return <AccessDenied message=\"You don't have permission to manage payout accounts.\" />;\n }\n\n if (error && isServerError(error)) {\n return (\n <ServerError\n title=\"Payout data unavailable\"\n message={error.message}\n onRetry={() => void loadData()}\n showRetry\n />\n );\n }\n\n const handleAddAccount = async () => {\n if (!billingAccountId) return;\n const payload = {\n billingAccountId,\n ...accountForm,\n };\n\n if (editingAccountId) {\n await updatePayoutAccount(editingAccountId, payload, requestContext);\n emit('billing.payout_account.updated', {\n route: '/billing/payouts',\n entityId: editingAccountId,\n source: 'payouts',\n });\n } else {\n await addPayoutAccount(payload, requestContext);\n emit('billing.payout_account.added', {\n route: '/billing/payouts',\n entityId: billingAccountId,\n source: 'payouts',\n });\n }\n\n setAccountForm({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n setEditingAccountId(null);\n await loadData();\n };\n\n const handleSetDefault = async (accountId: string) => {\n await setDefaultPayoutAccount(accountId, requestContext);\n await loadData();\n };\n\n const handleArchive = async (accountId: string) => {\n if (!window.confirm('Archive this payout account?')) return;\n await archivePayoutAccount(accountId, requestContext);\n emit('billing.payout_account.archived', {\n route: '/billing/payouts',\n entityId: accountId,\n source: 'payouts',\n });\n await loadData();\n };\n\n const handleEditAccount = (account: PayoutAccount) => {\n setEditingAccountId(account.id);\n setAccountForm((current) => ({\n ...current,\n label: account.label,\n type: account.type,\n providerPreference: account.providerPreference,\n country: account.country || current.country,\n currency: account.currency,\n accountHolderName: account.displayName || current.accountHolderName,\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n }));\n };\n\n const handleRequestPayout = async () => {\n if (!billingAccountId || !selectedAccountId || !requestAmount) return;\n await requestPayout(\n {\n billingAccountId,\n payoutAccountId: selectedAccountId,\n amount: Number(requestAmount),\n currency: accounts.find((account) => account.id === selectedAccountId)?.currency || 'USD',\n },\n requestContext\n );\n emit('billing.payout.requested', {\n route: '/billing/payouts',\n entityId: selectedAccountId,\n source: 'payouts',\n amount: Number(requestAmount),\n currency: accounts.find((account) => account.id === selectedAccountId)?.currency || 'USD',\n });\n setRequestAmount('');\n await loadData();\n };\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title=\"Payouts\"\n description=\"Register payout accounts, request withdrawals, and track disbursement status.\"\n />\n\n {error && !isServerError(error) ? (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4 text-sm text-status-error-text\">\n {error.message}\n </div>\n ) : null}\n\n <div className=\"grid gap-6 xl:grid-cols-[1.05fr,1.95fr]\">\n <section className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">\n {editingAccountId ? 'Edit payout account' : 'Add payout account'}\n </h2>\n <div className=\"space-y-3\">\n <input\n value={accountForm.label}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, label: event.target.value }))\n }\n placeholder=\"Label\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n <div className=\"grid gap-3 md:grid-cols-2\">\n <select\n value={accountForm.type}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, type: event.target.value }))\n }\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"BANK_ACCOUNT\">Bank account</option>\n <option value=\"UPI\">UPI</option>\n <option value=\"WALLET\">Wallet</option>\n </select>\n <select\n value={accountForm.providerPreference}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n providerPreference: event.target.value,\n }))\n }\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n <option value=\"AUTO\">Auto</option>\n <option value=\"STRIPE\">Stripe</option>\n <option value=\"RAZORPAY\">Razorpay</option>\n <option value=\"MANUAL\">Manual</option>\n </select>\n </div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <input\n value={accountForm.country}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n country: event.target.value.toUpperCase(),\n }))\n }\n placeholder=\"Country\"\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n <input\n value={accountForm.currency}\n onChange={(event) =>\n setAccountForm((current) => ({\n ...current,\n currency: event.target.value.toUpperCase(),\n }))\n }\n placeholder=\"Currency\"\n className=\"rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </div>\n <input\n value={accountForm.accountHolderName}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, accountHolderName: event.target.value }))\n }\n placeholder=\"Account holder name\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n {accountForm.type === 'BANK_ACCOUNT' ? (\n <>\n <input\n value={accountForm.bankName}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, bankName: event.target.value }))\n }\n placeholder=\"Bank name\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n <input\n value={accountForm.accountNumber}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, accountNumber: event.target.value }))\n }\n placeholder=\"Account number\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n <input\n value={\n accountForm.country === 'IN' ? accountForm.ifsc : accountForm.routingNumber\n }\n onChange={(event) =>\n setAccountForm((current) =>\n current.country === 'IN'\n ? { ...current, ifsc: event.target.value }\n : { ...current, routingNumber: event.target.value }\n )\n }\n placeholder={accountForm.country === 'IN' ? 'IFSC' : 'Routing number'}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n </>\n ) : accountForm.type === 'UPI' ? (\n <input\n value={accountForm.upiId}\n onChange={(event) =>\n setAccountForm((current) => ({ ...current, upiId: event.target.value }))\n }\n placeholder=\"UPI ID\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n ) : null}\n </div>\n <button\n type=\"button\"\n onClick={() => void handleAddAccount()}\n className=\"mt-4 inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Landmark className=\"size-4\" />\n {editingAccountId ? 'Update payout account' : 'Save payout account'}\n </button>\n {editingAccountId ? (\n <button\n type=\"button\"\n onClick={() => {\n setEditingAccountId(null);\n setAccountForm({\n label: '',\n type: 'BANK_ACCOUNT',\n providerPreference: 'AUTO',\n country: 'US',\n currency: 'USD',\n accountHolderName: '',\n bankName: '',\n accountNumber: '',\n routingNumber: '',\n ifsc: '',\n upiId: '',\n });\n }}\n className=\"mt-4 ml-3 inline-flex items-center gap-2 rounded-md border border-border-subtle px-4 py-2 text-sm font-medium text-text-primary\"\n >\n Cancel edit\n </button>\n ) : null}\n </section>\n\n <section className=\"space-y-4\">\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"mb-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Request payout</h2>\n <button\n type=\"button\"\n onClick={() => void loadData()}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-3 py-2 text-sm font-medium text-text-primary\"\n >\n <RefreshCw className=\"size-4\" />\n Refresh\n </button>\n </div>\n {accounts.length === 0 && !loading ? (\n <EmptyState\n icon={<Landmark className=\"size-8\" />}\n title=\"No payout accounts yet\"\n description=\"Add a payout account before requesting a withdrawal.\"\n />\n ) : (\n <div className=\"space-y-3\">\n <select\n value={selectedAccountId}\n onChange={(event) => setSelectedAccountId(event.target.value)}\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n >\n {accounts.map((account) => (\n <option key={account.id} value={account.id}>\n {account.label} · {account.currency} · {account.status}\n </option>\n ))}\n </select>\n <input\n value={requestAmount}\n onChange={(event) => setRequestAmount(event.target.value)}\n placeholder=\"Amount\"\n className=\"w-full rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary\"\n />\n <button\n type=\"button\"\n onClick={() => void handleRequestPayout()}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <Send className=\"size-4\" />\n Request payout\n </button>\n </div>\n )}\n\n {accounts.length > 0 ? (\n <div className=\"mt-4 space-y-3 rounded-md border border-border-subtle bg-bg-surface/60 p-3\">\n <h3 className=\"text-sm font-semibold text-text-primary\">Saved payout accounts</h3>\n {accounts.map((account) => (\n <div\n key={account.id}\n className=\"flex flex-wrap items-center justify-between gap-3 rounded-md border border-border-subtle/70 bg-bg-surface px-3 py-2 text-sm\"\n >\n <div>\n <p className=\"font-medium text-text-primary\">\n {account.label} {account.isDefault ? '• Default' : ''}\n </p>\n <p className=\"text-text-secondary\">\n {account.providerPreference} · {account.currency} · {account.status}\n </p>\n </div>\n <div className=\"flex flex-wrap gap-2\">\n <button\n type=\"button\"\n onClick={() => handleEditAccount(account)}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary\"\n >\n Edit\n </button>\n {!account.isDefault ? (\n <button\n type=\"button\"\n onClick={() => void handleSetDefault(account.id)}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-text-primary\"\n >\n Make default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={() => void handleArchive(account.id)}\n className=\"rounded-md border border-border-subtle px-3 py-1.5 text-xs font-medium text-status-error-text\"\n >\n Archive\n </button>\n </div>\n </div>\n ))}\n </div>\n ) : null}\n </div>\n\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <h2 className=\"mb-4 text-lg font-semibold text-text-primary\">Payout requests</h2>\n {requests.length === 0 && !loading ? (\n <EmptyState\n icon={<Send className=\"size-8\" />}\n title=\"No payout requests yet\"\n description=\"Your payout requests and processing updates will appear here.\"\n />\n ) : (\n <div className=\"overflow-x-auto\">\n <table className=\"min-w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border-subtle text-left text-text-secondary\">\n <th className=\"px-3 py-2\">Amount</th>\n <th className=\"px-3 py-2\">Provider</th>\n <th className=\"px-3 py-2\">Status</th>\n <th className=\"px-3 py-2\">Account</th>\n <th className=\"px-3 py-2\">Created</th>\n </tr>\n </thead>\n <tbody>\n {requests.map((request) => (\n <tr key={request.id} className=\"border-b border-border-subtle/70 text-text-primary\">\n <td className=\"px-3 py-2 font-medium\">\n {formatCurrency(request.requestedAmount, request.currency)}\n </td>\n <td className=\"px-3 py-2\">{request.provider}</td>\n <td className=\"px-3 py-2\">{request.status}</td>\n <td className=\"px-3 py-2\">{request.payoutAccount?.label || '-'}</td>\n <td className=\"px-3 py-2\">{formatDateTime(request.createdAt)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n )}\n </div>\n </section>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -143,9 +143,9 @@ var u = () => {
|
|
|
143
143
|
/* @__PURE__ */ c("div", { children: [
|
|
144
144
|
/* @__PURE__ */ c("label", {
|
|
145
145
|
htmlFor: "workspaceId",
|
|
146
|
-
className: "block text-sm font-medium text-
|
|
146
|
+
className: "block text-sm font-medium text-text-primary mb-1",
|
|
147
147
|
children: ["Workspace ID ", /* @__PURE__ */ s("span", {
|
|
148
|
-
className: "text-
|
|
148
|
+
className: "text-text-secondary font-normal",
|
|
149
149
|
children: "(optional)"
|
|
150
150
|
})]
|
|
151
151
|
}),
|
|
@@ -154,11 +154,11 @@ var u = () => {
|
|
|
154
154
|
type: "text",
|
|
155
155
|
value: b,
|
|
156
156
|
onChange: (e) => x(e.target.value),
|
|
157
|
-
className: "w-full px-3 py-2 border border-border rounded-md bg-
|
|
157
|
+
className: "w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-primary font-mono text-sm",
|
|
158
158
|
placeholder: "e.g. ws_01jk3n2… (leave blank to auto-resolve)"
|
|
159
159
|
}),
|
|
160
160
|
/* @__PURE__ */ s("p", {
|
|
161
|
-
className: "text-xs text-
|
|
161
|
+
className: "text-xs text-text-secondary mt-1",
|
|
162
162
|
children: "If blank, the first active workspace for this org is used automatically. Set explicitly when the org has multiple workspaces."
|
|
163
163
|
})
|
|
164
164
|
] }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlanAssignFreePage.js","names":[],"sources":["../../../../../src/billing/modules/plans/pages/PlanAssignFreePage.tsx"],"sourcesContent":["/**\n * Plans Module - Assign Plan Free (Admin only)\n *\n * Internal tool for assigning any plan to a billing account at no charge.\n * Protected by PLAN_ASSIGN_SECRET — only team members who know the secret\n * can use this page. Never expose to end users.\n *\n * Route: /billing/plans/assign-free\n */\n\nimport { useState, type FC, type FormEvent } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useAssignPlanFreeMutation } from '../../../../generated/global-operations';\nimport { usePlans } from '../hooks';\n\nexport const PlanAssignFreePage: 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\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n\n const [secret, setSecret] = useState('');\n const [billingAccountId, setBillingAccountId] = useState('');\n const [planId, setPlanId] = useState('');\n const [workspaceId, setWorkspaceId] = useState('');\n const [result, setResult] = useState<{ success: boolean; message: string } | null>(null);\n\n // Fetch all plans (including non-purchasable internal ones) for the dropdown\n const { plans, isLoading: isPlansLoading } = usePlans({ includeFree: true });\n\n const [assignPlanFree, { loading: isAssigning }] = useAssignPlanFreeMutation();\n\n if (!permissions.canManagePlans) {\n return (\n <AccessDenied\n message={tr(\n 'billing.assignFree.noPermission',\n \"You don't have permission to access this page.\"\n )}\n />\n );\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setResult(null);\n\n if (!secret.trim() || !billingAccountId.trim() || !planId) {\n setResult({ success: false, message: 'All fields are required.' });\n return;\n }\n\n try {\n const { data } = await assignPlanFree({\n variables: {\n secret: secret.trim(),\n billingAccountId: billingAccountId.trim(),\n planId,\n ...(workspaceId.trim() ? { workspaceId: workspaceId.trim() } : {}),\n },\n });\n\n if (data?.assignPlanFree) {\n const sub = data.assignPlanFree;\n setResult({\n success: true,\n message: `Plan assigned. Subscription ID: ${sub.id} · Status: ${sub.status} · Valid: ${new Date(sub.startDate).toLocaleDateString()} → ${new Date(sub.endDate).toLocaleDateString()}`,\n });\n // Clear sensitive fields\n setSecret('');\n setBillingAccountId('');\n setPlanId('');\n setWorkspaceId('');\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to assign plan.';\n setResult({ success: false, message: msg });\n }\n };\n\n const selectedPlan = plans.find((p) => p.id === planId);\n\n return (\n <div className=\"space-y-6 p-6 max-w-2xl\">\n <PageHeader\n title={tr('billing.assignFree.title', 'Assign Plan for Free')}\n description={tr(\n 'billing.assignFree.description',\n 'Internally assign any plan to a billing account at no charge. Requires the team secret.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/plans')}\n className=\"px-3 py-2 text-sm border border-border-subtle rounded-md text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n ← Back to Plans\n </button>\n }\n />\n\n {/* Warning banner */}\n <div className=\"flex items-start gap-3 p-4 rounded-lg border border-status-warning-border bg-status-warning-bg/10\">\n <svg\n className=\"size-5 text-status-warning-text shrink-0 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.962-.833-2.732 0L3.072 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n <div>\n <p className=\"text-sm font-medium text-status-warning-text\">Internal admin tool</p>\n <p className=\"text-xs text-status-warning-text/80 mt-0.5\">\n This bypasses all payment flows. The plan is assigned immediately with no charge. Use\n only for enterprise deals or internal accounts.\n </p>\n </div>\n </div>\n\n <form\n onSubmit={handleSubmit}\n className=\"border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]\"\n >\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">Assignment Details</h2>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Secret */}\n <div>\n <label htmlFor=\"secret\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Team Secret <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"secret\"\n type=\"password\"\n value={secret}\n onChange={(e) => setSecret(e.target.value)}\n autoComplete=\"off\"\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono\"\n placeholder=\"Enter PLAN_ASSIGN_SECRET\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n The secret key shared within the team. Never expose this to users.\n </p>\n </div>\n\n {/* Billing Account ID */}\n <div>\n <label\n htmlFor=\"billingAccountId\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Billing Account ID <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"billingAccountId\"\n type=\"text\"\n value={billingAccountId}\n onChange={(e) => setBillingAccountId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono text-sm\"\n placeholder=\"e.g. ba_01jk3n2...\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n Find this in the user's billing account settings or via the billing accounts list.\n </p>\n </div>\n\n {/* Workspace ID (optional — auto-resolved from org if omitted) */}\n <div>\n <label htmlFor=\"workspaceId\" className=\"block text-sm font-medium text-foreground mb-1\">\n Workspace ID <span className=\"text-muted-foreground font-normal\">(optional)</span>\n </label>\n <input\n id=\"workspaceId\"\n type=\"text\"\n value={workspaceId}\n onChange={(e) => setWorkspaceId(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. ws_01jk3n2… (leave blank to auto-resolve)\"\n />\n <p className=\"text-xs text-muted-foreground mt-1\">\n If blank, the first active workspace for this org is used automatically. Set\n explicitly when the org has multiple workspaces.\n </p>\n </div>\n\n {/* Plan selector */}\n <div>\n <label htmlFor=\"planId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Plan <span className=\"text-status-error-text\">*</span>\n </label>\n {isPlansLoading ? (\n <div className=\"h-10 bg-bg-sunken animate-pulse rounded-md\" />\n ) : (\n <select\n id=\"planId\"\n value={planId}\n onChange={(e) => setPlanId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n required\n >\n <option value=\"\" disabled>\n Select a plan…\n </option>\n {plans.map((plan) => (\n <option key={plan.id} value={plan.id}>\n {plan.name}\n {!plan.isPurchasable ? ' (internal)' : ''}\n {plan.price != null && plan.price > 0\n ? ` — ${plan.currency ?? 'USD'} ${plan.price}`\n : ''}\n </option>\n ))}\n </select>\n )}\n {selectedPlan && (\n <p className=\"text-xs text-text-muted mt-1\">\n {selectedPlan.isPurchasable ? 'Public plan' : 'Internal / non-purchasable plan'}\n {selectedPlan.productID ? ` · Product: ${selectedPlan.productID}` : ''}\n </p>\n )}\n </div>\n </div>\n\n {/* Result banner */}\n {result && (\n <div\n className={`mx-4 mb-4 p-3 rounded-lg border text-sm ${\n result.success\n ? 'border-status-success-border bg-status-success-bg/10 text-status-success-text'\n : 'border-status-error-border bg-status-error-bg/10 text-status-error-text'\n }`}\n >\n {result.message}\n </div>\n )}\n\n <div className=\"px-4 pb-4 flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={isAssigning || !secret || !billingAccountId || !planId}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isAssigning ? 'Assigning…' : 'Assign Plan for Free'}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setSecret('');\n setBillingAccountId('');\n setPlanId('');\n setWorkspaceId('');\n setResult(null);\n }}\n className=\"px-4 py-2 text-sm border border-border-subtle rounded-md text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Clear\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlanAssignFreePage.js","names":[],"sources":["../../../../../src/billing/modules/plans/pages/PlanAssignFreePage.tsx"],"sourcesContent":["/**\n * Plans Module - Assign Plan Free (Admin only)\n *\n * Internal tool for assigning any plan to a billing account at no charge.\n * Protected by PLAN_ASSIGN_SECRET — only team members who know the secret\n * can use this page. Never expose to end users.\n *\n * Route: /billing/plans/assign-free\n */\n\nimport { useState, type FC, type FormEvent } from 'react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport { AccessDenied, PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { useAssignPlanFreeMutation } from '../../../../generated/global-operations';\nimport { usePlans } from '../hooks';\n\nexport const PlanAssignFreePage: 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\n const navigateTo = useBillingNavigate();\n const permissions = useBillingPermissions();\n\n const [secret, setSecret] = useState('');\n const [billingAccountId, setBillingAccountId] = useState('');\n const [planId, setPlanId] = useState('');\n const [workspaceId, setWorkspaceId] = useState('');\n const [result, setResult] = useState<{ success: boolean; message: string } | null>(null);\n\n // Fetch all plans (including non-purchasable internal ones) for the dropdown\n const { plans, isLoading: isPlansLoading } = usePlans({ includeFree: true });\n\n const [assignPlanFree, { loading: isAssigning }] = useAssignPlanFreeMutation();\n\n if (!permissions.canManagePlans) {\n return (\n <AccessDenied\n message={tr(\n 'billing.assignFree.noPermission',\n \"You don't have permission to access this page.\"\n )}\n />\n );\n }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setResult(null);\n\n if (!secret.trim() || !billingAccountId.trim() || !planId) {\n setResult({ success: false, message: 'All fields are required.' });\n return;\n }\n\n try {\n const { data } = await assignPlanFree({\n variables: {\n secret: secret.trim(),\n billingAccountId: billingAccountId.trim(),\n planId,\n ...(workspaceId.trim() ? { workspaceId: workspaceId.trim() } : {}),\n },\n });\n\n if (data?.assignPlanFree) {\n const sub = data.assignPlanFree;\n setResult({\n success: true,\n message: `Plan assigned. Subscription ID: ${sub.id} · Status: ${sub.status} · Valid: ${new Date(sub.startDate).toLocaleDateString()} → ${new Date(sub.endDate).toLocaleDateString()}`,\n });\n // Clear sensitive fields\n setSecret('');\n setBillingAccountId('');\n setPlanId('');\n setWorkspaceId('');\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : 'Failed to assign plan.';\n setResult({ success: false, message: msg });\n }\n };\n\n const selectedPlan = plans.find((p) => p.id === planId);\n\n return (\n <div className=\"space-y-6 p-6 max-w-2xl\">\n <PageHeader\n title={tr('billing.assignFree.title', 'Assign Plan for Free')}\n description={tr(\n 'billing.assignFree.description',\n 'Internally assign any plan to a billing account at no charge. Requires the team secret.'\n )}\n actions={\n <button\n type=\"button\"\n onClick={() => navigateTo('/plans')}\n className=\"px-3 py-2 text-sm border border-border-subtle rounded-md text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n ← Back to Plans\n </button>\n }\n />\n\n {/* Warning banner */}\n <div className=\"flex items-start gap-3 p-4 rounded-lg border border-status-warning-border bg-status-warning-bg/10\">\n <svg\n className=\"size-5 text-status-warning-text shrink-0 mt-0.5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.962-.833-2.732 0L3.072 16.5c-.77.833.192 2.5 1.732 2.5z\"\n />\n </svg>\n <div>\n <p className=\"text-sm font-medium text-status-warning-text\">Internal admin tool</p>\n <p className=\"text-xs text-status-warning-text/80 mt-0.5\">\n This bypasses all payment flows. The plan is assigned immediately with no charge. Use\n only for enterprise deals or internal accounts.\n </p>\n </div>\n </div>\n\n <form\n onSubmit={handleSubmit}\n className=\"border border-border-subtle rounded-card bg-bg-surface overflow-hidden shadow-[var(--shadow-elevation-1)]\"\n >\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken/30\">\n <h2 className=\"font-semibold text-text-primary\">Assignment Details</h2>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Secret */}\n <div>\n <label htmlFor=\"secret\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Team Secret <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"secret\"\n type=\"password\"\n value={secret}\n onChange={(e) => setSecret(e.target.value)}\n autoComplete=\"off\"\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono\"\n placeholder=\"Enter PLAN_ASSIGN_SECRET\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n The secret key shared within the team. Never expose this to users.\n </p>\n </div>\n\n {/* Billing Account ID */}\n <div>\n <label\n htmlFor=\"billingAccountId\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n Billing Account ID <span className=\"text-status-error-text\">*</span>\n </label>\n <input\n id=\"billingAccountId\"\n type=\"text\"\n value={billingAccountId}\n onChange={(e) => setBillingAccountId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] font-mono text-sm\"\n placeholder=\"e.g. ba_01jk3n2...\"\n required\n />\n <p className=\"text-xs text-text-muted mt-1\">\n Find this in the user's billing account settings or via the billing accounts list.\n </p>\n </div>\n\n {/* Workspace ID (optional — auto-resolved from org if omitted) */}\n <div>\n <label htmlFor=\"workspaceId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Workspace ID <span className=\"text-text-secondary font-normal\">(optional)</span>\n </label>\n <input\n id=\"workspaceId\"\n type=\"text\"\n value={workspaceId}\n onChange={(e) => setWorkspaceId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-md bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-primary font-mono text-sm\"\n placeholder=\"e.g. ws_01jk3n2… (leave blank to auto-resolve)\"\n />\n <p className=\"text-xs text-text-secondary mt-1\">\n If blank, the first active workspace for this org is used automatically. Set\n explicitly when the org has multiple workspaces.\n </p>\n </div>\n\n {/* Plan selector */}\n <div>\n <label htmlFor=\"planId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n Plan <span className=\"text-status-error-text\">*</span>\n </label>\n {isPlansLoading ? (\n <div className=\"h-10 bg-bg-sunken animate-pulse rounded-md\" />\n ) : (\n <select\n id=\"planId\"\n value={planId}\n onChange={(e) => setPlanId(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n required\n >\n <option value=\"\" disabled>\n Select a plan…\n </option>\n {plans.map((plan) => (\n <option key={plan.id} value={plan.id}>\n {plan.name}\n {!plan.isPurchasable ? ' (internal)' : ''}\n {plan.price != null && plan.price > 0\n ? ` — ${plan.currency ?? 'USD'} ${plan.price}`\n : ''}\n </option>\n ))}\n </select>\n )}\n {selectedPlan && (\n <p className=\"text-xs text-text-muted mt-1\">\n {selectedPlan.isPurchasable ? 'Public plan' : 'Internal / non-purchasable plan'}\n {selectedPlan.productID ? ` · Product: ${selectedPlan.productID}` : ''}\n </p>\n )}\n </div>\n </div>\n\n {/* Result banner */}\n {result && (\n <div\n className={`mx-4 mb-4 p-3 rounded-lg border text-sm ${\n result.success\n ? 'border-status-success-border bg-status-success-bg/10 text-status-success-text'\n : 'border-status-error-border bg-status-error-bg/10 text-status-error-text'\n }`}\n >\n {result.message}\n </div>\n )}\n\n <div className=\"px-4 pb-4 flex items-center gap-3\">\n <button\n type=\"submit\"\n disabled={isAssigning || !secret || !billingAccountId || !planId}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isAssigning ? 'Assigning…' : 'Assign Plan for Free'}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n setSecret('');\n setBillingAccountId('');\n setPlanId('');\n setWorkspaceId('');\n setResult(null);\n }}\n className=\"px-4 py-2 text-sm border border-border-subtle rounded-md text-text-primary hover:bg-bg-sunken transition-colors\"\n >\n Clear\n </button>\n </div>\n </form>\n </div>\n );\n};\n"],"mappings":"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"}
|