@burdenoff/microfe-billing 2026.614.1 → 2026.623.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/dist/billing/BillingAdminRoutes.js +7 -6
  2. package/dist/billing/BillingAdminRoutes.js.map +1 -1
  3. package/dist/billing/BillingRoot.js +1 -1
  4. package/dist/billing/BillingRoot.js.map +1 -1
  5. package/dist/billing/modules/addons/components/FloatingCartDrawer.js +22 -22
  6. package/dist/billing/modules/addons/components/FloatingCartDrawer.js.map +1 -1
  7. package/dist/billing/modules/addons/pages/AddonCreatePage.js +31 -31
  8. package/dist/billing/modules/addons/pages/AddonCreatePage.js.map +1 -1
  9. package/dist/billing/modules/addons/pages/AddonDetailPage.js +39 -39
  10. package/dist/billing/modules/addons/pages/AddonDetailPage.js.map +1 -1
  11. package/dist/billing/modules/addons/pages/AddonEditPage.js +29 -29
  12. package/dist/billing/modules/addons/pages/AddonEditPage.js.map +1 -1
  13. package/dist/billing/modules/addons/pages/AddonsListPage.js +91 -91
  14. package/dist/billing/modules/addons/pages/AddonsListPage.js.map +1 -1
  15. package/dist/billing/modules/analytics/pages/AnalyticsPage.js +40 -40
  16. package/dist/billing/modules/analytics/pages/AnalyticsPage.js.map +1 -1
  17. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js +115 -115
  18. package/dist/billing/modules/billing/pages/InvoiceDetailPage.js.map +1 -1
  19. package/dist/billing/modules/billing/pages/InvoicesListPage.js +75 -72
  20. package/dist/billing/modules/billing/pages/InvoicesListPage.js.map +1 -1
  21. package/dist/billing/modules/billing/pages/RefundsPage.js +126 -126
  22. package/dist/billing/modules/billing/pages/RefundsPage.js.map +1 -1
  23. package/dist/billing/modules/billing/pages/UserRefundsPage.js +45 -45
  24. package/dist/billing/modules/billing/pages/UserRefundsPage.js.map +1 -1
  25. package/dist/billing/modules/checkout/components/BillingAccountSelector.js +25 -25
  26. package/dist/billing/modules/checkout/components/BillingAccountSelector.js.map +1 -1
  27. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js +31 -35
  28. package/dist/billing/modules/checkout/components/CompleteBillingAccountModal.js.map +1 -1
  29. package/dist/billing/modules/checkout/components/CreditsAmountInput.js +9 -9
  30. package/dist/billing/modules/checkout/components/CreditsAmountInput.js.map +1 -1
  31. package/dist/billing/modules/checkout/components/OrderSummary.js +31 -31
  32. package/dist/billing/modules/checkout/components/OrderSummary.js.map +1 -1
  33. package/dist/billing/modules/checkout/components/PromoCodeInput.js +8 -8
  34. package/dist/billing/modules/checkout/components/PromoCodeInput.js.map +1 -1
  35. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js +5 -5
  36. package/dist/billing/modules/checkout/components/RazorpayPaymentButton.js.map +1 -1
  37. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js +9 -9
  38. package/dist/billing/modules/checkout/components/SimpleAutoPayToggle.js.map +1 -1
  39. package/dist/billing/modules/checkout/components/StripePaymentForm.js +21 -21
  40. package/dist/billing/modules/checkout/components/StripePaymentForm.js.map +1 -1
  41. package/dist/billing/modules/checkout/components/SubscriptionSelector.js +11 -11
  42. package/dist/billing/modules/checkout/components/SubscriptionSelector.js.map +1 -1
  43. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js +31 -31
  44. package/dist/billing/modules/checkout/components/UnifiedPaymentMethodSelector.js.map +1 -1
  45. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js +23 -23
  46. package/dist/billing/modules/checkout/components/WorkspaceQuotaAssignmentModal.js.map +1 -1
  47. package/dist/billing/modules/checkout/pages/CheckoutPage.js +91 -91
  48. package/dist/billing/modules/checkout/pages/CheckoutPage.js.map +1 -1
  49. package/dist/billing/modules/coupons/pages/CouponDetailPage.js +62 -62
  50. package/dist/billing/modules/coupons/pages/CouponDetailPage.js.map +1 -1
  51. package/dist/billing/modules/coupons/pages/CouponsListPage.js +72 -60
  52. package/dist/billing/modules/coupons/pages/CouponsListPage.js.map +1 -1
  53. package/dist/billing/modules/coupons/pages/CreateCouponPage.js +66 -66
  54. package/dist/billing/modules/coupons/pages/CreateCouponPage.js.map +1 -1
  55. package/dist/billing/modules/coupons/pages/EditCouponPage.js +46 -46
  56. package/dist/billing/modules/coupons/pages/EditCouponPage.js.map +1 -1
  57. package/dist/billing/modules/credits/pages/AdminCreditsPage.js +19 -19
  58. package/dist/billing/modules/credits/pages/AdminCreditsPage.js.map +1 -1
  59. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js +37 -37
  60. package/dist/billing/modules/credits/pages/CreditTransactionsPage.js.map +1 -1
  61. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js +90 -90
  62. package/dist/billing/modules/credits/pages/CreditWithdrawalPage.js.map +1 -1
  63. package/dist/billing/modules/credits/pages/CreditsPage.js +41 -41
  64. package/dist/billing/modules/credits/pages/CreditsPage.js.map +1 -1
  65. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js +31 -31
  66. package/dist/billing/modules/dashboard/components/ActiveSubscriptionCard.js.map +1 -1
  67. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js +35 -35
  68. package/dist/billing/modules/dashboard/components/AddPaymentMethodModal.js.map +1 -1
  69. package/dist/billing/modules/dashboard/components/BillingAccountCard.js +24 -24
  70. package/dist/billing/modules/dashboard/components/BillingAccountCard.js.map +1 -1
  71. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js +99 -99
  72. package/dist/billing/modules/dashboard/components/CreateBillingAccountModal.js.map +1 -1
  73. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js +23 -23
  74. package/dist/billing/modules/dashboard/components/PaymentMethodsSection.js.map +1 -1
  75. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js +22 -22
  76. package/dist/billing/modules/dashboard/components/RecommendedAddonsSection.js.map +1 -1
  77. package/dist/billing/modules/dashboard/pages/OverviewPage.js +58 -58
  78. package/dist/billing/modules/dashboard/pages/OverviewPage.js.map +1 -1
  79. package/dist/billing/modules/discounts/pages/DiscountsListPage.js +126 -126
  80. package/dist/billing/modules/discounts/pages/DiscountsListPage.js.map +1 -1
  81. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js +83 -79
  82. package/dist/billing/modules/earnings/pages/PayoutAdminPage.js.map +1 -1
  83. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js +16 -16
  84. package/dist/billing/modules/plans/pages/PlanAssignFreePage.js.map +1 -1
  85. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js +40 -40
  86. package/dist/billing/modules/plans/pages/PlanBrowseDetailPage.js.map +1 -1
  87. package/dist/billing/modules/plans/pages/PlanCreatePage.js +35 -35
  88. package/dist/billing/modules/plans/pages/PlanCreatePage.js.map +1 -1
  89. package/dist/billing/modules/plans/pages/PlanDetailPage.js +57 -57
  90. package/dist/billing/modules/plans/pages/PlanDetailPage.js.map +1 -1
  91. package/dist/billing/modules/plans/pages/PlanEditPage.js +35 -35
  92. package/dist/billing/modules/plans/pages/PlanEditPage.js.map +1 -1
  93. package/dist/billing/modules/plans/pages/PlansBrowsePage.js +57 -57
  94. package/dist/billing/modules/plans/pages/PlansBrowsePage.js.map +1 -1
  95. package/dist/billing/modules/plans/pages/PlansListPage.js +52 -52
  96. package/dist/billing/modules/plans/pages/PlansListPage.js.map +1 -1
  97. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js +40 -39
  98. package/dist/billing/modules/promotions/pages/CreatePromotionPage.js.map +1 -1
  99. package/dist/billing/modules/promotions/pages/PromotionsListPage.js +22 -19
  100. package/dist/billing/modules/promotions/pages/PromotionsListPage.js.map +1 -1
  101. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js +34 -34
  102. package/dist/billing/modules/quota/pages/QuotaTemplateCreatePage.js.map +1 -1
  103. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js +47 -47
  104. package/dist/billing/modules/quota/pages/QuotaTemplateDetailPage.js.map +1 -1
  105. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js +39 -39
  106. package/dist/billing/modules/quota/pages/QuotaTemplateEditPage.js.map +1 -1
  107. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js +52 -52
  108. package/dist/billing/modules/quota/pages/QuotaTemplatesListPage.js.map +1 -1
  109. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js +23 -23
  110. package/dist/billing/modules/subscriptions/components/ManageSeatsModal.js.map +1 -1
  111. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js +259 -246
  112. package/dist/billing/modules/subscriptions/pages/SubscriptionDetailPage.js.map +1 -1
  113. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js +88 -85
  114. package/dist/billing/modules/subscriptions/pages/SubscriptionsListPage.js.map +1 -1
  115. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js +51 -51
  116. package/dist/billing/modules/subscriptions/pages/UpgradeSubscriptionPage.js.map +1 -1
  117. package/dist/billing/modules/usage/pages/UsagePage.js +206 -196
  118. package/dist/billing/modules/usage/pages/UsagePage.js.map +1 -1
  119. package/dist/billing/shared/components/ServerError.js +4 -4
  120. package/dist/billing/shared/components/ServerError.js.map +1 -1
  121. package/dist/billing/shared/components/StatCard.js +11 -33
  122. package/dist/billing/shared/components/StatCard.js.map +1 -1
  123. package/dist/billing/shared/ui/Card.js +15 -0
  124. package/dist/billing/shared/ui/Card.js.map +1 -0
  125. package/dist/billing/shared/ui/MetricCard.js +44 -0
  126. package/dist/billing/shared/ui/MetricCard.js.map +1 -0
  127. package/dist/billing/shared/ui/ProgressBar.js +30 -0
  128. package/dist/billing/shared/ui/ProgressBar.js.map +1 -0
  129. package/dist/billing/shared/ui/SectionHeader.js +2 -0
  130. package/dist/billing/shared/ui/StatusPill.js +28 -0
  131. package/dist/billing/shared/ui/StatusPill.js.map +1 -0
  132. package/dist/billing/shared/ui/index.js +5 -0
  133. package/dist/billing/shared/utils/tokens.js +13 -30
  134. package/dist/billing/shared/utils/tokens.js.map +1 -1
  135. package/package.json +1 -1
@@ -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 // Must be declared before the effects that reference it\n const handleSelectProvider = useCallback((provider: 'stripe' | 'razorpay') => {\n setSelectedProvider(provider);\n setStep('add-card');\n setError(null);\n }, []);\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (isOpen) {\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 // Auto-select provider when only one is available (skip the select-provider screen)\n useEffect(() => {\n if (step !== 'select-provider' || isLoadingConfig) return;\n if (showStripe && !showRazorpay) {\n handleSelectProvider('stripe');\n } else if (showRazorpay && !showStripe) {\n handleSelectProvider('razorpay');\n }\n }, [step, isLoadingConfig, showStripe, showRazorpay, handleSelectProvider]);\n\n // Initialize Stripe when provider is selected\n useEffect(() => {\n if (step !== 'add-card' || selectedProvider !== 'stripe') return;\n\n // Show error if config loaded but key is missing\n if (!stripePublishableKey && !isLoadingConfig) {\n setError('Stripe is not configured. Please contact support.');\n return;\n }\n\n if (!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, isLoadingConfig]);\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 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-[56px]\"\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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"}
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 // Must be declared before the effects that reference it\n const handleSelectProvider = useCallback((provider: 'stripe' | 'razorpay') => {\n setSelectedProvider(provider);\n setStep('add-card');\n setError(null);\n }, []);\n\n // Reset state when modal opens/closes\n useEffect(() => {\n if (isOpen) {\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 // Auto-select provider when only one is available (skip the select-provider screen)\n useEffect(() => {\n if (step !== 'select-provider' || isLoadingConfig) return;\n if (showStripe && !showRazorpay) {\n handleSelectProvider('stripe');\n } else if (showRazorpay && !showStripe) {\n handleSelectProvider('razorpay');\n }\n }, [step, isLoadingConfig, showStripe, showRazorpay, handleSelectProvider]);\n\n // Initialize Stripe when provider is selected\n useEffect(() => {\n if (step !== 'add-card' || selectedProvider !== 'stripe') return;\n\n // Show error if config loaded but key is missing\n if (!stripePublishableKey && !isLoadingConfig) {\n setError('Stripe is not configured. Please contact support.');\n return;\n }\n\n if (!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, isLoadingConfig]);\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 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-bg-overlay 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-bg-surface border border-border-subtle rounded-card shadow-[var(--shadow-elevation-4)] flex flex-col\"\n >\n {/* Header */}\n <header className=\"flex items-center justify-between p-4 border-b border-border-subtle flex-shrink-0\">\n <div className=\"flex items-center gap-3\">\n <div className=\"size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center\">\n <CreditCard className=\"size-5 text-text-link\" />\n </div>\n <div>\n <h2 id=\"modal-title\" className=\"text-lg font-semibold text-text-primary\">\n {step === 'success' ? 'Payment Method Added' : 'Add Payment Method'}\n </h2>\n <p className=\"text-sm text-text-secondary\">\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-button hover:bg-bg-sunken text-text-secondary hover:text-text-primary 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-text-secondary\" />\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-subtle rounded-lg hover:border-border-strong hover:bg-[var(--color-accent-soft)] 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-text-primary\">Stripe</p>\n <p className=\"text-sm text-text-secondary\">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-subtle rounded-lg hover:border-border-strong hover:bg-[var(--color-accent-soft)] 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-text-primary\">Razorpay</p>\n <p className=\"text-sm text-text-secondary\">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-text-primary\">\n {tr('billing.overview.noPaymentProviders', 'No Payment Providers Available')}\n </p>\n <p className=\"text-sm text-text-secondary 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-status-error-bg-subtle border border-status-error-border text-status-error-text\">\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-text-primary\"\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-border-default rounded-input bg-bg-surface text-text-primary placeholder:text-text-placeholder focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)] focus:border-border-strong\"\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-text-primary\">\n {tr('billing.overview.cardDetails', 'Card Details')}\n </label>\n <div className=\"relative\">\n <div\n ref={cardElementRef}\n className=\"p-3 border border-border-default rounded-lg bg-bg-surface min-h-[56px]\"\n />\n {isLoadingSdk && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-bg-overlay rounded-lg\">\n <Loader2 className=\"size-5 animate-spin text-text-secondary\" />\n <span className=\"ml-2 text-sm text-text-secondary\">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-border-default text-text-link focus:ring-[var(--color-focus-ring)]\"\n disabled={isProcessing}\n />\n <span className=\"text-sm text-text-primary\">\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-subtle\">\n <span className=\"text-xs text-text-secondary\">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-text-primary\">\n {tr('billing.overview.paymentMethodAdded', 'Payment method added successfully!')}\n </p>\n <p className=\"text-sm text-text-secondary 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-subtle bg-bg-sunken 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-text-primary hover:text-text-link 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-text-primary border border-border-subtle rounded-lg hover:bg-bg-sunken 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-action-primary-text bg-action-primary-bg rounded-lg hover:bg-action-primary-bgHover 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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"}
@@ -12,9 +12,9 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
12
12
  return /* @__PURE__ */ d("article", {
13
13
  "data-tour": x,
14
14
  className: `
15
- relative border rounded-lg bg-card transition-all duration-200
16
- ${h ? "border-primary ring-2 ring-primary/20" : "border-border"}
17
- ${w ? "shadow-md" : "shadow-sm"}
15
+ relative border rounded-card bg-bg-surface transition-all duration-200 ease-[var(--motion-easing-out)]
16
+ ${h ? "border-border-strong ring-1 ring-[var(--color-focus-ring)]" : "border-border-subtle"}
17
+ ${w ? "shadow-elevation-2" : "shadow-elevation-1"}
18
18
  ${g ? "cursor-pointer" : ""}
19
19
  ${b}
20
20
  `,
@@ -28,34 +28,34 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
28
28
  },
29
29
  children: [
30
30
  /* @__PURE__ */ u("header", {
31
- className: "p-4 border-b border-border",
31
+ className: "p-4 border-b border-border-subtle",
32
32
  children: /* @__PURE__ */ d("div", {
33
33
  className: "flex items-start justify-between gap-3",
34
34
  children: [/* @__PURE__ */ d("div", {
35
35
  className: "flex items-center gap-3 min-w-0",
36
36
  children: [/* @__PURE__ */ u("div", {
37
- className: "size-10 rounded-lg bg-primary/10 flex items-center justify-center flex-shrink-0",
38
- children: /* @__PURE__ */ u(n, { className: "size-5 text-primary" })
37
+ className: "size-10 rounded-lg bg-[var(--color-accent-soft)] flex items-center justify-center flex-shrink-0",
38
+ children: /* @__PURE__ */ u(n, { className: "size-5 text-text-link" })
39
39
  }), /* @__PURE__ */ d("div", {
40
40
  className: "min-w-0",
41
41
  children: [/* @__PURE__ */ d("div", {
42
42
  className: "flex items-center gap-2",
43
43
  children: [
44
44
  /* @__PURE__ */ u("h3", {
45
- className: "font-semibold text-foreground truncate",
45
+ className: "font-semibold text-text-primary truncate",
46
46
  children: p.name
47
47
  }),
48
48
  m && /* @__PURE__ */ u("span", {
49
- className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-primary/10 text-primary",
49
+ className: "inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-[var(--color-accent-soft)] text-text-link",
50
50
  children: C("billing.overview.default", "Default")
51
51
  }),
52
52
  h && /* @__PURE__ */ u("span", {
53
- className: "inline-flex items-center justify-center size-5 rounded-full bg-primary",
54
- children: /* @__PURE__ */ u(i, { className: "size-3 text-primary-foreground" })
53
+ className: "inline-flex items-center justify-center size-5 rounded-full bg-action-primary-bg",
54
+ children: /* @__PURE__ */ u(i, { className: "size-3 text-action-primary-text" })
55
55
  })
56
56
  ]
57
57
  }), /* @__PURE__ */ d("p", {
58
- className: "text-sm text-muted-foreground truncate flex items-center gap-1",
58
+ className: "text-sm text-text-secondary truncate flex items-center gap-1",
59
59
  children: [/* @__PURE__ */ u(l, { className: "size-3.5" }), p.email]
60
60
  })]
61
61
  })]
@@ -64,7 +64,7 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
64
64
  onClick: (e) => {
65
65
  e.stopPropagation(), _();
66
66
  },
67
- className: "p-2 rounded-lg hover:bg-muted text-muted-foreground hover:text-foreground transition-colors",
67
+ className: "p-2 rounded-button hover:bg-bg-sunken text-text-secondary hover:text-text-primary transition-colors",
68
68
  "aria-label": "Edit billing account",
69
69
  children: /* @__PURE__ */ u(c, { className: "size-4" })
70
70
  })]
@@ -77,10 +77,10 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
77
77
  children: [/* @__PURE__ */ d("div", {
78
78
  className: "space-y-1",
79
79
  children: [/* @__PURE__ */ u("p", {
80
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wide",
80
+ className: "text-xs font-medium text-text-secondary uppercase tracking-wide",
81
81
  children: "Credit Balance"
82
82
  }), /* @__PURE__ */ d("p", {
83
- className: "text-lg font-semibold text-foreground flex items-center gap-1.5",
83
+ className: "text-lg font-semibold text-text-primary flex items-center gap-1.5",
84
84
  children: [
85
85
  /* @__PURE__ */ u(o, { className: `size-4 ${e.warning.icon}` }),
86
86
  (p.creditAmount || 0).toLocaleString(),
@@ -90,17 +90,17 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
90
90
  }), /* @__PURE__ */ d("div", {
91
91
  className: "space-y-1",
92
92
  children: [/* @__PURE__ */ u("p", {
93
- className: "text-xs font-medium text-muted-foreground uppercase tracking-wide",
93
+ className: "text-xs font-medium text-text-secondary uppercase tracking-wide",
94
94
  children: "Payment Currency"
95
95
  }), /* @__PURE__ */ d("p", {
96
- className: "text-lg font-semibold text-foreground flex items-center gap-1.5",
97
- children: [/* @__PURE__ */ u(s, { className: "size-4 text-primary" }), p.currency || "USD"]
96
+ className: "text-lg font-semibold text-text-primary flex items-center gap-1.5",
97
+ children: [/* @__PURE__ */ u(s, { className: "size-4 text-text-link" }), p.currency || "USD"]
98
98
  })]
99
99
  })]
100
100
  }), /* @__PURE__ */ u("div", {
101
- className: "pt-3 border-t border-border",
101
+ className: "pt-3 border-t border-border-subtle",
102
102
  children: /* @__PURE__ */ d("p", {
103
- className: "text-xs text-muted-foreground flex items-center gap-1",
103
+ className: "text-xs text-text-secondary flex items-center gap-1",
104
104
  children: [
105
105
  /* @__PURE__ */ u(r, { className: "size-3.5" }),
106
106
  "Created ",
@@ -114,7 +114,7 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
114
114
  })]
115
115
  }),
116
116
  (v || y) && /* @__PURE__ */ u("footer", {
117
- className: "px-4 py-3 border-t border-border bg-muted/30 rounded-b-lg",
117
+ className: "px-4 py-3 border-t border-border-subtle bg-bg-sunken rounded-b-card",
118
118
  children: /* @__PURE__ */ d("div", {
119
119
  className: "flex items-center gap-2",
120
120
  children: [v && /* @__PURE__ */ d("button", {
@@ -122,22 +122,22 @@ var p = ({ account: p, isDefault: m = !1, isSelected: h = !1, onSelect: g, onEdi
122
122
  onClick: (e) => {
123
123
  e.stopPropagation(), v();
124
124
  },
125
- 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",
125
+ className: "flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button transition-colors",
126
126
  children: ["Transactions", /* @__PURE__ */ u(a, { className: "size-4" })]
127
127
  }), y && /* @__PURE__ */ d("button", {
128
128
  type: "button",
129
129
  onClick: (e) => {
130
130
  e.stopPropagation(), y();
131
131
  },
132
- 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",
132
+ className: "flex-1 flex items-center justify-center gap-1.5 px-3 py-2 text-sm font-medium text-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button transition-colors",
133
133
  children: ["Credit History", /* @__PURE__ */ u(a, { className: "size-4" })]
134
134
  })]
135
135
  })
136
136
  }),
137
137
  !p.isActive && /* @__PURE__ */ u("div", {
138
- className: "absolute inset-0 bg-background/60 backdrop-blur-sm rounded-lg flex items-center justify-center",
138
+ className: "absolute inset-0 bg-bg-overlay backdrop-blur-sm rounded-card flex items-center justify-center",
139
139
  children: /* @__PURE__ */ u("span", {
140
- className: "px-3 py-1.5 rounded-full bg-destructive/10 text-destructive text-sm font-medium",
140
+ className: "px-3 py-1.5 rounded-full bg-status-error-bg-subtle text-status-error-text text-sm font-medium",
141
141
  children: "Inactive"
142
142
  })
143
143
  })
@@ -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 /** Optional tour anchor applied to the card root (for onboarding tours). */\n dataTour?: 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 dataTour,\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 data-tour={dataTour}\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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"}
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 /** Optional tour anchor applied to the card root (for onboarding tours). */\n dataTour?: 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 dataTour,\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 data-tour={dataTour}\n className={`\n relative border rounded-card bg-bg-surface transition-all duration-200 ease-[var(--motion-easing-out)]\n ${isSelected ? 'border-border-strong ring-1 ring-[var(--color-focus-ring)]' : 'border-border-subtle'}\n ${isHovered ? 'shadow-elevation-2' : 'shadow-elevation-1'}\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-subtle\">\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-[var(--color-accent-soft)] flex items-center justify-center flex-shrink-0\">\n <Building2 className=\"size-5 text-text-link\" />\n </div>\n <div className=\"min-w-0\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-semibold text-text-primary 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-[var(--color-accent-soft)] text-text-link\">\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-action-primary-bg\">\n <Check className=\"size-3 text-action-primary-text\" />\n </span>\n )}\n </div>\n <p className=\"text-sm text-text-secondary 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-button hover:bg-bg-sunken text-text-secondary hover:text-text-primary 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-text-secondary uppercase tracking-wide\">\n Credit Balance\n </p>\n <p className=\"text-lg font-semibold text-text-primary 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-text-secondary uppercase tracking-wide\">\n Payment Currency\n </p>\n <p className=\"text-lg font-semibold text-text-primary flex items-center gap-1.5\">\n <CreditCard className=\"size-4 text-text-link\" />\n {account.currency || 'USD'}\n </p>\n </div>\n </div>\n\n {/* Meta Info */}\n <div className=\"pt-3 border-t border-border-subtle\">\n <p className=\"text-xs text-text-secondary 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-subtle bg-bg-sunken rounded-b-card\">\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-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button 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-text-secondary hover:text-text-primary hover:bg-bg-sunken rounded-button 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-bg-overlay backdrop-blur-sm rounded-card flex items-center justify-center\">\n <span className=\"px-3 py-1.5 rounded-full bg-status-error-bg-subtle text-status-error-text text-sm font-medium\">\n Inactive\n </span>\n </div>\n )}\n </article>\n );\n};\n"],"mappings":"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"}