import React, { useState } from 'react'; import { useStripe, useElements, CardElement } from '@stripe/react-stripe-js'; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogFooter, } from './ui/dialog'; import { Button } from './ui/button'; import { Checkbox } from './ui/checkbox'; import { Label } from './ui/label'; import { CreditCard, AlertCircle, Loader2 } from 'lucide-react'; import { toast } from 'sonner'; import api from '../utils/api'; /** * AddPaymentMethodDialog - Dialog for adding a new payment method using Stripe Elements * * This dialog should be wrapped in an Elements provider with a clientSecret * * @param {string} saveEndpoint - Optional custom API endpoint for saving (default: '/payment-methods') */ const AddPaymentMethodDialog = ({ open, onOpenChange, onSuccess, clientSecret, saveEndpoint = '/payment-methods', }) => { const stripe = useStripe(); const elements = useElements(); const [loading, setLoading] = useState(false); const [setAsDefault, setSetAsDefault] = useState(false); const [error, setError] = useState(null); const handleSubmit = async (e) => { e.preventDefault(); if (!stripe || !elements) { return; } setLoading(true); setError(null); try { // Get the CardElement const cardElement = elements.getElement(CardElement); if (!cardElement) { setError('Card element not found'); toast.error('Card element not found'); setLoading(false); return; } // Confirm the SetupIntent with the card element const { error: stripeError, setupIntent } = await stripe.confirmCardSetup( clientSecret, { payment_method: { card: cardElement, }, } ); if (stripeError) { setError(stripeError.message); toast.error(stripeError.message); setLoading(false); return; } if (setupIntent.status === 'succeeded') { // Save the payment method to our backend using the specified endpoint await api.post(saveEndpoint, { stripe_payment_method_id: setupIntent.payment_method, set_as_default: setAsDefault, }); toast.success('Payment method added successfully'); onSuccess?.(); onOpenChange(false); } else { setError(`Setup failed with status: ${setupIntent.status}`); toast.error('Failed to set up payment method'); } } catch (err) { const errorMessage = err.response?.data?.detail || err.message || 'Failed to save payment method'; setError(errorMessage); toast.error(errorMessage); } finally { setLoading(false); } }; return (
Add Payment Method Enter your card details securely
{/* Stripe Card Element */}
{/* Set as Default Checkbox */}
{/* Error Message */} {error && (

{error}

)} {/* Security Note */}

Your card information is securely processed by Stripe. We never store your full card number.

); }; export default AddPaymentMethodDialog;