From ae96e106d7563ac071f55e0306472a173f52a9ca Mon Sep 17 00:00:00 2001 From: Payton Swick Date: Tue, 2 Mar 2021 15:29:00 -0500 Subject: [PATCH] Woo Store: Remove LabelSettings and dependencies (#50491) * Remove only use of AddCardDialog * Remove AddCardDialog * Remove PaymentMethodForm * Remove CreditCardFormFields * Remove PaymentCountrySelect * Remove only use of LabelSettings * Remove LabelSettings * Remove CreditCardFormFields tests * Remove label-settings style import --- .../credit-card-form-fields/README.md | 67 --- .../credit-card-form-fields/index.jsx | 361 --------------- .../credit-card-form-fields/test/index.js | 38 -- .../payment-country-select/README.md | 15 - .../payment-country-select/index.jsx | 114 ----- .../payment-country-select/test/index.jsx | 98 ---- .../app/settings/shipping/index.js | 2 - .../woocommerce-services/style.scss | 1 - .../label-settings/add-credit-card-modal.js | 79 ---- .../views/label-settings/index.js | 130 ------ .../label-settings/label-payment-method.js | 107 ----- .../views/label-settings/label-settings.js | 425 ------------------ .../views/label-settings/style.scss | 111 ----- .../components/payment-method-form/index.jsx | 273 ----------- 14 files changed, 1821 deletions(-) delete mode 100644 client/components/credit-card-form-fields/README.md delete mode 100644 client/components/credit-card-form-fields/index.jsx delete mode 100644 client/components/credit-card-form-fields/test/index.js delete mode 100644 client/components/payment-country-select/README.md delete mode 100644 client/components/payment-country-select/index.jsx delete mode 100644 client/components/payment-country-select/test/index.jsx delete mode 100644 client/extensions/woocommerce/woocommerce-services/views/label-settings/add-credit-card-modal.js delete mode 100644 client/extensions/woocommerce/woocommerce-services/views/label-settings/index.js delete mode 100644 client/extensions/woocommerce/woocommerce-services/views/label-settings/label-payment-method.js delete mode 100644 client/extensions/woocommerce/woocommerce-services/views/label-settings/label-settings.js delete mode 100644 client/extensions/woocommerce/woocommerce-services/views/label-settings/style.scss delete mode 100644 client/me/purchases/components/payment-method-form/index.jsx diff --git a/client/components/credit-card-form-fields/README.md b/client/components/credit-card-form-fields/README.md deleted file mode 100644 index b2e40c91799d9..0000000000000 --- a/client/components/credit-card-form-fields/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# CreditCardFormFields - -`CreditCardFormFields` is a React component that is used to display a credit card form body with the following input fields: - -- Credit card number -- Credit card expiration date -- Credit card verification code, also known as [CVV](https://en.wikipedia.org/wiki/Card_security_code) -- Credit card holder name -- Credit card holder country -- Credit card holder postal Code - -Some of these fields use [masking](https://en.wikipedia.org/wiki/Input_mask), i.e. rules that govern what a user is allowed to enter in a text box. - -Brazil requires that users provide additional details when making payments. When a user selects Brazil from the country select menu, extra fields will appear: - -- Tax identification code, also known as [CPF](https://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas) -- Phone number -- Address, city and state details - -## Usage - -```jsx -import React, { Component } from 'react'; -import CreditCardFormFields from 'calypso/components/credit-card-form-fields'; - -class YourComponent extends Component { - render() { - return ( - - ); - } -} -``` - -## Properties - -This component makes use of the following properties, which are all required: - -### `card` - -An object containing a set of input fields as key/value pairs. - -### `countriesList` - -An object containing a set of countries as code/name pairs. - -### `eventFormName` - -A string used to distinguish events generated by this form in analytics. - -### `isFieldInvalid` - -A function that checks if a given field is valid or not. The function is passed the corresponding field name. - -### `onFieldChange` - -A function invoked when the value of an input field changes. This provides access to the raw value as well as the masked value if the corresponding field. - -### `autoFocus` - -Whether the first field (cardholder name) should steal the focus when this component is rendered. Default `true`. diff --git a/client/components/credit-card-form-fields/index.jsx b/client/components/credit-card-form-fields/index.jsx deleted file mode 100644 index e49e1905cad61..0000000000000 --- a/client/components/credit-card-form-fields/index.jsx +++ /dev/null @@ -1,361 +0,0 @@ -/** - * External dependencies - */ -import React, { useState } from 'react'; -import classNames from 'classnames'; -import PropTypes from 'prop-types'; -import { CardCvcElement, CardExpiryElement, CardNumberElement } from 'react-stripe-elements'; -import { isEmpty, noop } from 'lodash'; -import { localize, useTranslate } from 'i18n-calypso'; -import { useStripe, withStripeProps } from '@automattic/calypso-stripe'; - -/** - * Internal dependencies - */ -import FormInputValidation from 'calypso/components/forms/form-input-validation'; -import FormLabel from 'calypso/components/forms/form-label'; -import PaymentCountrySelect from 'calypso/components/payment-country-select'; -import { Input } from 'calypso/my-sites/domains/components/form'; -import { maskField, unmaskField, getCreditCardType } from 'calypso/lib/checkout'; - -const CardNumberElementWithValidation = withStripeElementValidation( CardNumberElement ); -const CardExpiryElementWithValidation = withStripeElementValidation( CardExpiryElement ); -const CardCvcElementWithValidation = withStripeElementValidation( CardCvcElement ); - -/** - * Style dependencies - */ -import './style.scss'; -import { customProperties } from '@automattic/calypso-color-schemes/js'; - -function withStripeElementValidation( ElementComponent ) { - return ( { getErrorMessage, fieldName, ...props } ) => { - const [ errorMessage, setErrorMessage ] = useState(); - const onChange = ( { error } ) => setErrorMessage( error ? error.message : null ); - const stripeFieldStyles = { - base: { - fontSize: '16px', - color: customProperties[ '--studio-gray-70' ], - fontFamily: - '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen-Sans", "Ubuntu", "Cantarell", "Helvetica Neue", sans-serif', - }, - invalid: { - color: customProperties[ '--studio-red-50' ], - }, - }; - - return ( - - - - - ); - }; -} - -function StripeElementErrors( { errorMessage, getErrorMessage, fieldName } ) { - // If `errorMessage` is set, it will be displayed; otherwise the - // `getErrorMessage` function will be called for the `fieldName` to determine - // the error message. - if ( ! errorMessage ) { - const errorMessages = getErrorMessage( fieldName ) || []; - errorMessage = errorMessages.length ? errorMessages[ 0 ] : null; - } - if ( ! errorMessage ) { - return null; - } - const id = `validation-field-${ fieldName }`; - return ; -} - -StripeElementErrors.propTypes = { - errorMessage: PropTypes.string, - getErrorMessage: PropTypes.func.isRequired, - fieldName: PropTypes.string.isRequired, -}; - -function CreditCardNumberField( { translate, getErrorMessage, disabled } ) { - const cardNumberLabel = translate( 'Card number', { - comment: 'Card number label on credit card form', - } ); - - const elementClasses = { - base: 'credit-card-form-fields__element', - invalid: 'is-error', - focus: 'has-focus', - }; - - return ( -
- - { cardNumberLabel } - { disabled ? ( - - ) : ( - - ) } - -
- ); -} - -CreditCardNumberField.propTypes = { - translate: PropTypes.func.isRequired, - createField: PropTypes.func.isRequired, - getErrorMessage: PropTypes.func.isRequired, - card: PropTypes.object.isRequired, -}; - -function CreditCardExpiryAndCvvFields( { translate, getErrorMessage, disabled } ) { - const cvcLabel = translate( 'Security code' ); - - const expiryLabel = translate( 'Expiry date' ); - - const elementClasses = { - base: 'credit-card-form-fields__element', - invalid: 'is-error', - focus: 'has-focus', - }; - - return ( - -
- - { expiryLabel } - { disabled ? ( - - ) : ( - - ) } - -
-
-
- - { cvcLabel } - { disabled ? ( - - ) : ( - - ) } - - -
-
-
- ); -} - -CreditCardExpiryAndCvvFields.propTypes = { - translate: PropTypes.func.isRequired, - createField: PropTypes.func.isRequired, - getErrorMessage: PropTypes.func.isRequired, - card: PropTypes.object.isRequired, -}; - -function LoadingField() { - return ; -} - -export class CreditCardFormFields extends React.Component { - static propTypes = { - card: PropTypes.object.isRequired, - countriesList: PropTypes.array.isRequired, - eventFormName: PropTypes.string, - onFieldChange: PropTypes.func, - getErrorMessage: PropTypes.func, - autoFocus: PropTypes.bool, - isNewTransaction: PropTypes.bool, - }; - - static defaultProps = { - eventFormName: 'Credit card input', - onFieldChange: noop, - getErrorMessage: noop, - autoFocus: false, - isNewTransaction: false, - }; - - createField = ( fieldName, componentClass, props ) => { - const errorMessage = this.props.getErrorMessage( fieldName ) || []; - return React.createElement( - componentClass, - Object.assign( - {}, - { - additionalClasses: 'credit-card-form-fields__field', - eventFormName: this.props.eventFormName, - isError: ! isEmpty( errorMessage ), - errorMessage: errorMessage[ 0 ], - name: fieldName, - onBlur: this.handleFieldChange, - onChange: this.handleFieldChange, - value: this.getFieldValue( fieldName ), - autoComplete: 'off', - }, - props - ) - ); - }; - - getFieldValue = ( fieldName ) => this.props.card[ fieldName ] || ''; - - updateFieldValues = ( fieldName, nextValue ) => { - const previousValue = this.getFieldValue( fieldName ); - - if ( previousValue === nextValue ) { - return; - } - - const { onFieldChange } = this.props; - - const rawDetails = { - [ fieldName ]: unmaskField( fieldName, previousValue, nextValue ), - }; - - const maskedDetails = { - [ fieldName ]: maskField( fieldName, previousValue, nextValue ), - }; - - if ( fieldName === 'number' ) { - rawDetails.brand = getCreditCardType( rawDetails[ fieldName ] ); - } - - onFieldChange( rawDetails, maskedDetails ); - }; - - handleFieldChange = ( event ) => { - this.updateFieldValues( event.target.name, event.target.value ); - }; - - render() { - const { translate, countriesList, autoFocus, isStripeLoading, stripeLoadingError } = this.props; - const creditCardFormFieldsExtrasClassNames = classNames( { - 'credit-card-form-fields__extras': true, - } ); - - const disabled = isFieldDisabled( { - isStripeLoading, - stripeLoadingError, - } ); - - /* eslint-disable jsx-a11y/no-autofocus */ - return ( -
- -
- -
- -
- - { this.createField( 'country', PaymentCountrySelect, { - label: translate( 'Country' ), - placeholder: ' ', - countriesList, - onChange: noop, - onCountrySelected: this.updateFieldValues, - disabled, - } ) } - - { this.createField( 'postal-code', Input, { - label: translate( 'Postal code' ), - placeholder: ' ', - disabled, - } ) } -
-
- ); - } -} - -function CardholderNameField( { createField, autoFocus } ) { - const translate = useTranslate(); - const { isStripeLoading, stripeLoadingError } = useStripe(); - - const disabled = isFieldDisabled( { - isStripeLoading, - stripeLoadingError, - } ); - - return ( - <> - { createField( 'name', Input, { - disabled, - autoFocus, - label: translate( 'Cardholder name' ), - placeholder: ' ', - description: translate( "Enter your name as it's written on the card" ), - } ) } - - ); -} - -function isFieldDisabled( { isStripeLoading, stripeLoadingError } ) { - const isStripeNotReady = isStripeLoading || stripeLoadingError; - return isStripeNotReady; -} - -function CvvCard( { className = '' } ) { - const translate = useTranslate(); - return ( - - - { translate( 'An image of the back of the card where you find the security code' ) } - - - - - - - - ); -} - -export default withStripeProps( localize( CreditCardFormFields ) ); diff --git a/client/components/credit-card-form-fields/test/index.js b/client/components/credit-card-form-fields/test/index.js deleted file mode 100644 index 0aa9504cc140a..0000000000000 --- a/client/components/credit-card-form-fields/test/index.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @jest-environment jsdom - */ - -/** - * External dependencies - */ -import { shallow } from 'enzyme'; -import React from 'react'; -import { identity, noop } from 'lodash'; - -/** - * Internal dependencies - */ -import { CreditCardFormFields } from '../'; -import CountrySpecificPaymentFields from 'calypso/my-sites/checkout/checkout/country-specific-payment-fields'; - -const defaultProps = { - card: {}, - countriesList: [], - eventFormName: 'A fine form', - translate: identity, - isFieldInvalid: identity, - onFieldChange: noop, - isNewTransaction: true, -}; - -describe( 'CreditCardFormFields', () => { - test( 'should have `CreditCardFormFields` class', () => { - const wrapper = shallow( ); - expect( wrapper.find( '.credit-card-form-fields' ) ).toHaveLength( 1 ); - } ); - - test( 'should not render ebanx fields', () => { - const wrapper = shallow( ); - expect( wrapper.find( CountrySpecificPaymentFields ) ).toHaveLength( 0 ); - } ); -} ); diff --git a/client/components/payment-country-select/README.md b/client/components/payment-country-select/README.md deleted file mode 100644 index 187f436f120f8..0000000000000 --- a/client/components/payment-country-select/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# PaymentCountrySelect - -`PaymentCountrySelect` is a React component that displays a form for selecting a country used in a payment or billing address. - -It is a wrapper around the more generic `CountrySelect` component, with the primary difference being that the user's selection is propagated as the default country to all other `PaymentCountrySelect` components on the site. The assumption is that a user who selects a particular country for one payment method (such as a new credit card) is likely to want to select the same country for any other payment methods used later (such as another credit card, or PayPal). - -## Properties - -This component accepts all the standard properties of the `CountrySelect` component, with the exception of `value` (since the default value of the country selector is controlled internally, as described in the previous section). - -In addition, there is one new property, which is optional: - -### `onCountrySelected` - -A function that is invoked when a country is selected in the component. The function is passed the field name and field value (i.e., the country code) as parameters. This function can be used by code which needs to react to all instances in which a country is selected (or unselected) in the component, regardless of whether the selection happened via user interaction with the country dropdown or due to the country being the default selected option when the component was rendered. (Note that if your code only needs to track changes due to user interaction, the standard `onChange` property supported by the `CountrySelect` component can be used with this component too.) diff --git a/client/components/payment-country-select/index.jsx b/client/components/payment-country-select/index.jsx deleted file mode 100644 index ca037a12f4eee..0000000000000 --- a/client/components/payment-country-select/index.jsx +++ /dev/null @@ -1,114 +0,0 @@ -/** - * External dependencies - */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { isFunction, noop, omit, some } from 'lodash'; - -/** - * Internal dependencies - */ -import CountrySelect from 'calypso/my-sites/domains/components/form/country-select'; -import getPaymentCountryCode from 'calypso/state/selectors/get-payment-country-code'; -import { setPaymentCountryCode } from 'calypso/state/payment/actions'; -import { setTaxCountryCode } from 'calypso/lib/cart/actions'; - -export class PaymentCountrySelect extends Component { - static propTypes = { - name: PropTypes.string.isRequired, - countriesList: PropTypes.array.isRequired, - onCountrySelected: PropTypes.func, - countryCode: PropTypes.string, - updateGlobalCountryCode: PropTypes.func, - }; - - static defaultProps = { - onCountrySelected: noop, - countryCode: '', - updateGlobalCountryCode: noop, - updateCartStore: setTaxCountryCode, - }; - - componentDidMount() { - // Notify the callback function about the country (or lack thereof) - // that is pre-selected at the time the component is first displayed - if ( this.props.countriesList.length ) { - const validCountryCode = this.getValidCountryCode( - this.props.countryCode, - this.props.countriesList - ); - this.props.onCountrySelected( this.props.name, validCountryCode ); - } - } - - componentDidUpdate( prevProps ) { - // There's a chance on first mount that 'countriesList' isn't filled yet - // which is why we listen to when 'countriesList' gets filled. - if ( ! prevProps.countriesList.length && this.props.countriesList.length ) { - const validCountryCode = this.getValidCountryCode( - this.props.countryCode, - this.props.countriesList - ); - this.props.onCountrySelected( this.props.name, validCountryCode ); - } - } - - // If the stored payment country isn't one of the allowed countries - // for this component, pass along the default value instead (so - // that the value the callback function receives never represents a - // country that it considers to be an invalid choice, and so that - // it always matches what the user actually sees pre-selected in - // the form field). - getValidCountryCode = ( countryCode, countriesList ) => - some( countriesList, [ 'code', countryCode ] ) ? countryCode : ''; - - handleFieldChange = ( event ) => { - this.props.updateGlobalCountryCode( event.target.value ); - this.props.updateCartStore( event.target.value ); - // Notify the callback function that a new country was selected. - this.props.onCountrySelected( event.target.name, event.target.value ); - // Also notify the standard onChange field handler, if there is one. - if ( isFunction( this.props.onChange ) ) { - this.props.onChange( event ); - } - }; - - render() { - const propsToOmit = [ - // Don't pass down props associated with the global payment country - // state. - 'countryCode', - 'updateGlobalCountryCode', - 'updateCartStore', - // Don't pass down this component's custom props. - 'onCountrySelected', - // Don't pass down standard CountrySelect props that this component - // overrides. - 'value', - 'onChange', - ]; - return ( - - ); - } -} - -export default connect( - ( state ) => { - return { - countryCode: getPaymentCountryCode( state ), - }; - }, - ( dispatch ) => { - return { - updateGlobalCountryCode: ( newCountryCode ) => { - dispatch( setPaymentCountryCode( newCountryCode ) ); - }, - }; - } -)( PaymentCountrySelect ); diff --git a/client/components/payment-country-select/test/index.jsx b/client/components/payment-country-select/test/index.jsx deleted file mode 100644 index 3f893e78ec70a..0000000000000 --- a/client/components/payment-country-select/test/index.jsx +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @jest-environment jsdom - */ - -/** - * External dependencies - */ -import React from 'react'; -import { mount, shallow } from 'enzyme'; -import emitter from 'calypso/lib/mixins/emitter'; - -/** - * Internal dependencies - */ -import CountrySelect from 'calypso/my-sites/domains/components/form/country-select'; -import { PaymentCountrySelect } from '../'; - -// Gets rid of warnings such as 'UnhandledPromiseRejectionWarning: Error: No available storage method found.' -jest.mock( 'calypso/lib/user', () => () => {} ); -jest.mock( 'calypso/lib/cart/actions', () => ( { - setTaxCountryCode: () => {}, -} ) ); - -describe( 'PaymentCountrySelect', () => { - let props; - - beforeEach( () => { - props = { - name: 'test-country-select', - label: 'Test country select', - countriesList: [ - { - code: 'US', - name: 'United States', - }, - { - code: 'AR', - name: 'Argentina', - }, - ], - countryCode: 'US', - }; - emitter( props.countriesList ); - } ); - - test( 'should display a country selection component with the expected properties', () => { - const wrapper = shallow( ); - expect( wrapper.is( CountrySelect ) ).toBe( true ); - expect( wrapper.prop( 'name' ) ).toEqual( props.name ); - expect( wrapper.prop( 'countriesList' ) ).toEqual( props.countriesList ); - expect( wrapper.prop( 'value' ) ).toEqual( props.countryCode ); - } ); - - test( 'should correctly communicate the country which is initially selected', () => { - // Test one of the allowed values in the country list. - props.countryCode = 'US'; - props.onCountrySelected = jest.fn(); - shallow( ); - expect( props.onCountrySelected ).toHaveBeenLastCalledWith( props.name, 'US' ); - - // Test another allowed value in the country list. - props.countryCode = 'AR'; - shallow( ); - expect( props.onCountrySelected ).toHaveBeenLastCalledWith( props.name, 'AR' ); - - // Test a country code which doesn't match one of the allowed values in - // the country list. When passed to the callback function, this should - // be treated as if no country was selected. - props.countryCode = 'invalid'; - shallow( ); - expect( props.onCountrySelected ).toHaveBeenLastCalledWith( props.name, '' ); - } ); - - test( 'should correctly communicate changes to the selected country', () => { - // Simulate changing the country from "US" to "AR" and check that each - // callback was called the expected number of times with the expected - // input. - props.countryCode = 'US'; - props.onCountrySelected = jest.fn(); - props.onChange = jest.fn(); - props.updateGlobalCountryCode = jest.fn(); - const wrapper = mount( ); - expect( props.onCountrySelected ).toHaveBeenLastCalledWith( props.name, 'US' ); - const simulatedChangeEvent = { - target: { - name: props.name, - value: 'AR', - }, - }; - wrapper.find( 'select[name="' + props.name + '"]' ).simulate( 'change', simulatedChangeEvent ); - expect( props.onCountrySelected ).toHaveBeenLastCalledWith( props.name, 'AR' ); - expect( props.onCountrySelected ).toHaveBeenCalledTimes( 2 ); - expect( props.onChange.mock.calls[ 0 ][ 0 ] ).toMatchObject( simulatedChangeEvent ); - expect( props.onChange ).toHaveBeenCalledTimes( 1 ); - expect( props.updateGlobalCountryCode ).toHaveBeenCalledWith( 'AR' ); - expect( props.updateGlobalCountryCode ).toHaveBeenCalledTimes( 1 ); - } ); -} ); diff --git a/client/extensions/woocommerce/app/settings/shipping/index.js b/client/extensions/woocommerce/app/settings/shipping/index.js index 8fc231e168a5c..35b3a347ca93a 100644 --- a/client/extensions/woocommerce/app/settings/shipping/index.js +++ b/client/extensions/woocommerce/app/settings/shipping/index.js @@ -12,7 +12,6 @@ import { connect } from 'react-redux'; * Internal dependencies */ import Main from 'calypso/components/main'; -import LabelSettings from 'woocommerce/woocommerce-services/views/label-settings'; import Packages from 'woocommerce/woocommerce-services/views/packages'; import { ProtectFormGuard } from 'calypso/lib/protect-form'; import ShippingHeader from './shipping-header'; @@ -48,7 +47,6 @@ class Shipping extends Component { - { wcsEnabled && } { wcsEnabled && } diff --git a/client/extensions/woocommerce/woocommerce-services/style.scss b/client/extensions/woocommerce/woocommerce-services/style.scss index 055890711f8cf..b85a5872cc118 100644 --- a/client/extensions/woocommerce/woocommerce-services/style.scss +++ b/client/extensions/woocommerce/woocommerce-services/style.scss @@ -3,7 +3,6 @@ @import 'components/info-tooltip/style'; @import 'components/settings-group-card/style'; @import 'components/text/style'; -@import 'views/label-settings/style'; @import 'views/packages/style'; @import 'views/service-settings/settings-form/style'; @import 'views/service-settings/shipping-services/style'; diff --git a/client/extensions/woocommerce/woocommerce-services/views/label-settings/add-credit-card-modal.js b/client/extensions/woocommerce/woocommerce-services/views/label-settings/add-credit-card-modal.js deleted file mode 100644 index 2cf91852c4b52..0000000000000 --- a/client/extensions/woocommerce/woocommerce-services/views/label-settings/add-credit-card-modal.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * External dependencies - */ -import React from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import { localize } from 'i18n-calypso'; -import { StripeHookProvider } from '@automattic/calypso-stripe'; - -/** - * Internal dependencies - */ -import { Dialog } from '@automattic/components'; -import { closeAddCardDialog } from 'woocommerce/woocommerce-services/state/label-settings/actions'; -import { getLabelSettingsForm } from 'woocommerce/woocommerce-services/state/label-settings/selectors'; -import PaymentMethodForm from 'calypso/me/purchases/components/payment-method-form'; -import { addStoredCard } from 'calypso/state/stored-cards/actions'; -import { getStripeConfiguration } from 'calypso/lib/store-transactions'; -import { recordTracksEvent } from 'calypso/lib/analytics/tracks'; -import { getCurrentUserLocale } from 'calypso/state/current-user/selectors'; - -function AddCardDialog( { - siteId, - isVisible, - translate, - closeAddCardDialog: closeDialog, - addStoredCard: saveStoredCard, - locale, -} ) { - const recordFormSubmitEvent = () => recordTracksEvent( 'calypso_add_credit_card_form_submit' ); - const onClose = () => closeDialog( siteId ); - - return ( - - - - - - ); -} - -AddCardDialog.propTypes = { - siteId: PropTypes.number.isRequired, - isVisible: PropTypes.bool, - translate: PropTypes.func.isRequired, - addStoredCard: PropTypes.func.isRequired, - closeAddCardDialog: PropTypes.func.isRequired, - locale: PropTypes.string, -}; - -const mapStateToProps = ( state, { siteId } ) => { - const form = getLabelSettingsForm( state, siteId ); - return { - isVisible: Boolean( form && form.addCardDialog ), - locale: getCurrentUserLocale( state ), - }; -}; - -const mapDispatchToProps = ( dispatch ) => { - return bindActionCreators( { closeAddCardDialog, addStoredCard }, dispatch ); -}; - -export default connect( mapStateToProps, mapDispatchToProps )( localize( AddCardDialog ) ); diff --git a/client/extensions/woocommerce/woocommerce-services/views/label-settings/index.js b/client/extensions/woocommerce/woocommerce-services/views/label-settings/index.js deleted file mode 100644 index ddd17db772e1a..0000000000000 --- a/client/extensions/woocommerce/woocommerce-services/views/label-settings/index.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * External dependencies - */ - -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import classNames from 'classnames'; -import { localize } from 'i18n-calypso'; -import { isBoolean } from 'lodash'; - -/** - * Internal dependencies - */ -import { Card } from '@automattic/components'; -import ExtendedHeader from 'woocommerce/components/extended-header'; -import FormToggle from 'calypso/components/forms/form-toggle'; -import LabelSettings from './label-settings'; -import QueryLabelSettings from 'woocommerce/woocommerce-services/components/query-label-settings'; -import { setFormDataValue, restorePristineSettings } from '../../state/label-settings/actions'; -import { getSelectedSiteId } from 'calypso/state/ui/selectors'; -import { - areLabelsEnabled, - areSettingsErrored, - userCanEditSettings, - userCanManagePayments, - getLabelSettingsFormMeta, -} from '../../state/label-settings/selectors'; - -class AccountSettingsRootView extends Component { - componentWillUnmount() { - this.props.restorePristineSettings( this.props.siteId ); - } - - setValue = ( key, value ) => { - this.props.onChange(); - this.props.setFormDataValue( this.props.siteId, key, value ); - }; - - onEnabledToggle = () => { - this.props.onChange(); - this.props.setFormDataValue( this.props.siteId, 'enabled', ! this.props.labelsEnabled ); - }; - - renderContent = () => { - const { isFetchError, siteId, translate } = this.props; - - if ( isFetchError ) { - return ( -

{ translate( 'Unable to get your settings. Please refresh the page to try again.' ) }

- ); - } - - return ; - }; - - render() { - const { - formMeta, - canManagePayments, - canEditSettings, - labelsEnabled, - siteId, - translate, - } = this.props; - - if ( ! formMeta ) { - return ; - } - - //hide the toggle when the enabled flag is not present (older version of WCS) and respect the setting otherwise. - const renderToggle = isBoolean( labelsEnabled ); - const hidden = isBoolean( labelsEnabled ) && ! labelsEnabled; - - return ( -
- - - { renderToggle && ( - - ) } - - -
- ); - } -} - -AccountSettingsRootView.propTypes = { - onChange: PropTypes.func.isRequired, - submit: PropTypes.func, -}; - -function mapStateToProps( state ) { - return { - siteId: getSelectedSiteId( state ), - formMeta: getLabelSettingsFormMeta( state ), - labelsEnabled: areLabelsEnabled( state ), - isFetchError: areSettingsErrored( state ), - canManagePayments: userCanManagePayments( state ), - canEditSettings: userCanEditSettings( state ), - }; -} - -function mapDispatchToProps( dispatch ) { - return bindActionCreators( - { - setFormDataValue, - restorePristineSettings, - }, - dispatch - ); -} - -export default connect( - mapStateToProps, - mapDispatchToProps -)( localize( AccountSettingsRootView ) ); diff --git a/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-payment-method.js b/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-payment-method.js deleted file mode 100644 index 23153155e6a01..0000000000000 --- a/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-payment-method.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * External dependencies - */ - -import React from 'react'; -import PropTypes from 'prop-types'; -import { localize } from 'i18n-calypso'; - -/** - * Internal dependencies - */ -import FormCheckbox from 'calypso/components/forms/form-checkbox'; -import { CompactCard } from '@automattic/components'; -import PaymentLogo from 'calypso/components/payment-logo'; - -export const getPaymentMethodTitle = ( translate, paymentType, digits ) => { - const supportedTypes = { - amex: translate( 'American Express' ), - discover: translate( 'Discover' ), - mastercard: translate( 'MasterCard' ), - visa: translate( 'VISA' ), - paypal: translate( 'PayPal' ), - }; - - if ( ! supportedTypes[ paymentType ] ) { - return null; - } - - if ( ! digits ) { - return supportedTypes[ paymentType ]; - } - - return translate( '%(card)s ****%(digits)s', { - args: { - card: supportedTypes[ paymentType ], - digits, - }, - } ); -}; - -const PaymentMethod = ( { - translate, - selected, - isLoading, - type, - digits, - name, - expiry, - onSelect, -} ) => { - const renderPlaceholder = () => ( - - - -
-

-

-

-
-

-

-
- ); - - if ( isLoading ) { - return renderPlaceholder(); - } - - const typeTitle = getPaymentMethodTitle( translate, type, digits ); - const typeId = typeTitle ? type : 'placeholder'; - const typeName = typeTitle || type; - - const expiryText = expiry - ? translate( 'Expires %(date)s', { - args: { date: expiry }, - context: 'date is of the form MM/YY', - } ) - : ''; - - return ( - - - -
-

{ typeName }

-

{ name }

-
-
{ expiryText }
-
- ); -}; - -PaymentMethod.propTypes = { - selected: PropTypes.bool.isRequired, - isLoading: PropTypes.bool, - type: PropTypes.string, - digits: PropTypes.string, - name: PropTypes.string, - expiry: PropTypes.string, - onSelect: PropTypes.func, -}; - -export default localize( PaymentMethod ); diff --git a/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-settings.js b/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-settings.js deleted file mode 100644 index 3144cabe5513d..0000000000000 --- a/client/extensions/woocommerce/woocommerce-services/views/label-settings/label-settings.js +++ /dev/null @@ -1,425 +0,0 @@ -/** - * External dependencies - */ - -import React, { Component } from 'react'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import PropTypes from 'prop-types'; -import { localize } from 'i18n-calypso'; -import { find, isBoolean } from 'lodash'; -import Gridicon from 'calypso/components/gridicon'; - -/** - * Internal dependencies - */ -import { getPaperSizes } from 'woocommerce/woocommerce-services/lib/pdf-label-utils'; -import { Button } from '@automattic/components'; -import FormCheckbox from 'calypso/components/forms/form-checkbox'; -import FormFieldSet from 'calypso/components/forms/form-fieldset'; -import FormLabel from 'calypso/components/forms/form-label'; -import FormSelect from 'calypso/components/forms/form-select'; -import Notice from 'calypso/components/notice'; -import NoticeAction from 'calypso/components/notice/notice-action'; -import PaymentMethod, { getPaymentMethodTitle } from './label-payment-method'; -import { getOrigin } from 'woocommerce/lib/nav-utils'; -import { - openAddCardDialog, - fetchSettings, -} from 'woocommerce/woocommerce-services/state/label-settings/actions'; -import { - areSettingsFetching, - areSettingsLoaded, - getEmailReceipts, - getLabelSettingsStoreOptions, - getMasterUserInfo, - getPaperSize, - getPaymentMethods, - getPaymentMethodsWarning, - getSelectedPaymentMethodId, - isPristine, - userCanEditSettings, - userCanManagePayments, -} from 'woocommerce/woocommerce-services/state/label-settings/selectors'; -import QueryStoredCards from 'calypso/components/data/query-stored-cards'; -import AddCardDialog from 'woocommerce/woocommerce-services/views/label-settings/add-credit-card-modal'; - -class ShippingLabels extends Component { - UNSAFE_componentWillMount() { - this.setState( { expanded: this.isExpanded( this.props ) } ); - } - - UNSAFE_componentWillReceiveProps( props ) { - if ( props.selectedPaymentMethod !== this.props.selectedPaymentMethod ) { - this.setState( { expanded: this.isExpanded( props ) } ); - } - } - - isExpanded( { canEditPayments, pristine, selectedPaymentMethod } ) { - return canEditPayments && ( ! selectedPaymentMethod || ! pristine ); - } - - renderPlaceholder() { - return ( -
- - - - - - - - - - -

- - -

- ); - } - - renderPaymentPermissionNotice = () => { - const { - canEditPayments, - canEditSettings, - masterUserName, - masterUserLogin, - translate, - } = this.props; - - // If the user can's edit any settings, there will be another notice for the whole section - if ( ! canEditSettings || canEditPayments ) { - return null; - } - - return ( - - { translate( - 'Only the site owner can manage shipping label payment methods. Please' + - ' contact %(ownerName)s (%(ownerLogin)s) to manage payment methods.', - { - args: { - ownerName: masterUserName, - ownerLogin: masterUserLogin, - }, - } - ) } - - ); - }; - - refetchSettings = () => { - this.props.fetchSettings( this.props.siteId ); - }; - - renderPaymentWarningNotice = () => { - const { paymentMethodsWarning, translate } = this.props; - if ( ! paymentMethodsWarning ) { - return; - } - - return ( - - { translate( 'Retry' ) } - - ); - }; - - renderSettingsPermissionNotice = () => { - const { canEditSettings, masterUserName, masterUserLogin, translate } = this.props; - if ( canEditSettings ) { - return null; - } - - return ( - - { translate( - 'Only the site owner can change these settings. Please contact %(ownerName)s (%(ownerLogin)s)' + - ' to change the shipping label settings.', - { - args: { - ownerName: masterUserName, - ownerLogin: masterUserLogin, - }, - } - ) } - - ); - }; - - renderAddCardExternalInfo = () => { - const { masterUserWpcomLogin, masterUserEmail, translate } = this.props; - - if ( ! masterUserWpcomLogin ) { - return null; - } - - return ( -

- { translate( - 'Credit cards are retrieved from the following WordPress.com account: %(wpcomLogin)s <%(wpcomEmail)s>', - { - args: { - wpcomLogin: masterUserWpcomLogin, - wpcomEmail: masterUserEmail, - }, - } - ) } -

- ); - }; - - onVisibilityChange = () => { - if ( ! document.hidden ) { - this.refetchSettings(); - } - if ( this.addCreditCardWindow && this.addCreditCardWindow.closed ) { - document.removeEventListener( 'visibilitychange', this.onVisibilityChange ); - } - }; - - renderPaymentsSection = () => { - const { - siteId, - canEditPayments, - paymentMethods, - selectedPaymentMethod, - isReloading, - translate, - } = this.props; - - if ( ! this.state.expanded ) { - const expand = ( event ) => { - event.preventDefault(); - this.setState( { expanded: true } ); - }; - - let summary; - - if ( selectedPaymentMethod ) { - const { card_type: selectedType, card_digits: selectedDigits } = find( paymentMethods, { - payment_method_id: selectedPaymentMethod, - } ); - - summary = translate( - "We'll charge the credit card on your " + - 'account (%(card)s) to pay for the labels you print', - { - args: { - card: getPaymentMethodTitle( translate, selectedType, selectedDigits ), - }, - } - ); - } else { - summary = translate( 'To purchase shipping labels, add a credit card.' ); - } - - return ( -
- { this.renderPaymentPermissionNotice() } -

{ summary }

- { canEditPayments && ( -

- -

- ) } -
- ); - } - - const onPaymentMethodChange = ( value ) => - this.props.setValue( 'selected_payment_method_id', value ); - - let description; - let buttonLabel; - if ( paymentMethods.length ) { - description = translate( - 'To purchase shipping labels, choose a credit card you have on file or add a new card.' - ); - buttonLabel = translate( 'Add another credit card' ); - } else { - description = translate( 'To purchase shipping labels, add a credit card.' ); - buttonLabel = translate( 'Add a credit card' ); - } - - const renderPaymentMethod = ( method, index ) => { - const onSelect = () => onPaymentMethodChange( method.payment_method_id ); - return ( - - ); - }; - - const openDialog = () => { - this.props.openAddCardDialog( siteId ); - }; - - const onAddCardExternal = () => { - this.addCreditCardWindow = window.open( getOrigin() + '/me/purchases/add-credit-card' ); - document.addEventListener( 'visibilitychange', this.onVisibilityChange ); - }; - - return ( -
- { this.renderPaymentPermissionNotice() } -

{ description }

- { ! isReloading && this.renderPaymentWarningNotice() } - - - { isReloading ? ( -
- - -
- ) : ( - paymentMethods.map( renderPaymentMethod ) - ) } - - - - { /* Render two buttons with internal/external classNames to conditionally show them in Calypso or wp-admin using CSS */ } - -
- { this.renderAddCardExternalInfo() } - -
-
- ); - }; - - renderEmailReceiptsSection = () => { - const { - emailReceipts, - translate, - masterUserName, - masterUserLogin, - masterUserEmail, - canEditSettings, - canEditPayments, - } = this.props; - - if ( ! isBoolean( emailReceipts ) ) { - return null; - } - - const onChange = () => this.props.setValue( 'email_receipts', ! emailReceipts ); - - return ( - - - { translate( 'Email receipts' ) } - - - - - { translate( - 'Email the label purchase receipts to %(ownerName)s (%(ownerLogin)s) at %(ownerEmail)s', - { - args: { - ownerName: masterUserName, - ownerLogin: masterUserLogin, - ownerEmail: masterUserEmail, - }, - } - ) } - - - - ); - }; - - renderContent = () => { - const { canEditSettings, isLoading, paperSize, storeOptions, translate } = this.props; - - if ( isLoading ) { - return this.renderPlaceholder(); - } - - const onPaperSizeChange = ( event ) => this.props.setValue( 'paper_size', event.target.value ); - const paperSizes = getPaperSizes( storeOptions.origin_country ); - - return ( -
- - { this.renderSettingsPermissionNotice() } - - { translate( 'Paper size' ) } - - - { Object.keys( paperSizes ).map( ( size ) => ( - - ) ) } - - - - { translate( 'Payment' ) } - { this.renderPaymentsSection() } - - { this.renderEmailReceiptsSection() } -
- ); - }; - - render() { - return
{ this.renderContent() }
; - } -} - -ShippingLabels.propTypes = { - siteId: PropTypes.number.isRequired, - setValue: PropTypes.func.isRequired, -}; - -export default connect( - ( state, { siteId } ) => { - return { - isLoading: areSettingsFetching( state, siteId ) && ! areSettingsLoaded( state, siteId ), - isReloading: areSettingsFetching( state, siteId ) && areSettingsLoaded( state, siteId ), - pristine: isPristine( state, siteId ), - paymentMethods: getPaymentMethods( state, siteId ), - paymentMethodsWarning: getPaymentMethodsWarning( state, siteId ), - selectedPaymentMethod: getSelectedPaymentMethodId( state, siteId ), - paperSize: getPaperSize( state, siteId ), - storeOptions: getLabelSettingsStoreOptions( state, siteId ), - canEditPayments: userCanManagePayments( state, siteId ), - canEditSettings: - userCanManagePayments( state, siteId ) || userCanEditSettings( state, siteId ), - emailReceipts: getEmailReceipts( state, siteId ), - ...getMasterUserInfo( state, siteId ), - }; - }, - ( dispatch ) => - bindActionCreators( - { - openAddCardDialog, - fetchSettings, - }, - dispatch - ) -)( localize( ShippingLabels ) ); diff --git a/client/extensions/woocommerce/woocommerce-services/views/label-settings/style.scss b/client/extensions/woocommerce/woocommerce-services/views/label-settings/style.scss deleted file mode 100644 index 6e5f74ac6e4f6..0000000000000 --- a/client/extensions/woocommerce/woocommerce-services/views/label-settings/style.scss +++ /dev/null @@ -1,111 +0,0 @@ -.label-settings__credit-card-description { - margin-bottom: 4px; - color: var( --color-text-subtle ); - padding-bottom: 8px; - - button { - color: var( --color-primary ); - } -} - -.card.label-settings__card { - margin-bottom: 14px; - display: flex; - flex-direction: row; - align-items: center; - cursor: pointer; -} - -.label-settings__card .payment-logo { - margin-top: 0; -} - -.form-checkbox.label-settings__card-checkbox { - margin-right: 20px; - float: left; -} - -.payment-logo { - float: left; - margin-top: 10px; - margin-right: 14px; -} - -.label-settings__card-details { - float: left; - flex-grow: 1; -} - -.label-settings__card-number { - margin-bottom: 0; - font-weight: 600; -} - -.label-settings__card-name { - margin-bottom: 0; -} - -.label-settings__card-date { - float: right; - font-style: italic; -} - -.label-settings__labels-container { - &.hidden { - visibility: hidden; - height: 0; - padding: 0; - overflow: hidden; - } - - .form-fieldset:last-child { - margin-bottom: 0; - } - - .label-settings__external { - display: none; - } -} - -.label-settings__placeholder { - @include placeholder(); - pointer-events: none; - background: var( --color-surface ); - - &::after { - content: none; - } - - .gridicon, - span, - p, - a, - button { - animation: loading-fade 1.6s ease-in-out infinite; - background-color: var( --color-neutral-5 ); - color: transparent; - cursor: default; - } - - p, - span { - display: block; - width: 100px; - height: 14px; - } - - button { - width: 200px; - height: 14px; - } - - .gridicon { - fill: transparent; - stroke: transparent; - } -} - -&.dialog.card.add-credit-card-modal .dialog__content { - max-width: 720px; - padding: 0; -} diff --git a/client/me/purchases/components/payment-method-form/index.jsx b/client/me/purchases/components/payment-method-form/index.jsx deleted file mode 100644 index 3df0bbbc43cdf..0000000000000 --- a/client/me/purchases/components/payment-method-form/index.jsx +++ /dev/null @@ -1,273 +0,0 @@ -/** - * External dependencies - */ -import React, { useState, useEffect } from 'react'; -import PropTypes from 'prop-types'; -import { localize } from 'i18n-calypso'; -import { camelCase, values } from 'lodash'; -import { useDispatch, useSelector } from 'react-redux'; -import debugFactory from 'debug'; -import { Card } from '@automattic/components'; -import { - createStripeSetupIntent, - StripeSetupIntentError, - StripeValidationError, - useStripe, -} from '@automattic/calypso-stripe'; - -/** - * Internal dependencies - */ -import Gridicon from 'calypso/components/gridicon'; -import CreditCardFormFields from 'calypso/components/credit-card-form-fields'; -import FormButton from 'calypso/components/forms/form-button'; -import { validatePaymentDetails } from 'calypso/lib/checkout'; -import ValidationErrorList from './validation-error-list'; -import { AUTO_RENEWAL, MANAGE_PURCHASES } from 'calypso/lib/url/support'; -import getCountries from 'calypso/state/selectors/get-countries'; -import QueryPaymentCountries from 'calypso/components/data/query-countries/payments'; -import { localizeUrl } from 'calypso/lib/i18n-utils'; -import { - getInitializedFields, - camelCaseFormFields, - kebabCaseFormFields, - assignAllFormFields, - areFormFieldsEmpty, - useDebounce, - saveOrUpdateCreditCard, -} from './helpers'; -import { errorNotice } from 'calypso/state/notices/actions'; - -/** - * Style dependencies - */ -import './style.scss'; - -const debug = debugFactory( 'calypso:credit-card-form' ); - -export function PaymentMethodForm( { - apiParams = {}, - initialValues = undefined, - purchase = undefined, - recordFormSubmitEvent, - saveStoredCard = null, - siteSlug = undefined, - successCallback, - autoFocus = true, - heading = undefined, - onCancel = undefined, - translate, -} ) { - const { - stripe, - stripeConfiguration, - reloadStripeConfiguration, - isStripeLoading, - stripeLoadingError, - } = useStripe(); - const [ formSubmitting, setFormSubmitting ] = useState( false ); - const [ formFieldValues, setFormFieldValues ] = useState( getInitializedFields( initialValues ) ); - const [ touchedFormFields, setTouchedFormFields ] = useState( {} ); - const [ formFieldErrors, setFormFieldErrors ] = useState( - camelCaseFormFields( - validatePaymentDetails( kebabCaseFormFields( formFieldValues ), 'stripe' ).errors - ) - ); - const [ debouncedFieldErrors, setDebouncedFieldErrors ] = useDebounce( formFieldErrors, 1000 ); - const countriesList = useSelector( ( state ) => getCountries( state, 'payments' ) ); - const reduxDispatch = useDispatch(); - - const onFieldChange = ( rawDetails ) => { - const newValues = { ...formFieldValues, ...camelCaseFormFields( rawDetails ) }; - setFormFieldValues( newValues ); - setTouchedFormFields( { ...touchedFormFields, ...camelCaseFormFields( rawDetails ) } ); - // Clear the errors of updated fields when typing then display them again after debounce - const clearedErrors = assignAllFormFields( camelCaseFormFields( rawDetails ), [] ); - setDebouncedFieldErrors( { ...debouncedFieldErrors, ...clearedErrors } ); - // Debounce updating validation errors - setFormFieldErrors( - camelCaseFormFields( - validatePaymentDetails( kebabCaseFormFields( newValues ), 'stripe' ).errors - ) - ); - }; - - const getErrorMessage = ( fieldName ) => { - const camelName = camelCase( fieldName ); - if ( touchedFormFields[ camelName ] ) { - return debouncedFieldErrors[ camelName ]; - } - return formFieldValues[ camelName ] && debouncedFieldErrors[ camelName ]; - }; - - const onSubmit = async ( event ) => { - event.preventDefault(); - - if ( formSubmitting ) { - return; - } - setFormSubmitting( true ); - - try { - setTouchedFormFields( formFieldErrors ); - if ( ! areFormFieldsEmpty( formFieldErrors ) ) { - throw new Error( translate( 'Your credit card information is not valid' ) ); - } - recordFormSubmitEvent(); - const createStripeSetupIntentAsync = async ( paymentDetails ) => { - const { name, country, 'postal-code': zip } = paymentDetails; - const paymentDetailsForStripe = { - name, - address: { - country: country, - postal_code: zip, - }, - }; - return createStripeSetupIntent( stripe, stripeConfiguration, paymentDetailsForStripe ); - }; - const parseStripeToken = ( response ) => response.payment_method; - await saveOrUpdateCreditCard( { - createCardToken: createStripeSetupIntentAsync, - saveStoredCard, - translate, - apiParams, - purchase, - siteSlug, - formFieldValues, - stripeConfiguration, - parseTokenFromResponse: parseStripeToken, - reduxDispatch, - } ); - successCallback(); - } catch ( error ) { - debug( 'Error while submitting', error ); - setFormSubmitting( false ); - error && reloadStripeConfiguration && reloadStripeConfiguration(); - error && displayError( { translate, error, reduxDispatch } ); - } - }; - - useEffect( () => { - if ( stripeLoadingError ) { - displayError( { translate, error: stripeLoadingError, reduxDispatch } ); - } - }, [ stripeLoadingError, translate, reduxDispatch ] ); - - const disabled = isStripeLoading || stripeLoadingError; - - return ( -
- - { heading &&
{ heading }
} - - -
- -

- -

-
- - - - { onCancel && ( - - { translate( 'Cancel' ) } - - ) } -
-
- ); -} - -PaymentMethodForm.propTypes = { - apiParams: PropTypes.object, - initialValues: PropTypes.object, - purchase: PropTypes.object, - recordFormSubmitEvent: PropTypes.func.isRequired, - saveStoredCard: PropTypes.func, - siteSlug: PropTypes.string, - successCallback: PropTypes.func.isRequired, - autoFocus: PropTypes.bool, - heading: PropTypes.string, - onCancel: PropTypes.func, - translate: PropTypes.func.isRequired, -}; - -function SaveButton( { translate, disabled, formSubmitting } ) { - return ( - - { formSubmitting - ? translate( 'Saving card…', { - context: 'Button label', - comment: 'Credit card', - } ) - : translate( 'Save card', { - context: 'Button label', - comment: 'Credit card', - } ) } - - ); -} - -function TosText( { translate } ) { - return translate( - 'By saving a credit card, you agree to our {{tosLink}}Terms of Service{{/tosLink}}, and if ' + - 'you use it to pay for a subscription or plan, you authorize your credit card to be charged ' + - 'on a recurring basis until you cancel, which you can do at any time. ' + - 'You understand {{autoRenewalSupportPage}}how your subscription works{{/autoRenewalSupportPage}} ' + - 'and {{managePurchasesSupportPage}}how to cancel{{/managePurchasesSupportPage}}.', - { - components: { - tosLink: ( - - ), - autoRenewalSupportPage: ( - - ), - managePurchasesSupportPage: ( - - ), - }, - } - ); -} - -function StripeError( { translate } ) { - return ( -
- { translate( - 'There was a problem with your credit card. Please check your information and try again.' - ) } -
- ); -} - -function displayError( { translate, error, reduxDispatch } ) { - if ( error instanceof StripeSetupIntentError || error instanceof StripeValidationError ) { - reduxDispatch( errorNotice( ) ); - return; - } - if ( typeof error.message === 'object' ) { - reduxDispatch( errorNotice( ) ); - return; - } - reduxDispatch( errorNotice( error.message ) ); -} - -export default localize( PaymentMethodForm );