import React, { useState } from 'react'; import { bool, func, object } from 'prop-types'; import { compose } from 'redux'; import { connect } from 'react-redux'; import { injectIntl, intlShape, FormattedMessage } from 'react-intl'; import { ensureCurrentUser, ensureStripeCustomer, ensurePaymentMethodCard } from '../../util/data'; import { propTypes } from '../../util/types'; import { savePaymentMethod, deletePaymentMethod } from '../../ducks/paymentMethods.duck'; import { handleCardSetup } from '../../ducks/stripe.duck'; import { manageDisableScrolling, isScrollingDisabled } from '../../ducks/UI.duck'; import { SavedCardDetails, LayoutSideNavigation, LayoutWrapperMain, LayoutWrapperAccountSettingsSideNav, LayoutWrapperTopbar, LayoutWrapperFooter, Footer, Page, UserNav, } from '../../components'; import { TopbarContainer } from '../../containers'; import { PaymentMethodsForm } from '../../forms'; import { createStripeSetupIntent, stripeCustomer, loadData } from './PaymentMethodsPage.duck.js'; import css from './PaymentMethodsPage.css'; const PaymentMethodsPageComponent = props => { const [isSubmitting, setIsSubmitting] = useState(false); const [cardState, setCardState] = useState(null); const { currentUser, addPaymentMethodError, deletePaymentMethodError, createStripeCustomerError, handleCardSetupError, deletePaymentMethodInProgress, onCreateSetupIntent, onHandleCardSetup, onSavePaymentMethod, onDeletePaymentMethod, fetchStripeCustomer, scrollingDisabled, onManageDisableScrolling, intl, stripeCustomerFetched, } = props; const getClientSecret = setupIntent => { return setupIntent && setupIntent.attributes ? setupIntent.attributes.clientSecret : null; }; const getPaymentParams = (currentUser, formValues) => { const { name, addressLine1, addressLine2, postal, state, city, country } = formValues; const addressMaybe = addressLine1 && postal ? { address: { city: city, country: country, line1: addressLine1, line2: addressLine2, postal_code: postal, state: state, }, } : {}; const billingDetails = { name, email: ensureCurrentUser(currentUser).attributes.email, ...addressMaybe, }; const paymentParams = { payment_method_data: { billing_details: billingDetails, }, }; return paymentParams; }; const handleSubmit = params => { setIsSubmitting(true); const ensuredCurrentUser = ensureCurrentUser(currentUser); const stripeCustomer = ensuredCurrentUser.stripeCustomer; const { stripe, card, formValues } = params; onCreateSetupIntent() .then(setupIntent => { const stripeParams = { stripe, card, setupIntentClientSecret: getClientSecret(setupIntent), paymentParams: getPaymentParams(currentUser, formValues), }; return onHandleCardSetup(stripeParams); }) .then(result => { const newPaymentMethod = result.setupIntent.payment_method; // Note: stripe.handleCardSetup might return an error inside successful call (200), but those are rejected in thunk functions. return onSavePaymentMethod(stripeCustomer, newPaymentMethod); }) .then(() => { // Update currentUser entity and its sub entities: stripeCustomer and defaultPaymentMethod fetchStripeCustomer(); setIsSubmitting(false); setCardState('default'); }) .catch(error => { console.error(error); setIsSubmitting(false); }); }; const handleRemovePaymentMethod = () => { onDeletePaymentMethod().then(() => { fetchStripeCustomer(); }); }; const title = intl.formatMessage({ id: 'PaymentMethodsPage.title' }); const ensuredCurrentUser = ensureCurrentUser(currentUser); const currentUserLoaded = !!ensuredCurrentUser.id; const hasDefaultPaymentMethod = currentUser && ensureStripeCustomer(currentUser.stripeCustomer).attributes.stripeCustomerId && ensurePaymentMethodCard(currentUser.stripeCustomer.defaultPaymentMethod).id; // Get first and last name of the current user and use it in the StripePaymentForm to autofill the name field const userName = currentUserLoaded ? `${ensuredCurrentUser.attributes.profile.firstName} ${ensuredCurrentUser.attributes.profile.lastName}` : null; const initalValuesForStripePayment = { name: userName }; const card = hasDefaultPaymentMethod ? ensurePaymentMethodCard(currentUser.stripeCustomer.defaultPaymentMethod).attributes.card : null; const showForm = cardState === 'replaceCard' || !hasDefaultPaymentMethod; const showCardDetails = !!hasDefaultPaymentMethod; return (

{!stripeCustomerFetched ? null : ( <> {showCardDetails ? ( ) : null} {showForm ? ( ) : null} )}