@burdenoff/microfe-billing 2026.624.3 → 2026.625.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/billing/BillingAdminRoutes.js +1 -1
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/modules/addons/pages/AddonCreatePage.js +2 -2
  4. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  5. package/dist/billing/modules/addons/pages/AddonDetailPage.js +4 -4
  6. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  7. package/dist/billing/modules/addons/pages/AddonEditPage.js +2 -2
  8. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  9. package/dist/billing/modules/addons/pages/AddonsListPage.js +1 -1
  10. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  11. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +98 -99
  12. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
  13. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +88 -85
  14. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  15. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +6 -6
  16. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  17. package/dist/billing/modules/billing/pages/InvoicesListPage.js +2 -2
  18. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  19. package/dist/billing/modules/billing/pages/RefundsPage.js +360 -370
  20. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  21. package/dist/billing/modules/billing/pages/UserRefundsPage.js +2 -2
  22. package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -1
  23. package/dist/billing/modules/checkout/components/BillingAccountSelector.js +1 -1
  24. package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
  25. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js +1 -1
  26. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js.map +1 -1
  27. package/dist/billing/modules/checkout/components/SubscriptionSelector.js +1 -1
  28. package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
  29. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js +2 -2
  30. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js.map +1 -1
  31. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +102 -104
  32. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  33. package/dist/billing/modules/coupons/pages/CouponsListPage.js +5 -5
  34. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  35. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +1 -1
  36. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  37. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +1 -1
  38. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  39. package/dist/billing/modules/credits/pages/CreditsPage.js +29 -28
  40. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  41. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +2 -2
  42. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
  43. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +1 -1
  44. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  45. package/dist/billing/modules/dashboard/components/BillingAccountCard.js +3 -3
  46. package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
  47. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +2 -2
  48. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
  49. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +1 -1
  50. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
  51. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +1 -1
  52. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
  53. package/dist/billing/modules/dashboard/pages/OverviewPage.js +139 -142
  54. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  55. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +6 -6
  56. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  57. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +4 -4
  58. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  59. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +1 -1
  60. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
  61. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +142 -133
  62. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  63. package/dist/billing/modules/plans/pages/PlanCreatePage.js +2 -2
  64. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  65. package/dist/billing/modules/plans/pages/PlanDetailPage.js +4 -4
  66. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  67. package/dist/billing/modules/plans/pages/PlanEditPage.js +2 -2
  68. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  69. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +4 -4
  70. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  71. package/dist/billing/modules/plans/pages/PlansListPage.js +2 -2
  72. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  73. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +4 -4
  74. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
  75. package/dist/billing/modules/promotions/pages/PromotionsListPage.js +2 -2
  76. package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -1
  77. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +2 -2
  78. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  79. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +5 -5
  80. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  81. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +2 -2
  82. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  83. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +1 -1
  84. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  85. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +259 -265
  86. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  87. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +7 -7
  88. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  89. package/dist/billing/modules/usage/pages/UsagePage.js +13 -13
  90. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  91. package/dist/billing/shared/ui/Card.js +1 -1
  92. package/dist/billing/shared/ui/Card.js.map +1 -1
  93. package/dist/billing/shared/ui/MetricCard.js +28 -21
  94. package/dist/billing/shared/ui/MetricCard.js.map +1 -1
  95. 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';\nimport { ResponsiveTable, type ResponsiveTableColumn } from '@burdenoff/fe-libs/ui';\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-bg-sunken/50 transition-colors disabled:opacity-50\"\n aria-label=\"Refund actions\"\n >\n {isProcessing ? (\n <Loader2 className=\"size-4 animate-spin text-text-muted\" />\n ) : (\n <MoreHorizontal className=\"size-4 text-text-muted\" />\n )}\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-bg-elevated border border-border-subtle rounded-input shadow-[var(--shadow-elevation-3)] 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-text-primary hover:bg-bg-sunken/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-bg-sunken/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-bg-sunken/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-bg-sunken/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-bg-elevated border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] 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-subtle\">\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-bg-sunken/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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\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-subtle rounded-md hover:bg-bg-sunken/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 && <p className=\"text-xs text-text-muted mt-1\">Looking up transaction…</p>}\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-text-muted grid grid-cols-2 gap-x-4 gap-y-0.5 mt-1\">\n <span>\n Account:{' '}\n <span className=\"text-text-primary font-mono text-xs\">\n {lookedUp.billingAccountId.slice(0, 16)}…\n </span>\n </span>\n <span>\n Paid:{' '}\n <span className=\"text-text-primary\">\n {formatCurrency(lookedUp.totalAmount, lookedUp.currency)}\n </span>\n </span>\n <span>\n Provider:{' '}\n <span className=\"text-text-primary capitalize\">{formData.provider}</span>\n </span>\n <span>\n Currency: <span className=\"text-text-primary\">{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-text-muted mb-1\">Provider</label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm capitalize\">\n {formData.provider}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">Currency</label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm\">\n {formData.currency}\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">\n Gateway Payment ID\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/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-text-muted mb-1\">\n Purchase Type\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm\">\n {formData.purchaseType}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">\n Purchase Detail\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/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-text-muted 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-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] ${\n isAmountExceedingMax ? 'border-status-error-text' : 'border-border-subtle'\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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] 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-subtle rounded-md hover:bg-bg-sunken/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-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bgHover 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-bg-elevated border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] max-w-md w-full mx-4\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle\">\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-bg-sunken/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-subtle rounded-md bg-bg-surface 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-subtle rounded-md hover:bg-bg-sunken/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-action-primary-text 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-bg-elevated border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] 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-subtle\">\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-bg-sunken/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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-subtle\">\n <div>\n <p className=\"text-xs text-text-muted 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-text-muted 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-text-muted 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-subtle\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bgHover 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 const refundColumns: ResponsiveTableColumn<RefundRecord>[] = [\n {\n key: 'date',\n header: 'Date',\n priority: 'primary',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <div className=\"flex flex-col\">\n <span className=\"text-sm text-text-primary\">\n {formatDateTime(record.createdAt).split(' ')[0]}\n </span>\n <span className=\"text-xs text-text-muted\">\n {formatDateTime(record.createdAt).split(' ')[1]}\n </span>\n </div>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => {\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n return (\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\">{STATUS_CONFIG[record.status].label}</span>\n </span>\n );\n },\n },\n {\n key: 'source',\n header: 'Source',\n priority: 'hidden-on-mobile',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm text-text-muted\">{SOURCE_LABELS[record.source]}</span>\n ),\n },\n {\n key: 'provider',\n header: 'Provider',\n priority: 'hidden-on-mobile',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm text-text-primary capitalize\">{record.provider}</span>\n ),\n },\n {\n key: 'paymentId',\n header: 'Payment ID',\n cellClassName: 'whitespace-nowrap max-w-[120px] sm:max-w-[200px] truncate',\n cell: (record) => (\n <span className=\"text-sm font-mono text-text-muted\">{record.gatewayPaymentId}</span>\n ),\n },\n {\n key: 'amount',\n header: 'Amount',\n headerClassName: 'text-right',\n cellClassName: 'text-right whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm font-medium tabular-nums\">\n {formatCurrency(record.amount, record.currency)}\n </span>\n ),\n },\n {\n key: 'reason',\n header: 'Reason',\n priority: 'hidden-on-mobile',\n cellClassName: 'max-w-[200px] truncate',\n cell: (record) => <span className=\"text-sm text-text-muted\">{record.reason || '-'}</span>,\n },\n ];\n\n const renderRefundActions = (record: RefundRecord) => (\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 );\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-bg-sunken 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-bg-sunken 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-bg-sunken 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-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken/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-button bg-action-primary-bg text-action-primary-text hover:bg-action-primary-bgHover 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-subtle\">\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-action-primary-bg text-text-link'\n : 'border-transparent text-text-muted hover:text-text-primary hover:border-border-subtle'\n }`}\n >\n {TAB_CONFIG[tab].label}\n {stats && (\n <span\n className={`px-2 py-0.5 text-xs rounded-full ${\n isActive\n ? 'bg-[var(--color-accent-soft)] text-text-link'\n : 'bg-bg-sunken text-text-muted'\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-text-muted\" />\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-subtle rounded-md bg-bg-surface\"\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-action-primary-bg bg-[var(--color-accent-soft)] text-text-link'\n : 'border-border-subtle bg-bg-surface hover:bg-bg-sunken/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-action-primary-bg text-action-primary-text\">\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-text-muted hover:text-text-primary 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-subtle rounded-lg bg-bg-sunken/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-subtle rounded-md bg-bg-surface\"\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-subtle rounded-md bg-bg-surface\"\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-subtle rounded-md bg-bg-surface text-sm\"\n />\n <span className=\"text-text-muted 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-subtle rounded-md bg-bg-surface 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-text-muted\" />}\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-subtle rounded-lg overflow-hidden\">\n <ResponsiveTable<RefundRecord>\n columns={refundColumns}\n data={filteredRecords}\n rowKey={(record) => record.id}\n rowActions={renderRefundActions}\n />\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-subtle pt-4\">\n <p className=\"text-sm text-text-muted 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-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken/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-text-muted 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-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken/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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"}
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';\nimport {\n CTAOverflowMenu,\n ResponsiveTable,\n type ResponsiveTableColumn,\n type CTAAction,\n} from '@burdenoff/fe-libs/ui';\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-bg-sunken/50 transition-colors disabled:opacity-50\"\n aria-label=\"Refund actions\"\n >\n {isProcessing ? (\n <Loader2 className=\"size-4 animate-spin text-text-muted\" />\n ) : (\n <MoreHorizontal className=\"size-4 text-text-muted\" />\n )}\n </button>\n\n {isOpen && (\n <div className=\"absolute right-0 top-full mt-1 z-50 min-w-[160px] bg-bg-elevated border border-border-subtle rounded-input shadow-[var(--shadow-elevation-3)] 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-text-primary hover:bg-bg-sunken/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-bg-sunken/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-bg-sunken/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-bg-sunken/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-bg-elevated border border-border-seam rounded-card shadow-[var(--shadow-elevation-4)] 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-subtle\">\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-bg-sunken/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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\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-subtle rounded-md hover:bg-bg-sunken/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 && <p className=\"text-xs text-text-muted mt-1\">Looking up transaction…</p>}\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-text-muted grid grid-cols-2 gap-x-4 gap-y-0.5 mt-1\">\n <span>\n Account:{' '}\n <span className=\"text-text-primary font-mono text-xs\">\n {lookedUp.billingAccountId.slice(0, 16)}…\n </span>\n </span>\n <span>\n Paid:{' '}\n <span className=\"text-text-primary\">\n {formatCurrency(lookedUp.totalAmount, lookedUp.currency)}\n </span>\n </span>\n <span>\n Provider:{' '}\n <span className=\"text-text-primary capitalize\">{formData.provider}</span>\n </span>\n <span>\n Currency: <span className=\"text-text-primary\">{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-text-muted mb-1\">Provider</label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm capitalize\">\n {formData.provider}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">Currency</label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm\">\n {formData.currency}\n </div>\n </div>\n </div>\n\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">\n Gateway Payment ID\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/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-text-muted mb-1\">\n Purchase Type\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/30 text-sm\">\n {formData.purchaseType}\n </div>\n </div>\n <div>\n <label className=\"block text-xs font-medium text-text-muted mb-1\">\n Purchase Detail\n </label>\n <div className=\"px-3 py-2 border border-border-subtle rounded-md bg-bg-sunken/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-text-muted 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-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] ${\n isAmountExceedingMax ? 'border-status-error-text' : 'border-border-subtle'\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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\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-subtle rounded-input bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] 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-subtle rounded-md hover:bg-bg-sunken/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-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bgHover 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-bg-elevated border border-border-seam rounded-card shadow-[var(--shadow-elevation-4)] max-w-md w-full mx-4\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle\">\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-bg-sunken/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-subtle rounded-md bg-bg-surface 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-subtle rounded-md hover:bg-bg-sunken/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-action-primary-text 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-bg-elevated border border-border-seam rounded-card shadow-[var(--shadow-elevation-4)] 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-subtle\">\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-bg-sunken/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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-text-muted 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-subtle\">\n <div>\n <p className=\"text-xs text-text-muted 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-text-muted 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-text-muted 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-subtle\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"w-full py-2 px-4 bg-action-primary-bg text-action-primary-text rounded-md hover:bg-action-primary-bgHover 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 const refundColumns: ResponsiveTableColumn<RefundRecord>[] = [\n {\n key: 'date',\n header: 'Date',\n priority: 'primary',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <div className=\"flex flex-col\">\n <span className=\"text-sm text-text-primary\">\n {formatDateTime(record.createdAt).split(' ')[0]}\n </span>\n <span className=\"text-xs text-text-muted\">\n {formatDateTime(record.createdAt).split(' ')[1]}\n </span>\n </div>\n ),\n },\n {\n key: 'status',\n header: 'Status',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => {\n const StatusIcon = STATUS_CONFIG[record.status].icon;\n return (\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\">{STATUS_CONFIG[record.status].label}</span>\n </span>\n );\n },\n },\n {\n key: 'source',\n header: 'Source',\n priority: 'hidden-on-mobile',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm text-text-muted\">{SOURCE_LABELS[record.source]}</span>\n ),\n },\n {\n key: 'provider',\n header: 'Provider',\n priority: 'hidden-on-mobile',\n cellClassName: 'whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm text-text-primary capitalize\">{record.provider}</span>\n ),\n },\n {\n key: 'paymentId',\n header: 'Payment ID',\n cellClassName: 'whitespace-nowrap max-w-[120px] sm:max-w-[200px] truncate',\n cell: (record) => (\n <span className=\"text-sm font-mono text-text-muted\">{record.gatewayPaymentId}</span>\n ),\n },\n {\n key: 'amount',\n header: 'Amount',\n headerClassName: 'text-right',\n cellClassName: 'text-right whitespace-nowrap',\n cell: (record) => (\n <span className=\"text-sm font-medium tabular-nums\">\n {formatCurrency(record.amount, record.currency)}\n </span>\n ),\n },\n {\n key: 'reason',\n header: 'Reason',\n priority: 'hidden-on-mobile',\n cellClassName: 'max-w-[200px] truncate',\n cell: (record) => <span className=\"text-sm text-text-muted\">{record.reason || '-'}</span>,\n },\n ];\n\n const renderRefundActions = (record: RefundRecord) => (\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 );\n\n if (isLoading) {\n return (\n <div className=\"space-y-6 p-6\">\n <div className=\"h-8 w-48 bg-bg-sunken 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-bg-sunken 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-bg-sunken 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 <CTAOverflowMenu\n primary={{\n label: 'Create Manual Refund',\n onSelect: () => setShowCreateModal(true),\n icon: <Plus className=\"size-4\" />,\n }}\n actions={[\n ...(unprocessedWebhooks.length > 0\n ? [\n {\n label: `Import ${unprocessedWebhooks.length} Failed Webhooks`,\n onSelect: handleCreateFromWebhooks,\n disabled: isCreatingFromWebhooks,\n icon: isCreatingFromWebhooks ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Download className=\"size-4\" />\n ),\n },\n ]\n : []),\n {\n label: 'Refresh',\n onSelect: () => {\n void refetch();\n },\n icon: <RefreshCw className=\"size-4\" />,\n },\n ] satisfies CTAAction[]}\n />\n }\n />\n\n {/* Tabs Navigation */}\n <div className=\"border-b border-border-subtle\">\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-action-primary-bg text-text-link'\n : 'border-transparent text-text-muted hover:text-text-primary hover:border-border-subtle'\n }`}\n >\n {TAB_CONFIG[tab].label}\n {stats && (\n <span\n className={`px-2 py-0.5 text-xs rounded-full ${\n isActive\n ? 'bg-[var(--color-accent-soft)] text-text-link'\n : 'bg-bg-sunken text-text-muted'\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-text-muted\" />\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-subtle rounded-md bg-bg-surface\"\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-action-primary-bg bg-[var(--color-accent-soft)] text-text-link'\n : 'border-border-subtle bg-bg-surface hover:bg-bg-sunken/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-action-primary-bg text-action-primary-text\">\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-text-muted hover:text-text-primary 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-subtle rounded-lg bg-bg-sunken/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-subtle rounded-md bg-bg-surface\"\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-subtle rounded-md bg-bg-surface\"\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-subtle rounded-md bg-bg-surface text-sm\"\n />\n <span className=\"text-text-muted 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-subtle rounded-md bg-bg-surface 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-text-muted\" />}\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-subtle rounded-lg overflow-hidden\">\n <ResponsiveTable<RefundRecord>\n columns={refundColumns}\n data={filteredRecords}\n rowKey={(record) => record.id}\n rowActions={renderRefundActions}\n />\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-subtle pt-4\">\n <p className=\"text-sm text-text-muted 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-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken/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-text-muted 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-button border border-border-subtle bg-bg-surface hover:bg-bg-sunken/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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"}
@@ -185,7 +185,7 @@ var C = () => {
185
185
  })]
186
186
  }),
187
187
  C && /* @__PURE__ */ y("div", {
188
- className: "border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
188
+ className: "border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
189
189
  children: [/* @__PURE__ */ y("div", {
190
190
  className: "flex items-center justify-between p-4 border-b border-border-subtle bg-bg-sunken",
191
191
  children: [/* @__PURE__ */ v("h2", {
@@ -329,7 +329,7 @@ var C = () => {
329
329
  })]
330
330
  }),
331
331
  /* @__PURE__ */ y("div", {
332
- className: "border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
332
+ className: "border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden",
333
333
  children: [/* @__PURE__ */ v("div", {
334
334
  className: "p-4 border-b border-border-subtle bg-bg-sunken",
335
335
  children: /* @__PURE__ */ v("h2", {
@@ -1 +1 @@
1
- {"version":3,"file":"UserRefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/UserRefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - User Refunds Page\n * Shows the user's refund request history and allows submitting new requests.\n */\n\nimport { useState, useEffect, useRef, type FC, type FormEvent } from 'react';\nimport {\n RotateCcw,\n PlusCircle,\n X,\n Clock,\n CheckCircle,\n XCircle,\n Loader2,\n Search,\n CreditCard,\n} from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { formatCurrency, formatDateTime } from '../../../shared/utils';\nimport { PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useGetBillingAccountsCheckoutQuery,\n useGetTransactionLazyQuery,\n useGetRefundRecordsQuery,\n useCreateRefundRecordMutation,\n type GetRefundRecordsQuery,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { RefundRecordStatus } from '../../../../generated/global-types';\n\ntype RefundItem = NonNullable<GetRefundRecordsQuery['getRefundRecords']['records']>[number];\ntype TxnLookup = NonNullable<GetTransactionQuery['getTransaction']>;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// ============================================================================\n// Status helpers\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; className: string; icon: FC<{ className?: string }> }\n> = {\n [RefundRecordStatus.Pending]: {\n label: 'In Review',\n className: 'bg-status-warning-bg/20 text-status-warning-text border-status-warning-border',\n icon: ({ className }) => <Clock className={className} />,\n },\n [RefundRecordStatus.Processing]: {\n label: 'Processing',\n className: 'bg-action-primary-bg/15 text-action-primary-bg border-action-primary-bg/30',\n icon: ({ className }) => <Loader2 className={`${className} animate-spin`} />,\n },\n [RefundRecordStatus.Completed]: {\n label: 'Refunded',\n className: 'bg-status-success-bg/20 text-status-success-text border-status-success-border',\n icon: ({ className }) => <CheckCircle className={className} />,\n },\n [RefundRecordStatus.Failed]: {\n label: 'Failed',\n className: 'bg-status-error-bg/20 text-status-error-text border-status-error-border',\n icon: ({ className }) => <XCircle className={className} />,\n },\n [RefundRecordStatus.Skipped]: {\n label: 'Closed',\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }) => <XCircle className={className} />,\n },\n};\n\nfunction StatusBadge({ status }: { status: string }) {\n const cfg = STATUS_CONFIG[status as RefundRecordStatus] ?? {\n label: status,\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }: { className?: string }) => <Clock className={className} />,\n };\n const Icon = cfg.icon;\n return (\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-xs font-medium ${cfg.className}`}\n >\n <Icon className=\"size-3\" />\n {cfg.label}\n </span>\n );\n}\n\n// ============================================================================\n// Main page\n// ============================================================================\n\nexport const UserRefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const navigateTo = useBillingNavigate();\n\n // Form state\n const [showForm, setShowForm] = useState(false);\n const [txnIdInput, setTxnIdInput] = useState('');\n const [lookedUpTxn, setLookedUpTxn] = useState<TxnLookup | null>(null);\n const [txnNotFound, setTxnNotFound] = useState(false);\n const [reason, setReason] = useState('');\n const [amount, setAmount] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n const [formSuccess, setFormSuccess] = useState(false);\n\n // All billing accounts\n const { data: accountsData, loading: accountsLoading } = useGetBillingAccountsCheckoutQuery({\n fetchPolicy: 'cache-and-network',\n });\n type BillingAccount = NonNullable<typeof accountsData>['getBillingAccountsByOrg'][number];\n const accounts: BillingAccount[] = accountsData?.getBillingAccountsByOrg ?? [];\n\n // Default to the first account; user can switch\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!selectedAccountId && accounts.length > 0) {\n setSelectedAccountId(accounts[0].id);\n }\n }, [accounts, selectedAccountId]);\n\n const selectedAccount = accounts.find((a) => a.id === selectedAccountId);\n\n // Transaction lookup by ID (lazy — fires when user enters a valid UUID)\n const [fetchTxn, { data: txnLookupData, loading: txnLookupLoading, error: txnLookupError }] =\n useGetTransactionLazyQuery({ fetchPolicy: 'network-only' });\n\n // Track the \"active\" lookup key so we only apply results for the latest request\n const lastLookupKey = useRef('');\n\n useEffect(() => {\n if (txnLookupLoading) return;\n const txn = txnLookupData?.getTransaction;\n if (txn) {\n setLookedUpTxn(txn);\n setTxnNotFound(false);\n setAmount(String(txn.amount));\n } else if (txnLookupData !== undefined || txnLookupError) {\n setLookedUpTxn(null);\n setTxnNotFound(true);\n setAmount('');\n }\n }, [txnLookupData, txnLookupLoading, txnLookupError]);\n\n const triggerLookup = (txnId: string, accountId: string) => {\n const key = `${txnId}::${accountId}`;\n lastLookupKey.current = key;\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n fetchTxn({ variables: { id: txnId, billingAccountId: accountId } });\n };\n\n const handleTxnIdChange = (value: string) => {\n setTxnIdInput(value);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(value.trim()) && selectedAccountId) {\n triggerLookup(value.trim(), selectedAccountId);\n }\n };\n\n // When account changes, re-fetch the transaction if one is entered\n const handleAccountChange = (accountId: string) => {\n setSelectedAccountId(accountId);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(txnIdInput.trim())) {\n triggerLookup(txnIdInput.trim(), accountId);\n }\n };\n\n // Refund history for selected account\n const {\n data: refundsData,\n loading: refundsLoading,\n refetch: refetchRefunds,\n } = useGetRefundRecordsQuery({\n variables: { billingAccountId: selectedAccountId, pageSize: 20, page: 1 },\n skip: !selectedAccountId,\n fetchPolicy: 'cache-and-network',\n });\n const refunds = refundsData?.getRefundRecords.records ?? [];\n\n const [createRefund, { loading: isSubmitting }] = useCreateRefundRecordMutation({\n refetchQueries: ['GetRefundRecords'],\n });\n\n const getGatewayInfo = (txn: TxnLookup | null) => {\n if (!txn) return null;\n if (txn.stripePaymentId) return { provider: 'STRIPE', gatewayPaymentId: txn.stripePaymentId };\n if (txn.razorpayPaymentId)\n return { provider: 'RAZORPAY', gatewayPaymentId: txn.razorpayPaymentId };\n return null;\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setFormError(null);\n\n if (!lookedUpTxn || !reason.trim() || !amount) {\n setFormError('Enter a valid transaction ID, an amount, and a reason.');\n return;\n }\n const gatewayInfo = getGatewayInfo(lookedUpTxn);\n if (!gatewayInfo) {\n setFormError('No payment gateway info found for this transaction. Please contact support.');\n return;\n }\n const parsedAmount = parseFloat(amount);\n if (isNaN(parsedAmount) || parsedAmount <= 0) {\n setFormError('Please enter a valid amount greater than 0.');\n return;\n }\n if (parsedAmount > lookedUpTxn.amount) {\n setFormError(\n `Cannot exceed the original payment amount (${formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}).`\n );\n return;\n }\n\n try {\n await createRefund({\n variables: {\n billingAccountId: selectedAccountId,\n provider: gatewayInfo.provider,\n gatewayPaymentId: gatewayInfo.gatewayPaymentId,\n amount: parsedAmount,\n currency: lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD',\n transactionId: lookedUpTxn.id,\n reason: reason.trim(),\n notes: `Requested by user via billing portal`,\n },\n });\n setFormSuccess(true);\n setShowForm(false);\n resetFormFields();\n await refetchRefunds();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to submit refund request.');\n }\n };\n\n const resetFormFields = () => {\n setTxnIdInput('');\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setReason('');\n setAmount('');\n setFormError(null);\n };\n\n const resetForm = () => {\n setShowForm(false);\n setFormSuccess(false);\n resetFormFields();\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refunds')}\n description={tr(\n 'billing.refunds.description',\n 'View your refund requests and submit new ones'\n )}\n actions={\n !showForm ? (\n <button\n type=\"button\"\n onClick={() => {\n setShowForm(true);\n setFormSuccess(false);\n }}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors\"\n >\n <PlusCircle className=\"size-4\" />\n {tr('billing.refunds.requestRefund', 'Request Refund')}\n </button>\n ) : undefined\n }\n />\n\n {/* Billing account switcher */}\n {!accountsLoading && accounts.length > 1 && (\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"size-4 text-text-secondary shrink-0\" />\n <label htmlFor=\"accountSwitch\" className=\"text-sm text-text-secondary shrink-0\">\n {tr('billing.refunds.account', 'Billing account')}\n </label>\n <select\n id=\"accountSwitch\"\n value={selectedAccountId ?? ''}\n onChange={(e) => handleAccountChange(e.target.value)}\n className=\"flex-1 px-3 py-1.5 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n >\n {accounts.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.currency}) — {a.email}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Success banner */}\n {formSuccess && (\n <div className=\"flex items-center justify-between p-4 rounded-lg border border-status-success-border bg-status-success-bg/10\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-4 text-status-success-text\" />\n <p className=\"text-sm text-status-success-text font-medium\">\n {tr(\n 'billing.refunds.submitted',\n 'Refund request submitted. Our team will review it shortly.'\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => setFormSuccess(false)}\n className=\"text-status-success-text hover:opacity-70\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n )}\n\n {/* Request Refund Form */}\n {showForm && (\n <div className=\"border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.newRequest', 'New Refund Request')}\n </h2>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-4 text-text-secondary\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {formError && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg/10\">\n <p className=\"text-sm text-status-error-text\">{formError}</p>\n </div>\n )}\n\n {/* Transaction ID lookup */}\n <div>\n <label htmlFor=\"txnId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.transactionId', 'Transaction ID')} *\n </label>\n <div className=\"relative\">\n <input\n id=\"txnId\"\n type=\"text\"\n value={txnIdInput}\n onChange={(e) => handleTxnIdChange(e.target.value)}\n placeholder=\"Paste your transaction ID...\"\n className=\"w-full pl-3 pr-9 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm font-mono\"\n />\n <div className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-text-secondary\">\n {txnLookupLoading ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n </div>\n </div>\n\n {/* Transaction lookup result */}\n {lookedUpTxn && (\n <div className=\"mt-2 p-3 rounded-button border border-status-success-border bg-status-success-bg/10 text-sm space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-3.5 text-status-success-text shrink-0\" />\n <span className=\"font-medium text-text-primary\">\n {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n <span className=\"text-text-secondary\">·</span>\n <span className=\"text-text-secondary\">\n {formatDateTime(lookedUpTxn.createdAt)}\n </span>\n {lookedUpTxn.stripePaymentId && (\n <span className=\"text-xs text-text-secondary\">Stripe</span>\n )}\n {lookedUpTxn.razorpayPaymentId && (\n <span className=\"text-xs text-text-secondary\">Razorpay</span>\n )}\n </div>\n {lookedUpTxn.description && (\n <p className=\"text-xs text-text-secondary pl-5\">{lookedUpTxn.description}</p>\n )}\n </div>\n )}\n {txnNotFound && txnIdInput.length > 0 && !txnLookupLoading && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr(\n 'billing.refunds.txnNotFound',\n 'Transaction not found in this billing account.'\n )}\n </p>\n )}\n {!UUID_RE.test(txnIdInput.trim()) && txnIdInput.length > 4 && (\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.txnIdHint',\n 'Transaction IDs look like: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n )}\n </p>\n )}\n </div>\n\n {/* Amount — only shown once transaction is found */}\n {lookedUpTxn && (\n <div>\n <label\n htmlFor=\"refundAmount\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('billing.refunds.amount', 'Refund Amount')} *\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n id=\"refundAmount\"\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={lookedUpTxn.amount}\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n required\n className=\"w-40 px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n placeholder=\"0.00\"\n />\n <span className=\"text-sm text-text-secondary\">\n {lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD'}\n </span>\n <span className=\"text-xs text-text-secondary\">\n max {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n </div>\n </div>\n )}\n\n {/* Reason */}\n <div>\n <label htmlFor=\"reason\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.reason', 'Reason for refund')} *\n </label>\n <textarea\n id=\"reason\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n required\n rows={3}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm resize-none\"\n placeholder={tr(\n 'billing.refunds.reasonPlaceholder',\n 'Describe why you are requesting a refund...'\n )}\n />\n </div>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !lookedUpTxn || !reason.trim() || !amount}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting\n ? tr('billing.refunds.submitting', 'Submitting...')\n : tr('billing.refunds.submitRequest', 'Submit Request')}\n </button>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"px-4 py-2 text-sm border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors\"\n >\n {tr('billing.common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n </div>\n )}\n\n {/* Refund history */}\n <div className=\"border border-border-subtle rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.history', 'Refund History')}\n </h2>\n </div>\n\n {accountsLoading || refundsLoading ? (\n <div className=\"p-8 flex items-center justify-center\">\n <Loader2 className=\"size-5 animate-spin text-text-secondary\" />\n </div>\n ) : refunds.length === 0 ? (\n <div className=\"p-10 flex flex-col items-center text-center gap-3\">\n <RotateCcw className=\"size-8 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('billing.refunds.noRefunds', 'No refund requests yet')}\n </p>\n <p className=\"text-xs text-text-secondary max-w-sm\">\n {tr(\n 'billing.refunds.noRefundsHint',\n 'If you have an issue with a payment, click \"Request Refund\" to get started.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"divide-y divide-border-subtle\">\n {refunds.map((r: RefundItem) => (\n <li\n key={r.id}\n className=\"flex items-start gap-4 p-4 hover:bg-bg-sunken transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(r.amount, r.currency)}\n </span>\n <StatusBadge status={r.status} />\n {r.purchaseDetail && (\n <span className=\"text-xs text-text-secondary truncate\">\n {r.purchaseDetail}\n </span>\n )}\n </div>\n {r.reason && (\n <p className=\"text-xs text-text-secondary mt-1 line-clamp-2\">{r.reason}</p>\n )}\n {r.errorMessage && r.status === RefundRecordStatus.Failed && (\n <p className=\"text-xs text-status-error-text mt-1\">{r.errorMessage}</p>\n )}\n </div>\n <div className=\"text-right shrink-0\">\n <p className=\"text-xs text-text-secondary\">{formatDateTime(r.createdAt)}</p>\n {r.processedAt && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Processed {formatDateTime(r.processedAt)}\n </p>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.footer',\n 'Refund requests are reviewed by our team within 3–5 business days. For urgent issues, contact support.'\n )}{' '}\n <button\n type=\"button\"\n onClick={() => navigateTo('/transactions/' + selectedAccountId)}\n className=\"underline hover:no-underline\"\n >\n {tr('billing.refunds.viewTransactions', 'View all transactions')}\n </button>\n </p>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"UserRefundsPage.js","names":[],"sources":["../../../../../src/billing/modules/billing/pages/UserRefundsPage.tsx"],"sourcesContent":["/**\n * Billing Module - User Refunds Page\n * Shows the user's refund request history and allows submitting new requests.\n */\n\nimport { useState, useEffect, useRef, type FC, type FormEvent } from 'react';\nimport {\n RotateCcw,\n PlusCircle,\n X,\n Clock,\n CheckCircle,\n XCircle,\n Loader2,\n Search,\n CreditCard,\n} from 'lucide-react';\nimport { useBillingNavigate } from '../../../hooks/useBillingNavigate';\nimport { formatCurrency, formatDateTime } from '../../../shared/utils';\nimport { PageHeader } from '../../../shared/components';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n useGetBillingAccountsCheckoutQuery,\n useGetTransactionLazyQuery,\n useGetRefundRecordsQuery,\n useCreateRefundRecordMutation,\n type GetRefundRecordsQuery,\n type GetTransactionQuery,\n} from '../../../../generated/global-operations';\nimport { RefundRecordStatus } from '../../../../generated/global-types';\n\ntype RefundItem = NonNullable<GetRefundRecordsQuery['getRefundRecords']['records']>[number];\ntype TxnLookup = NonNullable<GetTransactionQuery['getTransaction']>;\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\n\n// ============================================================================\n// Status helpers\n// ============================================================================\n\nconst STATUS_CONFIG: Record<\n RefundRecordStatus,\n { label: string; className: string; icon: FC<{ className?: string }> }\n> = {\n [RefundRecordStatus.Pending]: {\n label: 'In Review',\n className: 'bg-status-warning-bg/20 text-status-warning-text border-status-warning-border',\n icon: ({ className }) => <Clock className={className} />,\n },\n [RefundRecordStatus.Processing]: {\n label: 'Processing',\n className: 'bg-action-primary-bg/15 text-action-primary-bg border-action-primary-bg/30',\n icon: ({ className }) => <Loader2 className={`${className} animate-spin`} />,\n },\n [RefundRecordStatus.Completed]: {\n label: 'Refunded',\n className: 'bg-status-success-bg/20 text-status-success-text border-status-success-border',\n icon: ({ className }) => <CheckCircle className={className} />,\n },\n [RefundRecordStatus.Failed]: {\n label: 'Failed',\n className: 'bg-status-error-bg/20 text-status-error-text border-status-error-border',\n icon: ({ className }) => <XCircle className={className} />,\n },\n [RefundRecordStatus.Skipped]: {\n label: 'Closed',\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }) => <XCircle className={className} />,\n },\n};\n\nfunction StatusBadge({ status }: { status: string }) {\n const cfg = STATUS_CONFIG[status as RefundRecordStatus] ?? {\n label: status,\n className: 'bg-bg-sunken text-text-secondary border-border-subtle',\n icon: ({ className }: { className?: string }) => <Clock className={className} />,\n };\n const Icon = cfg.icon;\n return (\n <span\n className={`inline-flex items-center gap-1 px-2 py-0.5 rounded-full border text-xs font-medium ${cfg.className}`}\n >\n <Icon className=\"size-3\" />\n {cfg.label}\n </span>\n );\n}\n\n// ============================================================================\n// Main page\n// ============================================================================\n\nexport const UserRefundsPage: FC = () => {\n const { t } = useI18n();\n const tr = (key: string, fallback: string) => {\n const v = t(key);\n return v === key ? fallback : v;\n };\n const navigateTo = useBillingNavigate();\n\n // Form state\n const [showForm, setShowForm] = useState(false);\n const [txnIdInput, setTxnIdInput] = useState('');\n const [lookedUpTxn, setLookedUpTxn] = useState<TxnLookup | null>(null);\n const [txnNotFound, setTxnNotFound] = useState(false);\n const [reason, setReason] = useState('');\n const [amount, setAmount] = useState('');\n const [formError, setFormError] = useState<string | null>(null);\n const [formSuccess, setFormSuccess] = useState(false);\n\n // All billing accounts\n const { data: accountsData, loading: accountsLoading } = useGetBillingAccountsCheckoutQuery({\n fetchPolicy: 'cache-and-network',\n });\n type BillingAccount = NonNullable<typeof accountsData>['getBillingAccountsByOrg'][number];\n const accounts: BillingAccount[] = accountsData?.getBillingAccountsByOrg ?? [];\n\n // Default to the first account; user can switch\n const [selectedAccountId, setSelectedAccountId] = useState<string | undefined>(undefined);\n useEffect(() => {\n if (!selectedAccountId && accounts.length > 0) {\n setSelectedAccountId(accounts[0].id);\n }\n }, [accounts, selectedAccountId]);\n\n const selectedAccount = accounts.find((a) => a.id === selectedAccountId);\n\n // Transaction lookup by ID (lazy — fires when user enters a valid UUID)\n const [fetchTxn, { data: txnLookupData, loading: txnLookupLoading, error: txnLookupError }] =\n useGetTransactionLazyQuery({ fetchPolicy: 'network-only' });\n\n // Track the \"active\" lookup key so we only apply results for the latest request\n const lastLookupKey = useRef('');\n\n useEffect(() => {\n if (txnLookupLoading) return;\n const txn = txnLookupData?.getTransaction;\n if (txn) {\n setLookedUpTxn(txn);\n setTxnNotFound(false);\n setAmount(String(txn.amount));\n } else if (txnLookupData !== undefined || txnLookupError) {\n setLookedUpTxn(null);\n setTxnNotFound(true);\n setAmount('');\n }\n }, [txnLookupData, txnLookupLoading, txnLookupError]);\n\n const triggerLookup = (txnId: string, accountId: string) => {\n const key = `${txnId}::${accountId}`;\n lastLookupKey.current = key;\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n fetchTxn({ variables: { id: txnId, billingAccountId: accountId } });\n };\n\n const handleTxnIdChange = (value: string) => {\n setTxnIdInput(value);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(value.trim()) && selectedAccountId) {\n triggerLookup(value.trim(), selectedAccountId);\n }\n };\n\n // When account changes, re-fetch the transaction if one is entered\n const handleAccountChange = (accountId: string) => {\n setSelectedAccountId(accountId);\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setAmount('');\n if (UUID_RE.test(txnIdInput.trim())) {\n triggerLookup(txnIdInput.trim(), accountId);\n }\n };\n\n // Refund history for selected account\n const {\n data: refundsData,\n loading: refundsLoading,\n refetch: refetchRefunds,\n } = useGetRefundRecordsQuery({\n variables: { billingAccountId: selectedAccountId, pageSize: 20, page: 1 },\n skip: !selectedAccountId,\n fetchPolicy: 'cache-and-network',\n });\n const refunds = refundsData?.getRefundRecords.records ?? [];\n\n const [createRefund, { loading: isSubmitting }] = useCreateRefundRecordMutation({\n refetchQueries: ['GetRefundRecords'],\n });\n\n const getGatewayInfo = (txn: TxnLookup | null) => {\n if (!txn) return null;\n if (txn.stripePaymentId) return { provider: 'STRIPE', gatewayPaymentId: txn.stripePaymentId };\n if (txn.razorpayPaymentId)\n return { provider: 'RAZORPAY', gatewayPaymentId: txn.razorpayPaymentId };\n return null;\n };\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault();\n setFormError(null);\n\n if (!lookedUpTxn || !reason.trim() || !amount) {\n setFormError('Enter a valid transaction ID, an amount, and a reason.');\n return;\n }\n const gatewayInfo = getGatewayInfo(lookedUpTxn);\n if (!gatewayInfo) {\n setFormError('No payment gateway info found for this transaction. Please contact support.');\n return;\n }\n const parsedAmount = parseFloat(amount);\n if (isNaN(parsedAmount) || parsedAmount <= 0) {\n setFormError('Please enter a valid amount greater than 0.');\n return;\n }\n if (parsedAmount > lookedUpTxn.amount) {\n setFormError(\n `Cannot exceed the original payment amount (${formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}).`\n );\n return;\n }\n\n try {\n await createRefund({\n variables: {\n billingAccountId: selectedAccountId,\n provider: gatewayInfo.provider,\n gatewayPaymentId: gatewayInfo.gatewayPaymentId,\n amount: parsedAmount,\n currency: lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD',\n transactionId: lookedUpTxn.id,\n reason: reason.trim(),\n notes: `Requested by user via billing portal`,\n },\n });\n setFormSuccess(true);\n setShowForm(false);\n resetFormFields();\n await refetchRefunds();\n } catch (err) {\n setFormError(err instanceof Error ? err.message : 'Failed to submit refund request.');\n }\n };\n\n const resetFormFields = () => {\n setTxnIdInput('');\n setLookedUpTxn(null);\n setTxnNotFound(false);\n setReason('');\n setAmount('');\n setFormError(null);\n };\n\n const resetForm = () => {\n setShowForm(false);\n setFormSuccess(false);\n resetFormFields();\n };\n\n return (\n <div className=\"space-y-6 p-6 max-w-3xl\">\n <PageHeader\n title={tr('billing.refunds.title', 'Refunds')}\n description={tr(\n 'billing.refunds.description',\n 'View your refund requests and submit new ones'\n )}\n actions={\n !showForm ? (\n <button\n type=\"button\"\n onClick={() => {\n setShowForm(true);\n setFormSuccess(false);\n }}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors\"\n >\n <PlusCircle className=\"size-4\" />\n {tr('billing.refunds.requestRefund', 'Request Refund')}\n </button>\n ) : undefined\n }\n />\n\n {/* Billing account switcher */}\n {!accountsLoading && accounts.length > 1 && (\n <div className=\"flex items-center gap-3\">\n <CreditCard className=\"size-4 text-text-secondary shrink-0\" />\n <label htmlFor=\"accountSwitch\" className=\"text-sm text-text-secondary shrink-0\">\n {tr('billing.refunds.account', 'Billing account')}\n </label>\n <select\n id=\"accountSwitch\"\n value={selectedAccountId ?? ''}\n onChange={(e) => handleAccountChange(e.target.value)}\n className=\"flex-1 px-3 py-1.5 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n >\n {accounts.map((a) => (\n <option key={a.id} value={a.id}>\n {a.name} ({a.currency}) — {a.email}\n </option>\n ))}\n </select>\n </div>\n )}\n\n {/* Success banner */}\n {formSuccess && (\n <div className=\"flex items-center justify-between p-4 rounded-lg border border-status-success-border bg-status-success-bg/10\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-4 text-status-success-text\" />\n <p className=\"text-sm text-status-success-text font-medium\">\n {tr(\n 'billing.refunds.submitted',\n 'Refund request submitted. Our team will review it shortly.'\n )}\n </p>\n </div>\n <button\n type=\"button\"\n onClick={() => setFormSuccess(false)}\n className=\"text-status-success-text hover:opacity-70\"\n >\n <X className=\"size-4\" />\n </button>\n </div>\n )}\n\n {/* Request Refund Form */}\n {showForm && (\n <div className=\"border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"flex items-center justify-between p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.newRequest', 'New Refund Request')}\n </h2>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"p-1 rounded hover:bg-bg-sunken transition-colors\"\n >\n <X className=\"size-4 text-text-secondary\" />\n </button>\n </div>\n\n <form onSubmit={handleSubmit} className=\"p-4 space-y-4\">\n {formError && (\n <div className=\"p-3 rounded-lg border border-status-error-border bg-status-error-bg/10\">\n <p className=\"text-sm text-status-error-text\">{formError}</p>\n </div>\n )}\n\n {/* Transaction ID lookup */}\n <div>\n <label htmlFor=\"txnId\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.transactionId', 'Transaction ID')} *\n </label>\n <div className=\"relative\">\n <input\n id=\"txnId\"\n type=\"text\"\n value={txnIdInput}\n onChange={(e) => handleTxnIdChange(e.target.value)}\n placeholder=\"Paste your transaction ID...\"\n className=\"w-full pl-3 pr-9 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm font-mono\"\n />\n <div className=\"absolute right-2.5 top-1/2 -translate-y-1/2 text-text-secondary\">\n {txnLookupLoading ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Search className=\"size-4\" />\n )}\n </div>\n </div>\n\n {/* Transaction lookup result */}\n {lookedUpTxn && (\n <div className=\"mt-2 p-3 rounded-button border border-status-success-border bg-status-success-bg/10 text-sm space-y-0.5\">\n <div className=\"flex items-center gap-2\">\n <CheckCircle className=\"size-3.5 text-status-success-text shrink-0\" />\n <span className=\"font-medium text-text-primary\">\n {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n <span className=\"text-text-secondary\">·</span>\n <span className=\"text-text-secondary\">\n {formatDateTime(lookedUpTxn.createdAt)}\n </span>\n {lookedUpTxn.stripePaymentId && (\n <span className=\"text-xs text-text-secondary\">Stripe</span>\n )}\n {lookedUpTxn.razorpayPaymentId && (\n <span className=\"text-xs text-text-secondary\">Razorpay</span>\n )}\n </div>\n {lookedUpTxn.description && (\n <p className=\"text-xs text-text-secondary pl-5\">{lookedUpTxn.description}</p>\n )}\n </div>\n )}\n {txnNotFound && txnIdInput.length > 0 && !txnLookupLoading && (\n <p className=\"mt-1 text-xs text-status-error-text\">\n {tr(\n 'billing.refunds.txnNotFound',\n 'Transaction not found in this billing account.'\n )}\n </p>\n )}\n {!UUID_RE.test(txnIdInput.trim()) && txnIdInput.length > 4 && (\n <p className=\"mt-1 text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.txnIdHint',\n 'Transaction IDs look like: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'\n )}\n </p>\n )}\n </div>\n\n {/* Amount — only shown once transaction is found */}\n {lookedUpTxn && (\n <div>\n <label\n htmlFor=\"refundAmount\"\n className=\"block text-sm font-medium text-text-primary mb-1\"\n >\n {tr('billing.refunds.amount', 'Refund Amount')} *\n </label>\n <div className=\"flex items-center gap-2\">\n <input\n id=\"refundAmount\"\n type=\"number\"\n step=\"0.01\"\n min=\"0.01\"\n max={lookedUpTxn.amount}\n value={amount}\n onChange={(e) => setAmount(e.target.value)}\n required\n className=\"w-40 px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm\"\n placeholder=\"0.00\"\n />\n <span className=\"text-sm text-text-secondary\">\n {lookedUpTxn.currency ?? selectedAccount?.currency ?? 'USD'}\n </span>\n <span className=\"text-xs text-text-secondary\">\n max {formatCurrency(lookedUpTxn.amount, lookedUpTxn.currency)}\n </span>\n </div>\n </div>\n )}\n\n {/* Reason */}\n <div>\n <label htmlFor=\"reason\" className=\"block text-sm font-medium text-text-primary mb-1\">\n {tr('billing.refunds.reason', 'Reason for refund')} *\n </label>\n <textarea\n id=\"reason\"\n value={reason}\n onChange={(e) => setReason(e.target.value)}\n required\n rows={3}\n className=\"w-full px-3 py-2 border border-border-subtle rounded-button bg-bg-surface text-text-primary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] text-sm resize-none\"\n placeholder={tr(\n 'billing.refunds.reasonPlaceholder',\n 'Describe why you are requesting a refund...'\n )}\n />\n </div>\n\n <div className=\"flex items-center gap-3 pt-1\">\n <button\n type=\"submit\"\n disabled={isSubmitting || !lookedUpTxn || !reason.trim() || !amount}\n className=\"px-4 py-2 text-sm font-medium bg-action-primary-bg text-action-primary-text rounded-button hover:bg-action-primary-bgHover transition-colors disabled:opacity-50 disabled:cursor-not-allowed\"\n >\n {isSubmitting\n ? tr('billing.refunds.submitting', 'Submitting...')\n : tr('billing.refunds.submitRequest', 'Submit Request')}\n </button>\n <button\n type=\"button\"\n onClick={resetForm}\n className=\"px-4 py-2 text-sm border border-border-subtle text-text-primary rounded-button hover:bg-bg-sunken transition-colors\"\n >\n {tr('billing.common.cancel', 'Cancel')}\n </button>\n </div>\n </form>\n </div>\n )}\n\n {/* Refund history */}\n <div className=\"border border-border-seam rounded-card bg-bg-surface shadow-elevation-1 overflow-hidden\">\n <div className=\"p-4 border-b border-border-subtle bg-bg-sunken\">\n <h2 className=\"font-semibold text-text-primary\">\n {tr('billing.refunds.history', 'Refund History')}\n </h2>\n </div>\n\n {accountsLoading || refundsLoading ? (\n <div className=\"p-8 flex items-center justify-center\">\n <Loader2 className=\"size-5 animate-spin text-text-secondary\" />\n </div>\n ) : refunds.length === 0 ? (\n <div className=\"p-10 flex flex-col items-center text-center gap-3\">\n <RotateCcw className=\"size-8 text-text-secondary\" />\n <p className=\"text-sm font-medium text-text-primary\">\n {tr('billing.refunds.noRefunds', 'No refund requests yet')}\n </p>\n <p className=\"text-xs text-text-secondary max-w-sm\">\n {tr(\n 'billing.refunds.noRefundsHint',\n 'If you have an issue with a payment, click \"Request Refund\" to get started.'\n )}\n </p>\n </div>\n ) : (\n <ul className=\"divide-y divide-border-subtle\">\n {refunds.map((r: RefundItem) => (\n <li\n key={r.id}\n className=\"flex items-start gap-4 p-4 hover:bg-bg-sunken transition-colors\"\n >\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium text-text-primary\">\n {formatCurrency(r.amount, r.currency)}\n </span>\n <StatusBadge status={r.status} />\n {r.purchaseDetail && (\n <span className=\"text-xs text-text-secondary truncate\">\n {r.purchaseDetail}\n </span>\n )}\n </div>\n {r.reason && (\n <p className=\"text-xs text-text-secondary mt-1 line-clamp-2\">{r.reason}</p>\n )}\n {r.errorMessage && r.status === RefundRecordStatus.Failed && (\n <p className=\"text-xs text-status-error-text mt-1\">{r.errorMessage}</p>\n )}\n </div>\n <div className=\"text-right shrink-0\">\n <p className=\"text-xs text-text-secondary\">{formatDateTime(r.createdAt)}</p>\n {r.processedAt && (\n <p className=\"text-xs text-text-secondary mt-0.5\">\n Processed {formatDateTime(r.processedAt)}\n </p>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n </div>\n\n <p className=\"text-xs text-text-secondary\">\n {tr(\n 'billing.refunds.footer',\n 'Refund requests are reviewed by our team within 3–5 business days. For urgent issues, contact support.'\n )}{' '}\n <button\n type=\"button\"\n onClick={() => navigateTo('/transactions/' + selectedAccountId)}\n className=\"underline hover:no-underline\"\n >\n {tr('billing.refunds.viewTransactions', 'View all transactions')}\n </button>\n </p>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAkCA,IAAM,IAAU,mEAMV,IAGF;EACD,EAAmB,UAAU;EAC5B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAkB,cAAa,CAAA;EACzD;EACA,EAAmB,aAAa;EAC/B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAS,WAAW,GAAG,EAAU,gBAAkB,CAAA;EAC7E;EACA,EAAmB,YAAY;EAC9B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAwB,cAAa,CAAA;EAC/D;EACA,EAAmB,SAAS;EAC3B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAoB,cAAa,CAAA;EAC3D;EACA,EAAmB,UAAU;EAC5B,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAgB,kBAAC,GAAD,EAAoB,cAAa,CAAA;EAC3D;CACF;AAED,SAAS,GAAY,EAAE,aAA8B;CACnD,IAAM,IAAM,EAAc,MAAiC;EACzD,OAAO;EACP,WAAW;EACX,OAAO,EAAE,mBAAwC,kBAAC,GAAD,EAAkB,cAAa,CAAA;EACjF,EACK,IAAO,EAAI;AACjB,QACE,kBAAC,QAAD;EACE,WAAW,sFAAsF,EAAI;YADvG,CAGE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC1B,EAAI,MACA;;;AAQX,IAAa,UAA4B;CACvC,IAAM,EAAE,SAAM,GAAS,EACjB,KAAM,GAAa,MAAqB;EAC5C,IAAM,IAAI,EAAE,EAAI;AAChB,SAAO,MAAM,IAAM,IAAW;IAE1B,IAAa,GAAoB,EAGjC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAY,KAAiB,EAAS,GAAG,EAC1C,CAAC,GAAa,KAAkB,EAA2B,KAAK,EAChE,CAAC,GAAa,KAAkB,EAAS,GAAM,EAC/C,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAQ,KAAa,EAAS,GAAG,EAClC,CAAC,GAAW,KAAgB,EAAwB,KAAK,EACzD,CAAC,IAAa,KAAkB,EAAS,GAAM,EAG/C,EAAE,MAAM,IAAc,SAAS,MAAoB,EAAmC,EAC1F,aAAa,qBACd,CAAC,EAEI,IAA6B,IAAc,2BAA2B,EAAE,EAGxE,CAAC,GAAmB,KAAwB,EAA6B,KAAA,EAAU;AACzF,SAAgB;AACd,EAAI,CAAC,KAAqB,EAAS,SAAS,KAC1C,EAAqB,EAAS,GAAG,GAAG;IAErC,CAAC,GAAU,EAAkB,CAAC;CAEjC,IAAM,IAAkB,EAAS,MAAM,MAAM,EAAE,OAAO,EAAkB,EAGlE,CAAC,GAAU,EAAE,MAAM,GAAe,SAAS,GAAkB,OAAO,OACxE,EAA2B,EAAE,aAAa,gBAAgB,CAAC,EAGvD,IAAgB,EAAO,GAAG;AAEhC,SAAgB;AACd,MAAI,EAAkB;EACtB,IAAM,IAAM,GAAe;AAC3B,EAAI,KACF,EAAe,EAAI,EACnB,EAAe,GAAM,EACrB,EAAU,OAAO,EAAI,OAAO,CAAC,KACpB,MAAkB,KAAA,KAAa,OACxC,EAAe,KAAK,EACpB,EAAe,GAAK,EACpB,EAAU,GAAG;IAEd;EAAC;EAAe;EAAkB;EAAe,CAAC;CAErD,IAAM,KAAiB,GAAe,MAAsB;AAM1D,EAJA,EAAc,UADF,GAAG,EAAM,IAAI,KAEzB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACb,EAAS,EAAE,WAAW;GAAE,IAAI;GAAO,kBAAkB;GAAW,EAAE,CAAC;IAG/D,MAAqB,MAAkB;AAK3C,EAJA,EAAc,EAAM,EACpB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACT,EAAQ,KAAK,EAAM,MAAM,CAAC,IAAI,KAChC,EAAc,EAAM,MAAM,EAAE,EAAkB;IAK5C,MAAuB,MAAsB;AAKjD,EAJA,EAAqB,EAAU,EAC/B,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACT,EAAQ,KAAK,EAAW,MAAM,CAAC,IACjC,EAAc,EAAW,MAAM,EAAE,EAAU;IAKzC,EACJ,MAAM,IACN,SAAS,IACT,SAAS,OACP,EAAyB;EAC3B,WAAW;GAAE,kBAAkB;GAAmB,UAAU;GAAI,MAAM;GAAG;EACzE,MAAM,CAAC;EACP,aAAa;EACd,CAAC,EACI,IAAU,IAAa,iBAAiB,WAAW,EAAE,EAErD,CAAC,IAAc,EAAE,SAAS,OAAkB,EAA8B,EAC9E,gBAAgB,CAAC,mBAAmB,EACrC,CAAC,EAEI,KAAkB,MACjB,IACD,EAAI,kBAAwB;EAAE,UAAU;EAAU,kBAAkB,EAAI;EAAiB,GACzF,EAAI,oBACC;EAAE,UAAU;EAAY,kBAAkB,EAAI;EAAmB,GACnE,OAJU,MAOb,KAAe,OAAO,MAAiB;AAI3C,MAHA,EAAE,gBAAgB,EAClB,EAAa,KAAK,EAEd,CAAC,KAAe,CAAC,EAAO,MAAM,IAAI,CAAC,GAAQ;AAC7C,KAAa,yDAAyD;AACtE;;EAEF,IAAM,IAAc,EAAe,EAAY;AAC/C,MAAI,CAAC,GAAa;AAChB,KAAa,8EAA8E;AAC3F;;EAEF,IAAM,IAAe,WAAW,EAAO;AACvC,MAAI,MAAM,EAAa,IAAI,KAAgB,GAAG;AAC5C,KAAa,8CAA8C;AAC3D;;AAEF,MAAI,IAAe,EAAY,QAAQ;AACrC,KACE,8CAA8C,EAAe,EAAY,QAAQ,EAAY,SAAS,CAAC,IACxG;AACD;;AAGF,MAAI;AAgBF,GAfA,MAAM,GAAa,EACjB,WAAW;IACT,kBAAkB;IAClB,UAAU,EAAY;IACtB,kBAAkB,EAAY;IAC9B,QAAQ;IACR,UAAU,EAAY,YAAY,GAAiB,YAAY;IAC/D,eAAe,EAAY;IAC3B,QAAQ,EAAO,MAAM;IACrB,OAAO;IACR,EACF,CAAC,EACF,EAAe,GAAK,EACpB,EAAY,GAAM,EAClB,GAAiB,EACjB,MAAM,IAAgB;WACf,GAAK;AACZ,KAAa,aAAe,QAAQ,EAAI,UAAU,mCAAmC;;IAInF,UAAwB;AAM5B,EALA,EAAc,GAAG,EACjB,EAAe,KAAK,EACpB,EAAe,GAAM,EACrB,EAAU,GAAG,EACb,EAAU,GAAG,EACb,EAAa,KAAK;IAGd,UAAkB;AAGtB,EAFA,EAAY,GAAM,EAClB,EAAe,GAAM,EACrB,GAAiB;;AAGnB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,GAAD;IACE,OAAO,EAAG,yBAAyB,UAAU;IAC7C,aAAa,EACX,+BACA,gDACD;IACD,SACG,IAYG,KAAA,IAXF,kBAAC,UAAD;KACE,MAAK;KACL,eAAe;AAEb,MADA,EAAY,GAAK,EACjB,EAAe,GAAM;;KAEvB,WAAU;eANZ,CAQE,kBAAC,IAAD,EAAY,WAAU,UAAW,CAAA,EAChC,EAAG,iCAAiC,iBAAiB,CAC/C;;IAGb,CAAA;GAGD,CAAC,KAAmB,EAAS,SAAS,KACrC,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD,EAAY,WAAU,uCAAwC,CAAA;KAC9D,kBAAC,SAAD;MAAO,SAAQ;MAAgB,WAAU;gBACtC,EAAG,2BAA2B,kBAAkB;MAC3C,CAAA;KACR,kBAAC,UAAD;MACE,IAAG;MACH,OAAO,KAAqB;MAC5B,WAAW,MAAM,GAAoB,EAAE,OAAO,MAAM;MACpD,WAAU;gBAET,EAAS,KAAK,MACb,kBAAC,UAAD;OAAmB,OAAO,EAAE;iBAA5B;QACG,EAAE;QAAK;QAAG,EAAE;QAAS;QAAK,EAAE;QACtB;SAFI,EAAE,GAEN,CACT;MACK,CAAA;KACL;;GAIP,MACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,GAAD,EAAa,WAAU,mCAAoC,CAAA,EAC3D,kBAAC,KAAD;MAAG,WAAU;gBACV,EACC,6BACA,6DACD;MACC,CAAA,CACA;QACN,kBAAC,UAAD;KACE,MAAK;KACL,eAAe,EAAe,GAAM;KACpC,WAAU;eAEV,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;KACjB,CAAA,CACL;;GAIP,KACC,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,8BAA8B,qBAAqB;MACpD,CAAA,EACL,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAEV,kBAAC,GAAD,EAAG,WAAU,8BAA+B,CAAA;MACrC,CAAA,CACL;QAEN,kBAAC,QAAD;KAAM,UAAU;KAAc,WAAU;eAAxC;MACG,KACC,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,KAAD;QAAG,WAAU;kBAAkC;QAAc,CAAA;OACzD,CAAA;MAIR,kBAAC,OAAD,EAAA,UAAA;OACE,kBAAC,SAAD;QAAO,SAAQ;QAAQ,WAAU;kBAAjC,CACG,EAAG,iCAAiC,iBAAiB,EAAC,KACjD;;OACR,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,OAAO;SACP,WAAW,MAAM,GAAkB,EAAE,OAAO,MAAM;SAClD,aAAY;SACZ,WAAU;SACV,CAAA,EACF,kBAAC,OAAD;SAAK,WAAU;mBACZ,IACC,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,GAE3C,kBAAC,IAAD,EAAQ,WAAU,UAAW,CAAA;SAE3B,CAAA,CACF;;OAGL,KACC,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,GAAD,EAAa,WAAU,8CAA+C,CAAA;UACtE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAY,QAAQ,EAAY,SAAS;WACpD,CAAA;UACP,kBAAC,QAAD;WAAM,WAAU;qBAAsB;WAAQ,CAAA;UAC9C,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAY,UAAU;WACjC,CAAA;UACN,EAAY,mBACX,kBAAC,QAAD;WAAM,WAAU;qBAA8B;WAAa,CAAA;UAE5D,EAAY,qBACX,kBAAC,QAAD;WAAM,WAAU;qBAA8B;WAAe,CAAA;UAE3D;YACL,EAAY,eACX,kBAAC,KAAD;SAAG,WAAU;mBAAoC,EAAY;SAAgB,CAAA,CAE3E;;OAEP,KAAe,EAAW,SAAS,KAAK,CAAC,KACxC,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,+BACA,iDACD;QACC,CAAA;OAEL,CAAC,EAAQ,KAAK,EAAW,MAAM,CAAC,IAAI,EAAW,SAAS,KACvD,kBAAC,KAAD;QAAG,WAAU;kBACV,EACC,6BACA,kEACD;QACC,CAAA;OAEF,EAAA,CAAA;MAGL,KACC,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OACE,SAAQ;OACR,WAAU;iBAFZ,CAIG,EAAG,0BAA0B,gBAAgB,EAAC,KACzC;UACR,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,SAAD;SACE,IAAG;SACH,MAAK;SACL,MAAK;SACL,KAAI;SACJ,KAAK,EAAY;SACjB,OAAO;SACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;SAC1C,UAAA;SACA,WAAU;SACV,aAAY;SACZ,CAAA;QACF,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAY,YAAY,GAAiB,YAAY;SACjD,CAAA;QACP,kBAAC,QAAD;SAAM,WAAU;mBAAhB,CAA8C,QACvC,EAAe,EAAY,QAAQ,EAAY,SAAS,CACxD;;QACH;SACF,EAAA,CAAA;MAIR,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,SAAD;OAAO,SAAQ;OAAS,WAAU;iBAAlC,CACG,EAAG,0BAA0B,oBAAoB,EAAC,KAC7C;UACR,kBAAC,YAAD;OACE,IAAG;OACH,OAAO;OACP,WAAW,MAAM,EAAU,EAAE,OAAO,MAAM;OAC1C,UAAA;OACA,MAAM;OACN,WAAU;OACV,aAAa,EACX,qCACA,8CACD;OACD,CAAA,CACE,EAAA,CAAA;MAEN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,UAAD;QACE,MAAK;QACL,UAAU,KAAgB,CAAC,KAAe,CAAC,EAAO,MAAM,IAAI,CAAC;QAC7D,WAAU;kBAET,IACG,EAAG,8BAA8B,gBAAgB,GACjD,EAAG,iCAAiC,iBAAiB;QAClD,CAAA,EACT,kBAAC,UAAD;QACE,MAAK;QACL,SAAS;QACT,WAAU;kBAET,EAAG,yBAAyB,SAAS;QAC/B,CAAA,CACL;;MACD;OACH;;GAIR,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAG,2BAA2B,iBAAiB;MAC7C,CAAA;KACD,CAAA,EAEL,KAAmB,KAClB,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,GAAD,EAAS,WAAU,2CAA4C,CAAA;KAC3D,CAAA,GACJ,EAAQ,WAAW,IACrB,kBAAC,OAAD;KAAK,WAAU;eAAf;MACE,kBAAC,IAAD,EAAW,WAAU,8BAA+B,CAAA;MACpD,kBAAC,KAAD;OAAG,WAAU;iBACV,EAAG,6BAA6B,yBAAyB;OACxD,CAAA;MACJ,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,iCACA,gFACD;OACC,CAAA;MACA;SAEN,kBAAC,MAAD;KAAI,WAAU;eACX,EAAQ,KAAK,MACZ,kBAAC,MAAD;MAEE,WAAU;gBAFZ,CAIE,kBAAC,OAAD;OAAK,WAAU;iBAAf;QACE,kBAAC,OAAD;SAAK,WAAU;mBAAf;UACE,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAe,EAAE,QAAQ,EAAE,SAAS;WAChC,CAAA;UACP,kBAAC,IAAD,EAAa,QAAQ,EAAE,QAAU,CAAA;UAChC,EAAE,kBACD,kBAAC,QAAD;WAAM,WAAU;qBACb,EAAE;WACE,CAAA;UAEL;;QACL,EAAE,UACD,kBAAC,KAAD;SAAG,WAAU;mBAAiD,EAAE;SAAW,CAAA;QAE5E,EAAE,gBAAgB,EAAE,WAAW,EAAmB,UACjD,kBAAC,KAAD;SAAG,WAAU;mBAAuC,EAAE;SAAiB,CAAA;QAErE;UACN,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACE,kBAAC,KAAD;QAAG,WAAU;kBAA+B,EAAe,EAAE,UAAU;QAAK,CAAA,EAC3E,EAAE,eACD,kBAAC,KAAD;QAAG,WAAU;kBAAb,CAAkD,cACrC,EAAe,EAAE,YAAY,CACtC;UAEF;SACH;QA9BE,EAAE,GA8BJ,CACL;KACC,CAAA,CAEH;;GAEN,kBAAC,KAAD;IAAG,WAAU;cAAb;KACG,EACC,0BACA,yGACD;KAAE;KACH,kBAAC,UAAD;MACE,MAAK;MACL,eAAe,EAAW,mBAAmB,EAAkB;MAC/D,WAAU;gBAET,EAAG,oCAAoC,wBAAwB;MACzD,CAAA;KACP;;GACA"}
@@ -94,7 +94,7 @@ var f = ({ accounts: f, selectedAccountId: p, onSelect: m, isLoading: h = !1, di
94
94
  children: _
95
95
  }),
96
96
  b && !g && /* @__PURE__ */ l("div", {
97
- className: "absolute left-0 right-0 z-50 mt-1 max-h-64 overflow-auto rounded-card border border-border-subtle bg-bg-elevated shadow-elevation-3",
97
+ className: "absolute left-0 right-0 z-50 mt-1 max-h-64 overflow-auto rounded-card border border-border-seam bg-bg-elevated shadow-elevation-3",
98
98
  children: f.map((t) => {
99
99
  let n = t.id === p;
100
100
  return /* @__PURE__ */ u("button", {