@burdenoff/microfe-billing 2026.526.1 → 2026.528.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/BillingAdminRoutes.js +1 -1
- package/dist/billing/BillingAdminRoutes.js.map +1 -1
- package/dist/billing/BillingUserRoutes.js +1 -1
- package/dist/billing/BillingUserRoutes.js.map +1 -1
- package/dist/billing/modules/addons/components/FloatingCartDrawer.js +15 -8
- package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +13 -6
- package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonCreatePage.js +1 -1
- package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonDetailPage.js +8 -4
- package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonEditPage.js +3 -2
- package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +44 -23
- package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
- package/dist/billing/modules/addons/pages/AddonsListPage.js +60 -31
- package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +9 -9
- package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
- package/dist/billing/modules/analytics/pages/AnalyticsPage.js +8 -8
- package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +16 -10
- package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/InvoicesListPage.js +24 -16
- package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +5 -1
- package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/RefundsPage.js +46 -29
- package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
- package/dist/billing/modules/billing/pages/TransactionsPage.js +34 -22
- package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
- package/dist/billing/modules/checkout/components/BillingAccountSelector.js +10 -10
- package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
- package/dist/billing/modules/checkout/components/CreditsAmountInput.js +3 -3
- package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
- package/dist/billing/modules/checkout/components/NativeCheckoutView.js +7 -0
- package/dist/billing/modules/checkout/components/NativeCheckoutView.js.map +1 -1
- package/dist/billing/modules/checkout/components/OrderSummary.js +13 -13
- package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
- package/dist/billing/modules/checkout/components/PromoCodeInput.js +5 -5
- package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
- package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
- package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
- package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +4 -4
- package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
- package/dist/billing/modules/checkout/components/StripePaymentForm.js +11 -11
- package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
- package/dist/billing/modules/checkout/components/SubscriptionSelector.js +3 -3
- package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
- package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +8 -8
- package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
- package/dist/billing/modules/checkout/pages/CheckoutPage.js +61 -52
- package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js +22 -15
- package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CouponsListPage.js +30 -21
- package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js +9 -8
- package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
- package/dist/billing/modules/coupons/pages/EditCouponPage.js +11 -8
- package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/AdminCreditsPage.js +1 -1
- package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +22 -17
- package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +15 -8
- package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
- package/dist/billing/modules/credits/pages/CreditsPage.js +17 -11
- package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
- package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +15 -11
- package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +21 -17
- package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
- package/dist/billing/modules/dashboard/components/BillingAccountCard.js +14 -11
- package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
- package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +32 -26
- package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
- package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +14 -10
- package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +18 -11
- package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
- package/dist/billing/modules/dashboard/pages/OverviewPage.js +44 -32
- package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js +35 -26
- package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/EarningsPage.js +15 -15
- package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +11 -11
- package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
- package/dist/billing/modules/earnings/pages/PayoutsPage.js +5 -5
- package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +9 -4
- package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanCreatePage.js +1 -1
- package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanDetailPage.js +13 -8
- package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlanEditPage.js +3 -2
- package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js +14 -7
- package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
- package/dist/billing/modules/plans/pages/PlansListPage.js +23 -9
- package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaPage.js +11 -7
- package/dist/billing/modules/quota/pages/QuotaPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +3 -3
- package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +6 -2
- package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +5 -4
- package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +26 -12
- package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/SettingsPage.js +356 -349
- package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +157 -123
- package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +13 -8
- package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +15 -7
- package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +30 -20
- package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +25 -16
- package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
- package/dist/billing/modules/usage/pages/UsagePage.js +50 -34
- package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
- package/dist/billing/shared/components/AccessDenied.js +2 -2
- package/dist/billing/shared/components/AccessDenied.js.map +1 -1
- package/dist/billing/shared/components/ActorIdentity.js +67 -0
- package/dist/billing/shared/components/ActorIdentity.js.map +1 -0
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js +6 -2
- package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js.map +1 -1
- package/dist/billing/shared/components/EmptyState.js +7 -21
- package/dist/billing/shared/components/EmptyState.js.map +1 -1
- package/dist/billing/shared/components/PageHeader.js +7 -19
- package/dist/billing/shared/components/PageHeader.js.map +1 -1
- package/dist/billing/shared/components/ServerError.js +5 -4
- package/dist/billing/shared/components/ServerError.js.map +1 -1
- package/dist/billing/shared/components/index.js +1 -0
- package/dist/billing/shared/hooks/index.js +1 -0
- package/dist/billing/shared/hooks/useActorProfiles.js +113 -0
- package/dist/billing/shared/hooks/useActorProfiles.js.map +1 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/RefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - Refunds Page\n * Admin page for managing refund records\n */\n\nimport { useState, useRef, useEffect, useMemo, useCallback, type FC } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n RefreshCw,\n Plus,\n MoreHorizontal,\n Eye,\n Play,\n SkipForward,\n RotateCcw,\n ChevronLeft,\n ChevronRight,\n X,\n Search,\n Filter,\n AlertTriangle,\n CheckCircle,\n Clock,\n XCircle,\n Loader2,\n Ban,\n Download,\n // Calendar - available but not currently used\n} from 'lucide-react';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport {\n useRefunds,\n type RefundRecord,\n type RefundRecordStatus,\n type RefundSource,\n type RefundRecordFilters,\n} from '../hooks';\nimport {\n GetTransactionDocument,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { AccessDenied, PageHeader, EmptyState, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; color: string; icon: FC<{ className?: string }> }\n> = {\n PENDING: { label: 'Pending', color: 'yellow', icon: Clock },\n PROCESSING: { label: 'Processing', color: 'blue', icon: Loader2 },\n COMPLETED: { label: 'Completed', color: 'green', icon: CheckCircle },\n FAILED: { label: 'Failed', color: 'red', icon: XCircle },\n SKIPPED: { label: 'Skipped', color: 'gray', icon: Ban },\n};\n\nconst SOURCE_LABELS: Record<RefundSource, string> = {\n MANUAL: 'Manual',\n WEBHOOK_RECOVERY: 'Webhook Recovery',\n SUBSCRIPTION_CANCEL: 'Subscription Cancel',\n DUPLICATE_PAYMENT: 'Duplicate Payment',\n};\n\nconst PROVIDER_OPTIONS = ['stripe', 'razorpay'];\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\nconst getStatusBadgeClasses = (color: string): string => {\n const classes: Record<string, string> = {\n yellow: `${statusTokens.warning.bg} ${statusTokens.warning.text}`,\n blue: `${statusTokens.info.bg} ${statusTokens.info.text}`,\n green: `${statusTokens.success.bg} ${statusTokens.success.text}`,\n red: `${statusTokens.error.bg} ${statusTokens.error.text}`,\n gray: `${statusTokens.neutral.bg} ${statusTokens.neutral.text}`,\n };\n return classes[color] || classes.gray;\n};\n\n// Actions Dropdown\ninterface RefundActionsDropdownProps {\n record: RefundRecord;\n onViewDetails: () => void;\n onProcess: () => void;\n onSkip: () => void;\n onRetry: () => void;\n isProcessing: boolean;\n}\n\nconst RefundActionsDropdown: FC<RefundActionsDropdownProps> = ({\n record,\n onViewDetails,\n onProcess,\n onSkip,\n onRetry,\n isProcessing,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n const canProcess = record.status === 'PENDING';\n const canSkip = record.status === 'PENDING';\n const canRetry = record.status === 'FAILED';\n\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <button\n onClick={() => setIsOpen(!isOpen)}\n disabled={isProcessing}\n className=\"p-1.5 rounded-md hover:bg-muted/50 transition-colors disabled:opacity-50\"\n aria-label=\"Refund actions\"\n >\n {isProcessing ? (\n <Loader2 className=\"w-4 h-4 animate-spin text-muted-foreground\" />\n ) : (\n <MoreHorizontal className=\"w-4 h-4 text-muted-foreground\" />\n )}\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-popover border border-border rounded-md shadow-lg py-1\">\n <button\n onClick={() => {\n onViewDetails();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted/50 transition-colors\"\n >\n <Eye className=\"w-4 h-4\" />\n View Details\n </button>\n\n {canProcess && (\n <button\n onClick={() => {\n onProcess();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.success.text} hover:bg-muted/50 transition-colors`}\n >\n <Play className=\"w-4 h-4\" />\n Process Refund\n </button>\n )}\n\n {canSkip && (\n <button\n onClick={() => {\n onSkip();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.warning.text} hover:bg-muted/50 transition-colors`}\n >\n <SkipForward className=\"w-4 h-4\" />\n Skip Refund\n </button>\n )}\n\n {canRetry && (\n <button\n onClick={() => {\n onRetry();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.info.text} hover:bg-muted/50 transition-colors`}\n >\n <RotateCcw className=\"w-4 h-4\" />\n Retry Refund\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// Create Refund Modal\ninterface CreateRefundModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (data: CreateRefundFormData) => Promise<void>;\n isSubmitting: boolean;\n}\n\ninterface CreateRefundFormData {\n billingAccountId?: string;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId?: string;\n amount: number;\n currency: string;\n purchaseType?: string;\n purchaseDetail?: string;\n reason?: string;\n notes?: string;\n transactionId?: string;\n}\n\ninterface LookedUpTransaction {\n id: string;\n billingAccountId: string;\n amount: number;\n totalAmount: number; // amount + tax (what was actually charged)\n currency: string;\n description: string | null;\n razorpayPaymentId: string | null;\n stripePaymentId: string | null;\n metadata: Record<string, unknown> | null;\n}\n\nconst EMPTY_FORM: CreateRefundFormData = {\n provider: 'stripe',\n gatewayPaymentId: '',\n amount: 0,\n currency: 'USD',\n};\n\nconst CreateRefundModal: FC<CreateRefundModalProps> = ({\n isOpen,\n onClose,\n onSubmit,\n isSubmitting,\n}) => {\n const client = useApolloClient();\n const [transactionId, setTransactionId] = useState('');\n const [lookedUp, setLookedUp] = useState<LookedUpTransaction | null>(null);\n const [lookupError, setLookupError] = useState<string | null>(null);\n const [isLookingUp, setIsLookingUp] = useState(false);\n const [formData, setFormData] = useState<CreateRefundFormData>(EMPTY_FORM);\n\n const reset = () => {\n setTransactionId('');\n setLookedUp(null);\n setLookupError(null);\n setFormData(EMPTY_FORM);\n };\n\n const handleClose = () => {\n reset();\n onClose();\n };\n\n const lookupTransaction = useCallback(\n async (id: string) => {\n const trimmed = id.trim();\n if (!trimmed) return;\n setIsLookingUp(true);\n setLookupError(null);\n setLookedUp(null);\n try {\n const { data } = await client.query<GetTransactionQuery>({\n query: GetTransactionDocument,\n variables: { id: trimmed },\n fetchPolicy: 'network-only',\n });\n const txn = data?.getTransaction ?? null;\n if (!txn) {\n setLookupError('Transaction not found. Check the ID and try again.');\n setFormData(EMPTY_FORM);\n return;\n }\n const meta = txn.metadata as Record<string, unknown> | null;\n const totalAmount = typeof meta?.total === 'number' ? meta.total : txn.amount;\n const lookedUpWithTotal: LookedUpTransaction = {\n id: txn.id,\n billingAccountId: txn.billingAccountId,\n amount: txn.amount,\n totalAmount,\n currency: txn.currency,\n description: txn.description ?? null,\n razorpayPaymentId: txn.razorpayPaymentId ?? null,\n stripePaymentId: txn.stripePaymentId ?? null,\n metadata: txn.metadata ?? null,\n };\n setLookedUp(lookedUpWithTotal);\n const provider = txn.razorpayPaymentId ? 'razorpay' : 'stripe';\n const gatewayPaymentId = txn.razorpayPaymentId ?? txn.stripePaymentId ?? '';\n const purchaseType = (meta?.purchaseType as string) ?? '';\n const purchaseDetail = txn.description ?? '';\n setFormData({\n transactionId: txn.id,\n billingAccountId: txn.billingAccountId,\n provider,\n gatewayPaymentId,\n currency: txn.currency,\n amount: totalAmount,\n purchaseType,\n purchaseDetail,\n reason: '',\n notes: '',\n });\n } catch {\n setLookupError('Failed to look up transaction. Ensure the ID is correct.');\n setFormData(EMPTY_FORM);\n } finally {\n setIsLookingUp(false);\n }\n },\n [client]\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n await onSubmit(formData);\n reset();\n };\n\n if (!isOpen) return null;\n\n const maxAmount = lookedUp?.totalAmount ?? undefined;\n const isAmountExceedingMax = maxAmount !== undefined && formData.amount > maxAmount + 0.01;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={handleClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Create Manual Refund</h2>\n <button\n onClick={handleClose}\n className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\"\n >\n <X className=\"w-5 h-5\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {/* Step 1: Transaction ID lookup */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">Transaction ID *</label>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={transactionId}\n onChange={(e) => {\n setTransactionId(e.target.value);\n setLookedUp(null);\n setLookupError(null);\n }}\n onBlur={() => lookupTransaction(transactionId)}\n className=\"flex-1 px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Paste transaction UUID...\"\n required\n />\n <button\n type=\"button\"\n onClick={() => lookupTransaction(transactionId)}\n disabled={!transactionId.trim() || isLookingUp}\n className=\"px-3 py-2 border border-border rounded-md hover:bg-muted/50 transition-colors disabled:opacity-50 flex items-center gap-1 text-sm\"\n >\n {isLookingUp ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Search className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n {lookupError && <p className=\"text-xs text-status-error-text mt-1\">{lookupError}</p>}\n {isLookingUp && (\n <p className=\"text-xs text-muted-foreground mt-1\">Looking up transaction...</p>\n )}\n </div>\n\n {/* Auto-filled fields — shown once transaction is found */}\n {lookedUp && (\n <>\n {/* Transaction summary banner */}\n <div className=\"p-3 bg-status-success-bg-subtle border border-border-subtle rounded-md text-sm space-y-1\">\n <div className=\"flex items-center gap-2 text-status-success-text font-medium\">\n <CheckCircle className=\"w-4 h-4\" />\n Transaction found\n </div>\n <div className=\"text-muted-foreground grid grid-cols-2 gap-x-4 gap-y-0.5 mt-1\">\n <span>\n Account:{' '}\n <span className=\"text-foreground font-mono text-xs\">\n {lookedUp.billingAccountId.slice(0, 16)}…\n </span>\n </span>\n <span>\n Paid:{' '}\n <span className=\"text-foreground\">\n {formatCurrency(lookedUp.totalAmount, lookedUp.currency)}\n </span>\n </span>\n <span>\n Provider:{' '}\n <span className=\"text-foreground capitalize\">{formData.provider}</span>\n </span>\n <span>\n Currency: <span className=\"text-foreground\">{lookedUp.currency}</span>\n </span>\n </div>\n </div>\n\n {/* Read-only auto-filled fields */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Provider\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm capitalize\">\n {formData.provider}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Currency\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm\">\n {formData.currency}\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Gateway Payment ID\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm font-mono truncate\">\n {formData.gatewayPaymentId}\n </div>\n </div>\n\n {formData.purchaseType && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Purchase Type\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm\">\n {formData.purchaseType}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Purchase Detail\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm truncate\">\n {formData.purchaseDetail || '—'}\n </div>\n </div>\n </div>\n )}\n\n {/* Editable: Amount (capped at transaction amount) */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Refund Amount *\n <span className=\"text-xs text-muted-foreground ml-1\">\n (max {formatCurrency(maxAmount!, formData.currency)})\n </span>\n </label>\n <input\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={maxAmount}\n value={formData.amount}\n onChange={(e) =>\n setFormData({ ...formData, amount: parseFloat(e.target.value) || 0 })\n }\n className={`w-full px-3 py-2 border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary ${\n isAmountExceedingMax ? 'border-status-error-text' : 'border-border'\n }`}\n required\n />\n {isAmountExceedingMax && (\n <p className=\"text-xs text-status-error-text mt-1\">\n Amount cannot exceed the original payment of{' '}\n {formatCurrency(maxAmount!, formData.currency)}\n </p>\n )}\n </div>\n\n {/* Editable: Reason & Notes */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">Reason</label>\n <input\n type=\"text\"\n value={formData.reason || ''}\n onChange={(e) => setFormData({ ...formData, reason: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Reason for refund\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Notes</label>\n <textarea\n value={formData.notes || ''}\n onChange={(e) => setFormData({ ...formData, notes: 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 resize-none\"\n rows={2}\n placeholder=\"Internal notes\"\n />\n </div>\n </>\n )}\n\n <div className=\"flex gap-2 pt-2\">\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"flex-1 py-2 px-4 border border-border rounded-md hover:bg-muted/50 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={\n isSubmitting ||\n !lookedUp ||\n !formData.gatewayPaymentId ||\n formData.amount <= 0 ||\n isAmountExceedingMax\n }\n className=\"flex-1 py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n >\n {isSubmitting && <Loader2 className=\"w-4 h-4 animate-spin\" />}\n Create Refund\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\n// Skip Refund Modal\ninterface SkipRefundModalProps {\n isOpen: boolean;\n record: RefundRecord | null;\n onClose: () => void;\n onSubmit: (reason: string) => Promise<void>;\n isSubmitting: boolean;\n}\n\nconst SkipRefundModal: FC<SkipRefundModalProps> = ({\n isOpen,\n record,\n onClose,\n onSubmit,\n isSubmitting,\n}) => {\n const [reason, setReason] = useState('');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n await onSubmit(reason);\n setReason('');\n };\n\n if (!isOpen || !record) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={onClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-md w-full mx-4\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Skip Refund</h2>\n <button onClick={onClose} className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\">\n <X className=\"w-5 h-5\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n <div\n className={`p-3 ${statusTokens.warning.bg} border ${statusTokens.warning.border} rounded-md`}\n >\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className={`w-5 h-5 ${statusTokens.warning.icon} mt-0.5`} />\n <div>\n <p className={`text-sm font-medium ${statusTokens.warning.text}`}>\n You are about to skip this refund\n </p>\n <p className={`text-sm ${statusTokens.warning.text} mt-1`}>\n Amount: {formatCurrency(record.amount, record.currency)}\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Reason for skipping *</label>\n <textarea\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background resize-none\"\n rows={3}\n placeholder=\"Explain why this refund is being skipped...\"\n required\n />\n </div>\n\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"flex-1 py-2 px-4 border border-border rounded-md hover:bg-muted/50 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting || !reason.trim()}\n className={`flex-1 py-2 px-4 ${statusTokens.warning.dot} text-primary-foreground rounded-md hover:opacity-90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2`}\n >\n {isSubmitting && <Loader2 className=\"w-4 h-4 animate-spin\" />}\n Skip Refund\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\n// Refund Details Modal\ninterface RefundDetailsModalProps {\n record: RefundRecord | null;\n onClose: () => void;\n}\n\nconst RefundDetailsModal: FC<RefundDetailsModalProps> = ({ record, onClose }) => {\n if (!record) return null;\n\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={onClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Refund Details</h2>\n <button onClick={onClose} className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\">\n <X className=\"w-5 h-5\" />\n </button>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Status Banner */}\n <div\n className={`flex items-center gap-2 p-3 rounded-md ${getStatusBadgeClasses(STATUS_CONFIG[record.status].color)}`}\n >\n <StatusIcon className=\"w-5 h-5\" />\n <span className=\"font-medium\">{STATUS_CONFIG[record.status].label}</span>\n </div>\n\n {/* Basic Info */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Refund ID</p>\n <p className=\"text-sm font-mono break-all\">{record.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Source</p>\n <p className=\"text-sm\">{SOURCE_LABELS[record.source]}</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Amount</p>\n <p className=\"text-lg font-semibold\">\n {formatCurrency(record.amount, record.currency)}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Provider</p>\n <p className=\"text-sm capitalize\">{record.provider}</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayPaymentId}</p>\n </div>\n {record.gatewayOrderId && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Order ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayOrderId}</p>\n </div>\n )}\n </div>\n\n {record.gatewayRefundId && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Refund ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayRefundId}</p>\n </div>\n )}\n\n {(record.purchaseType || record.purchaseDetail) && (\n <div className=\"grid grid-cols-2 gap-4\">\n {record.purchaseType && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Purchase Type</p>\n <p className=\"text-sm\">{record.purchaseType}</p>\n </div>\n )}\n {record.purchaseDetail && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Purchase Detail</p>\n <p className=\"text-sm\">{record.purchaseDetail}</p>\n </div>\n )}\n </div>\n )}\n\n {record.reason && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Reason</p>\n <p className=\"text-sm\">{record.reason}</p>\n </div>\n )}\n\n {record.notes && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Notes</p>\n <p className=\"text-sm\">{record.notes}</p>\n </div>\n )}\n\n {record.errorMessage && (\n <div\n className={`p-3 ${statusTokens.error.bg} border ${statusTokens.error.border} rounded-md`}\n >\n <p className={`text-xs ${statusTokens.error.text} mb-1`}>Error Message</p>\n <p className={`text-sm ${statusTokens.error.text}`}>{record.errorMessage}</p>\n </div>\n )}\n\n <div className=\"grid grid-cols-2 gap-4 pt-2 border-t border-border\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Created At</p>\n <p className=\"text-sm\">{formatDateTime(record.createdAt)}</p>\n </div>\n {record.processedAt && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Processed At</p>\n <p className=\"text-sm\">{formatDateTime(record.processedAt)}</p>\n </div>\n )}\n </div>\n\n {record.retryCount > 0 && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Retry Count</p>\n <p className=\"text-sm\">{record.retryCount}</p>\n </div>\n )}\n </div>\n\n <div className=\"p-4 border-t border-border\">\n <button\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\ntype TabStatus = 'PENDING' | 'COMPLETED' | 'FAILED' | 'ALL';\n\nconst TAB_CONFIG: Record<TabStatus, { label: string; status?: RefundRecordStatus }> = {\n PENDING: { label: 'Pending', status: 'PENDING' },\n COMPLETED: { label: 'Completed', status: 'COMPLETED' },\n FAILED: { label: 'Failed', status: 'FAILED' },\n ALL: { label: 'All', status: undefined },\n};\n\nexport const RefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const permissions = useBillingPermissions();\n\n // State\n const [activeTab, setActiveTab] = useState<TabStatus>('PENDING');\n const [searchQuery, setSearchQuery] = useState('');\n const [filters, setFilters] = useState<RefundRecordFilters>({});\n const [showFilters, setShowFilters] = useState(false);\n const [selectedRecord, setSelectedRecord] = useState<RefundRecord | null>(null);\n const [showCreateModal, setShowCreateModal] = useState(false);\n const [showSkipModal, setShowSkipModal] = useState(false);\n const [recordToSkip, setRecordToSkip] = useState<RefundRecord | null>(null);\n const [actionLoadingId, setActionLoadingId] = useState<string | null>(null);\n\n // Build filters based on active tab - memoized to prevent infinite re-render loop\n // (useRefundRecords has a useEffect on options.filters, so a new object every render would cause\n // infinite updates if tabFilters were not stable)\n const tabFilters = useMemo<RefundRecordFilters>(\n () => ({\n ...filters,\n status: TAB_CONFIG[activeTab].status,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- filters is an object; spread ensures correct deps\n [\n activeTab,\n filters.source,\n filters.provider,\n filters.billingAccountId,\n filters.fromDate,\n filters.toDate,\n ]\n );\n\n // Data hooks - filters automatically applied based on active tab\n const {\n records,\n stats,\n pagination,\n isLoading,\n recordsError,\n unprocessedWebhooks,\n refetch,\n goToNextPage,\n goToPreviousPage,\n setFilters: updateFilters,\n createRefundRecord,\n processRefund,\n skipRefund,\n retryRefund,\n createRefundRecordsFromFailedWebhooks,\n isCreating,\n isProcessing,\n isCreatingFromWebhooks,\n } = useRefunds({ filters: tabFilters });\n\n // Permission check\n if (!permissions.canViewPayments) {\n return <AccessDenied message=\"You don't have permission to view refunds.\" />;\n }\n\n // Error handling\n if (recordsError && isServerError(recordsError)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title=\"Server Unavailable\"\n message=\"Unable to load refunds. The server might be down or experiencing issues.\"\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n // Handlers\n const handleTabChange = (tab: TabStatus) => {\n setActiveTab(tab);\n // Reset filters when changing tabs\n setFilters({});\n setSearchQuery('');\n };\n\n const handleFilterChange = (key: keyof RefundRecordFilters, value: string | undefined) => {\n // Don't allow status filter changes as tabs control status\n if (key === 'status') return;\n\n const newFilters = { ...filters, [key]: value || undefined };\n setFilters(newFilters);\n updateFilters({ ...newFilters, status: TAB_CONFIG[activeTab].status });\n };\n\n const handleCreateRefund = async (data: CreateRefundFormData) => {\n try {\n await createRefundRecord(data);\n setShowCreateModal(false);\n } catch (error) {\n console.error('Failed to create refund:', error);\n }\n };\n\n const handleProcess = async (record: RefundRecord) => {\n setActionLoadingId(record.id);\n try {\n const result = await processRefund(record.id);\n if (!result.success && result.error) {\n console.error('Refund processing failed:', result.error);\n }\n } catch (error) {\n console.error('Failed to process refund:', error);\n } finally {\n setActionLoadingId(null);\n }\n };\n\n const handleSkip = async (reason: string) => {\n if (!recordToSkip) return;\n try {\n await skipRefund(recordToSkip.id, reason);\n setShowSkipModal(false);\n setRecordToSkip(null);\n } catch (error) {\n console.error('Failed to skip refund:', error);\n }\n };\n\n const handleRetry = async (record: RefundRecord) => {\n setActionLoadingId(record.id);\n try {\n const result = await retryRefund(record.id);\n if (!result.success && result.error) {\n console.error('Refund retry failed:', result.error);\n }\n } catch (error) {\n console.error('Failed to retry refund:', error);\n } finally {\n setActionLoadingId(null);\n }\n };\n\n const handleCreateFromWebhooks = async () => {\n try {\n await createRefundRecordsFromFailedWebhooks();\n } catch (error) {\n console.error('Failed to create refunds from webhooks:', error);\n }\n };\n\n // Filter records by search query (client-side)\n const filteredRecords = searchQuery\n ? records.filter(\n (r) =>\n r.gatewayPaymentId.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.gatewayOrderId?.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.reason?.toLowerCase().includes(searchQuery.toLowerCase())\n )\n : records;\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"grid grid-cols-5 gap-4\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-24 bg-muted animate-pulse rounded-lg\" />\n ))}\n </div>\n <div className=\"space-y-2\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-16 bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refund Management')}\n description=\"View and manage refund records\"\n actions={\n <div className=\"flex items-center gap-2\">\n {unprocessedWebhooks.length > 0 && (\n <button\n onClick={handleCreateFromWebhooks}\n disabled={isCreatingFromWebhooks}\n className={`inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border ${statusTokens.warning.border} ${statusTokens.warning.bg} ${statusTokens.warning.text} hover:opacity-90 transition-colors disabled:opacity-50`}\n >\n {isCreatingFromWebhooks ? (\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n ) : (\n <Download className=\"w-4 h-4\" />\n )}\n Import {unprocessedWebhooks.length} Failed Webhooks\n </button>\n )}\n <button\n onClick={() => refetch()}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 transition-colors\"\n >\n <RefreshCw className=\"w-4 h-4\" />\n Refresh\n </button>\n <button\n onClick={() => setShowCreateModal(true)}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus className=\"w-4 h-4\" />\n Create Manual Refund\n </button>\n </div>\n }\n />\n\n {/* Tabs Navigation */}\n <div className=\"border-b border-border\">\n <div className=\"flex flex-wrap gap-2 sm:gap-0\">\n {(Object.keys(TAB_CONFIG) as TabStatus[]).map((tab) => {\n const isActive = activeTab === tab;\n const count = stats\n ? tab === 'PENDING'\n ? stats.pending\n : tab === 'COMPLETED'\n ? stats.completed\n : tab === 'FAILED'\n ? stats.failed\n : stats.pending +\n stats.processing +\n stats.completed +\n stats.failed +\n stats.skipped\n : 0;\n\n return (\n <button\n key={tab}\n onClick={() => handleTabChange(tab)}\n className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? 'border-primary text-primary'\n : 'border-transparent text-muted-foreground hover:text-foreground hover:border-border'\n }`}\n >\n {TAB_CONFIG[tab].label}\n {stats && (\n <span\n className={`px-2 py-0.5 text-xs rounded-full ${\n isActive ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'\n }`}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-col sm:flex-row gap-4\">\n {/* Search */}\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\n <input\n type=\"text\"\n placeholder=\"Search by payment ID, order ID, or reason...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 border border-border rounded-md bg-background\"\n />\n </div>\n\n {/* Filter Toggle */}\n <button\n onClick={() => setShowFilters(!showFilters)}\n className={`inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border transition-colors ${\n showFilters\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border bg-background hover:bg-muted/50'\n }`}\n >\n <Filter className=\"w-4 h-4\" />\n Filters\n {Object.values(filters).filter(Boolean).length > 0 && (\n <span className=\"px-1.5 py-0.5 text-xs rounded-full bg-primary text-primary-foreground\">\n {Object.values(filters).filter(Boolean).length}\n </span>\n )}\n </button>\n\n {/* Clear Filters */}\n {Object.values(filters).filter(Boolean).length > 0 && (\n <button\n onClick={() => {\n setFilters({});\n updateFilters({});\n }}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md text-muted-foreground hover:text-foreground transition-colors\"\n >\n <X className=\"w-4 h-4\" />\n Clear\n </button>\n )}\n </div>\n\n {/* Expanded Filters */}\n {showFilters && (\n <div className=\"p-4 border border-border rounded-lg bg-muted/30 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">Source</label>\n <select\n value={filters.source || ''}\n onChange={(e) => handleFilterChange('source', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n >\n <option value=\"\">All Sources</option>\n {Object.entries(SOURCE_LABELS).map(([key, label]) => (\n <option key={key} value={key}>\n {label}\n </option>\n ))}\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Provider</label>\n <select\n value={filters.provider || ''}\n onChange={(e) => handleFilterChange('provider', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n >\n <option value=\"\">All Providers</option>\n {PROVIDER_OPTIONS.map((p) => (\n <option key={p} value={p}>\n {p.charAt(0).toUpperCase() + p.slice(1)}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"sm:col-span-2 lg:col-span-1\">\n <label className=\"block text-sm font-medium mb-1\">Date Range</label>\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center gap-2\">\n <input\n type=\"date\"\n value={filters.fromDate ? filters.fromDate.split('T')[0] : ''}\n onChange={(e) =>\n handleFilterChange(\n 'fromDate',\n e.target.value ? new Date(e.target.value).toISOString() : undefined\n )\n }\n className=\"w-full sm:flex-1 px-2 py-2 border border-border rounded-md bg-background text-sm\"\n />\n <span className=\"text-muted-foreground hidden sm:inline\">-</span>\n <input\n type=\"date\"\n value={filters.toDate ? filters.toDate.split('T')[0] : ''}\n onChange={(e) =>\n handleFilterChange(\n 'toDate',\n e.target.value ? new Date(e.target.value).toISOString() : undefined\n )\n }\n className=\"w-full sm:flex-1 px-2 py-2 border border-border rounded-md bg-background text-sm\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Table */}\n {filteredRecords.length === 0 ? (\n <EmptyState\n icon={<RefreshCw className=\"w-6 h-6 text-muted-foreground\" />}\n title=\"No refund records found\"\n description={\n Object.values(filters).filter(Boolean).length > 0\n ? 'Try adjusting your filters.'\n : activeTab === 'PENDING'\n ? 'No pending refunds to process.'\n : 'Refund records will appear here when created.'\n }\n />\n ) : (\n <div className=\"border border-border rounded-lg overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[400px]\">\n <thead className=\"bg-muted/50\">\n <tr>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Date\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Status\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden sm:table-cell\">\n Source\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden md:table-cell\">\n Provider\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Payment ID\n </th>\n <th className=\"text-right text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Amount\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden lg:table-cell\">\n Reason\n </th>\n <th className=\"px-2 py-2 w-10\"></th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {filteredRecords.map((record) => {\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n return (\n <tr key={record.id} className=\"hover:bg-muted/30 transition-colors\">\n <td className=\"px-3 py-2 text-sm text-foreground whitespace-nowrap\">\n <div className=\"flex flex-col\">\n <span>{formatDateTime(record.createdAt).split(' ')[0]}</span>\n <span className=\"text-xs text-muted-foreground\">\n {formatDateTime(record.createdAt).split(' ')[1]}\n </span>\n </div>\n </td>\n <td className=\"px-3 py-2 whitespace-nowrap\">\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n STATUS_CONFIG[record.status].color\n )}`}\n >\n <StatusIcon className=\"w-3 h-3\" />\n <span className=\"hidden sm:inline\">\n {STATUS_CONFIG[record.status].label}\n </span>\n </span>\n </td>\n <td className=\"px-3 py-2 text-sm text-muted-foreground whitespace-nowrap hidden sm:table-cell\">\n {SOURCE_LABELS[record.source]}\n </td>\n <td className=\"px-3 py-2 text-sm text-foreground capitalize whitespace-nowrap hidden md:table-cell\">\n {record.provider}\n </td>\n <td className=\"px-3 py-2 text-sm font-mono text-muted-foreground whitespace-nowrap max-w-[120px] sm:max-w-[200px] truncate\">\n {record.gatewayPaymentId}\n </td>\n <td className=\"px-3 py-2 text-sm text-right font-medium whitespace-nowrap\">\n {formatCurrency(record.amount, record.currency)}\n </td>\n <td className=\"px-3 py-2 text-sm text-muted-foreground max-w-[200px] truncate hidden lg:table-cell\">\n {record.reason || '-'}\n </td>\n <td className=\"px-2 py-2 text-center\">\n <RefundActionsDropdown\n record={record}\n onViewDetails={() => setSelectedRecord(record)}\n onProcess={() => handleProcess(record)}\n onSkip={() => {\n setRecordToSkip(record);\n setShowSkipModal(true);\n }}\n onRetry={() => handleRetry(record)}\n isProcessing={actionLoadingId === record.id}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {/* Pagination */}\n {pagination.totalCount > 0 && (\n <div className=\"flex flex-col sm:flex-row items-center justify-between gap-4 border-t border-border pt-4\">\n <p className=\"text-sm text-muted-foreground text-center sm:text-left\">\n Showing {pagination.page * pagination.pageSize + 1} to{' '}\n {Math.min((pagination.page + 1) * pagination.pageSize, pagination.totalCount)} of{' '}\n {pagination.totalCount} refunds\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n onClick={goToPreviousPage}\n disabled={!pagination.hasPrevious}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <ChevronLeft className=\"w-4 h-4\" />\n <span className=\"hidden sm:inline\">Previous</span>\n </button>\n <span className=\"text-sm text-muted-foreground px-2\">\n <span className=\"hidden sm:inline\">Page </span>\n {pagination.page + 1} <span className=\"hidden sm:inline\">of</span>\n <span className=\"sm:hidden\">/</span>{' '}\n {Math.ceil(pagination.totalCount / pagination.pageSize)}\n </span>\n <button\n onClick={goToNextPage}\n disabled={!pagination.hasMore}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <span className=\"hidden sm:inline\">Next</span>\n <ChevronRight className=\"w-4 h-4\" />\n </button>\n </div>\n </div>\n )}\n\n {/* Modals */}\n <CreateRefundModal\n isOpen={showCreateModal}\n onClose={() => setShowCreateModal(false)}\n onSubmit={handleCreateRefund}\n isSubmitting={isCreating}\n />\n\n <SkipRefundModal\n isOpen={showSkipModal}\n record={recordToSkip}\n onClose={() => {\n setShowSkipModal(false);\n setRecordToSkip(null);\n }}\n onSubmit={handleSkip}\n isSubmitting={isProcessing}\n />\n\n <RefundDetailsModal record={selectedRecord} onClose={() => setSelectedRecord(null)} />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/RefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - Refunds Page\n * Admin page for managing refund records\n */\n\nimport { useState, useRef, useEffect, useMemo, useCallback, type FC } from 'react';\nimport { useApolloClient } from '@apollo/client/react';\nimport {\n RefreshCw,\n Plus,\n MoreHorizontal,\n Eye,\n Play,\n SkipForward,\n RotateCcw,\n ChevronLeft,\n ChevronRight,\n X,\n Search,\n Filter,\n AlertTriangle,\n CheckCircle,\n Clock,\n XCircle,\n Loader2,\n Ban,\n Download,\n // Calendar - available but not currently used\n} from 'lucide-react';\nimport { useBillingPermissions } from '../../../hooks/useBillingPermissions';\nimport {\n useRefunds,\n type RefundRecord,\n type RefundRecordStatus,\n type RefundSource,\n type RefundRecordFilters,\n} from '../hooks';\nimport {\n GetTransactionDocument,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { AccessDenied, PageHeader, EmptyState, ServerError } from '../../../shared/components';\nimport { formatCurrency, formatDateTime, isServerError } from '../../../shared/utils';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; color: string; icon: FC<{ className?: string }> }\n> = {\n PENDING: { label: 'Pending', color: 'yellow', icon: Clock },\n PROCESSING: { label: 'Processing', color: 'blue', icon: Loader2 },\n COMPLETED: { label: 'Completed', color: 'green', icon: CheckCircle },\n FAILED: { label: 'Failed', color: 'red', icon: XCircle },\n SKIPPED: { label: 'Skipped', color: 'gray', icon: Ban },\n};\n\nconst SOURCE_LABELS: Record<RefundSource, string> = {\n MANUAL: 'Manual',\n WEBHOOK_RECOVERY: 'Webhook Recovery',\n SUBSCRIPTION_CANCEL: 'Subscription Cancel',\n DUPLICATE_PAYMENT: 'Duplicate Payment',\n};\n\nconst PROVIDER_OPTIONS = ['stripe', 'razorpay'];\n\n// ============================================================================\n// Helper Components\n// ============================================================================\n\nconst getStatusBadgeClasses = (color: string): string => {\n const classes: Record<string, string> = {\n yellow: `${statusTokens.warning.bg} ${statusTokens.warning.text}`,\n blue: `${statusTokens.info.bg} ${statusTokens.info.text}`,\n green: `${statusTokens.success.bg} ${statusTokens.success.text}`,\n red: `${statusTokens.error.bg} ${statusTokens.error.text}`,\n gray: `${statusTokens.neutral.bg} ${statusTokens.neutral.text}`,\n };\n return classes[color] || classes.gray;\n};\n\n// Actions Dropdown\ninterface RefundActionsDropdownProps {\n record: RefundRecord;\n onViewDetails: () => void;\n onProcess: () => void;\n onSkip: () => void;\n onRetry: () => void;\n isProcessing: boolean;\n}\n\nconst RefundActionsDropdown: FC<RefundActionsDropdownProps> = ({\n record,\n onViewDetails,\n onProcess,\n onSkip,\n onRetry,\n isProcessing,\n}) => {\n const [isOpen, setIsOpen] = useState(false);\n const dropdownRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n document.addEventListener('mousedown', handleClickOutside);\n return () => document.removeEventListener('mousedown', handleClickOutside);\n }, []);\n\n const canProcess = record.status === 'PENDING';\n const canSkip = record.status === 'PENDING';\n const canRetry = record.status === 'FAILED';\n\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <button\n type=\"button\"\n onClick={() => setIsOpen(!isOpen)}\n disabled={isProcessing}\n className=\"p-1.5 rounded-md hover:bg-muted/50 transition-colors disabled:opacity-50\"\n aria-label=\"Refund actions\"\n >\n {isProcessing ? (\n <Loader2 className=\"size-4 animate-spin text-muted-foreground\" />\n ) : (\n <MoreHorizontal className=\"size-4 text-muted-foreground\" />\n )}\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-popover border border-border rounded-md shadow-lg py-1\">\n <button\n type=\"button\"\n onClick={() => {\n onViewDetails();\n setIsOpen(false);\n }}\n className=\"w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted/50 transition-colors\"\n >\n <Eye className=\"size-4\" />\n View Details\n </button>\n\n {canProcess && (\n <button\n type=\"button\"\n onClick={() => {\n onProcess();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.success.text} hover:bg-muted/50 transition-colors`}\n >\n <Play className=\"size-4\" />\n Process Refund\n </button>\n )}\n\n {canSkip && (\n <button\n type=\"button\"\n onClick={() => {\n onSkip();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.warning.text} hover:bg-muted/50 transition-colors`}\n >\n <SkipForward className=\"size-4\" />\n Skip Refund\n </button>\n )}\n\n {canRetry && (\n <button\n type=\"button\"\n onClick={() => {\n onRetry();\n setIsOpen(false);\n }}\n className={`w-full flex items-center gap-2 px-3 py-2 text-sm ${statusTokens.info.text} hover:bg-muted/50 transition-colors`}\n >\n <RotateCcw className=\"size-4\" />\n Retry Refund\n </button>\n )}\n </div>\n )}\n </div>\n );\n};\n\n// Create Refund Modal\ninterface CreateRefundModalProps {\n isOpen: boolean;\n onClose: () => void;\n onSubmit: (data: CreateRefundFormData) => Promise<void>;\n isSubmitting: boolean;\n}\n\ninterface CreateRefundFormData {\n billingAccountId?: string;\n provider: string;\n gatewayPaymentId: string;\n gatewayOrderId?: string;\n amount: number;\n currency: string;\n purchaseType?: string;\n purchaseDetail?: string;\n reason?: string;\n notes?: string;\n transactionId?: string;\n}\n\ninterface LookedUpTransaction {\n id: string;\n billingAccountId: string;\n amount: number;\n totalAmount: number; // amount + tax (what was actually charged)\n currency: string;\n description: string | null;\n razorpayPaymentId: string | null;\n stripePaymentId: string | null;\n metadata: Record<string, unknown> | null;\n}\n\nconst EMPTY_FORM: CreateRefundFormData = {\n provider: 'stripe',\n gatewayPaymentId: '',\n amount: 0,\n currency: 'USD',\n};\n\nconst CreateRefundModal: FC<CreateRefundModalProps> = ({\n isOpen,\n onClose,\n onSubmit,\n isSubmitting,\n}) => {\n const client = useApolloClient();\n const [transactionId, setTransactionId] = useState('');\n const [lookedUp, setLookedUp] = useState<LookedUpTransaction | null>(null);\n const [lookupError, setLookupError] = useState<string | null>(null);\n const [isLookingUp, setIsLookingUp] = useState(false);\n const [formData, setFormData] = useState<CreateRefundFormData>(EMPTY_FORM);\n\n const reset = () => {\n setTransactionId('');\n setLookedUp(null);\n setLookupError(null);\n setFormData(EMPTY_FORM);\n };\n\n const handleClose = () => {\n reset();\n onClose();\n };\n\n const lookupTransaction = useCallback(\n async (id: string) => {\n const trimmed = id.trim();\n if (!trimmed) return;\n setIsLookingUp(true);\n setLookupError(null);\n setLookedUp(null);\n try {\n const { data } = await client.query<GetTransactionQuery>({\n query: GetTransactionDocument,\n variables: { id: trimmed },\n fetchPolicy: 'network-only',\n });\n const txn = data?.getTransaction ?? null;\n if (!txn) {\n setLookupError('Transaction not found. Check the ID and try again.');\n setFormData(EMPTY_FORM);\n return;\n }\n const meta = txn.metadata as Record<string, unknown> | null;\n const totalAmount = typeof meta?.total === 'number' ? meta.total : txn.amount;\n const lookedUpWithTotal: LookedUpTransaction = {\n id: txn.id,\n billingAccountId: txn.billingAccountId,\n amount: txn.amount,\n totalAmount,\n currency: txn.currency,\n description: txn.description ?? null,\n razorpayPaymentId: txn.razorpayPaymentId ?? null,\n stripePaymentId: txn.stripePaymentId ?? null,\n metadata: txn.metadata ?? null,\n };\n setLookedUp(lookedUpWithTotal);\n const provider = txn.razorpayPaymentId ? 'razorpay' : 'stripe';\n const gatewayPaymentId = txn.razorpayPaymentId ?? txn.stripePaymentId ?? '';\n const purchaseType = (meta?.purchaseType as string) ?? '';\n const purchaseDetail = txn.description ?? '';\n setFormData({\n transactionId: txn.id,\n billingAccountId: txn.billingAccountId,\n provider,\n gatewayPaymentId,\n currency: txn.currency,\n amount: totalAmount,\n purchaseType,\n purchaseDetail,\n reason: '',\n notes: '',\n });\n } catch {\n setLookupError('Failed to look up transaction. Ensure the ID is correct.');\n setFormData(EMPTY_FORM);\n } finally {\n setIsLookingUp(false);\n }\n },\n [client]\n );\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n await onSubmit(formData);\n reset();\n };\n\n if (!isOpen) return null;\n\n const maxAmount = lookedUp?.totalAmount ?? undefined;\n const isAmountExceedingMax = maxAmount !== undefined && formData.amount > maxAmount + 0.01;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={handleClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Create Manual Refund</h2>\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {/* Step 1: Transaction ID lookup */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">Transaction ID *</label>\n <div className=\"flex gap-2\">\n <input\n type=\"text\"\n value={transactionId}\n onChange={(e) => {\n setTransactionId(e.target.value);\n setLookedUp(null);\n setLookupError(null);\n }}\n onBlur={() => lookupTransaction(transactionId)}\n className=\"flex-1 px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Paste transaction UUID...\"\n required\n />\n <button\n type=\"button\"\n onClick={() => lookupTransaction(transactionId)}\n disabled={!transactionId.trim() || isLookingUp}\n className=\"px-3 py-2 border border-border rounded-md hover:bg-muted/50 transition-colors disabled:opacity-50 flex items-center gap-1 text-sm\"\n >\n {isLookingUp ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n </button>\n </div>\n {lookupError && <p className=\"text-xs text-status-error-text mt-1\">{lookupError}</p>}\n {isLookingUp && (\n <p className=\"text-xs text-muted-foreground mt-1\">Looking up transaction…</p>\n )}\n </div>\n\n {/* Auto-filled fields — shown once transaction is found */}\n {lookedUp && (\n <>\n {/* Transaction summary banner */}\n <div className=\"p-3 bg-status-success-bg-subtle border border-border-subtle rounded-md text-sm space-y-1\">\n <div className=\"flex items-center gap-2 text-status-success-text font-medium\">\n <CheckCircle className=\"size-4\" />\n Transaction found\n </div>\n <div className=\"text-muted-foreground grid grid-cols-2 gap-x-4 gap-y-0.5 mt-1\">\n <span>\n Account:{' '}\n <span className=\"text-foreground font-mono text-xs\">\n {lookedUp.billingAccountId.slice(0, 16)}…\n </span>\n </span>\n <span>\n Paid:{' '}\n <span className=\"text-foreground\">\n {formatCurrency(lookedUp.totalAmount, lookedUp.currency)}\n </span>\n </span>\n <span>\n Provider:{' '}\n <span className=\"text-foreground capitalize\">{formData.provider}</span>\n </span>\n <span>\n Currency: <span className=\"text-foreground\">{lookedUp.currency}</span>\n </span>\n </div>\n </div>\n\n {/* Read-only auto-filled fields */}\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Provider\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm capitalize\">\n {formData.provider}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Currency\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm\">\n {formData.currency}\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Gateway Payment ID\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm font-mono truncate\">\n {formData.gatewayPaymentId}\n </div>\n </div>\n\n {formData.purchaseType && (\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Purchase Type\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm\">\n {formData.purchaseType}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-muted-foreground mb-1\">\n Purchase Detail\n </label>\n <div className=\"px-3 py-2 border border-border rounded-md bg-muted/30 text-sm truncate\">\n {formData.purchaseDetail || '—'}\n </div>\n </div>\n </div>\n )}\n\n {/* Editable: Amount (capped at transaction amount) */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">\n Refund Amount *\n <span className=\"text-xs text-muted-foreground ml-1\">\n (max {formatCurrency(maxAmount!, formData.currency)})\n </span>\n </label>\n <input\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={maxAmount}\n value={formData.amount}\n onChange={(e) =>\n setFormData({ ...formData, amount: parseFloat(e.target.value) || 0 })\n }\n className={`w-full px-3 py-2 border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary ${\n isAmountExceedingMax ? 'border-status-error-text' : 'border-border'\n }`}\n required\n />\n {isAmountExceedingMax && (\n <p className=\"text-xs text-status-error-text mt-1\">\n Amount cannot exceed the original payment of{' '}\n {formatCurrency(maxAmount!, formData.currency)}\n </p>\n )}\n </div>\n\n {/* Editable: Reason & Notes */}\n <div>\n <label className=\"block text-sm font-medium mb-1\">Reason</label>\n <input\n type=\"text\"\n value={formData.reason || ''}\n onChange={(e) => setFormData({ ...formData, reason: e.target.value })}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background text-foreground focus:outline-none focus:ring-2 focus:ring-primary\"\n placeholder=\"Reason for refund\"\n />\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Notes</label>\n <textarea\n value={formData.notes || ''}\n onChange={(e) => setFormData({ ...formData, notes: 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 resize-none\"\n rows={2}\n placeholder=\"Internal notes\"\n />\n </div>\n </>\n )}\n\n <div className=\"flex gap-2 pt-2\">\n <button\n type=\"button\"\n onClick={handleClose}\n className=\"flex-1 py-2 px-4 border border-border rounded-md hover:bg-muted/50 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={\n isSubmitting ||\n !lookedUp ||\n !formData.gatewayPaymentId ||\n formData.amount <= 0 ||\n isAmountExceedingMax\n }\n className=\"flex-1 py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2\"\n >\n {isSubmitting && <Loader2 className=\"size-4 animate-spin\" />}\n Create Refund\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\n// Skip Refund Modal\ninterface SkipRefundModalProps {\n isOpen: boolean;\n record: RefundRecord | null;\n onClose: () => void;\n onSubmit: (reason: string) => Promise<void>;\n isSubmitting: boolean;\n}\n\nconst SkipRefundModal: FC<SkipRefundModalProps> = ({\n isOpen,\n record,\n onClose,\n onSubmit,\n isSubmitting,\n}) => {\n const [reason, setReason] = useState('');\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n await onSubmit(reason);\n setReason('');\n };\n\n if (!isOpen || !record) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={onClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-md w-full mx-4\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Skip Refund</h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n <div\n className={`p-3 ${statusTokens.warning.bg} border ${statusTokens.warning.border} rounded-md`}\n >\n <div className=\"flex items-start gap-2\">\n <AlertTriangle className={`size-5 ${statusTokens.warning.icon} mt-0.5`} />\n <div>\n <p className={`text-sm font-medium ${statusTokens.warning.text}`}>\n You are about to skip this refund\n </p>\n <p className={`text-sm ${statusTokens.warning.text} mt-1`}>\n Amount: {formatCurrency(record.amount, record.currency)}\n </p>\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Reason for skipping *</label>\n <textarea\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background resize-none\"\n rows={3}\n placeholder=\"Explain why this refund is being skipped...\"\n required\n />\n </div>\n\n <div className=\"flex gap-2\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"flex-1 py-2 px-4 border border-border rounded-md hover:bg-muted/50 transition-colors\"\n >\n Cancel\n </button>\n <button\n type=\"submit\"\n disabled={isSubmitting || !reason.trim()}\n className={`flex-1 py-2 px-4 ${statusTokens.warning.dot} text-primary-foreground rounded-md hover:opacity-90 transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2`}\n >\n {isSubmitting && <Loader2 className=\"size-4 animate-spin\" />}\n Skip Refund\n </button>\n </div>\n </form>\n </div>\n </div>\n );\n};\n\n// Refund Details Modal\ninterface RefundDetailsModalProps {\n record: RefundRecord | null;\n onClose: () => void;\n}\n\nconst RefundDetailsModal: FC<RefundDetailsModalProps> = ({ record, onClose }) => {\n if (!record) return null;\n\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n <div className=\"absolute inset-0 bg-overlay-scrim\" onClick={onClose} />\n <div className=\"relative bg-background border border-border rounded-lg shadow-xl max-w-lg w-full mx-4 max-h-[90vh] overflow-auto\">\n <div className=\"flex items-center justify-between p-4 border-b border-border\">\n <h2 className=\"text-lg font-semibold\">Refund Details</h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 rounded-md hover:bg-muted/50 transition-colors\"\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n <div className=\"p-4 space-y-4\">\n {/* Status Banner */}\n <div\n className={`flex items-center gap-2 p-3 rounded-md ${getStatusBadgeClasses(STATUS_CONFIG[record.status].color)}`}\n >\n <StatusIcon className=\"size-5\" />\n <span className=\"font-medium\">{STATUS_CONFIG[record.status].label}</span>\n </div>\n\n {/* Basic Info */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Refund ID</p>\n <p className=\"text-sm font-mono break-all\">{record.id}</p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Source</p>\n <p className=\"text-sm\">{SOURCE_LABELS[record.source]}</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Amount</p>\n <p className=\"text-lg font-semibold\">\n {formatCurrency(record.amount, record.currency)}\n </p>\n </div>\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Provider</p>\n <p className=\"text-sm capitalize\">{record.provider}</p>\n </div>\n </div>\n\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Payment ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayPaymentId}</p>\n </div>\n {record.gatewayOrderId && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Order ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayOrderId}</p>\n </div>\n )}\n </div>\n\n {record.gatewayRefundId && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Gateway Refund ID</p>\n <p className=\"text-sm font-mono break-all\">{record.gatewayRefundId}</p>\n </div>\n )}\n\n {(record.purchaseType || record.purchaseDetail) && (\n <div className=\"grid grid-cols-2 gap-4\">\n {record.purchaseType && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Purchase Type</p>\n <p className=\"text-sm\">{record.purchaseType}</p>\n </div>\n )}\n {record.purchaseDetail && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Purchase Detail</p>\n <p className=\"text-sm\">{record.purchaseDetail}</p>\n </div>\n )}\n </div>\n )}\n\n {record.reason && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Reason</p>\n <p className=\"text-sm\">{record.reason}</p>\n </div>\n )}\n\n {record.notes && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Notes</p>\n <p className=\"text-sm\">{record.notes}</p>\n </div>\n )}\n\n {record.errorMessage && (\n <div\n className={`p-3 ${statusTokens.error.bg} border ${statusTokens.error.border} rounded-md`}\n >\n <p className={`text-xs ${statusTokens.error.text} mb-1`}>Error Message</p>\n <p className={`text-sm ${statusTokens.error.text}`}>{record.errorMessage}</p>\n </div>\n )}\n\n <div className=\"grid grid-cols-2 gap-4 pt-2 border-t border-border\">\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Created At</p>\n <p className=\"text-sm\">{formatDateTime(record.createdAt)}</p>\n </div>\n {record.processedAt && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Processed At</p>\n <p className=\"text-sm\">{formatDateTime(record.processedAt)}</p>\n </div>\n )}\n </div>\n\n {record.retryCount > 0 && (\n <div>\n <p className=\"text-xs text-muted-foreground mb-1\">Retry Count</p>\n <p className=\"text-sm\">{record.retryCount}</p>\n </div>\n )}\n </div>\n\n <div className=\"p-4 border-t border-border\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors\"\n >\n Close\n </button>\n </div>\n </div>\n </div>\n );\n};\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\ntype TabStatus = 'PENDING' | 'COMPLETED' | 'FAILED' | 'ALL';\n\nconst TAB_CONFIG: Record<TabStatus, { label: string; status?: RefundRecordStatus }> = {\n PENDING: { label: 'Pending', status: 'PENDING' },\n COMPLETED: { label: 'Completed', status: 'COMPLETED' },\n FAILED: { label: 'Failed', status: 'FAILED' },\n ALL: { label: 'All', status: undefined },\n};\n\nexport const RefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string): string => {\n const translated = t(key);\n return translated === key ? fallback : translated;\n };\n const permissions = useBillingPermissions();\n\n // State\n const [activeTab, setActiveTab] = useState<TabStatus>('PENDING');\n const [searchQuery, setSearchQuery] = useState('');\n const [filters, setFilters] = useState<RefundRecordFilters>({});\n const [showFilters, setShowFilters] = useState(false);\n const [selectedRecord, setSelectedRecord] = useState<RefundRecord | null>(null);\n const [showCreateModal, setShowCreateModal] = useState(false);\n const [showSkipModal, setShowSkipModal] = useState(false);\n const [recordToSkip, setRecordToSkip] = useState<RefundRecord | null>(null);\n const [actionLoadingId, setActionLoadingId] = useState<string | null>(null);\n\n // Build filters based on active tab - memoized to prevent infinite re-render loop\n // (useRefundRecords has a useEffect on options.filters, so a new object every render would cause\n // infinite updates if tabFilters were not stable)\n const tabFilters = useMemo<RefundRecordFilters>(\n () => ({\n ...filters,\n status: TAB_CONFIG[activeTab].status,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- filters is an object; spread ensures correct deps\n [\n activeTab,\n filters.source,\n filters.provider,\n filters.billingAccountId,\n filters.fromDate,\n filters.toDate,\n ]\n );\n\n // Data hooks - filters automatically applied based on active tab\n const {\n records,\n stats,\n pagination,\n isLoading,\n recordsError,\n unprocessedWebhooks,\n refetch,\n goToNextPage,\n goToPreviousPage,\n setFilters: updateFilters,\n createRefundRecord,\n processRefund,\n skipRefund,\n retryRefund,\n createRefundRecordsFromFailedWebhooks,\n isCreating,\n isProcessing,\n isCreatingFromWebhooks,\n } = useRefunds({ filters: tabFilters });\n\n // Permission check\n if (!permissions.canViewPayments) {\n return <AccessDenied message=\"You don't have permission to view refunds.\" />;\n }\n\n // Error handling\n if (recordsError && isServerError(recordsError)) {\n return (\n <div className=\"p-6\">\n <ServerError\n title=\"Server Unavailable\"\n message=\"Unable to load refunds. The server might be down or experiencing issues.\"\n onRetry={() => refetch()}\n showRetry\n />\n </div>\n );\n }\n\n // Handlers\n const handleTabChange = (tab: TabStatus) => {\n setActiveTab(tab);\n // Reset filters when changing tabs\n setFilters({});\n setSearchQuery('');\n };\n\n const handleFilterChange = (key: keyof RefundRecordFilters, value: string | undefined) => {\n // Don't allow status filter changes as tabs control status\n if (key === 'status') return;\n\n const newFilters = { ...filters, [key]: value || undefined };\n setFilters(newFilters);\n updateFilters({ ...newFilters, status: TAB_CONFIG[activeTab].status });\n };\n\n const handleCreateRefund = async (data: CreateRefundFormData) => {\n try {\n await createRefundRecord(data);\n setShowCreateModal(false);\n } catch (error) {\n console.error('Failed to create refund:', error);\n }\n };\n\n const handleProcess = async (record: RefundRecord) => {\n setActionLoadingId(record.id);\n try {\n const result = await processRefund(record.id);\n if (!result.success && result.error) {\n console.error('Refund processing failed:', result.error);\n }\n } catch (error) {\n console.error('Failed to process refund:', error);\n } finally {\n setActionLoadingId(null);\n }\n };\n\n const handleSkip = async (reason: string) => {\n if (!recordToSkip) return;\n try {\n await skipRefund(recordToSkip.id, reason);\n setShowSkipModal(false);\n setRecordToSkip(null);\n } catch (error) {\n console.error('Failed to skip refund:', error);\n }\n };\n\n const handleRetry = async (record: RefundRecord) => {\n setActionLoadingId(record.id);\n try {\n const result = await retryRefund(record.id);\n if (!result.success && result.error) {\n console.error('Refund retry failed:', result.error);\n }\n } catch (error) {\n console.error('Failed to retry refund:', error);\n } finally {\n setActionLoadingId(null);\n }\n };\n\n const handleCreateFromWebhooks = async () => {\n try {\n await createRefundRecordsFromFailedWebhooks();\n } catch (error) {\n console.error('Failed to create refunds from webhooks:', error);\n }\n };\n\n // Filter records by search query (client-side)\n const filteredRecords = searchQuery\n ? records.filter(\n (r) =>\n r.gatewayPaymentId.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.gatewayOrderId?.toLowerCase().includes(searchQuery.toLowerCase()) ||\n r.reason?.toLowerCase().includes(searchQuery.toLowerCase())\n )\n : records;\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-muted animate-pulse rounded\" />\n <div className=\"grid grid-cols-5 gap-4\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-24 bg-muted animate-pulse rounded-lg\" />\n ))}\n </div>\n <div className=\"space-y-2\">\n {[1, 2, 3, 4, 5].map((i) => (\n <div key={i} className=\"h-16 bg-muted animate-pulse rounded\" />\n ))}\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-6 p-6\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refund Management')}\n description=\"View and manage refund records\"\n actions={\n <div className=\"flex items-center gap-2\">\n {unprocessedWebhooks.length > 0 && (\n <button\n type=\"button\"\n onClick={handleCreateFromWebhooks}\n disabled={isCreatingFromWebhooks}\n className={`inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border ${statusTokens.warning.border} ${statusTokens.warning.bg} ${statusTokens.warning.text} hover:opacity-90 transition-colors disabled:opacity-50`}\n >\n {isCreatingFromWebhooks ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Download className=\"size-4\" />\n )}\n Import {unprocessedWebhooks.length} Failed Webhooks\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => refetch()}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 transition-colors\"\n >\n <RefreshCw className=\"size-4\" />\n Refresh\n </button>\n <button\n type=\"button\"\n onClick={() => setShowCreateModal(true)}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors\"\n >\n <Plus className=\"size-4\" />\n Create Manual Refund\n </button>\n </div>\n }\n />\n\n {/* Tabs Navigation */}\n <div className=\"border-b border-border\">\n <div className=\"flex flex-wrap gap-2 sm:gap-0\">\n {(Object.keys(TAB_CONFIG) as TabStatus[]).map((tab) => {\n const isActive = activeTab === tab;\n const count = stats\n ? tab === 'PENDING'\n ? stats.pending\n : tab === 'COMPLETED'\n ? stats.completed\n : tab === 'FAILED'\n ? stats.failed\n : stats.pending +\n stats.processing +\n stats.completed +\n stats.failed +\n stats.skipped\n : 0;\n\n return (\n <button\n type=\"button\"\n key={tab}\n onClick={() => handleTabChange(tab)}\n className={`flex items-center gap-2 px-4 py-3 text-sm font-medium border-b-2 transition-colors whitespace-nowrap ${\n isActive\n ? 'border-primary text-primary'\n : 'border-transparent text-muted-foreground hover:text-foreground hover:border-border'\n }`}\n >\n {TAB_CONFIG[tab].label}\n {stats && (\n <span\n className={`px-2 py-0.5 text-xs rounded-full ${\n isActive ? 'bg-primary/10 text-primary' : 'bg-muted text-muted-foreground'\n }`}\n >\n {count}\n </span>\n )}\n </button>\n );\n })}\n </div>\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-col sm:flex-row gap-4\">\n {/* Search */}\n <div className=\"relative flex-1\">\n <Search className=\"absolute left-3 top-1/2 -translate-y-1/2 size-4 text-muted-foreground\" />\n <input\n type=\"text\"\n placeholder=\"Search by payment ID, order ID, or reason...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"w-full pl-[3.25rem] pr-4 py-2 border border-border rounded-md bg-background\"\n />\n </div>\n\n {/* Filter Toggle */}\n <button\n type=\"button\"\n onClick={() => setShowFilters(!showFilters)}\n className={`inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md border transition-colors ${\n showFilters\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border bg-background hover:bg-muted/50'\n }`}\n >\n <Filter className=\"size-4\" />\n Filters\n {Object.values(filters).filter(Boolean).length > 0 && (\n <span className=\"px-1.5 py-0.5 text-xs rounded-full bg-primary text-primary-foreground\">\n {Object.values(filters).filter(Boolean).length}\n </span>\n )}\n </button>\n\n {/* Clear Filters */}\n {Object.values(filters).filter(Boolean).length > 0 && (\n <button\n type=\"button\"\n onClick={() => {\n setFilters({});\n updateFilters({});\n }}\n className=\"inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md text-muted-foreground hover:text-foreground transition-colors\"\n >\n <X className=\"size-4\" />\n Clear\n </button>\n )}\n </div>\n\n {/* Expanded Filters */}\n {showFilters && (\n <div className=\"p-4 border border-border rounded-lg bg-muted/30 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4\">\n <div>\n <label className=\"block text-sm font-medium mb-1\">Source</label>\n <select\n value={filters.source || ''}\n onChange={(e) => handleFilterChange('source', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n >\n <option value=\"\">All Sources</option>\n {Object.entries(SOURCE_LABELS).map(([key, label]) => (\n <option key={key} value={key}>\n {label}\n </option>\n ))}\n </select>\n </div>\n\n <div>\n <label className=\"block text-sm font-medium mb-1\">Provider</label>\n <select\n value={filters.provider || ''}\n onChange={(e) => handleFilterChange('provider', e.target.value)}\n className=\"w-full px-3 py-2 border border-border rounded-md bg-background\"\n >\n <option value=\"\">All Providers</option>\n {PROVIDER_OPTIONS.map((p) => (\n <option key={p} value={p}>\n {p.charAt(0).toUpperCase() + p.slice(1)}\n </option>\n ))}\n </select>\n </div>\n\n <div className=\"sm:col-span-2 lg:col-span-1\">\n <label className=\"block text-sm font-medium mb-1\">Date Range</label>\n <div className=\"flex flex-col sm:flex-row items-start sm:items-center gap-2\">\n <input\n type=\"date\"\n value={filters.fromDate ? filters.fromDate.split('T')[0] : ''}\n onChange={(e) =>\n handleFilterChange(\n 'fromDate',\n e.target.value ? new Date(e.target.value).toISOString() : undefined\n )\n }\n className=\"w-full sm:flex-1 p-2 border border-border rounded-md bg-background text-sm\"\n />\n <span className=\"text-muted-foreground hidden sm:inline\">-</span>\n <input\n type=\"date\"\n value={filters.toDate ? filters.toDate.split('T')[0] : ''}\n onChange={(e) =>\n handleFilterChange(\n 'toDate',\n e.target.value ? new Date(e.target.value).toISOString() : undefined\n )\n }\n className=\"w-full sm:flex-1 p-2 border border-border rounded-md bg-background text-sm\"\n />\n </div>\n </div>\n </div>\n )}\n\n {/* Table */}\n {filteredRecords.length === 0 ? (\n <EmptyState\n icon={<RefreshCw className=\"size-6 text-muted-foreground\" />}\n title=\"No refund records found\"\n description={\n Object.values(filters).filter(Boolean).length > 0\n ? 'Try adjusting your filters.'\n : activeTab === 'PENDING'\n ? 'No pending refunds to process.'\n : 'Refund records will appear here when created.'\n }\n />\n ) : (\n <div className=\"border border-border rounded-lg overflow-hidden\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full min-w-[400px]\">\n <thead className=\"bg-muted/50\">\n <tr>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Date\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Status\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden sm:table-cell\">\n Source\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden md:table-cell\">\n Provider\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Payment ID\n </th>\n <th className=\"text-right text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap\">\n Amount\n </th>\n <th className=\"text-left text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap hidden lg:table-cell\">\n Reason\n </th>\n <th className=\"p-2 w-10\"></th>\n </tr>\n </thead>\n <tbody className=\"divide-y divide-border\">\n {filteredRecords.map((record) => {\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n return (\n <tr key={record.id} className=\"hover:bg-muted/30 transition-colors\">\n <td className=\"px-3 py-2 text-sm text-foreground whitespace-nowrap\">\n <div className=\"flex flex-col\">\n <span>{formatDateTime(record.createdAt).split(' ')[0]}</span>\n <span className=\"text-xs text-muted-foreground\">\n {formatDateTime(record.createdAt).split(' ')[1]}\n </span>\n </div>\n </td>\n <td className=\"px-3 py-2 whitespace-nowrap\">\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium rounded ${getStatusBadgeClasses(\n STATUS_CONFIG[record.status].color\n )}`}\n >\n <StatusIcon className=\"size-3\" />\n <span className=\"hidden sm:inline\">\n {STATUS_CONFIG[record.status].label}\n </span>\n </span>\n </td>\n <td className=\"px-3 py-2 text-sm text-muted-foreground whitespace-nowrap hidden sm:table-cell\">\n {SOURCE_LABELS[record.source]}\n </td>\n <td className=\"px-3 py-2 text-sm text-foreground capitalize whitespace-nowrap hidden md:table-cell\">\n {record.provider}\n </td>\n <td className=\"px-3 py-2 text-sm font-mono text-muted-foreground whitespace-nowrap max-w-[120px] sm:max-w-[200px] truncate\">\n {record.gatewayPaymentId}\n </td>\n <td className=\"px-3 py-2 text-sm text-right font-medium whitespace-nowrap\">\n {formatCurrency(record.amount, record.currency)}\n </td>\n <td className=\"px-3 py-2 text-sm text-muted-foreground max-w-[200px] truncate hidden lg:table-cell\">\n {record.reason || '-'}\n </td>\n <td className=\"p-2 text-center\">\n <RefundActionsDropdown\n record={record}\n onViewDetails={() => setSelectedRecord(record)}\n onProcess={() => handleProcess(record)}\n onSkip={() => {\n setRecordToSkip(record);\n setShowSkipModal(true);\n }}\n onRetry={() => handleRetry(record)}\n isProcessing={actionLoadingId === record.id}\n />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n </div>\n </div>\n )}\n\n {/* Pagination */}\n {pagination.totalCount > 0 && (\n <div className=\"flex flex-col sm:flex-row items-center justify-between gap-4 border-t border-border pt-4\">\n <p className=\"text-sm text-muted-foreground text-center sm:text-left\">\n Showing {pagination.page * pagination.pageSize + 1} to{' '}\n {Math.min((pagination.page + 1) * pagination.pageSize, pagination.totalCount)} of{' '}\n {pagination.totalCount} refunds\n </p>\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={goToPreviousPage}\n disabled={!pagination.hasPrevious}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <ChevronLeft className=\"size-4\" />\n <span className=\"hidden sm:inline\">Previous</span>\n </button>\n <span className=\"text-sm text-muted-foreground px-2\">\n <span className=\"hidden sm:inline\">Page </span>\n {pagination.page + 1} <span className=\"hidden sm:inline\">of</span>\n <span className=\"sm:hidden\">/</span>{' '}\n {Math.ceil(pagination.totalCount / pagination.pageSize)}\n </span>\n <button\n type=\"button\"\n onClick={goToNextPage}\n disabled={!pagination.hasMore}\n className=\"inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors\"\n >\n <span className=\"hidden sm:inline\">Next</span>\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n </div>\n )}\n\n {/* Modals */}\n <CreateRefundModal\n isOpen={showCreateModal}\n onClose={() => setShowCreateModal(false)}\n onSubmit={handleCreateRefund}\n isSubmitting={isCreating}\n />\n\n <SkipRefundModal\n isOpen={showSkipModal}\n record={recordToSkip}\n onClose={() => {\n setShowSkipModal(false);\n setRecordToSkip(null);\n }}\n onSubmit={handleSkip}\n isSubmitting={isProcessing}\n />\n\n <RefundDetailsModal record={selectedRecord} onClose={() => setSelectedRecord(null)} />\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -33,24 +33,27 @@ var F = {
|
|
|
33
33
|
className: "relative overflow-visible",
|
|
34
34
|
ref: o,
|
|
35
35
|
children: [/* @__PURE__ */ M("button", {
|
|
36
|
+
type: "button",
|
|
36
37
|
onClick: () => a(!i),
|
|
37
38
|
className: "p-1.5 rounded-md hover:bg-muted/50 transition-colors",
|
|
38
39
|
"aria-label": "Transaction actions",
|
|
39
|
-
children: /* @__PURE__ */ M(E, { className: "
|
|
40
|
+
children: /* @__PURE__ */ M(E, { className: "size-4 text-muted-foreground" })
|
|
40
41
|
}), i && /* @__PURE__ */ N("div", {
|
|
41
42
|
className: "absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-popover border border-border rounded-md shadow-lg py-1",
|
|
42
43
|
children: [/* @__PURE__ */ N("button", {
|
|
44
|
+
type: "button",
|
|
43
45
|
onClick: () => {
|
|
44
46
|
t(), a(!1);
|
|
45
47
|
},
|
|
46
48
|
className: "w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted/50 transition-colors whitespace-nowrap",
|
|
47
|
-
children: [/* @__PURE__ */ M(C, { className: "
|
|
49
|
+
children: [/* @__PURE__ */ M(C, { className: "size-4" }), "View Details"]
|
|
48
50
|
}), e.type === "payment" && r && /* @__PURE__ */ N("button", {
|
|
51
|
+
type: "button",
|
|
49
52
|
onClick: () => {
|
|
50
53
|
n(), a(!1);
|
|
51
54
|
},
|
|
52
55
|
className: "w-full flex items-center gap-2 px-3 py-2 text-sm text-foreground hover:bg-muted/50 transition-colors whitespace-nowrap",
|
|
53
|
-
children: [/* @__PURE__ */ M(w, { className: "
|
|
56
|
+
children: [/* @__PURE__ */ M(w, { className: "size-4" }), "View Invoice"]
|
|
54
57
|
})]
|
|
55
58
|
})]
|
|
56
59
|
});
|
|
@@ -75,10 +78,11 @@ var F = {
|
|
|
75
78
|
className: "text-lg font-semibold",
|
|
76
79
|
children: "Transaction Details"
|
|
77
80
|
}), /* @__PURE__ */ M("button", {
|
|
81
|
+
type: "button",
|
|
78
82
|
onClick: t,
|
|
79
83
|
className: "p-1 rounded-md hover:bg-muted/50 transition-colors",
|
|
80
84
|
"aria-label": "Close transaction details",
|
|
81
|
-
children: /* @__PURE__ */ M(O, { className: "
|
|
85
|
+
children: /* @__PURE__ */ M(O, { className: "size-5" })
|
|
82
86
|
})]
|
|
83
87
|
}),
|
|
84
88
|
/* @__PURE__ */ N("div", {
|
|
@@ -187,19 +191,21 @@ var F = {
|
|
|
187
191
|
children: ["Provider: ", c]
|
|
188
192
|
}),
|
|
189
193
|
r && n && /* @__PURE__ */ N("button", {
|
|
194
|
+
type: "button",
|
|
190
195
|
onClick: () => n(e),
|
|
191
196
|
className: "flex items-center gap-2 text-sm text-primary hover:underline",
|
|
192
|
-
children: [/* @__PURE__ */ M(w, { className: "
|
|
197
|
+
children: [/* @__PURE__ */ M(w, { className: "size-4" }), "View Invoice"]
|
|
193
198
|
})
|
|
194
199
|
]
|
|
195
200
|
}),
|
|
196
201
|
!_ && r && n && /* @__PURE__ */ M("div", {
|
|
197
202
|
className: "p-3 bg-muted/50 rounded-lg",
|
|
198
203
|
children: /* @__PURE__ */ N("button", {
|
|
204
|
+
type: "button",
|
|
199
205
|
onClick: () => n(e),
|
|
200
206
|
className: "flex items-center gap-2 text-sm text-primary hover:underline",
|
|
201
207
|
children: [
|
|
202
|
-
/* @__PURE__ */ M(w, { className: "
|
|
208
|
+
/* @__PURE__ */ M(w, { className: "size-4" }),
|
|
203
209
|
"View Invoice ",
|
|
204
210
|
c && `(${c})`
|
|
205
211
|
]
|
|
@@ -210,7 +216,7 @@ var F = {
|
|
|
210
216
|
children: [
|
|
211
217
|
/* @__PURE__ */ N("div", {
|
|
212
218
|
className: "flex items-center gap-2",
|
|
213
|
-
children: [/* @__PURE__ */ M("div", { className: "
|
|
219
|
+
children: [/* @__PURE__ */ M("div", { className: "size-1.5 rounded-full bg-status-error-bg" }), /* @__PURE__ */ M("p", {
|
|
214
220
|
className: "text-sm font-semibold text-status-error-text",
|
|
215
221
|
children: "Refund Information"
|
|
216
222
|
})]
|
|
@@ -224,11 +230,12 @@ var F = {
|
|
|
224
230
|
className: "text-sm font-mono text-status-error-text",
|
|
225
231
|
children: C
|
|
226
232
|
})] }), T && /* @__PURE__ */ N("button", {
|
|
233
|
+
type: "button",
|
|
227
234
|
onClick: () => {
|
|
228
235
|
u("light"), d(T);
|
|
229
236
|
},
|
|
230
237
|
className: "flex items-center gap-2 text-sm text-status-error-text hover:underline",
|
|
231
|
-
children: [/* @__PURE__ */ M(w, { className: "
|
|
238
|
+
children: [/* @__PURE__ */ M(w, { className: "size-4" }), "Download Credit Note PDF"]
|
|
232
239
|
})]
|
|
233
240
|
}),
|
|
234
241
|
D && /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("p", {
|
|
@@ -280,6 +287,7 @@ var F = {
|
|
|
280
287
|
/* @__PURE__ */ M("div", {
|
|
281
288
|
className: "p-4 border-t border-border",
|
|
282
289
|
children: /* @__PURE__ */ M("button", {
|
|
290
|
+
type: "button",
|
|
283
291
|
onClick: t,
|
|
284
292
|
className: "w-full py-2 px-4 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors",
|
|
285
293
|
children: "Close"
|
|
@@ -310,7 +318,7 @@ var F = {
|
|
|
310
318
|
className: "p-6",
|
|
311
319
|
children: /* @__PURE__ */ M(n, {
|
|
312
320
|
icon: /* @__PURE__ */ M("svg", {
|
|
313
|
-
className: "
|
|
321
|
+
className: "size-6 text-muted-foreground",
|
|
314
322
|
fill: "none",
|
|
315
323
|
viewBox: "0 0 24 24",
|
|
316
324
|
stroke: "currentColor",
|
|
@@ -351,9 +359,10 @@ var F = {
|
|
|
351
359
|
className: "space-y-6 p-6",
|
|
352
360
|
children: [
|
|
353
361
|
/* @__PURE__ */ N("button", {
|
|
362
|
+
type: "button",
|
|
354
363
|
onClick: () => O("/overview"),
|
|
355
364
|
className: "inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors",
|
|
356
|
-
children: [/* @__PURE__ */ M(_, { className: "
|
|
365
|
+
children: [/* @__PURE__ */ M(_, { className: "size-4" }), "Back to Overview"]
|
|
357
366
|
}),
|
|
358
367
|
/* @__PURE__ */ M(t, {
|
|
359
368
|
title: h("billing.transactions.title", "Transaction History"),
|
|
@@ -366,7 +375,7 @@ var F = {
|
|
|
366
375
|
children: [
|
|
367
376
|
/* @__PURE__ */ N("div", {
|
|
368
377
|
className: "flex items-start gap-2",
|
|
369
|
-
children: [/* @__PURE__ */ M(S, { className: "
|
|
378
|
+
children: [/* @__PURE__ */ M(S, { className: "size-4 text-muted-foreground mt-0.5" }), /* @__PURE__ */ N("div", { children: [
|
|
370
379
|
/* @__PURE__ */ M("p", {
|
|
371
380
|
className: "text-xs text-muted-foreground mb-0.5",
|
|
372
381
|
children: "Account"
|
|
@@ -377,16 +386,16 @@ var F = {
|
|
|
377
386
|
}),
|
|
378
387
|
j.isActive ? /* @__PURE__ */ N("span", {
|
|
379
388
|
className: "inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-success-bg-subtle text-status-success-text",
|
|
380
|
-
children: [/* @__PURE__ */ M(y, { className: "
|
|
389
|
+
children: [/* @__PURE__ */ M(y, { className: "size-3" }), "Active"]
|
|
381
390
|
}) : /* @__PURE__ */ N("span", {
|
|
382
391
|
className: "inline-flex items-center gap-1 mt-1 px-1.5 py-0.5 text-xs font-medium rounded bg-status-error-bg-subtle text-status-error-text",
|
|
383
|
-
children: [/* @__PURE__ */ M(k, { className: "
|
|
392
|
+
children: [/* @__PURE__ */ M(k, { className: "size-3" }), "Inactive"]
|
|
384
393
|
})
|
|
385
394
|
] })]
|
|
386
395
|
}),
|
|
387
396
|
/* @__PURE__ */ N("div", {
|
|
388
397
|
className: "flex items-start gap-2",
|
|
389
|
-
children: [/* @__PURE__ */ M(T, { className: "
|
|
398
|
+
children: [/* @__PURE__ */ M(T, { className: "size-4 text-muted-foreground mt-0.5" }), /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("p", {
|
|
390
399
|
className: "text-xs text-muted-foreground mb-0.5",
|
|
391
400
|
children: "Email"
|
|
392
401
|
}), /* @__PURE__ */ M("p", {
|
|
@@ -396,7 +405,7 @@ var F = {
|
|
|
396
405
|
}),
|
|
397
406
|
/* @__PURE__ */ N("div", {
|
|
398
407
|
className: "flex items-start gap-2",
|
|
399
|
-
children: [/* @__PURE__ */ M(D, { className: "
|
|
408
|
+
children: [/* @__PURE__ */ M(D, { className: "size-4 text-muted-foreground mt-0.5" }), /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("p", {
|
|
400
409
|
className: "text-xs text-muted-foreground mb-0.5",
|
|
401
410
|
children: "Credits Balance"
|
|
402
411
|
}), /* @__PURE__ */ N("p", {
|
|
@@ -406,7 +415,7 @@ var F = {
|
|
|
406
415
|
}),
|
|
407
416
|
/* @__PURE__ */ N("div", {
|
|
408
417
|
className: "flex items-start gap-2",
|
|
409
|
-
children: [/* @__PURE__ */ M(w, { className: "
|
|
418
|
+
children: [/* @__PURE__ */ M(w, { className: "size-4 text-muted-foreground mt-0.5" }), /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("p", {
|
|
410
419
|
className: "text-xs text-muted-foreground mb-0.5",
|
|
411
420
|
children: "Tax ID"
|
|
412
421
|
}), /* @__PURE__ */ M("p", {
|
|
@@ -416,7 +425,7 @@ var F = {
|
|
|
416
425
|
}),
|
|
417
426
|
/* @__PURE__ */ N("div", {
|
|
418
427
|
className: "flex items-start gap-2",
|
|
419
|
-
children: [/* @__PURE__ */ M(v, { className: "
|
|
428
|
+
children: [/* @__PURE__ */ M(v, { className: "size-4 text-muted-foreground mt-0.5" }), /* @__PURE__ */ N("div", { children: [/* @__PURE__ */ M("p", {
|
|
420
429
|
className: "text-xs text-muted-foreground mb-0.5",
|
|
421
430
|
children: "Member Since"
|
|
422
431
|
}), /* @__PURE__ */ M("p", {
|
|
@@ -437,6 +446,7 @@ var F = {
|
|
|
437
446
|
"refund",
|
|
438
447
|
"adjustment"
|
|
439
448
|
].map((e) => /* @__PURE__ */ M("button", {
|
|
449
|
+
type: "button",
|
|
440
450
|
onClick: () => q(e),
|
|
441
451
|
className: `px-3 py-1.5 text-sm font-medium rounded-md transition-colors ${K === e ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
|
|
442
452
|
children: e === "all" ? "All" : F[e]
|
|
@@ -445,7 +455,7 @@ var F = {
|
|
|
445
455
|
}),
|
|
446
456
|
$.length === 0 ? /* @__PURE__ */ M(n, {
|
|
447
457
|
icon: /* @__PURE__ */ M("svg", {
|
|
448
|
-
className: "
|
|
458
|
+
className: "size-6 text-muted-foreground",
|
|
449
459
|
fill: "none",
|
|
450
460
|
viewBox: "0 0 24 24",
|
|
451
461
|
stroke: "currentColor",
|
|
@@ -485,7 +495,7 @@ var F = {
|
|
|
485
495
|
className: "text-center text-sm font-medium text-muted-foreground px-3 py-2 whitespace-nowrap",
|
|
486
496
|
children: "Status"
|
|
487
497
|
}),
|
|
488
|
-
/* @__PURE__ */ M("th", { className: "
|
|
498
|
+
/* @__PURE__ */ M("th", { className: "p-2 w-10" })
|
|
489
499
|
] })
|
|
490
500
|
}), /* @__PURE__ */ M("tbody", {
|
|
491
501
|
className: "divide-y divide-border",
|
|
@@ -516,7 +526,7 @@ var F = {
|
|
|
516
526
|
})
|
|
517
527
|
}),
|
|
518
528
|
/* @__PURE__ */ M("td", {
|
|
519
|
-
className: "
|
|
529
|
+
className: "p-2 text-center",
|
|
520
530
|
children: /* @__PURE__ */ M(L, {
|
|
521
531
|
transaction: e,
|
|
522
532
|
onViewDetails: () => Y(e),
|
|
@@ -548,10 +558,11 @@ var F = {
|
|
|
548
558
|
className: "flex items-center gap-2",
|
|
549
559
|
children: [
|
|
550
560
|
/* @__PURE__ */ N("button", {
|
|
561
|
+
type: "button",
|
|
551
562
|
onClick: G,
|
|
552
563
|
disabled: !B.hasPrevious,
|
|
553
564
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
554
|
-
children: [/* @__PURE__ */ M(b, { className: "
|
|
565
|
+
children: [/* @__PURE__ */ M(b, { className: "size-4" }), "Previous"]
|
|
555
566
|
}),
|
|
556
567
|
/* @__PURE__ */ N("span", {
|
|
557
568
|
className: "text-sm text-muted-foreground px-2",
|
|
@@ -563,10 +574,11 @@ var F = {
|
|
|
563
574
|
]
|
|
564
575
|
}),
|
|
565
576
|
/* @__PURE__ */ N("button", {
|
|
577
|
+
type: "button",
|
|
566
578
|
onClick: W,
|
|
567
579
|
disabled: !B.hasMore,
|
|
568
580
|
className: "inline-flex items-center gap-1 px-3 py-1.5 text-sm font-medium rounded-md border border-border bg-background hover:bg-muted/50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors",
|
|
569
|
-
children: ["Next", /* @__PURE__ */ M(x, { className: "
|
|
581
|
+
children: ["Next", /* @__PURE__ */ M(x, { className: "size-4" })]
|
|
570
582
|
})
|
|
571
583
|
]
|
|
572
584
|
})]
|