@burdenoff/microfe-billing 2026.624.1 → 2026.624.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +125 -150
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +146 -153
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js +164 -179
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/EarningsPage.js +229 -291
- package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +69 -74
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutsPage.js +142 -148
- package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/SettingsPage.js +125 -117
- package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +78 -66
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +68 -83
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.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
|
@@ -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-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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"}
|
|
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';\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n ResponsiveTable,\n type ResponsiveTableColumn,\n} from '@burdenoff/fe-libs/ui';\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\nconst payoutRequestColumns: ResponsiveTableColumn<PayoutRequest>[] = [\n {\n key: 'amount',\n header: 'Amount',\n priority: 'primary',\n cell: (request) => (\n <span className=\"tabular-nums\">\n {formatCurrency(request.requestedAmount, request.currency)}\n </span>\n ),\n },\n { key: 'provider', header: 'Provider', cell: (request) => request.provider },\n { key: 'status', header: 'Status', cell: (request) => request.status },\n {\n key: 'account',\n header: 'Account',\n cell: (request) => request.payoutAccount?.label || '-',\n },\n {\n key: 'created',\n header: 'Created',\n cell: (request) => formatDateTime(request.createdAt),\n },\n];\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 const [archiveAccountId, setArchiveAccountId] = 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 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={() => setArchiveAccountId(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 <ResponsiveTable\n data={requests}\n rowKey={(request) => request.id}\n columns={payoutRequestColumns}\n />\n )}\n </div>\n </section>\n </div>\n\n <AlertDialog\n open={archiveAccountId !== null}\n onOpenChange={(open) => {\n if (!open) setArchiveAccountId(null);\n }}\n >\n <AlertDialogContent>\n <AlertDialogHeader>\n <AlertDialogTitle>Archive payout account?</AlertDialogTitle>\n <AlertDialogDescription>\n Archive this payout account? You can add a new one at any time.\n </AlertDialogDescription>\n </AlertDialogHeader>\n <AlertDialogFooter>\n <AlertDialogCancel>Cancel</AlertDialogCancel>\n <AlertDialogAction\n onClick={() => {\n const id = archiveAccountId;\n setArchiveAccountId(null);\n if (id) void handleArchive(id);\n }}\n >\n Archive\n </AlertDialogAction>\n </AlertDialogFooter>\n </AlertDialogContent>\n </AlertDialog>\n </div>\n );\n};\n"],"mappings":"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"}
|