/** * External dependencies */ import { __, sprintf } from '@wordpress/i18n'; import classnames from 'classnames'; import { cloneElement, Component } from '@wordpress/element'; import { compose } from '@wordpress/compose'; import { Button, FormToggle } from '@wordpress/components'; import { withDispatch } from '@wordpress/data'; /** * WooCommerce dependencies */ import { Card, H, Plugins } from '@woocommerce/components'; import { getHistory, getNewPath, updateQueryString, } from '@woocommerce/navigation'; import { ONBOARDING_STORE_NAME, OPTIONS_STORE_NAME, PLUGINS_STORE_NAME, pluginNames, } from '@woocommerce/data'; /** * Internal dependencies */ import { recordEvent } from 'lib/tracks'; import { getCountryCode } from 'dashboard/utils'; import withSelect from 'wc-api/with-select'; import { getPaymentMethods } from './methods'; class Payments extends Component { constructor( props ) { super( ...arguments ); const { methods } = props; const enabledMethods = {}; methods.forEach( ( method ) => ( enabledMethods[ method.key ] = method.isEnabled ) ); this.state = { busyMethod: null, enabledMethods, recommendedMethod: this.getRecommendedMethod(), }; this.completeTask = this.completeTask.bind( this ); this.markConfigured = this.markConfigured.bind( this ); this.skipTask = this.skipTask.bind( this ); } componentDidUpdate() { const { recommendedMethod } = this.state; const method = this.getRecommendedMethod(); if ( recommendedMethod !== method ) { this.setState( { recommendedMethod: method, } ); } } getRecommendedMethod() { const { methods } = this.props; return methods.find( ( m ) => m.key === 'wcpay' && m.visible ) ? 'wcpay' : 'stripe'; } async completeTask() { const { createNotice, methods, updateOptions } = this.props; const update = await updateOptions( { woocommerce_task_list_payments: { completed: 1, timestamp: Math.floor( Date.now() / 1000 ), }, } ); recordEvent( 'tasklist_payment_done', { configured: methods .filter( ( method ) => method.isConfigured ) .map( ( method ) => method.key ), } ); if ( update.success ) { createNotice( 'success', __( '💰 Ka-ching! Your store can now accept payments 💳', 'woocommerce-admin' ) ); getHistory().push( getNewPath( {}, '/', {} ) ); } else { createNotice( 'error', __( 'There was a problem updating settings', 'woocommerce-admin' ) ); } } skipTask() { const { methods, updateOptions } = this.props; updateOptions( { woocommerce_task_list_payments: { skipped: 1, timestamp: Math.floor( Date.now() / 1000 ), }, } ); recordEvent( 'tasklist_payment_skip_task', { options: methods.map( ( method ) => method.key ), } ); getHistory().push( getNewPath( {}, '/', {} ) ); } markConfigured( method ) { const { enabledMethods } = this.state; this.setState( { enabledMethods: { ...enabledMethods, [ method ]: true, }, } ); getHistory().push( getNewPath( { task: 'payments' }, '/', {} ) ); recordEvent( 'tasklist_payment_connect_method', { payment_method: method, } ); } getCurrentMethod() { const { methods, query } = this.props; if ( ! query.method ) { return; } return methods.find( ( method ) => method.key === query.method ); } getInstallStep() { const currentMethod = this.getCurrentMethod(); if ( ! currentMethod.plugins || ! currentMethod.plugins.length ) { return; } const { activePlugins } = this.props; const pluginsToInstall = currentMethod.plugins.filter( ( method ) => ! activePlugins.includes( method ) ); const pluginNamesString = currentMethod.plugins .map( ( pluginSlug ) => pluginNames[ pluginSlug ] ) .join( ' ' + __( 'and', 'woocommerce-admin' ) + ' ' ); return { key: 'install', label: sprintf( __( 'Install %s', 'woocommerce-admin' ), pluginNamesString ), content: ( { recordEvent( 'tasklist_payment_install_method', { plugins: currentMethod.plugins, } ); } } autoInstall pluginSlugs={ currentMethod.plugins } /> ), isComplete: ! pluginsToInstall.length, }; } toggleMethod( key ) { const { methods, options, updateOptions } = this.props; const { enabledMethods } = this.state; const method = methods.find( ( option ) => option.key === key ); enabledMethods[ key ] = ! enabledMethods[ key ]; this.setState( { enabledMethods } ); recordEvent( 'tasklist_payment_toggle', { enabled: ! method.isEnabled, payment_method: key, } ); updateOptions( { [ method.optionName ]: { ...options[ method.optionName ], enabled: method.isEnabled ? 'no' : 'yes', }, } ); } async handleClick( method ) { const { methods } = this.props; const { key, onClick } = method; recordEvent( 'tasklist_payment_setup', { options: methods.map( ( option ) => option.key ), selected: key, } ); if ( onClick ) { this.setState( { busyMethod: key } ); await new Promise( onClick ) .then( () => { this.setState( { busyMethod: null } ); } ) .catch( () => { this.setState( { busyMethod: null } ); } ); return; } updateQueryString( { method: key, } ); } render() { const currentMethod = this.getCurrentMethod(); const { busyMethod, enabledMethods, recommendedMethod } = this.state; const { methods, query, requesting } = this.props; const configuredMethods = methods.filter( ( method ) => method.isConfigured ).length; if ( currentMethod ) { return ( { cloneElement( currentMethod.container, { query, installStep: this.getInstallStep(), markConfigured: this.markConfigured, hasCbdIndustry: currentMethod.hasCbdIndustry, } ) } ); } return (
{ methods.map( ( method ) => { const { before, container, content, isConfigured, key, title, visible, } = method; if ( ! visible ) { return null; } const classes = classnames( 'woocommerce-task-payment', 'is-narrow', ! isConfigured && 'woocommerce-task-payment-not-configured', 'woocommerce-task-payment-' + key ); const isRecommended = key === recommendedMethod && ! isConfigured; const showRecommendedRibbon = isRecommended && key !== 'wcpay'; const showRecommendedPill = isRecommended && key === 'wcpay'; return (
{ showRecommendedRibbon && (
{ __( 'Recommended', 'woocommerce-admin' ) }
) } { before }
{ title } { showRecommendedPill && ( { __( 'Recommended', 'woocommerce-admin' ) } ) }
{ content }
{ container && ! isConfigured ? ( ) : ( this.toggleMethod( key ) } onClick={ ( e ) => e.stopPropagation() } /> ) }
); } ) }
{ configuredMethods.length === 0 ? ( ) : ( ) }
); } } export default compose( withDispatch( ( dispatch ) => { const { createNotice } = dispatch( 'core/notices' ); const { installAndActivatePlugins } = dispatch( PLUGINS_STORE_NAME ); const { updateOptions } = dispatch( OPTIONS_STORE_NAME ); return { createNotice, installAndActivatePlugins, updateOptions, }; } ), withSelect( ( select, props ) => { const { createNotice, installAndActivatePlugins } = props; const { getProfileItems } = select( ONBOARDING_STORE_NAME ); const { getOption, isOptionsUpdating } = select( OPTIONS_STORE_NAME ); const { getActivePlugins, isJetpackConnected } = select( PLUGINS_STORE_NAME ); const activePlugins = getActivePlugins(); const profileItems = getProfileItems(); const optionNames = [ 'woocommerce_default_country', 'woocommerce_woocommerce_payments_settings', 'woocommerce_stripe_settings', 'woocommerce_ppec_paypal_settings', 'woocommerce_payfast_settings', 'woocommerce_square_credit_card_settings', 'woocommerce_klarna_payments_settings', 'woocommerce_kco_settings', 'wc_square_refresh_tokens', 'woocommerce_cod_settings', 'woocommerce_bacs_settings', 'woocommerce_bacs_accounts', ]; const options = optionNames.reduce( ( result, name ) => { result[ name ] = getOption( name ); return result; }, {} ); const countryCode = getCountryCode( options.woocommerce_default_country ); const methods = getPaymentMethods( { activePlugins, countryCode, createNotice, installAndActivatePlugins, isJetpackConnected: isJetpackConnected(), options, profileItems, } ); const requesting = isOptionsUpdating(); return { countryCode, profileItems, activePlugins, options, methods, requesting, }; } ) )( Payments );