@burdenoff/microfe-billing 2026.526.1 → 2026.528.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (145) hide show
  1. package/dist/billing/BillingAdminRoutes.js +1 -1
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/BillingUserRoutes.js +1 -1
  4. package/dist/billing/BillingUserRoutes.js.map +1 -1
  5. package/dist/billing/modules/addons/components/FloatingCartDrawer.js +15 -8
  6. package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
  7. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js +13 -6
  8. package/dist/billing/modules/addons/pages/AddonBrowseDetailPage.js.map +1 -1
  9. package/dist/billing/modules/addons/pages/AddonCreatePage.js +1 -1
  10. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  11. package/dist/billing/modules/addons/pages/AddonDetailPage.js +8 -4
  12. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  13. package/dist/billing/modules/addons/pages/AddonEditPage.js +3 -2
  14. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  15. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js +44 -23
  16. package/dist/billing/modules/addons/pages/AddonsBrowsePage.js.map +1 -1
  17. package/dist/billing/modules/addons/pages/AddonsListPage.js +60 -31
  18. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  19. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js +9 -9
  20. package/dist/billing/modules/affiliate/pages/AffiliateDashboardPage.js.map +1 -1
  21. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +8 -8
  22. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  23. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +16 -10
  24. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  25. package/dist/billing/modules/billing/pages/InvoicesListPage.js +24 -16
  26. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  27. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js +5 -1
  28. package/dist/billing/modules/billing/pages/PaymentMethodsPage.js.map +1 -1
  29. package/dist/billing/modules/billing/pages/RefundsPage.js +46 -29
  30. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  31. package/dist/billing/modules/billing/pages/TransactionsPage.js +34 -22
  32. package/dist/billing/modules/billing/pages/TransactionsPage.js.map +1 -1
  33. package/dist/billing/modules/checkout/components/BillingAccountSelector.js +10 -10
  34. package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
  35. package/dist/billing/modules/checkout/components/CreditsAmountInput.js +3 -3
  36. package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
  37. package/dist/billing/modules/checkout/components/NativeCheckoutView.js +7 -0
  38. package/dist/billing/modules/checkout/components/NativeCheckoutView.js.map +1 -1
  39. package/dist/billing/modules/checkout/components/OrderSummary.js +13 -13
  40. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  41. package/dist/billing/modules/checkout/components/PromoCodeInput.js +5 -5
  42. package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
  43. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
  44. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
  45. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +4 -4
  46. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
  47. package/dist/billing/modules/checkout/components/StripePaymentForm.js +11 -11
  48. package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
  49. package/dist/billing/modules/checkout/components/SubscriptionSelector.js +3 -3
  50. package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
  51. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +8 -8
  52. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
  53. package/dist/billing/modules/checkout/pages/CheckoutPage.js +61 -52
  54. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  55. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +22 -15
  56. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  57. package/dist/billing/modules/coupons/pages/CouponsListPage.js +30 -21
  58. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  59. package/dist/billing/modules/coupons/pages/CreateCouponPage.js +9 -8
  60. package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
  61. package/dist/billing/modules/coupons/pages/EditCouponPage.js +11 -8
  62. package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
  63. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +1 -1
  64. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  65. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +22 -17
  66. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  67. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +15 -8
  68. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  69. package/dist/billing/modules/credits/pages/CreditsPage.js +17 -11
  70. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  71. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +15 -11
  72. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
  73. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +21 -17
  74. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  75. package/dist/billing/modules/dashboard/components/BillingAccountCard.js +14 -11
  76. package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
  77. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +32 -26
  78. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
  79. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +14 -10
  80. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
  81. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +18 -11
  82. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
  83. package/dist/billing/modules/dashboard/pages/OverviewPage.js +44 -32
  84. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  85. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +35 -26
  86. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  87. package/dist/billing/modules/earnings/pages/EarningsPage.js +15 -15
  88. package/dist/billing/modules/earnings/pages/EarningsPage.js.map +1 -1
  89. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +11 -11
  90. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  91. package/dist/billing/modules/earnings/pages/PayoutsPage.js +5 -5
  92. package/dist/billing/modules/earnings/pages/PayoutsPage.js.map +1 -1
  93. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +9 -4
  94. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  95. package/dist/billing/modules/plans/pages/PlanCreatePage.js +1 -1
  96. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  97. package/dist/billing/modules/plans/pages/PlanDetailPage.js +13 -8
  98. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  99. package/dist/billing/modules/plans/pages/PlanEditPage.js +3 -2
  100. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  101. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +14 -7
  102. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  103. package/dist/billing/modules/plans/pages/PlansListPage.js +23 -9
  104. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  105. package/dist/billing/modules/quota/pages/QuotaPage.js +11 -7
  106. package/dist/billing/modules/quota/pages/QuotaPage.js.map +1 -1
  107. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +3 -3
  108. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  109. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +6 -2
  110. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  111. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +5 -4
  112. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  113. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +26 -12
  114. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  115. package/dist/billing/modules/settings/pages/SettingsPage.js +356 -349
  116. package/dist/billing/modules/settings/pages/SettingsPage.js.map +1 -1
  117. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js +157 -123
  118. package/dist/billing/modules/settings/pages/TeamPermissionsPage.js.map +1 -1
  119. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +13 -8
  120. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
  121. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +15 -7
  122. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  123. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +30 -20
  124. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  125. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +25 -16
  126. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  127. package/dist/billing/modules/usage/pages/UsagePage.js +50 -34
  128. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  129. package/dist/billing/shared/components/AccessDenied.js +2 -2
  130. package/dist/billing/shared/components/AccessDenied.js.map +1 -1
  131. package/dist/billing/shared/components/ActorIdentity.js +67 -0
  132. package/dist/billing/shared/components/ActorIdentity.js.map +1 -0
  133. package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js +6 -2
  134. package/dist/billing/shared/components/CurrencyPriceOverridesEditor.js.map +1 -1
  135. package/dist/billing/shared/components/EmptyState.js +7 -21
  136. package/dist/billing/shared/components/EmptyState.js.map +1 -1
  137. package/dist/billing/shared/components/PageHeader.js +7 -19
  138. package/dist/billing/shared/components/PageHeader.js.map +1 -1
  139. package/dist/billing/shared/components/ServerError.js +5 -4
  140. package/dist/billing/shared/components/ServerError.js.map +1 -1
  141. package/dist/billing/shared/components/index.js +1 -0
  142. package/dist/billing/shared/hooks/index.js +1 -0
  143. package/dist/billing/shared/hooks/useActorProfiles.js +113 -0
  144. package/dist/billing/shared/hooks/useActorProfiles.js.map +1 -0
  145. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"ActiveSubscriptionCard.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/ActiveSubscriptionCard.tsx"],"sourcesContent":["/**\n * Active Subscription Card Component\n * Displays the active subscription details with renewal info\n */\n\nimport { type FC, useMemo } from 'react';\nimport {\n Crown,\n Calendar,\n ArrowRight,\n RefreshCw,\n Clock,\n CreditCard,\n Zap,\n AlertTriangle,\n Coins,\n} from 'lucide-react';\nimport type { BillingSubscription } from '../../../shared/types';\nimport { statusTokens, alertTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface ActiveSubscriptionCardProps {\n subscription: BillingSubscription | null;\n onViewDetails?: () => void;\n onUpgrade?: () => void;\n onManage?: () => void;\n onPurchasePlan?: () => void;\n className?: string;\n}\n\nexport const ActiveSubscriptionCard: FC<ActiveSubscriptionCardProps> = ({\n subscription,\n onViewDetails,\n onUpgrade,\n onManage,\n onPurchasePlan,\n className = '',\n}) => {\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 formatDate = (dateString: string | undefined) => {\n if (!dateString) return 'N/A';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n };\n\n const formatCurrency = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n minimumFractionDigits: 2,\n }).format(amount);\n };\n\n const daysUntilEnd = useMemo(() => {\n if (!subscription?.endDate) return null;\n const end = new Date(subscription.endDate);\n const now = new Date();\n const diff = Math.ceil((end.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));\n return diff;\n }, [subscription?.endDate]);\n\n const isExpiringSoon = daysUntilEnd !== null && daysUntilEnd <= 7 && daysUntilEnd > 0;\n const isExpired = daysUntilEnd !== null && daysUntilEnd <= 0;\n\n const getStatusColor = () => {\n if (isExpired) return `${statusTokens.error.text} ${statusTokens.error.bg}`;\n if (isExpiringSoon) return `${statusTokens.warning.text} ${statusTokens.warning.bg}`;\n return `${statusTokens.success.text} ${statusTokens.success.bg}`;\n };\n\n const getStatusText = () => {\n if (isExpired) return 'Expired';\n if (isExpiringSoon) return 'Expiring Soon';\n return 'Active';\n };\n\n // No subscription state\n if (!subscription) {\n return (\n <section className={`border border-border rounded-lg bg-card p-6 ${className}`}>\n <div className=\"flex flex-col items-center text-center py-4\">\n <div className=\"w-16 h-16 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 flex items-center justify-center mb-4\">\n <Zap className=\"w-8 h-8 text-primary\" />\n </div>\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">\n {tr('billing.overview.noActiveSubscription', 'No Active Subscription')}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-6 max-w-sm\">\n Subscribe to a plan to unlock premium features and get the most out of your account\n </p>\n {onPurchasePlan && (\n <button\n onClick={onPurchasePlan}\n className=\"inline-flex items-center gap-2 px-6 py-2.5 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors\"\n >\n Browse Plans\n <ArrowRight className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </section>\n );\n }\n\n const plan = subscription.plan;\n\n return (\n <section className={`border border-border rounded-lg bg-card overflow-hidden ${className}`}>\n {/* Expiring Soon Banner */}\n {isExpiringSoon && (\n <div className={`px-4 py-2 ${alertTokens.warning.container} border-b`}>\n <div className={`flex items-center gap-2 ${alertTokens.warning.text}`}>\n <AlertTriangle className=\"w-4 h-4\" />\n <span className=\"text-sm font-medium\">\n Your subscription expires in {daysUntilEnd} day{daysUntilEnd !== 1 ? 's' : ''}\n </span>\n </div>\n </div>\n )}\n\n {/* Header */}\n <header className=\"p-4 sm:p-6 border-b border-border\">\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4\">\n <div className=\"flex items-start gap-4\">\n <div className=\"w-12 h-12 rounded-lg bg-gradient-to-br from-primary to-primary/60 flex items-center justify-center flex-shrink-0\">\n <Crown className=\"w-6 h-6 text-primary-foreground\" />\n </div>\n <div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h3 className=\"text-lg font-semibold text-foreground\">\n {plan?.name || 'Subscription'}\n </h3>\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${getStatusColor()}`}\n >\n {getStatusText()}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {plan && formatCurrency(plan.price, plan.currency)} / {plan?.duration || 'month'}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {onManage && (\n <button\n onClick={onManage}\n className=\"px-4 py-2 text-sm font-medium text-foreground border border-border rounded-lg hover:bg-muted transition-colors\"\n >\n Manage\n </button>\n )}\n {onUpgrade && !isExpired && (\n <button\n onClick={onUpgrade}\n className=\"px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors\"\n >\n Upgrade\n </button>\n )}\n </div>\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 sm:p-6\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n {/* Start Date */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Started\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n <Calendar className=\"w-4 h-4 text-muted-foreground\" />\n {formatDate(subscription.startDate)}\n </p>\n </div>\n\n {/* End Date */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n {isExpired ? 'Expired' : 'Ends'}\n </p>\n <p\n className={`text-sm font-medium flex items-center gap-2 ${isExpired ? statusTokens.error.text : isExpiringSoon ? statusTokens.warning.text : 'text-foreground'}`}\n >\n <Clock className=\"w-4 h-4\" />\n {formatDate(subscription.endDate)}\n </p>\n </div>\n\n {/* Auto Renewal */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Auto Renewal\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n <RefreshCw\n className={`w-4 h-4 ${subscription.autoRenewal ? statusTokens.success.icon : 'text-muted-foreground'}`}\n />\n {subscription.autoRenewal ? 'Enabled' : 'Disabled'}\n </p>\n </div>\n\n {/* Payment Gateway */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Payment Via\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n {subscription.paymentGateway === 'CREDITS' ? (\n <Coins className={`w-4 h-4 ${statusTokens.warning.icon}`} />\n ) : (\n <CreditCard className=\"w-4 h-4 text-muted-foreground\" />\n )}\n {subscription.paymentGateway === 'CREDITS'\n ? 'Credits'\n : subscription.paymentGateway === 'STRIPE'\n ? 'Stripe'\n : subscription.paymentGateway === 'RAZORPAY'\n ? 'Razorpay'\n : subscription.paymentGateway || 'N/A'}\n </p>\n </div>\n </div>\n\n {/* Next Billing */}\n {subscription.nextBillingDate && subscription.autoRenewal && !isExpired && (\n <div className=\"mt-6 p-4 rounded-lg bg-muted/50 border border-border\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2\">\n <div>\n <p className=\"text-sm font-medium text-foreground\">\n {tr('billing.overview.nextBillingDate', 'Next billing date')}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n You&apos;ll be charged automatically\n </p>\n </div>\n <p className=\"text-sm font-semibold text-foreground\">\n {formatDate(subscription.nextBillingDate)}\n </p>\n </div>\n </div>\n )}\n </div>\n\n {/* Footer */}\n {onViewDetails && (\n <footer className=\"px-4 sm:px-6 py-3 border-t border-border bg-muted/30\">\n <button\n onClick={onViewDetails}\n className=\"w-full flex items-center justify-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\n >\n View Subscription Details\n <ArrowRight className=\"w-4 h-4\" />\n </button>\n </footer>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ActiveSubscriptionCard.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/ActiveSubscriptionCard.tsx"],"sourcesContent":["/**\n * Active Subscription Card Component\n * Displays the active subscription details with renewal info\n */\n\nimport { type FC, useMemo } from 'react';\nimport {\n Crown,\n Calendar,\n ArrowRight,\n RefreshCw,\n Clock,\n CreditCard,\n Zap,\n AlertTriangle,\n Coins,\n} from 'lucide-react';\nimport type { BillingSubscription } from '../../../shared/types';\nimport { statusTokens, alertTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface ActiveSubscriptionCardProps {\n subscription: BillingSubscription | null;\n onViewDetails?: () => void;\n onUpgrade?: () => void;\n onManage?: () => void;\n onPurchasePlan?: () => void;\n className?: string;\n}\n\nexport const ActiveSubscriptionCard: FC<ActiveSubscriptionCardProps> = ({\n subscription,\n onViewDetails,\n onUpgrade,\n onManage,\n onPurchasePlan,\n className = '',\n}) => {\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 formatDate = (dateString: string | undefined) => {\n if (!dateString) return 'N/A';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n };\n\n const formatCurrency = (amount: number, currency: string) => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n minimumFractionDigits: 2,\n }).format(amount);\n };\n\n const daysUntilEnd = useMemo(() => {\n if (!subscription?.endDate) return null;\n const end = new Date(subscription.endDate);\n const now = new Date();\n const diff = Math.ceil((end.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));\n return diff;\n }, [subscription?.endDate]);\n\n const isExpiringSoon = daysUntilEnd !== null && daysUntilEnd <= 7 && daysUntilEnd > 0;\n const isExpired = daysUntilEnd !== null && daysUntilEnd <= 0;\n\n const getStatusColor = () => {\n if (isExpired) return `${statusTokens.error.text} ${statusTokens.error.bg}`;\n if (isExpiringSoon) return `${statusTokens.warning.text} ${statusTokens.warning.bg}`;\n return `${statusTokens.success.text} ${statusTokens.success.bg}`;\n };\n\n const getStatusText = () => {\n if (isExpired) return 'Expired';\n if (isExpiringSoon) return 'Expiring Soon';\n return 'Active';\n };\n\n // No subscription state\n if (!subscription) {\n return (\n <section className={`border border-border rounded-lg bg-card p-6 ${className}`}>\n <div className=\"flex flex-col items-center text-center py-4\">\n <div className=\"size-16 rounded-full bg-gradient-to-br from-primary/20 to-primary/5 flex items-center justify-center mb-4\">\n <Zap className=\"size-8 text-primary\" />\n </div>\n <h3 className=\"text-lg font-semibold text-foreground mb-2\">\n {tr('billing.overview.noActiveSubscription', 'No Active Subscription')}\n </h3>\n <p className=\"text-sm text-muted-foreground mb-6 max-w-sm\">\n Subscribe to a plan to unlock premium features and get the most out of your account\n </p>\n {onPurchasePlan && (\n <button\n type=\"button\"\n onClick={onPurchasePlan}\n className=\"inline-flex items-center gap-2 px-6 py-2.5 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors\"\n >\n Browse Plans\n <ArrowRight className=\"size-4\" />\n </button>\n )}\n </div>\n </section>\n );\n }\n\n const plan = subscription.plan;\n\n return (\n <section className={`border border-border rounded-lg bg-card overflow-hidden ${className}`}>\n {/* Expiring Soon Banner */}\n {isExpiringSoon && (\n <div className={`px-4 py-2 ${alertTokens.warning.container} border-b`}>\n <div className={`flex items-center gap-2 ${alertTokens.warning.text}`}>\n <AlertTriangle className=\"size-4\" />\n <span className=\"text-sm font-medium\">\n Your subscription expires in {daysUntilEnd} day{daysUntilEnd !== 1 ? 's' : ''}\n </span>\n </div>\n </div>\n )}\n\n {/* Header */}\n <header className=\"p-4 sm:p-6 border-b border-border\">\n <div className=\"flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4\">\n <div className=\"flex items-start gap-4\">\n <div className=\"size-12 rounded-lg bg-gradient-to-br from-primary to-primary/60 flex items-center justify-center flex-shrink-0\">\n <Crown className=\"size-6 text-primary-foreground\" />\n </div>\n <div>\n <div className=\"flex items-center gap-2 flex-wrap\">\n <h3 className=\"text-lg font-semibold text-foreground\">\n {plan?.name || 'Subscription'}\n </h3>\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium ${getStatusColor()}`}\n >\n {getStatusText()}\n </span>\n </div>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {plan && formatCurrency(plan.price, plan.currency)} / {plan?.duration || 'month'}\n </p>\n </div>\n </div>\n <div className=\"flex items-center gap-2\">\n {onManage && (\n <button\n type=\"button\"\n onClick={onManage}\n className=\"px-4 py-2 text-sm font-medium text-foreground border border-border rounded-lg hover:bg-muted transition-colors\"\n >\n Manage\n </button>\n )}\n {onUpgrade && !isExpired && (\n <button\n type=\"button\"\n onClick={onUpgrade}\n className=\"px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors\"\n >\n Upgrade\n </button>\n )}\n </div>\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 sm:p-6\">\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">\n {/* Start Date */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Started\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n <Calendar className=\"size-4 text-muted-foreground\" />\n {formatDate(subscription.startDate)}\n </p>\n </div>\n\n {/* End Date */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n {isExpired ? 'Expired' : 'Ends'}\n </p>\n <p\n className={`text-sm font-medium flex items-center gap-2 ${isExpired ? statusTokens.error.text : isExpiringSoon ? statusTokens.warning.text : 'text-foreground'}`}\n >\n <Clock className=\"size-4\" />\n {formatDate(subscription.endDate)}\n </p>\n </div>\n\n {/* Auto Renewal */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Auto Renewal\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n <RefreshCw\n className={`size-4 ${subscription.autoRenewal ? statusTokens.success.icon : 'text-muted-foreground'}`}\n />\n {subscription.autoRenewal ? 'Enabled' : 'Disabled'}\n </p>\n </div>\n\n {/* Payment Gateway */}\n <div className=\"space-y-1.5\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Payment Via\n </p>\n <p className=\"text-sm font-medium text-foreground flex items-center gap-2\">\n {subscription.paymentGateway === 'CREDITS' ? (\n <Coins className={`size-4 ${statusTokens.warning.icon}`} />\n ) : (\n <CreditCard className=\"size-4 text-muted-foreground\" />\n )}\n {subscription.paymentGateway === 'CREDITS'\n ? 'Credits'\n : subscription.paymentGateway === 'STRIPE'\n ? 'Stripe'\n : subscription.paymentGateway === 'RAZORPAY'\n ? 'Razorpay'\n : subscription.paymentGateway || 'N/A'}\n </p>\n </div>\n </div>\n\n {/* Next Billing */}\n {subscription.nextBillingDate && subscription.autoRenewal && !isExpired && (\n <div className=\"mt-6 p-4 rounded-lg bg-muted/50 border border-border\">\n <div className=\"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2\">\n <div>\n <p className=\"text-sm font-medium text-foreground\">\n {tr('billing.overview.nextBillingDate', 'Next billing date')}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n You&apos;ll be charged automatically\n </p>\n </div>\n <p className=\"text-sm font-semibold text-foreground\">\n {formatDate(subscription.nextBillingDate)}\n </p>\n </div>\n </div>\n )}\n </div>\n\n {/* Footer */}\n {onViewDetails && (\n <footer className=\"px-4 sm:px-6 py-3 border-t border-border bg-muted/30\">\n <button\n type=\"button\"\n onClick={onViewDetails}\n className=\"w-full flex items-center justify-center gap-2 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors\"\n >\n View Subscription Details\n <ArrowRight className=\"size-4\" />\n </button>\n </footer>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
@@ -184,8 +184,8 @@ var g = (e, t) => new Promise((n, r) => {
184
184
  children: [/* @__PURE__ */ m("div", {
185
185
  className: "flex items-center gap-3",
186
186
  children: [/* @__PURE__ */ p("div", {
187
- className: "w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center",
188
- children: /* @__PURE__ */ p(u, { className: "w-5 h-5 text-primary" })
187
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center",
188
+ children: /* @__PURE__ */ p(u, { className: "size-5 text-primary" })
189
189
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h2", {
190
190
  id: "modal-title",
191
191
  className: "text-lg font-semibold text-foreground",
@@ -200,27 +200,29 @@ var g = (e, t) => new Promise((n, r) => {
200
200
  ]
201
201
  })] })]
202
202
  }), /* @__PURE__ */ p("button", {
203
+ type: "button",
203
204
  onClick: v,
204
205
  disabled: H,
205
206
  className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50",
206
207
  "aria-label": "Close modal",
207
- children: /* @__PURE__ */ p(ee, { className: "w-5 h-5" })
208
+ children: /* @__PURE__ */ p(ee, { className: "size-5" })
208
209
  })]
209
210
  }),
210
211
  /* @__PURE__ */ p("div", {
211
212
  className: "p-4 overflow-y-auto flex-1",
212
213
  children: ne ? /* @__PURE__ */ p("div", {
213
214
  className: "flex items-center justify-center py-8",
214
- children: /* @__PURE__ */ p(d, { className: "w-6 h-6 animate-spin text-muted-foreground" })
215
+ children: /* @__PURE__ */ p(d, { className: "size-6 animate-spin text-muted-foreground" })
215
216
  }) : I === "select-provider" ? /* @__PURE__ */ m("div", {
216
217
  className: "space-y-3",
217
218
  children: [
218
219
  F && /* @__PURE__ */ m("button", {
220
+ type: "button",
219
221
  onClick: () => Z("stripe"),
220
222
  className: "w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left",
221
223
  children: [/* @__PURE__ */ p("div", {
222
- className: "w-12 h-12 rounded-lg bg-accent-violet-subtle flex items-center justify-center",
223
- children: /* @__PURE__ */ p(u, { className: "w-6 h-6 text-accent-violet" })
224
+ className: "size-12 rounded-lg bg-accent-violet-subtle flex items-center justify-center",
225
+ children: /* @__PURE__ */ p(u, { className: "size-6 text-accent-violet" })
224
226
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
225
227
  className: "font-medium text-foreground",
226
228
  children: "Stripe"
@@ -230,11 +232,12 @@ var g = (e, t) => new Promise((n, r) => {
230
232
  })] })]
231
233
  }),
232
234
  P && /* @__PURE__ */ m("button", {
235
+ type: "button",
233
236
  onClick: () => Z("razorpay"),
234
237
  className: "w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left",
235
238
  children: [/* @__PURE__ */ p("div", {
236
- className: "w-12 h-12 rounded-lg bg-status-info-bg-subtle flex items-center justify-center",
237
- children: /* @__PURE__ */ p(u, { className: "w-6 h-6 text-accent-blue" })
239
+ className: "size-12 rounded-lg bg-status-info-bg-subtle flex items-center justify-center",
240
+ children: /* @__PURE__ */ p(u, { className: "size-6 text-accent-blue" })
238
241
  }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
239
242
  className: "font-medium text-foreground",
240
243
  children: "Razorpay"
@@ -246,7 +249,7 @@ var g = (e, t) => new Promise((n, r) => {
246
249
  !F && !P && /* @__PURE__ */ m("div", {
247
250
  className: "flex flex-col items-center py-8 text-center",
248
251
  children: [
249
- /* @__PURE__ */ p(c, { className: "w-12 h-12 text-status-warning-text mb-3" }),
252
+ /* @__PURE__ */ p(c, { className: "size-12 text-status-warning-text mb-3" }),
250
253
  /* @__PURE__ */ p("p", {
251
254
  className: "font-medium text-foreground",
252
255
  children: C("billing.overview.noPaymentProviders", "No Payment Providers Available")
@@ -263,7 +266,7 @@ var g = (e, t) => new Promise((n, r) => {
263
266
  children: [
264
267
  B && /* @__PURE__ */ m("div", {
265
268
  className: "flex items-center gap-2 p-3 rounded-lg bg-destructive/10 border border-destructive/20 text-destructive",
266
- children: [/* @__PURE__ */ p(c, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ p("p", {
269
+ children: [/* @__PURE__ */ p(c, { className: "size-4 flex-shrink-0" }), /* @__PURE__ */ p("p", {
267
270
  className: "text-sm",
268
271
  children: B
269
272
  })]
@@ -293,12 +296,12 @@ var g = (e, t) => new Promise((n, r) => {
293
296
  className: "relative",
294
297
  children: [/* @__PURE__ */ p("div", {
295
298
  ref: T,
296
- className: "px-3 py-3 border border-input rounded-lg bg-background min-h-[44px]"
299
+ className: "p-3 border border-input rounded-lg bg-background min-h-[44px]"
297
300
  }), W && /* @__PURE__ */ m("div", {
298
301
  className: "absolute inset-0 flex items-center justify-center bg-background/80 rounded-lg",
299
- children: [/* @__PURE__ */ p(d, { className: "w-5 h-5 animate-spin text-muted-foreground" }), /* @__PURE__ */ p("span", {
302
+ children: [/* @__PURE__ */ p(d, { className: "size-5 animate-spin text-muted-foreground" }), /* @__PURE__ */ p("span", {
300
303
  className: "ml-2 text-sm text-muted-foreground",
301
- children: "Loading Stripe..."
304
+ children: "Loading Stripe"
302
305
  })]
303
306
  })]
304
307
  })]
@@ -316,7 +319,7 @@ var g = (e, t) => new Promise((n, r) => {
316
319
  type: "checkbox",
317
320
  checked: J,
318
321
  onChange: (e) => Y(e.target.checked),
319
- className: "w-4 h-4 rounded border-input text-primary focus:ring-primary/20",
322
+ className: "size-4 rounded border-input text-primary focus:ring-primary/20",
320
323
  disabled: H
321
324
  }), /* @__PURE__ */ p("span", {
322
325
  className: "text-sm text-foreground",
@@ -338,8 +341,8 @@ var g = (e, t) => new Promise((n, r) => {
338
341
  className: "flex flex-col items-center py-8 text-center",
339
342
  children: [
340
343
  /* @__PURE__ */ p("div", {
341
- className: "w-16 h-16 rounded-full bg-status-success-bg-subtle flex items-center justify-center mb-4",
342
- children: /* @__PURE__ */ p(l, { className: "w-8 h-8 text-status-success-text" })
344
+ className: "size-16 rounded-full bg-status-success-bg-subtle flex items-center justify-center mb-4",
345
+ children: /* @__PURE__ */ p(l, { className: "size-8 text-status-success-text" })
343
346
  }),
344
347
  /* @__PURE__ */ p("p", {
345
348
  className: "font-medium text-foreground",
@@ -371,10 +374,11 @@ var g = (e, t) => new Promise((n, r) => {
371
374
  className: "px-4 py-2 text-sm font-medium text-foreground border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-50",
372
375
  children: "Cancel"
373
376
  }), I === "add-card" && /* @__PURE__ */ p("button", {
377
+ type: "button",
374
378
  onClick: ie,
375
379
  disabled: H || j || W || R === "stripe" && !re,
376
380
  className: "inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors disabled:opacity-50",
377
- children: H || j ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(d, { className: "w-4 h-4 animate-spin" }), R === "razorpay" ? "Processing..." : "Saving..."] }) : W ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(d, { className: "w-4 h-4 animate-spin" }), "Loading..."] }) : R === "stripe" ? "Add Card" : "Add Payment Method (₹1)"
381
+ children: H || j ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(d, { className: "size-4 animate-spin" }), R === "razorpay" ? "Processing..." : "Saving..."] }) : W ? /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ p(d, { className: "size-4 animate-spin" }), "Loading"] }) : R === "stripe" ? "Add Card" : "Add Payment Method (₹1)"
378
382
  })]
379
383
  })]
380
384
  })
@@ -1 +1 @@
1
- {"version":3,"file":"AddPaymentMethodModal.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/AddPaymentMethodModal.tsx"],"sourcesContent":["/**\n * Add Payment Method Modal Component\n * Modal for adding a new payment method via Stripe or Razorpay SDKs\n */\n\nimport { type FC, useState, useCallback, useEffect, useRef } from 'react';\nimport { X, CreditCard, Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePaymentProviderConfig, useDashboardMutations } from '../hooks';\nimport { PaymentProviderPreference } from '../../../shared/types';\nimport { getStripeCardElementStyle } from '../../../shared/utils';\n\n// Stripe types (loaded dynamically)\ndeclare global {\n interface Window {\n Stripe?: (key: string) => StripeInstance;\n Razorpay?: new (options: RazorpayOptions) => RazorpayInstance;\n }\n}\n\ninterface StripeInstance {\n elements: () => StripeElements;\n createPaymentMethod: (options: {\n type: 'card';\n card: StripeCardElement;\n billing_details?: { name?: string };\n }) => Promise<{\n paymentMethod?: {\n id: string;\n card?: { brand: string; last4: string; exp_month: number; exp_year: number };\n };\n error?: { message: string };\n }>;\n confirmCardSetup: (\n clientSecret: string,\n options?: {\n payment_method?: {\n card: StripeCardElement;\n billing_details?: { name?: string };\n };\n }\n ) => Promise<{\n setupIntent?: {\n id: string;\n status: string;\n payment_method?: string;\n };\n error?: { message: string };\n }>;\n}\n\ninterface StripeElements {\n create: (type: 'card', options?: object) => StripeCardElement;\n}\n\ninterface StripeCardElement {\n mount: (element: HTMLElement | string) => void;\n unmount: () => void;\n on: (\n event: string,\n handler: (event: { complete: boolean; error?: { message: string } }) => void\n ) => void;\n destroy: () => void;\n}\n\ninterface RazorpayOptions {\n key: string;\n amount: number;\n currency: string;\n order_id: string;\n customer_id?: string;\n name: string;\n description: string;\n method?: 'card' | 'upi' | 'netbanking' | 'wallet' | 'emi' | 'cardless_emi';\n handler: (response: RazorpayResponse) => void;\n modal?: { ondismiss?: () => void };\n prefill?: { name?: string; email?: string; contact?: string };\n notes?: Record<string, string>;\n config?: {\n display?: {\n hide?: Array<{ method: string }>;\n preferences?: {\n show_default_blocks?: boolean;\n };\n };\n };\n}\n\ninterface RazorpayInstance {\n open: () => void;\n close: () => void;\n}\n\ninterface RazorpayResponse {\n razorpay_payment_id: string;\n razorpay_token?: string;\n}\n\ninterface AddPaymentMethodModalProps {\n isOpen: boolean;\n onClose: () => void;\n billingAccountId: string;\n currency: string; // e.g., 'INR', 'USD'\n country?: string; // e.g., 'IN', 'US' - from billing address\n onSuccess?: () => void;\n}\n\ntype ModalStep = 'select-provider' | 'add-card' | 'processing' | 'success';\n\n// Load external script dynamically\nconst loadScript = (src: string, id: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (document.getElementById(id)) {\n resolve();\n return;\n }\n const script = document.createElement('script');\n script.id = id;\n script.src = src;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`Failed to load ${src}`));\n document.head.appendChild(script);\n });\n};\n\nexport const AddPaymentMethodModal: FC<AddPaymentMethodModalProps> = ({\n isOpen,\n onClose,\n billingAccountId,\n currency,\n country,\n onSuccess,\n}) => {\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 modalRef = useRef<HTMLDivElement>(null);\n const cardElementRef = useRef<HTMLDivElement>(null);\n const stripeCardElementRef = useRef<StripeCardElement | null>(null);\n const stripeRef = useRef<StripeInstance | null>(null);\n\n // Only fetch payment provider config when modal is open\n const {\n stripeEnabled,\n stripePublishableKey,\n razorpayEnabled,\n isLoading: isLoadingConfig,\n } = usePaymentProviderConfig(!isOpen);\n const { isAddingPaymentMethod, verifyPaymentMethod } = useDashboardMutations();\n\n // Determine which providers to show based on currency and country\n // Razorpay: India only (INR currency OR IN country)\n // Stripe: International (non-INR OR non-IN country)\n const isIndianAccount = currency?.toUpperCase() === 'INR' || country?.toUpperCase() === 'IN';\n const showRazorpay = razorpayEnabled && isIndianAccount;\n const showStripe = stripeEnabled && !isIndianAccount;\n\n const [step, setStep] = useState<ModalStep>('select-provider');\n const [selectedProvider, setSelectedProvider] = useState<'stripe' | 'razorpay' | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isProcessing, setIsProcessing] = useState(false);\n const [isLoadingSdk, setIsLoadingSdk] = useState(false);\n const [cardholderName, setCardholderName] = useState('');\n const [setAsDefault, setSetAsDefault] = useState(true);\n const [isCardComplete, setIsCardComplete] = useState(false);\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (isOpen) {\n // Always start with provider selection\n setStep('select-provider');\n setSelectedProvider(null);\n setError(null);\n setCardholderName('');\n setSetAsDefault(true);\n setIsCardComplete(false);\n } else {\n // Cleanup Stripe element when modal closes\n if (stripeCardElementRef.current) {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n }\n }\n }, [isOpen]);\n\n // Note: We always show provider selection, even if only one is available\n // This ensures the user explicitly chooses their payment provider\n\n // Initialize Stripe when provider is selected\n useEffect(() => {\n if (step !== 'add-card' || selectedProvider !== 'stripe' || !stripePublishableKey) return;\n\n const initStripe = async () => {\n setIsLoadingSdk(true);\n try {\n await loadScript('https://js.stripe.com/v3/', 'stripe-js');\n\n if (!window.Stripe) {\n throw new Error('Stripe SDK failed to load');\n }\n\n const stripe = window.Stripe(stripePublishableKey);\n stripeRef.current = stripe;\n\n // Wait for the card element container to be mounted in the DOM\n let attempts = 0;\n while (!cardElementRef.current && attempts < 50) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n attempts++;\n }\n\n if (!cardElementRef.current) {\n throw new Error('Card element container not found after 5 seconds');\n }\n\n if (stripeCardElementRef.current) {\n return;\n }\n\n const elements = stripe.elements();\n const cardElement = elements.create('card', {\n style: getStripeCardElementStyle('system-ui, -apple-system, sans-serif'),\n });\n\n cardElement.mount(cardElementRef.current);\n stripeCardElementRef.current = cardElement;\n\n cardElement.on('change', (event) => {\n setIsCardComplete(event.complete);\n if (event.error) {\n setError(event.error.message);\n } else {\n setError(null);\n }\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load Stripe');\n } finally {\n setIsLoadingSdk(false);\n }\n };\n\n initStripe();\n\n return () => {\n if (stripeCardElementRef.current) {\n try {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n } catch {\n // Stripe element may already be detached during modal teardown.\n }\n }\n };\n }, [step, selectedProvider, stripePublishableKey]);\n\n // Handle escape key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen && !isProcessing) {\n onClose();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, isProcessing, onClose]);\n\n const handleSelectProvider = useCallback((provider: 'stripe' | 'razorpay') => {\n setSelectedProvider(provider);\n setStep('add-card');\n setError(null);\n }, []);\n\n const handleStripeSubmit = useCallback(async () => {\n if (!stripeRef.current || !stripeCardElementRef.current) {\n setError('Stripe not initialized');\n return;\n }\n\n if (!cardholderName.trim()) {\n setError('Please enter the cardholder name');\n return;\n }\n\n setIsProcessing(true);\n setError(null);\n\n try {\n // Step 1: Call backend to create SetupIntent and get client secret\n const verificationResult = await verifyPaymentMethod({\n billingAccountId,\n currency: 'USD',\n provider: PaymentProviderPreference.STRIPE,\n setAsDefault,\n });\n\n if (!verificationResult.clientSecret) {\n throw new Error('Failed to initiate card verification');\n }\n\n // Step 2: Confirm card setup using the client secret (no charge)\n const { setupIntent, error: stripeError } = await stripeRef.current.confirmCardSetup(\n verificationResult.clientSecret,\n {\n payment_method: {\n card: stripeCardElementRef.current,\n billing_details: { name: cardholderName },\n },\n }\n );\n\n if (stripeError) {\n throw new Error(stripeError.message);\n }\n\n if (setupIntent?.status !== 'succeeded') {\n throw new Error('Card verification failed');\n }\n\n // Step 3: Show success (webhook will save the payment method)\n setStep('success');\n\n // Wait for webhook to process (2 seconds) before refetching\n await new Promise((resolve) => setTimeout(resolve, 2000));\n onSuccess?.();\n\n // Show success message briefly before closing\n setTimeout(() => {\n onClose();\n }, 500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add payment method');\n setIsProcessing(false);\n }\n }, [cardholderName, setAsDefault, billingAccountId, verifyPaymentMethod, onSuccess, onClose]);\n\n const handleRazorpaySubmit = useCallback(async () => {\n setIsProcessing(true);\n setError(null);\n\n try {\n // Load Razorpay SDK\n setIsLoadingSdk(true);\n try {\n await loadScript('https://checkout.razorpay.com/v1/checkout.js', 'razorpay-sdk');\n } catch {\n setError('Failed to load Razorpay SDK');\n setIsProcessing(false);\n setIsLoadingSdk(false);\n return;\n }\n setIsLoadingSdk(false);\n\n // Initiate ₹1 verification payment\n const verificationResult = await verifyPaymentMethod({\n billingAccountId,\n currency: 'INR',\n provider: PaymentProviderPreference.RAZORPAY,\n setAsDefault,\n });\n\n if (\n !verificationResult.success ||\n !verificationResult.orderId ||\n !verificationResult.razorpayKeyId\n ) {\n setError(verificationResult.error || 'Failed to initiate verification');\n setIsProcessing(false);\n return;\n }\n\n // Open Razorpay checkout with ALL payment methods\n if (!window.Razorpay) {\n setError('Razorpay SDK not loaded');\n setIsProcessing(false);\n return;\n }\n\n const options = {\n key: verificationResult.razorpayKeyId,\n amount: (verificationResult.amount ?? 0) * 100, // Convert to paise\n currency: verificationResult.currency.toUpperCase(),\n order_id: verificationResult.orderId,\n customer_id: verificationResult.razorpayCustomerId, // Link to customer for saving\n name: 'Add Payment Method',\n description: `₹${verificationResult.amount} verification charge (refundable)`,\n prefill: {\n name: verificationResult.prefillName,\n email: verificationResult.prefillEmail,\n contact: verificationResult.prefillContact,\n },\n notes: {\n purchaseType: 'PAYMENT_METHOD_VERIFICATION',\n default_method: setAsDefault.toString(),\n },\n handler: async () => {\n // Payment successful - payment method will be saved via webhook\n setStep('success');\n\n // Wait for webhook to process (2 seconds) before refetching\n await new Promise((resolve) => setTimeout(resolve, 2000));\n onSuccess?.();\n\n // Show success message briefly before closing\n setTimeout(() => {\n onClose();\n }, 500);\n },\n modal: {\n ondismiss: () => {\n setIsProcessing(false);\n setError('Payment cancelled');\n },\n },\n };\n\n const rzp = new window.Razorpay(options);\n rzp.open();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add payment method');\n setIsProcessing(false);\n }\n }, [setAsDefault, billingAccountId, verifyPaymentMethod, onSuccess, onClose]);\n\n const handleSubmit = useCallback(() => {\n if (selectedProvider === 'stripe') {\n handleStripeSubmit();\n } else if (selectedProvider === 'razorpay') {\n handleRazorpaySubmit();\n }\n }, [selectedProvider, handleStripeSubmit, handleRazorpaySubmit]);\n\n if (!isOpen) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"modal-title\"\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-background/80 backdrop-blur-sm\"\n onClick={!isProcessing ? onClose : undefined}\n aria-hidden=\"true\"\n />\n\n {/* Modal */}\n <div\n ref={modalRef}\n className=\"relative w-full max-w-md max-h-[90vh] mx-4 bg-card border border-border rounded-lg shadow-xl flex flex-col\"\n >\n {/* Header */}\n <header className=\"flex items-center justify-between p-4 border-b border-border flex-shrink-0\">\n <div className=\"flex items-center gap-3\">\n <div className=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center\">\n <CreditCard className=\"w-5 h-5 text-primary\" />\n </div>\n <div>\n <h2 id=\"modal-title\" className=\"text-lg font-semibold text-foreground\">\n {step === 'success' ? 'Payment Method Added' : 'Add Payment Method'}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {step === 'select-provider' && 'Choose a payment provider'}\n {step === 'add-card' &&\n (selectedProvider === 'stripe'\n ? 'Add card via Stripe'\n : 'Add payment method with ₹1 verification')}\n {step === 'processing' && 'Processing...'}\n {step === 'success' && 'Your payment method has been saved'}\n </p>\n </div>\n </div>\n <button\n onClick={onClose}\n disabled={isProcessing}\n className=\"p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50\"\n aria-label=\"Close modal\"\n >\n <X className=\"w-5 h-5\" />\n </button>\n </header>\n\n {/* Content */}\n <div className=\"p-4 overflow-y-auto flex-1\">\n {isLoadingConfig ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"w-6 h-6 animate-spin text-muted-foreground\" />\n </div>\n ) : step === 'select-provider' ? (\n <div className=\"space-y-3\">\n {showStripe && (\n <button\n onClick={() => handleSelectProvider('stripe')}\n className=\"w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left\"\n >\n <div className=\"w-12 h-12 rounded-lg bg-accent-violet-subtle flex items-center justify-center\">\n <CreditCard className=\"w-6 h-6 text-accent-violet\" />\n </div>\n <div>\n <p className=\"font-medium text-foreground\">Stripe</p>\n <p className=\"text-sm text-muted-foreground\">Cards, Apple Pay, Google Pay</p>\n </div>\n </button>\n )}\n {showRazorpay && (\n <button\n onClick={() => handleSelectProvider('razorpay')}\n className=\"w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left\"\n >\n <div className=\"w-12 h-12 rounded-lg bg-status-info-bg-subtle flex items-center justify-center\">\n <CreditCard className=\"w-6 h-6 text-accent-blue\" />\n </div>\n <div>\n <p className=\"font-medium text-foreground\">Razorpay</p>\n <p className=\"text-sm text-muted-foreground\">UPI, Netbanking, Cards</p>\n </div>\n </button>\n )}\n {!showStripe && !showRazorpay && (\n <div className=\"flex flex-col items-center py-8 text-center\">\n <AlertCircle className=\"w-12 h-12 text-status-warning-text mb-3\" />\n <p className=\"font-medium text-foreground\">\n {tr('billing.overview.noPaymentProviders', 'No Payment Providers Available')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {isIndianAccount\n ? 'Razorpay is not configured for Indian accounts. Please contact support.'\n : 'Stripe is not configured for international accounts. Please contact support.'}\n </p>\n </div>\n )}\n </div>\n ) : step === 'add-card' ? (\n <div className=\"space-y-4\">\n {/* Error Message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 border border-destructive/20 text-destructive\">\n <AlertCircle className=\"w-4 h-4 flex-shrink-0\" />\n <p className=\"text-sm\">{error}</p>\n </div>\n )}\n\n {/* Cardholder Name - only for Stripe */}\n {selectedProvider === 'stripe' && (\n <div className=\"space-y-1.5\">\n <label\n htmlFor=\"cardholderName\"\n className=\"block text-sm font-medium text-foreground\"\n >\n Cardholder Name\n </label>\n <input\n type=\"text\"\n id=\"cardholderName\"\n value={cardholderName}\n onChange={(e) => setCardholderName(e.target.value)}\n className=\"w-full px-3 py-2 border border-input rounded-lg bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n placeholder=\"John Doe\"\n disabled={isProcessing}\n />\n </div>\n )}\n\n {/* Stripe Card Element */}\n {selectedProvider === 'stripe' && (\n <div className=\"space-y-1.5\">\n <label className=\"block text-sm font-medium text-foreground\">\n {tr('billing.overview.cardDetails', 'Card Details')}\n </label>\n <div className=\"relative\">\n <div\n ref={cardElementRef}\n className=\"px-3 py-3 border border-input rounded-lg bg-background min-h-[44px]\"\n />\n {isLoadingSdk && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/80 rounded-lg\">\n <Loader2 className=\"w-5 h-5 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">\n Loading Stripe...\n </span>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Razorpay - Verification Info */}\n {selectedProvider === 'razorpay' && (\n <div className=\"p-3 border border-border-subtle rounded-lg bg-status-info-bg-subtle\">\n <p className=\"text-sm text-status-info-text\">\n <strong>Verification Process:</strong> A ₹1 charge will be made to verify your\n payment method. This amount will be refunded immediately after verification.\n </p>\n </div>\n )}\n\n {/* Set as default */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={setAsDefault}\n onChange={(e) => setSetAsDefault(e.target.checked)}\n className=\"w-4 h-4 rounded border-input text-primary focus:ring-primary/20\"\n disabled={isProcessing}\n />\n <span className=\"text-sm text-foreground\">\n {tr('billing.overview.setAsDefault', 'Set as default payment method')}\n </span>\n </label>\n\n {/* Provider badge */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border\">\n <span className=\"text-xs text-muted-foreground\">Secured by</span>\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n selectedProvider === 'stripe'\n ? 'bg-accent-violet-subtle text-accent-violet'\n : 'bg-status-info-bg-subtle text-status-info-text'\n }`}\n >\n {selectedProvider === 'stripe' ? 'Stripe' : 'Razorpay'}\n </span>\n </div>\n </div>\n ) : (\n /* Success state */\n <div className=\"flex flex-col items-center py-8 text-center\">\n <div className=\"w-16 h-16 rounded-full bg-status-success-bg-subtle flex items-center justify-center mb-4\">\n <CheckCircle2 className=\"w-8 h-8 text-status-success-text\" />\n </div>\n <p className=\"font-medium text-foreground\">\n {tr('billing.overview.paymentMethodAdded', 'Payment method added successfully!')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your payment method has been securely saved.\n </p>\n </div>\n )}\n </div>\n\n {/* Footer */}\n {step !== 'success' && (\n <footer className=\"flex items-center justify-between gap-3 p-4 border-t border-border bg-muted/30 rounded-b-lg flex-shrink-0\">\n {step === 'add-card' && showStripe && showRazorpay ? (\n <button\n type=\"button\"\n onClick={() => {\n setStep('select-provider');\n setSelectedProvider(null);\n setError(null);\n // Cleanup Stripe element\n if (stripeCardElementRef.current) {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n }\n }}\n disabled={isProcessing}\n className=\"px-4 py-2 text-sm font-medium text-foreground hover:text-primary transition-colors disabled:opacity-50\"\n >\n Back\n </button>\n ) : (\n <div />\n )}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isProcessing}\n className=\"px-4 py-2 text-sm font-medium text-foreground border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-50\"\n >\n Cancel\n </button>\n {step === 'add-card' && (\n <button\n onClick={handleSubmit}\n disabled={\n isProcessing ||\n isAddingPaymentMethod ||\n isLoadingSdk ||\n (selectedProvider === 'stripe' && !isCardComplete)\n }\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {isProcessing || isAddingPaymentMethod ? (\n <>\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n {selectedProvider === 'razorpay' ? 'Processing...' : 'Saving...'}\n </>\n ) : isLoadingSdk ? (\n <>\n <Loader2 className=\"w-4 h-4 animate-spin\" />\n Loading...\n </>\n ) : selectedProvider === 'stripe' ? (\n 'Add Card'\n ) : (\n 'Add Payment Method (₹1)'\n )}\n </button>\n )}\n </div>\n </footer>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AA8GA,IAAM,KAAc,GAAa,MACxB,IAAI,SAAS,GAAS,MAAW;AACtC,KAAI,SAAS,eAAe,EAAG,EAAE;AAC/B,KAAS;AACT;;CAEF,IAAM,IAAS,SAAS,cAAc,SAAS;AAM/C,CALA,EAAO,KAAK,GACZ,EAAO,MAAM,GACb,EAAO,QAAQ,IACf,EAAO,eAAe,GAAS,EAC/B,EAAO,gBAAgB,EAAO,gBAAI,MAAM,kBAAkB,IAAM,CAAC,EACjE,SAAS,KAAK,YAAY,EAAO;EACjC,EAGS,KAAyD,EACpE,WACA,YACA,qBACA,aACA,YACA,mBACI;CACJ,IAAM,EAAE,UAAM,GAAS,EACjB,KAAM,GAAa,MAA6B;EACpD,IAAM,IAAa,GAAE,EAAI;AACzB,SAAO,MAAe,IAAM,IAAW;IAEnC,IAAW,EAAuB,KAAK,EACvC,IAAiB,EAAuB,KAAK,EAC7C,IAAuB,EAAiC,KAAK,EAC7D,IAAY,EAA8B,KAAK,EAG/C,EACJ,kBACA,yBACA,oBACA,WAAW,OACT,EAAyB,CAAC,EAAO,EAC/B,EAAE,0BAAuB,2BAAwB,GAAuB,EAKxE,IAAkB,GAAU,aAAa,KAAK,SAAS,GAAS,aAAa,KAAK,MAClF,IAAe,KAAmB,GAClC,IAAa,KAAiB,CAAC,GAE/B,CAAC,GAAM,KAAW,EAAoB,kBAAkB,EACxD,CAAC,GAAkB,KAAuB,EAAuC,KAAK,EACtF,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,CAAC,GAAc,KAAmB,EAAS,GAAM,EACjD,CAAC,GAAc,KAAmB,EAAS,GAAM,EACjD,CAAC,GAAgB,KAAqB,EAAS,GAAG,EAClD,CAAC,GAAc,KAAmB,EAAS,GAAK,EAChD,CAAC,IAAgB,KAAqB,EAAS,GAAM;AA6F3D,CA1FA,QAAgB;AACd,EAAI,KAEF,EAAQ,kBAAkB,EAC1B,EAAoB,KAAK,EACzB,EAAS,KAAK,EACd,EAAkB,GAAG,EACrB,EAAgB,GAAK,EACrB,EAAkB,GAAM,IAKtB,EAAqB,aADrB,EAAqB,QAAQ,SAAS,EACP;IAGlC,CAAC,EAAO,CAAC,EAMZ,QACM,MAAS,cAAc,MAAqB,YAAY,CAAC,IAAsB,WAEhE,YAAY;AAC7B,IAAgB,GAAK;AACrB,MAAI;AAGF,OAFA,MAAM,EAAW,6BAA6B,YAAY,EAEtD,CAAC,OAAO,OACV,OAAU,MAAM,4BAA4B;GAG9C,IAAM,IAAS,OAAO,OAAO,EAAqB;AAClD,KAAU,UAAU;GAGpB,IAAI,IAAW;AACf,UAAO,CAAC,EAAe,WAAW,IAAW,IAE3C,CADA,MAAM,IAAI,SAAS,MAAY,WAAW,GAAS,IAAI,CAAC,EACxD;AAGF,OAAI,CAAC,EAAe,QAClB,OAAU,MAAM,mDAAmD;AAGrE,OAAI,EAAqB,QACvB;GAIF,IAAM,IADW,EAAO,UAAU,CACL,OAAO,QAAQ,EAC1C,OAAO,EAA0B,uCAAuC,EACzE,CAAC;AAKF,GAHA,EAAY,MAAM,EAAe,QAAQ,EACzC,EAAqB,UAAU,GAE/B,EAAY,GAAG,WAAW,MAAU;AAElC,IADA,EAAkB,EAAM,SAAS,EAC7B,EAAM,QACR,EAAS,EAAM,MAAM,QAAQ,GAE7B,EAAS,KAAK;KAEhB;WACK,GAAK;AACZ,KAAS,aAAe,QAAQ,EAAI,UAAU,wBAAwB;YAC9D;AACR,KAAgB,GAAM;;KAId,QAEC;AACX,MAAI,EAAqB,QACvB,KAAI;AAEF,GADA,EAAqB,QAAQ,SAAS,EACtC,EAAqB,UAAU;UACzB;KAKX;EAAC;EAAM;EAAkB;EAAqB,CAAC,EAGlD,QAAgB;EACd,IAAM,KAAiB,MAAqB;AAC1C,GAAI,EAAE,QAAQ,YAAY,KAAU,CAAC,KACnC,GAAS;;AAIb,SADA,SAAS,iBAAiB,WAAW,EAAc,QACtC,SAAS,oBAAoB,WAAW,EAAc;IAClE;EAAC;EAAQ;EAAc;EAAQ,CAAC;CAEnC,IAAM,IAAuB,GAAa,MAAoC;AAG5E,EAFA,EAAoB,EAAS,EAC7B,EAAQ,WAAW,EACnB,EAAS,KAAK;IACb,EAAE,CAAC,EAEA,IAAqB,EAAY,YAAY;AACjD,MAAI,CAAC,EAAU,WAAW,CAAC,EAAqB,SAAS;AACvD,KAAS,yBAAyB;AAClC;;AAGF,MAAI,CAAC,EAAe,MAAM,EAAE;AAC1B,KAAS,mCAAmC;AAC5C;;AAIF,EADA,EAAgB,GAAK,EACrB,EAAS,KAAK;AAEd,MAAI;GAEF,IAAM,IAAqB,MAAM,EAAoB;IACnD;IACA,UAAU;IACV,UAAU,EAA0B;IACpC;IACD,CAAC;AAEF,OAAI,CAAC,EAAmB,aACtB,OAAU,MAAM,uCAAuC;GAIzD,IAAM,EAAE,gBAAa,OAAO,MAAgB,MAAM,EAAU,QAAQ,iBAClE,EAAmB,cACnB,EACE,gBAAgB;IACd,MAAM,EAAqB;IAC3B,iBAAiB,EAAE,MAAM,GAAgB;IAC1C,EACF,CACF;AAED,OAAI,EACF,OAAU,MAAM,EAAY,QAAQ;AAGtC,OAAI,GAAa,WAAW,YAC1B,OAAU,MAAM,2BAA2B;AAW7C,GAPA,EAAQ,UAAU,EAGlB,MAAM,IAAI,SAAS,MAAY,WAAW,GAAS,IAAK,CAAC,EACzD,KAAa,EAGb,iBAAiB;AACf,OAAS;MACR,IAAI;WACA,GAAK;AAEZ,GADA,EAAS,aAAe,QAAQ,EAAI,UAAU,+BAA+B,EAC7E,EAAgB,GAAM;;IAEvB;EAAC;EAAgB;EAAc;EAAkB;EAAqB;EAAW;EAAQ,CAAC,EAEvF,IAAuB,EAAY,YAAY;AAEnD,EADA,EAAgB,GAAK,EACrB,EAAS,KAAK;AAEd,MAAI;AAEF,KAAgB,GAAK;AACrB,OAAI;AACF,UAAM,EAAW,gDAAgD,eAAe;WAC1E;AAGN,IAFA,EAAS,8BAA8B,EACvC,EAAgB,GAAM,EACtB,EAAgB,GAAM;AACtB;;AAEF,KAAgB,GAAM;GAGtB,IAAM,IAAqB,MAAM,EAAoB;IACnD;IACA,UAAU;IACV,UAAU,EAA0B;IACpC;IACD,CAAC;AAEF,OACE,CAAC,EAAmB,WACpB,CAAC,EAAmB,WACpB,CAAC,EAAmB,eACpB;AAEA,IADA,EAAS,EAAmB,SAAS,kCAAkC,EACvE,EAAgB,GAAM;AACtB;;AAIF,OAAI,CAAC,OAAO,UAAU;AAEpB,IADA,EAAS,0BAA0B,EACnC,EAAgB,GAAM;AACtB;;GAGF,IAAM,IAAU;IACd,KAAK,EAAmB;IACxB,SAAS,EAAmB,UAAU,KAAK;IAC3C,UAAU,EAAmB,SAAS,aAAa;IACnD,UAAU,EAAmB;IAC7B,aAAa,EAAmB;IAChC,MAAM;IACN,aAAa,IAAI,EAAmB,OAAO;IAC3C,SAAS;KACP,MAAM,EAAmB;KACzB,OAAO,EAAmB;KAC1B,SAAS,EAAmB;KAC7B;IACD,OAAO;KACL,cAAc;KACd,gBAAgB,EAAa,UAAU;KACxC;IACD,SAAS,YAAY;AASnB,KAPA,EAAQ,UAAU,EAGlB,MAAM,IAAI,SAAS,MAAY,WAAW,GAAS,IAAK,CAAC,EACzD,KAAa,EAGb,iBAAiB;AACf,SAAS;QACR,IAAI;;IAET,OAAO,EACL,iBAAiB;AAEf,KADA,EAAgB,GAAM,EACtB,EAAS,oBAAoB;OAEhC;IACF;AAEW,OAAI,OAAO,SAAS,EAAQ,CACpC,MAAM;WACH,GAAK;AAEZ,GADA,EAAS,aAAe,QAAQ,EAAI,UAAU,+BAA+B,EAC7E,EAAgB,GAAM;;IAEvB;EAAC;EAAc;EAAkB;EAAqB;EAAW;EAAQ,CAAC,EAEvE,KAAe,QAAkB;AACrC,EAAI,MAAqB,WACvB,GAAoB,GACX,MAAqB,cAC9B,GAAsB;IAEvB;EAAC;EAAkB;EAAoB;EAAqB,CAAC;AAIhE,QAFK,IAGH,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,mBAAgB;YAJlB,CAOE,kBAAC,OAAD;GACE,WAAU;GACV,SAAU,IAAyB,KAAA,IAAV;GACzB,eAAY;GACZ,CAAA,EAGF,kBAAC,OAAD;GACE,KAAK;GACL,WAAU;aAFZ;IAKE,kBAAC,UAAD;KAAQ,WAAU;eAAlB,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,OAAD;OAAK,WAAU;iBACb,kBAAC,GAAD,EAAY,WAAU,wBAAyB,CAAA;OAC3C,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;OAAI,IAAG;OAAc,WAAU;iBAC5B,MAAS,YAAY,yBAAyB;OAC5C,CAAA,EACL,kBAAC,KAAD;OAAG,WAAU;iBAAb;QACG,MAAS,qBAAqB;QAC9B,MAAS,eACP,MAAqB,WAClB,wBACA;QACL,MAAS,gBAAgB;QACzB,MAAS,aAAa;QACrB;SACA,EAAA,CAAA,CACF;SACN,kBAAC,UAAD;MACE,SAAS;MACT,UAAU;MACV,WAAU;MACV,cAAW;gBAEX,kBAAC,IAAD,EAAG,WAAU,WAAY,CAAA;MAClB,CAAA,CACF;;IAGT,kBAAC,OAAD;KAAK,WAAU;eACZ,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA;MAC9D,CAAA,GACJ,MAAS,oBACX,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACG,KACC,kBAAC,UAAD;QACE,eAAe,EAAqB,SAAS;QAC7C,WAAU;kBAFZ,CAIE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD,EAAY,WAAU,8BAA+B,CAAA;SACjD,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBAA8B;SAAU,CAAA,EACrD,kBAAC,KAAD;SAAG,WAAU;mBAAgC;SAAgC,CAAA,CACzE,EAAA,CAAA,CACC;;OAEV,KACC,kBAAC,UAAD;QACE,eAAe,EAAqB,WAAW;QAC/C,WAAU;kBAFZ,CAIE,kBAAC,OAAD;SAAK,WAAU;mBACb,kBAAC,GAAD,EAAY,WAAU,4BAA6B,CAAA;SAC/C,CAAA,EACN,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,KAAD;SAAG,WAAU;mBAA8B;SAAY,CAAA,EACvD,kBAAC,KAAD;SAAG,WAAU;mBAAgC;SAA0B,CAAA,CACnE,EAAA,CAAA,CACC;;OAEV,CAAC,KAAc,CAAC,KACf,kBAAC,OAAD;QAAK,WAAU;kBAAf;SACE,kBAAC,GAAD,EAAa,WAAU,2CAA4C,CAAA;SACnE,kBAAC,KAAD;UAAG,WAAU;oBACV,EAAG,uCAAuC,iCAAiC;UAC1E,CAAA;SACJ,kBAAC,KAAD;UAAG,WAAU;oBACV,IACG,4EACA;UACF,CAAA;SACA;;OAEJ;UACJ,MAAS,aACX,kBAAC,OAAD;MAAK,WAAU;gBAAf;OAEG,KACC,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,GAAD,EAAa,WAAU,yBAA0B,CAAA,EACjD,kBAAC,KAAD;SAAG,WAAU;mBAAW;SAAU,CAAA,CAC9B;;OAIP,MAAqB,YACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SACE,SAAQ;SACR,WAAU;mBACX;SAEO,CAAA,EACR,kBAAC,SAAD;SACE,MAAK;SACL,IAAG;SACH,OAAO;SACP,WAAW,MAAM,EAAkB,EAAE,OAAO,MAAM;SAClD,WAAU;SACV,aAAY;SACZ,UAAU;SACV,CAAA,CACE;;OAIP,MAAqB,YACpB,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,SAAD;SAAO,WAAU;mBACd,EAAG,gCAAgC,eAAe;SAC7C,CAAA,EACR,kBAAC,OAAD;SAAK,WAAU;mBAAf,CACE,kBAAC,OAAD;UACE,KAAK;UACL,WAAU;UACV,CAAA,EACD,KACC,kBAAC,OAAD;UAAK,WAAU;oBAAf,CACE,kBAAC,GAAD,EAAS,WAAU,8CAA+C,CAAA,EAClE,kBAAC,QAAD;WAAM,WAAU;qBAAqC;WAE9C,CAAA,CACH;YAEJ;WACF;;OAIP,MAAqB,cACpB,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,KAAD;SAAG,WAAU;mBAAb,CACE,kBAAC,UAAD,EAAA,UAAQ,yBAA8B,CAAA,EAAA,wHAEpC;;QACA,CAAA;OAIR,kBAAC,SAAD;QAAO,WAAU;kBAAjB,CACE,kBAAC,SAAD;SACE,MAAK;SACL,SAAS;SACT,WAAW,MAAM,EAAgB,EAAE,OAAO,QAAQ;SAClD,WAAU;SACV,UAAU;SACV,CAAA,EACF,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAG,iCAAiC,gCAAgC;SAChE,CAAA,CACD;;OAGR,kBAAC,OAAD;QAAK,WAAU;kBAAf,CACE,kBAAC,QAAD;SAAM,WAAU;mBAAgC;SAAiB,CAAA,EACjE,kBAAC,QAAD;SACE,WAAW,oEACT,MAAqB,WACjB,+CACA;mBAGL,MAAqB,WAAW,WAAW;SACvC,CAAA,CACH;;OACF;UAGN,kBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,GAAD,EAAc,WAAU,oCAAqC,CAAA;QACzD,CAAA;OACN,kBAAC,KAAD;QAAG,WAAU;kBACV,EAAG,uCAAuC,qCAAqC;QAC9E,CAAA;OACJ,kBAAC,KAAD;QAAG,WAAU;kBAAqC;QAE9C,CAAA;OACA;;KAEJ,CAAA;IAGL,MAAS,aACR,kBAAC,UAAD;KAAQ,WAAU;eAAlB,CACG,MAAS,cAAc,KAAc,IACpC,kBAAC,UAAD;MACE,MAAK;MACL,eAAe;AAKb,OAJA,EAAQ,kBAAkB,EAC1B,EAAoB,KAAK,EACzB,EAAS,KAAK,EAEd,AAEE,EAAqB,aADrB,EAAqB,QAAQ,SAAS,EACP;;MAGnC,UAAU;MACV,WAAU;gBACX;MAEQ,CAAA,GAET,kBAAC,OAAD,EAAO,CAAA,EAET,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,SAAS;OACT,UAAU;OACV,WAAU;iBACX;OAEQ,CAAA,EACR,MAAS,cACR,kBAAC,UAAD;OACE,SAAS;OACT,UACE,KACA,KACA,KACC,MAAqB,YAAY,CAAC;OAErC,WAAU;iBAET,KAAgB,IACf,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,EAC3C,MAAqB,aAAa,kBAAkB,YACpD,EAAA,CAAA,GACD,IACF,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD,EAAS,WAAU,wBAAyB,CAAA,EAAA,aAE3C,EAAA,CAAA,GACD,MAAqB,WACvB,aAEA;OAEK,CAAA,CAEP;QACC;;IAEP;KACF;MAnRY"}
1
+ {"version":3,"file":"AddPaymentMethodModal.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/AddPaymentMethodModal.tsx"],"sourcesContent":["/**\n * Add Payment Method Modal Component\n * Modal for adding a new payment method via Stripe or Razorpay SDKs\n */\n\nimport { type FC, useState, useCallback, useEffect, useRef } from 'react';\nimport { X, CreditCard, Loader2, AlertCircle, CheckCircle2 } from 'lucide-react';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport { usePaymentProviderConfig, useDashboardMutations } from '../hooks';\nimport { PaymentProviderPreference } from '../../../shared/types';\nimport { getStripeCardElementStyle } from '../../../shared/utils';\n\n// Stripe types (loaded dynamically)\ndeclare global {\n interface Window {\n Stripe?: (key: string) => StripeInstance;\n Razorpay?: new (options: RazorpayOptions) => RazorpayInstance;\n }\n}\n\ninterface StripeInstance {\n elements: () => StripeElements;\n createPaymentMethod: (options: {\n type: 'card';\n card: StripeCardElement;\n billing_details?: { name?: string };\n }) => Promise<{\n paymentMethod?: {\n id: string;\n card?: { brand: string; last4: string; exp_month: number; exp_year: number };\n };\n error?: { message: string };\n }>;\n confirmCardSetup: (\n clientSecret: string,\n options?: {\n payment_method?: {\n card: StripeCardElement;\n billing_details?: { name?: string };\n };\n }\n ) => Promise<{\n setupIntent?: {\n id: string;\n status: string;\n payment_method?: string;\n };\n error?: { message: string };\n }>;\n}\n\ninterface StripeElements {\n create: (type: 'card', options?: object) => StripeCardElement;\n}\n\ninterface StripeCardElement {\n mount: (element: HTMLElement | string) => void;\n unmount: () => void;\n on: (\n event: string,\n handler: (event: { complete: boolean; error?: { message: string } }) => void\n ) => void;\n destroy: () => void;\n}\n\ninterface RazorpayOptions {\n key: string;\n amount: number;\n currency: string;\n order_id: string;\n customer_id?: string;\n name: string;\n description: string;\n method?: 'card' | 'upi' | 'netbanking' | 'wallet' | 'emi' | 'cardless_emi';\n handler: (response: RazorpayResponse) => void;\n modal?: { ondismiss?: () => void };\n prefill?: { name?: string; email?: string; contact?: string };\n notes?: Record<string, string>;\n config?: {\n display?: {\n hide?: Array<{ method: string }>;\n preferences?: {\n show_default_blocks?: boolean;\n };\n };\n };\n}\n\ninterface RazorpayInstance {\n open: () => void;\n close: () => void;\n}\n\ninterface RazorpayResponse {\n razorpay_payment_id: string;\n razorpay_token?: string;\n}\n\ninterface AddPaymentMethodModalProps {\n isOpen: boolean;\n onClose: () => void;\n billingAccountId: string;\n currency: string; // e.g., 'INR', 'USD'\n country?: string; // e.g., 'IN', 'US' - from billing address\n onSuccess?: () => void;\n}\n\ntype ModalStep = 'select-provider' | 'add-card' | 'processing' | 'success';\n\n// Load external script dynamically\nconst loadScript = (src: string, id: string): Promise<void> => {\n return new Promise((resolve, reject) => {\n if (document.getElementById(id)) {\n resolve();\n return;\n }\n const script = document.createElement('script');\n script.id = id;\n script.src = src;\n script.async = true;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error(`Failed to load ${src}`));\n document.head.appendChild(script);\n });\n};\n\nexport const AddPaymentMethodModal: FC<AddPaymentMethodModalProps> = ({\n isOpen,\n onClose,\n billingAccountId,\n currency,\n country,\n onSuccess,\n}) => {\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 modalRef = useRef<HTMLDivElement>(null);\n const cardElementRef = useRef<HTMLDivElement>(null);\n const stripeCardElementRef = useRef<StripeCardElement | null>(null);\n const stripeRef = useRef<StripeInstance | null>(null);\n\n // Only fetch payment provider config when modal is open\n const {\n stripeEnabled,\n stripePublishableKey,\n razorpayEnabled,\n isLoading: isLoadingConfig,\n } = usePaymentProviderConfig(!isOpen);\n const { isAddingPaymentMethod, verifyPaymentMethod } = useDashboardMutations();\n\n // Determine which providers to show based on currency and country\n // Razorpay: India only (INR currency OR IN country)\n // Stripe: International (non-INR OR non-IN country)\n const isIndianAccount = currency?.toUpperCase() === 'INR' || country?.toUpperCase() === 'IN';\n const showRazorpay = razorpayEnabled && isIndianAccount;\n const showStripe = stripeEnabled && !isIndianAccount;\n\n const [step, setStep] = useState<ModalStep>('select-provider');\n const [selectedProvider, setSelectedProvider] = useState<'stripe' | 'razorpay' | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [isProcessing, setIsProcessing] = useState(false);\n const [isLoadingSdk, setIsLoadingSdk] = useState(false);\n const [cardholderName, setCardholderName] = useState('');\n const [setAsDefault, setSetAsDefault] = useState(true);\n const [isCardComplete, setIsCardComplete] = useState(false);\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (isOpen) {\n // Always start with provider selection\n setStep('select-provider');\n setSelectedProvider(null);\n setError(null);\n setCardholderName('');\n setSetAsDefault(true);\n setIsCardComplete(false);\n } else {\n // Cleanup Stripe element when modal closes\n if (stripeCardElementRef.current) {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n }\n }\n }, [isOpen]);\n\n // Note: We always show provider selection, even if only one is available\n // This ensures the user explicitly chooses their payment provider\n\n // Initialize Stripe when provider is selected\n useEffect(() => {\n if (step !== 'add-card' || selectedProvider !== 'stripe' || !stripePublishableKey) return;\n\n const initStripe = async () => {\n setIsLoadingSdk(true);\n try {\n await loadScript('https://js.stripe.com/v3/', 'stripe-js');\n\n if (!window.Stripe) {\n throw new Error('Stripe SDK failed to load');\n }\n\n const stripe = window.Stripe(stripePublishableKey);\n stripeRef.current = stripe;\n\n // Wait for the card element container to be mounted in the DOM\n let attempts = 0;\n while (!cardElementRef.current && attempts < 50) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n attempts++;\n }\n\n if (!cardElementRef.current) {\n throw new Error('Card element container not found after 5 seconds');\n }\n\n if (stripeCardElementRef.current) {\n return;\n }\n\n const elements = stripe.elements();\n const cardElement = elements.create('card', {\n style: getStripeCardElementStyle('system-ui, -apple-system, sans-serif'),\n });\n\n cardElement.mount(cardElementRef.current);\n stripeCardElementRef.current = cardElement;\n\n cardElement.on('change', (event) => {\n setIsCardComplete(event.complete);\n if (event.error) {\n setError(event.error.message);\n } else {\n setError(null);\n }\n });\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to load Stripe');\n } finally {\n setIsLoadingSdk(false);\n }\n };\n\n initStripe();\n\n return () => {\n if (stripeCardElementRef.current) {\n try {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n } catch {\n // Stripe element may already be detached during modal teardown.\n }\n }\n };\n }, [step, selectedProvider, stripePublishableKey]);\n\n // Handle escape key\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape' && isOpen && !isProcessing) {\n onClose();\n }\n };\n document.addEventListener('keydown', handleKeyDown);\n return () => document.removeEventListener('keydown', handleKeyDown);\n }, [isOpen, isProcessing, onClose]);\n\n const handleSelectProvider = useCallback((provider: 'stripe' | 'razorpay') => {\n setSelectedProvider(provider);\n setStep('add-card');\n setError(null);\n }, []);\n\n const handleStripeSubmit = useCallback(async () => {\n if (!stripeRef.current || !stripeCardElementRef.current) {\n setError('Stripe not initialized');\n return;\n }\n\n if (!cardholderName.trim()) {\n setError('Please enter the cardholder name');\n return;\n }\n\n setIsProcessing(true);\n setError(null);\n\n try {\n // Step 1: Call backend to create SetupIntent and get client secret\n const verificationResult = await verifyPaymentMethod({\n billingAccountId,\n currency: 'USD',\n provider: PaymentProviderPreference.STRIPE,\n setAsDefault,\n });\n\n if (!verificationResult.clientSecret) {\n throw new Error('Failed to initiate card verification');\n }\n\n // Step 2: Confirm card setup using the client secret (no charge)\n const { setupIntent, error: stripeError } = await stripeRef.current.confirmCardSetup(\n verificationResult.clientSecret,\n {\n payment_method: {\n card: stripeCardElementRef.current,\n billing_details: { name: cardholderName },\n },\n }\n );\n\n if (stripeError) {\n throw new Error(stripeError.message);\n }\n\n if (setupIntent?.status !== 'succeeded') {\n throw new Error('Card verification failed');\n }\n\n // Step 3: Show success (webhook will save the payment method)\n setStep('success');\n\n // Wait for webhook to process (2 seconds) before refetching\n await new Promise((resolve) => setTimeout(resolve, 2000));\n onSuccess?.();\n\n // Show success message briefly before closing\n setTimeout(() => {\n onClose();\n }, 500);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add payment method');\n setIsProcessing(false);\n }\n }, [cardholderName, setAsDefault, billingAccountId, verifyPaymentMethod, onSuccess, onClose]);\n\n const handleRazorpaySubmit = useCallback(async () => {\n setIsProcessing(true);\n setError(null);\n\n try {\n // Load Razorpay SDK\n setIsLoadingSdk(true);\n try {\n await loadScript('https://checkout.razorpay.com/v1/checkout.js', 'razorpay-sdk');\n } catch {\n setError('Failed to load Razorpay SDK');\n setIsProcessing(false);\n setIsLoadingSdk(false);\n return;\n }\n setIsLoadingSdk(false);\n\n // Initiate ₹1 verification payment\n const verificationResult = await verifyPaymentMethod({\n billingAccountId,\n currency: 'INR',\n provider: PaymentProviderPreference.RAZORPAY,\n setAsDefault,\n });\n\n if (\n !verificationResult.success ||\n !verificationResult.orderId ||\n !verificationResult.razorpayKeyId\n ) {\n setError(verificationResult.error || 'Failed to initiate verification');\n setIsProcessing(false);\n return;\n }\n\n // Open Razorpay checkout with ALL payment methods\n if (!window.Razorpay) {\n setError('Razorpay SDK not loaded');\n setIsProcessing(false);\n return;\n }\n\n const options = {\n key: verificationResult.razorpayKeyId,\n amount: (verificationResult.amount ?? 0) * 100, // Convert to paise\n currency: verificationResult.currency.toUpperCase(),\n order_id: verificationResult.orderId,\n customer_id: verificationResult.razorpayCustomerId, // Link to customer for saving\n name: 'Add Payment Method',\n description: `₹${verificationResult.amount} verification charge (refundable)`,\n prefill: {\n name: verificationResult.prefillName,\n email: verificationResult.prefillEmail,\n contact: verificationResult.prefillContact,\n },\n notes: {\n purchaseType: 'PAYMENT_METHOD_VERIFICATION',\n default_method: setAsDefault.toString(),\n },\n handler: async () => {\n // Payment successful - payment method will be saved via webhook\n setStep('success');\n\n // Wait for webhook to process (2 seconds) before refetching\n await new Promise((resolve) => setTimeout(resolve, 2000));\n onSuccess?.();\n\n // Show success message briefly before closing\n setTimeout(() => {\n onClose();\n }, 500);\n },\n modal: {\n ondismiss: () => {\n setIsProcessing(false);\n setError('Payment cancelled');\n },\n },\n };\n\n const rzp = new window.Razorpay(options);\n rzp.open();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add payment method');\n setIsProcessing(false);\n }\n }, [setAsDefault, billingAccountId, verifyPaymentMethod, onSuccess, onClose]);\n\n const handleSubmit = useCallback(() => {\n if (selectedProvider === 'stripe') {\n handleStripeSubmit();\n } else if (selectedProvider === 'razorpay') {\n handleRazorpaySubmit();\n }\n }, [selectedProvider, handleStripeSubmit, handleRazorpaySubmit]);\n\n if (!isOpen) return null;\n\n return (\n <div\n className=\"fixed inset-0 z-50 flex items-center justify-center\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-labelledby=\"modal-title\"\n >\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-background/80 backdrop-blur-sm\"\n onClick={!isProcessing ? onClose : undefined}\n aria-hidden=\"true\"\n />\n\n {/* Modal */}\n <div\n ref={modalRef}\n className=\"relative w-full max-w-md max-h-[90vh] mx-4 bg-card border border-border rounded-lg shadow-xl flex flex-col\"\n >\n {/* Header */}\n <header className=\"flex items-center justify-between p-4 border-b border-border flex-shrink-0\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-primary/10 flex items-center justify-center\">\n <CreditCard className=\"size-5 text-primary\" />\n </div>\n <div>\n <h2 id=\"modal-title\" className=\"text-lg font-semibold text-foreground\">\n {step === 'success' ? 'Payment Method Added' : 'Add Payment Method'}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {step === 'select-provider' && 'Choose a payment provider'}\n {step === 'add-card' &&\n (selectedProvider === 'stripe'\n ? 'Add card via Stripe'\n : 'Add payment method with ₹1 verification')}\n {step === 'processing' && 'Processing...'}\n {step === 'success' && 'Your payment method has been saved'}\n </p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isProcessing}\n className=\"p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50\"\n aria-label=\"Close modal\"\n >\n <X className=\"size-5\" />\n </button>\n </header>\n\n {/* Content */}\n <div className=\"p-4 overflow-y-auto flex-1\">\n {isLoadingConfig ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"size-6 animate-spin text-muted-foreground\" />\n </div>\n ) : step === 'select-provider' ? (\n <div className=\"space-y-3\">\n {showStripe && (\n <button\n type=\"button\"\n onClick={() => handleSelectProvider('stripe')}\n className=\"w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left\"\n >\n <div className=\"size-12 rounded-lg bg-accent-violet-subtle flex items-center justify-center\">\n <CreditCard className=\"size-6 text-accent-violet\" />\n </div>\n <div>\n <p className=\"font-medium text-foreground\">Stripe</p>\n <p className=\"text-sm text-muted-foreground\">Cards, Apple Pay, Google Pay</p>\n </div>\n </button>\n )}\n {showRazorpay && (\n <button\n type=\"button\"\n onClick={() => handleSelectProvider('razorpay')}\n className=\"w-full flex items-center gap-4 p-4 border border-border rounded-lg hover:border-primary hover:bg-primary/5 transition-colors text-left\"\n >\n <div className=\"size-12 rounded-lg bg-status-info-bg-subtle flex items-center justify-center\">\n <CreditCard className=\"size-6 text-accent-blue\" />\n </div>\n <div>\n <p className=\"font-medium text-foreground\">Razorpay</p>\n <p className=\"text-sm text-muted-foreground\">UPI, Netbanking, Cards</p>\n </div>\n </button>\n )}\n {!showStripe && !showRazorpay && (\n <div className=\"flex flex-col items-center py-8 text-center\">\n <AlertCircle className=\"size-12 text-status-warning-text mb-3\" />\n <p className=\"font-medium text-foreground\">\n {tr('billing.overview.noPaymentProviders', 'No Payment Providers Available')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n {isIndianAccount\n ? 'Razorpay is not configured for Indian accounts. Please contact support.'\n : 'Stripe is not configured for international accounts. Please contact support.'}\n </p>\n </div>\n )}\n </div>\n ) : step === 'add-card' ? (\n <div className=\"space-y-4\">\n {/* Error Message */}\n {error && (\n <div className=\"flex items-center gap-2 p-3 rounded-lg bg-destructive/10 border border-destructive/20 text-destructive\">\n <AlertCircle className=\"size-4 flex-shrink-0\" />\n <p className=\"text-sm\">{error}</p>\n </div>\n )}\n\n {/* Cardholder Name - only for Stripe */}\n {selectedProvider === 'stripe' && (\n <div className=\"space-y-1.5\">\n <label\n htmlFor=\"cardholderName\"\n className=\"block text-sm font-medium text-foreground\"\n >\n Cardholder Name\n </label>\n <input\n type=\"text\"\n id=\"cardholderName\"\n value={cardholderName}\n onChange={(e) => setCardholderName(e.target.value)}\n className=\"w-full px-3 py-2 border border-input rounded-lg bg-background text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary/20 focus:border-primary\"\n placeholder=\"John Doe\"\n disabled={isProcessing}\n />\n </div>\n )}\n\n {/* Stripe Card Element */}\n {selectedProvider === 'stripe' && (\n <div className=\"space-y-1.5\">\n <label className=\"block text-sm font-medium text-foreground\">\n {tr('billing.overview.cardDetails', 'Card Details')}\n </label>\n <div className=\"relative\">\n <div\n ref={cardElementRef}\n className=\"p-3 border border-input rounded-lg bg-background min-h-[44px]\"\n />\n {isLoadingSdk && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-background/80 rounded-lg\">\n <Loader2 className=\"size-5 animate-spin text-muted-foreground\" />\n <span className=\"ml-2 text-sm text-muted-foreground\">Loading Stripe…</span>\n </div>\n )}\n </div>\n </div>\n )}\n\n {/* Razorpay - Verification Info */}\n {selectedProvider === 'razorpay' && (\n <div className=\"p-3 border border-border-subtle rounded-lg bg-status-info-bg-subtle\">\n <p className=\"text-sm text-status-info-text\">\n <strong>Verification Process:</strong> A ₹1 charge will be made to verify your\n payment method. This amount will be refunded immediately after verification.\n </p>\n </div>\n )}\n\n {/* Set as default */}\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={setAsDefault}\n onChange={(e) => setSetAsDefault(e.target.checked)}\n className=\"size-4 rounded border-input text-primary focus:ring-primary/20\"\n disabled={isProcessing}\n />\n <span className=\"text-sm text-foreground\">\n {tr('billing.overview.setAsDefault', 'Set as default payment method')}\n </span>\n </label>\n\n {/* Provider badge */}\n <div className=\"flex items-center gap-2 pt-2 border-t border-border\">\n <span className=\"text-xs text-muted-foreground\">Secured by</span>\n <span\n className={`inline-flex items-center px-2 py-0.5 rounded text-xs font-medium ${\n selectedProvider === 'stripe'\n ? 'bg-accent-violet-subtle text-accent-violet'\n : 'bg-status-info-bg-subtle text-status-info-text'\n }`}\n >\n {selectedProvider === 'stripe' ? 'Stripe' : 'Razorpay'}\n </span>\n </div>\n </div>\n ) : (\n /* Success state */\n <div className=\"flex flex-col items-center py-8 text-center\">\n <div className=\"size-16 rounded-full bg-status-success-bg-subtle flex items-center justify-center mb-4\">\n <CheckCircle2 className=\"size-8 text-status-success-text\" />\n </div>\n <p className=\"font-medium text-foreground\">\n {tr('billing.overview.paymentMethodAdded', 'Payment method added successfully!')}\n </p>\n <p className=\"text-sm text-muted-foreground mt-1\">\n Your payment method has been securely saved.\n </p>\n </div>\n )}\n </div>\n\n {/* Footer */}\n {step !== 'success' && (\n <footer className=\"flex items-center justify-between gap-3 p-4 border-t border-border bg-muted/30 rounded-b-lg flex-shrink-0\">\n {step === 'add-card' && showStripe && showRazorpay ? (\n <button\n type=\"button\"\n onClick={() => {\n setStep('select-provider');\n setSelectedProvider(null);\n setError(null);\n // Cleanup Stripe element\n if (stripeCardElementRef.current) {\n stripeCardElementRef.current.destroy();\n stripeCardElementRef.current = null;\n }\n }}\n disabled={isProcessing}\n className=\"px-4 py-2 text-sm font-medium text-foreground hover:text-primary transition-colors disabled:opacity-50\"\n >\n Back\n </button>\n ) : (\n <div />\n )}\n <div className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n disabled={isProcessing}\n className=\"px-4 py-2 text-sm font-medium text-foreground border border-border rounded-lg hover:bg-muted transition-colors disabled:opacity-50\"\n >\n Cancel\n </button>\n {step === 'add-card' && (\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={\n isProcessing ||\n isAddingPaymentMethod ||\n isLoadingSdk ||\n (selectedProvider === 'stripe' && !isCardComplete)\n }\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-primary-foreground bg-primary rounded-lg hover:bg-primary/90 transition-colors disabled:opacity-50\"\n >\n {isProcessing || isAddingPaymentMethod ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n {selectedProvider === 'razorpay' ? 'Processing...' : 'Saving...'}\n </>\n ) : isLoadingSdk ? (\n <>\n <Loader2 className=\"size-4 animate-spin\" />\n Loading…\n </>\n ) : selectedProvider === 'stripe' ? (\n 'Add Card'\n ) : (\n 'Add Payment Method (₹1)'\n )}\n </button>\n )}\n </div>\n </footer>\n )}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -33,8 +33,8 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
33
33
  children: [/* @__PURE__ */ d("div", {
34
34
  className: "flex items-center gap-3 min-w-0",
35
35
  children: [/* @__PURE__ */ u("div", {
36
- className: "w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0",
37
- children: /* @__PURE__ */ u(n, { className: "w-5 h-5 text-primary" })
36
+ className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0",
37
+ children: /* @__PURE__ */ u(n, { className: "size-5 text-primary" })
38
38
  }), /* @__PURE__ */ d("div", {
39
39
  className: "min-w-0",
40
40
  children: [/* @__PURE__ */ d("div", {
@@ -49,22 +49,23 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
49
49
  children: S("billing.overview.default", "Default")
50
50
  }),
51
51
  h && /* @__PURE__ */ u("span", {
52
- className: "inline-flex items-center justify-center w-5 h-5 rounded-full bg-primary",
53
- children: /* @__PURE__ */ u(i, { className: "w-3 h-3 text-primary-foreground" })
52
+ className: "inline-flex items-center justify-center size-5 rounded-full bg-primary",
53
+ children: /* @__PURE__ */ u(i, { className: "size-3 text-primary-foreground" })
54
54
  })
55
55
  ]
56
56
  }), /* @__PURE__ */ d("p", {
57
57
  className: "text-sm text-muted-foreground truncate flex items-center gap-1",
58
- children: [/* @__PURE__ */ u(l, { className: "w-3.5 h-3.5" }), p.email]
58
+ children: [/* @__PURE__ */ u(l, { className: "size-3.5" }), p.email]
59
59
  })]
60
60
  })]
61
61
  }), _ && /* @__PURE__ */ u("button", {
62
+ type: "button",
62
63
  onClick: (e) => {
63
64
  e.stopPropagation(), _();
64
65
  },
65
66
  className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors",
66
67
  "aria-label": "Edit billing account",
67
- children: /* @__PURE__ */ u(c, { className: "w-4 h-4" })
68
+ children: /* @__PURE__ */ u(c, { className: "size-4" })
68
69
  })]
69
70
  })
70
71
  }),
@@ -80,7 +81,7 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
80
81
  }), /* @__PURE__ */ d("p", {
81
82
  className: "text-lg font-semibold text-foreground flex items-center gap-1.5",
82
83
  children: [
83
- /* @__PURE__ */ u(o, { className: `w-4 h-4 ${e.warning.icon}` }),
84
+ /* @__PURE__ */ u(o, { className: `size-4 ${e.warning.icon}` }),
84
85
  (p.creditAmount || 0).toLocaleString(),
85
86
  " Credits"
86
87
  ]
@@ -92,7 +93,7 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
92
93
  children: "Payment Currency"
93
94
  }), /* @__PURE__ */ d("p", {
94
95
  className: "text-lg font-semibold text-foreground flex items-center gap-1.5",
95
- children: [/* @__PURE__ */ u(s, { className: "w-4 h-4 text-primary" }), p.currency || "USD"]
96
+ children: [/* @__PURE__ */ u(s, { className: "size-4 text-primary" }), p.currency || "USD"]
96
97
  })]
97
98
  })]
98
99
  }), /* @__PURE__ */ u("div", {
@@ -100,7 +101,7 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
100
101
  children: /* @__PURE__ */ d("p", {
101
102
  className: "text-xs text-muted-foreground flex items-center gap-1",
102
103
  children: [
103
- /* @__PURE__ */ u(r, { className: "w-3.5 h-3.5" }),
104
+ /* @__PURE__ */ u(r, { className: "size-3.5" }),
104
105
  "Created ",
105
106
  ((e) => new Date(e).toLocaleDateString("en-US", {
106
107
  year: "numeric",
@@ -116,17 +117,19 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
116
117
  children: /* @__PURE__ */ d("div", {
117
118
  className: "flex items-center gap-2",
118
119
  children: [v && /* @__PURE__ */ d("button", {
120
+ type: "button",
119
121
  onClick: (e) => {
120
122
  e.stopPropagation(), v();
121
123
  },
122
124
  className: "flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors",
123
- children: ["Transactions", /* @__PURE__ */ u(a, { className: "w-4 h-4" })]
125
+ children: ["Transactions", /* @__PURE__ */ u(a, { className: "size-4" })]
124
126
  }), y && /* @__PURE__ */ d("button", {
127
+ type: "button",
125
128
  onClick: (e) => {
126
129
  e.stopPropagation(), y();
127
130
  },
128
131
  className: "flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors",
129
- children: ["Credit History", /* @__PURE__ */ u(a, { className: "w-4 h-4" })]
132
+ children: ["Credit History", /* @__PURE__ */ u(a, { className: "size-4" })]
130
133
  })]
131
134
  })
132
135
  }),
@@ -1 +1 @@
1
- {"version":3,"file":"BillingAccountCard.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/BillingAccountCard.tsx"],"sourcesContent":["/**\n * Billing Account Card Component\n * Displays billing account details with actions\n */\n\nimport { type FC, useState } from 'react';\nimport {\n Building2,\n Mail,\n CreditCard,\n Edit2,\n ChevronRight,\n Coins,\n Check,\n Calendar,\n} from 'lucide-react';\nimport type { BillingAccount } from '../../../shared/types';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface BillingAccountCardProps {\n account: BillingAccount;\n isDefault?: boolean;\n isSelected?: boolean;\n onSelect?: () => void;\n onEdit?: () => void;\n onViewTransactions?: () => void;\n onViewCreditTransactions?: () => void;\n className?: string;\n}\n\nexport const BillingAccountCard: FC<BillingAccountCardProps> = ({\n account,\n isDefault = false,\n isSelected = false,\n onSelect,\n onEdit,\n onViewTransactions,\n onViewCreditTransactions,\n className = '',\n}) => {\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 [isHovered, setIsHovered] = useState(false);\n\n const formatDate = (dateString: string) => {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n };\n\n return (\n <article\n className={`\n relative border rounded-lg bg-card transition-all duration-200\n ${isSelected ? 'border-primary ring-2 ring-primary/20' : 'border-border'}\n ${isHovered ? 'shadow-md' : 'shadow-sm'}\n ${onSelect ? 'cursor-pointer' : ''}\n ${className}\n `}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onClick={onSelect}\n role={onSelect ? 'button' : 'article'}\n tabIndex={onSelect ? 0 : undefined}\n onKeyDown={(e) => {\n if (onSelect && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onSelect();\n }\n }}\n >\n {/* Header */}\n <header className=\"p-4 border-b border-border\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3 min-w-0\">\n <div className=\"w-10 h-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0\">\n <Building2 className=\"w-5 h-5 text-primary\" />\n </div>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold text-foreground truncate\">{account.name}</h3>\n {isDefault && (\n <span className=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-primary/10 text-primary\">\n {tr('billing.overview.default', 'Default')}\n </span>\n )}\n {isSelected && (\n <span className=\"inline-flex items-center justify-center w-5 h-5 rounded-full bg-primary\">\n <Check className=\"w-3 h-3 text-primary-foreground\" />\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground truncate flex items-center gap-1\">\n <Mail className=\"w-3.5 h-3.5\" />\n {account.email}\n </p>\n </div>\n </div>\n {onEdit && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n className=\"p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Edit billing account\"\n >\n <Edit2 className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 space-y-4\">\n {/* Stats Grid */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Credit Balance\n </p>\n <p className=\"text-lg font-semibold text-foreground flex items-center gap-1.5\">\n <Coins className={`w-4 h-4 ${statusTokens.warning.icon}`} />\n {(account.creditAmount || 0).toLocaleString()} Credits\n </p>\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Payment Currency\n </p>\n <p className=\"text-lg font-semibold text-foreground flex items-center gap-1.5\">\n <CreditCard className=\"w-4 h-4 text-primary\" />\n {account.currency || 'USD'}\n </p>\n </div>\n </div>\n\n {/* Meta Info */}\n <div className=\"pt-3 border-t border-border\">\n <p className=\"text-xs text-muted-foreground flex items-center gap-1\">\n <Calendar className=\"w-3.5 h-3.5\" />\n Created {formatDate(account.createdAt)}\n </p>\n </div>\n </div>\n\n {/* Footer Actions */}\n {(onViewTransactions || onViewCreditTransactions) && (\n <footer className=\"px-4 py-3 border-t border-border bg-muted/30 rounded-b-lg\">\n <div className=\"flex items-center gap-2\">\n {onViewTransactions && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onViewTransactions();\n }}\n className=\"flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors\"\n >\n Transactions\n <ChevronRight className=\"w-4 h-4\" />\n </button>\n )}\n {onViewCreditTransactions && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onViewCreditTransactions();\n }}\n className=\"flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors\"\n >\n Credit History\n <ChevronRight className=\"w-4 h-4\" />\n </button>\n )}\n </div>\n </footer>\n )}\n\n {/* Status indicator */}\n {!account.isActive && (\n <div className=\"absolute inset-0 bg-background/60 backdrop-blur-sm rounded-lg flex items-center justify-center\">\n <span className=\"px-3 py-1.5 rounded-full bg-destructive/10 text-destructive text-sm font-medium\">\n Inactive\n </span>\n </div>\n )}\n </article>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"BillingAccountCard.js","names":[],"sources":["../../../../../src/billing/modules/dashboard/components/BillingAccountCard.tsx"],"sourcesContent":["/**\n * Billing Account Card Component\n * Displays billing account details with actions\n */\n\nimport { type FC, useState } from 'react';\nimport {\n Building2,\n Mail,\n CreditCard,\n Edit2,\n ChevronRight,\n Coins,\n Check,\n Calendar,\n} from 'lucide-react';\nimport type { BillingAccount } from '../../../shared/types';\nimport { statusTokens } from '../../../shared/utils/tokens';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\n\ninterface BillingAccountCardProps {\n account: BillingAccount;\n isDefault?: boolean;\n isSelected?: boolean;\n onSelect?: () => void;\n onEdit?: () => void;\n onViewTransactions?: () => void;\n onViewCreditTransactions?: () => void;\n className?: string;\n}\n\nexport const BillingAccountCard: FC<BillingAccountCardProps> = ({\n account,\n isDefault = false,\n isSelected = false,\n onSelect,\n onEdit,\n onViewTransactions,\n onViewCreditTransactions,\n className = '',\n}) => {\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 [isHovered, setIsHovered] = useState(false);\n\n const formatDate = (dateString: string) => {\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n };\n\n return (\n <article\n className={`\n relative border rounded-lg bg-card transition-all duration-200\n ${isSelected ? 'border-primary ring-2 ring-primary/20' : 'border-border'}\n ${isHovered ? 'shadow-md' : 'shadow-sm'}\n ${onSelect ? 'cursor-pointer' : ''}\n ${className}\n `}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onClick={onSelect}\n role={onSelect ? 'button' : 'article'}\n tabIndex={onSelect ? 0 : undefined}\n onKeyDown={(e) => {\n if (onSelect && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onSelect();\n }\n }}\n >\n {/* Header */}\n <header className=\"p-4 border-b border-border\">\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"flex items-center gap-3 min-w-0\">\n <div className=\"size-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0\">\n <Building2 className=\"size-5 text-primary\" />\n </div>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold text-foreground truncate\">{account.name}</h3>\n {isDefault && (\n <span className=\"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-primary/10 text-primary\">\n {tr('billing.overview.default', 'Default')}\n </span>\n )}\n {isSelected && (\n <span className=\"inline-flex items-center justify-center size-5 rounded-full bg-primary\">\n <Check className=\"size-3 text-primary-foreground\" />\n </span>\n )}\n </div>\n <p className=\"text-sm text-muted-foreground truncate flex items-center gap-1\">\n <Mail className=\"size-3.5\" />\n {account.email}\n </p>\n </div>\n </div>\n {onEdit && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onEdit();\n }}\n className=\"p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors\"\n aria-label=\"Edit billing account\"\n >\n <Edit2 className=\"size-4\" />\n </button>\n )}\n </div>\n </header>\n\n {/* Body */}\n <div className=\"p-4 space-y-4\">\n {/* Stats Grid */}\n <div className=\"grid grid-cols-2 gap-4\">\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Credit Balance\n </p>\n <p className=\"text-lg font-semibold text-foreground flex items-center gap-1.5\">\n <Coins className={`size-4 ${statusTokens.warning.icon}`} />\n {(account.creditAmount || 0).toLocaleString()} Credits\n </p>\n </div>\n <div className=\"space-y-1\">\n <p className=\"text-xs font-medium text-muted-foreground uppercase tracking-wide\">\n Payment Currency\n </p>\n <p className=\"text-lg font-semibold text-foreground flex items-center gap-1.5\">\n <CreditCard className=\"size-4 text-primary\" />\n {account.currency || 'USD'}\n </p>\n </div>\n </div>\n\n {/* Meta Info */}\n <div className=\"pt-3 border-t border-border\">\n <p className=\"text-xs text-muted-foreground flex items-center gap-1\">\n <Calendar className=\"size-3.5\" />\n Created {formatDate(account.createdAt)}\n </p>\n </div>\n </div>\n\n {/* Footer Actions */}\n {(onViewTransactions || onViewCreditTransactions) && (\n <footer className=\"px-4 py-3 border-t border-border bg-muted/30 rounded-b-lg\">\n <div className=\"flex items-center gap-2\">\n {onViewTransactions && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onViewTransactions();\n }}\n className=\"flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors\"\n >\n Transactions\n <ChevronRight className=\"size-4\" />\n </button>\n )}\n {onViewCreditTransactions && (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n onViewCreditTransactions();\n }}\n className=\"flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:bg-muted rounded-md transition-colors\"\n >\n Credit History\n <ChevronRight className=\"size-4\" />\n </button>\n )}\n </div>\n </footer>\n )}\n\n {/* Status indicator */}\n {!account.isActive && (\n <div className=\"absolute inset-0 bg-background/60 backdrop-blur-sm rounded-lg flex items-center justify-center\">\n <span className=\"px-3 py-1.5 rounded-full bg-destructive/10 text-destructive text-sm font-medium\">\n Inactive\n </span>\n </div>\n )}\n </article>\n );\n};\n"],"mappings":"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"}