From b4c71ae6449cdbd7a2f721aa346e743d5fae3a90 Mon Sep 17 00:00:00 2001 From: Joshua T Flowers Date: Wed, 2 Jun 2021 16:54:04 -0400 Subject: [PATCH] Add BACS as default fallback payment gateway (https://github.com/woocommerce/woocommerce-admin/pull/7073) * Add bacs method to fallback methods * Register bacs plugin to override default setup * Clean up prop usage * Add changelog entry * Fix imports for onboarding package * Fix card divider * Return early in updateSettings * Move recommended gateway up to remote payments index * Fix text domains --- .../client/task-list/style.scss | 4 + .../components/BacsPaymentGatewaySetup.js | 178 ++++++++++++++++++ .../components/PaymentConnect.js | 1 + .../components/PaymentMethod.js | 8 +- .../RecommendedPaymentGatewayList.js | 131 +++---------- .../RecommendedPaymentGatewayListItem.js | 110 +++++++++++ .../tasks/payments/RemotePayments/index.js | 45 +++-- .../images/onboarding/bacs.svg | 72 +++++++ plugins/woocommerce-admin/readme.txt | 1 + .../DefaultPaymentGateways.php | 9 + 10 files changed, 429 insertions(+), 130 deletions(-) create mode 100644 plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/BacsPaymentGatewaySetup.js create mode 100644 plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayListItem.js create mode 100644 plugins/woocommerce-admin/images/onboarding/bacs.svg diff --git a/plugins/woocommerce-admin/client/task-list/style.scss b/plugins/woocommerce-admin/client/task-list/style.scss index f51682e6fb2..d8ecba7859f 100644 --- a/plugins/woocommerce-admin/client/task-list/style.scss +++ b/plugins/woocommerce-admin/client/task-list/style.scss @@ -223,6 +223,10 @@ max-width: 70px; } } + + .components-card__divider:last-child { + display: none; + } } .woocommerce-task-payment-method { diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/BacsPaymentGatewaySetup.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/BacsPaymentGatewaySetup.js new file mode 100644 index 00000000000..7c8ec7e2804 --- /dev/null +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/BacsPaymentGatewaySetup.js @@ -0,0 +1,178 @@ +/** + * External dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Button } from '@wordpress/components'; +import { Form, H, TextControl } from '@woocommerce/components'; +import { OPTIONS_STORE_NAME } from '@woocommerce/data'; +import { registerPlugin } from '@wordpress/plugins'; +import { useDispatch, useSelect } from '@wordpress/data'; +import { WooRemotePayment } from '@woocommerce/onboarding'; + +const initialFormValues = { + account_name: '', + account_number: '', + bank_name: '', + sort_code: '', + iban: '', + bic: '', +}; + +const BacsPaymentGatewaySetup = () => { + const isUpdating = useSelect( ( select ) => { + return select( OPTIONS_STORE_NAME ).isOptionsUpdating(); + } ); + const { createNotice } = useDispatch( 'core/notices' ); + const { updateOptions } = useDispatch( OPTIONS_STORE_NAME ); + + const validate = ( values ) => { + const errors = {}; + + if ( ! values.account_number && ! values.iban ) { + errors.account_number = errors.iban = __( + 'Please enter an account number or IBAN', + 'woocommerce-admin' + ); + } + + return errors; + }; + + const updateSettings = async ( values, markConfigured ) => { + const update = await updateOptions( { + woocommerce_bacs_settings: { + enabled: 'yes', + }, + woocommerce_bacs_accounts: [ values ], + } ); + + if ( update.success ) { + markConfigured(); + createNotice( + 'success', + __( + 'Direct bank transfer details added successfully', + 'woocommerce-admin' + ) + ); + return; + } + + createNotice( + 'error', + __( + 'There was a problem saving your payment settings', + 'woocommerce-admin' + ) + ); + }; + + return ( + <> + + { ( { markConfigured } ) => { + return ( +
+ updateSettings( values, markConfigured ) + } + validate={ validate } + > + { ( { getInputProps, handleSubmit } ) => { + return ( + <> + + { __( + 'Add your bank details', + 'woocommerce-admin' + ) } + +

+ { __( + 'These details are required to receive payments via bank transfer', + 'woocommerce-admin' + ) } +

+
+ + + + + + +
+ + + ); + } } +
+ ); + } } +
+ + ); +}; + +registerPlugin( 'wc-admin-payment-gateway-setup-bacs', { + render: BacsPaymentGatewaySetup, +} ); diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentConnect.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentConnect.js index 30288f78071..65bc3390164 100644 --- a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentConnect.js +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentConnect.js @@ -119,6 +119,7 @@ export const PaymentConnect = ( { defaultSubmit: handleSubmit, defaultFields: fields, markConfigured: () => markConfigured( id ), + paymentGateway, } } id={ id } /> diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentMethod.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentMethod.js index 27fbbadfc96..be0bd2baec6 100644 --- a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentMethod.js +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/PaymentMethod.js @@ -28,7 +28,7 @@ export const PaymentMethod = ( { method, recordConnectStartEvent, } ) => { - const { key, plugins, title } = method; + const { key, plugins = [], title } = method; const slot = useSlot( `woocommerce_remote_payment_${ key }` ); const hasFills = Boolean( slot?.fills?.length ); const [ isPluginLoaded, setIsPluginLoaded ] = useState( false ); @@ -139,7 +139,7 @@ export const PaymentMethod = ( { }; const stepperPending = - ! installStep.isComplete || + ! installStep?.isComplete || isOptionUpdating || isPaymentGatewayResolving || ! isPluginLoaded; @@ -149,7 +149,7 @@ export const PaymentMethod = ( { @@ -166,6 +166,8 @@ export const PaymentMethod = ( { defaultStepper: DefaultStepper, defaultInstallStep: installStep, defaultConnectStep: connectStep, + markConfigured: () => markConfigured( key ), + paymentGateway, } } id={ key } /> diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayList.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayList.js index 52d74da69eb..3f67c759a5b 100644 --- a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayList.js +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayList.js @@ -1,121 +1,38 @@ /** * External dependencies */ -import classnames from 'classnames'; -import { Fragment } from '@wordpress/element'; -import { - Card, - CardBody, - CardMedia, - CardHeader, - CardDivider, -} from '@wordpress/components'; -import { Text } from '@woocommerce/experimental'; -import { recordEvent } from '@woocommerce/tracks'; -import { RecommendedRibbon, SetupRequired } from '@woocommerce/onboarding'; +import { Card, CardHeader } from '@wordpress/components'; /** * Internal dependencies */ -import { PaymentAction } from '../../../components/PaymentAction'; +import { RecommendedPaymentGatewayListItem } from './RecommendedPaymentGatewayListItem'; import './RecommendedPaymentGatewayList.scss'; export const RecommendedPaymentGatewayList = ( { - recommendedMethod, heading, - installedPaymentGateways, + recommendedPaymentGateway, recommendedPaymentGateways, markConfigured, -} ) => ( - - { heading } - { recommendedPaymentGateways.map( ( method, index ) => { - const { - image, - content, - key, - plugins = [], - title, - is_visible: isVisible, - loading, - } = method; - - if ( ! isVisible ) { - return null; - } - - const installedPaymentGateway = installedPaymentGateways[ key ]; - const { - enabled: isEnabled = false, - needs_setup: needsSetup = false, - required_settings_keys: requiredSettingsKeys = [], - settings_url: manageUrl, - } = installedPaymentGateway || {}; - - const isConfigured = ! needsSetup; - const hasSetup = Boolean( - plugins.length || requiredSettingsKeys.length - ); - const isRecommended = key === recommendedMethod && ! isConfigured; - const showRecommendedRibbon = isRecommended; - - const classes = classnames( - 'woocommerce-task-payment', - 'woocommerce-task-card', - ! isConfigured && 'woocommerce-task-payment-not-configured', - 'woocommerce-task-payment-' + key - ); - - return ( - - { index !== 0 && } - - - { - -
- { showRecommendedRibbon && } - - { title } - { isEnabled && ! isConfigured && ( - - ) } - -
- { content } -
-
-
- - recordEvent( 'tasklist_payment_setup', { - options: recommendedPaymentGateways.map( - ( option ) => option.key - ), - selected: key, - } ) - } - onSetupCallback={ method.onClick } - /> -
-
-
- ); - } ) } -
-); +} ) => { + return ( + + { heading } + { Array.from( recommendedPaymentGateways.values() ).map( + ( paymentGateway ) => { + const { key } = paymentGateway; + return ( + + ); + } + ) } + + ); +}; diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayListItem.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayListItem.js new file mode 100644 index 00000000000..d071d19b435 --- /dev/null +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/components/RecommendedPaymentGatewayList/RecommendedPaymentGatewayListItem.js @@ -0,0 +1,110 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import { Fragment } from '@wordpress/element'; +import { CardBody, CardMedia, CardDivider } from '@wordpress/components'; +import { PAYMENT_GATEWAYS_STORE_NAME } from '@woocommerce/data'; +import { RecommendedRibbon, SetupRequired } from '@woocommerce/onboarding'; +import { recordEvent } from '@woocommerce/tracks'; +import { Text, useSlot } from '@woocommerce/experimental'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { PaymentAction } from '../../../components/PaymentAction'; + +import './RecommendedPaymentGatewayList.scss'; + +export const RecommendedPaymentGatewayListItem = ( { + isRecommended, + paymentGateway, + markConfigured, + recommendedPaymentGatewayKeys, +} ) => { + const { + image, + content, + key, + plugins = [], + title, + is_visible: isVisible, + loading, + } = paymentGateway; + + const slot = useSlot( `woocommerce_remote_payment_${ key }` ); + + const installedPaymentGateway = useSelect( ( select ) => { + return ( + select( PAYMENT_GATEWAYS_STORE_NAME ).getPaymentGateway( key ) || {} + ); + } ); + + if ( ! isVisible ) { + return null; + } + + const { + enabled: isEnabled = false, + needs_setup: needsSetup = false, + required_settings_keys: requiredSettingsKeys = [], + settings_url: manageUrl, + } = installedPaymentGateway; + + const isConfigured = ! needsSetup; + const hasFills = Boolean( slot?.fills?.length ); + const hasSetup = Boolean( + plugins.length || requiredSettingsKeys.length || hasFills + ); + const showRecommendedRibbon = isRecommended && ! isConfigured; + + const classes = classnames( + 'woocommerce-task-payment', + 'woocommerce-task-card', + ! isConfigured && 'woocommerce-task-payment-not-configured', + 'woocommerce-task-payment-' + key + ); + + return ( + + + + { + +
+ { showRecommendedRibbon && } + + { title } + { isEnabled && ! isConfigured && } + +
+ { content } +
+
+
+ + recordEvent( 'tasklist_payment_setup', { + options: recommendedPaymentGatewayKeys, + selected: key, + } ) + } + /> +
+
+ +
+ ); +}; diff --git a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/index.js b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/index.js index 265b77d921d..7acefe2eed4 100644 --- a/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/index.js +++ b/plugins/woocommerce-admin/client/task-list/tasks/payments/RemotePayments/index.js @@ -18,6 +18,7 @@ import { useMemo, useCallback } from '@wordpress/element'; import { RecommendedPaymentGatewayList } from './components/RecommendedPaymentGatewayList'; import { PaymentMethod } from './components/PaymentMethod'; import { WCPayMethodCard } from '../components/WCPayMethodCard'; +import './components/BacsPaymentGatewaySetup'; const RECOMMENDED_GATEWAY_KEYS = [ 'woocommerce_payments', @@ -73,16 +74,6 @@ export const RemotePayments = ( { query } ) => { }; } ); - const recommendedMethod = useMemo( () => { - for ( const key in RECOMMENDED_GATEWAY_KEYS ) { - const gateway = paymentGatewayRecommendations.get( key ); - if ( gateway && gateway.visible ) { - return gateway; - } - } - return null; - }, [ paymentGatewayRecommendations ] ); - const enablePaymentGateway = ( paymentGatewayKey ) => { if ( ! paymentGatewayKey ) { return; @@ -124,6 +115,16 @@ export const RemotePayments = ( { query } ) => { } ); }, [] ); + const recommendedPaymentGateway = useMemo( () => { + for ( const key in RECOMMENDED_GATEWAY_KEYS ) { + const gateway = paymentGatewayRecommendations.get( key ); + if ( gateway && gateway.visible ) { + return gateway; + } + } + return null; + }, [ paymentGatewayRecommendations ] ); + const currentPaymentGateway = useMemo( () => { if ( ! query.method || @@ -176,23 +177,27 @@ export const RemotePayments = ( { query } ) => { { !! enabledPaymentGatewayRecommendations.size && ( ) } { !! additionalPaymentGatewayRecommendations.size && ( ) } diff --git a/plugins/woocommerce-admin/images/onboarding/bacs.svg b/plugins/woocommerce-admin/images/onboarding/bacs.svg new file mode 100644 index 00000000000..5a8d958278e --- /dev/null +++ b/plugins/woocommerce-admin/images/onboarding/bacs.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/woocommerce-admin/readme.txt b/plugins/woocommerce-admin/readme.txt index 843eb371210..fce43b7cda8 100644 --- a/plugins/woocommerce-admin/readme.txt +++ b/plugins/woocommerce-admin/readme.txt @@ -96,6 +96,7 @@ Release and roadmap notes are available on the [WooCommerce Developers Blog](htt - Add: Progressive setup checklist copy and call to action buttons. #6956 - Add: Add Paystack as fallback gateway #7025 - Add: Add COD method to default payment gateway recommendations #7057 +- Add: Add BACS as default fallback payment gateway #7073 - Add: A/B test of progressive checklist features. #7089 - Dev: Update package-lock to fix versioning of local packages. #6843 - Dev: Use rule processing for remote payment methods #6830 diff --git a/plugins/woocommerce-admin/src/Features/RemotePaymentMethods/DefaultPaymentGateways.php b/plugins/woocommerce-admin/src/Features/RemotePaymentMethods/DefaultPaymentGateways.php index fe1679e6c4d..660f5263b0a 100644 --- a/plugins/woocommerce-admin/src/Features/RemotePaymentMethods/DefaultPaymentGateways.php +++ b/plugins/woocommerce-admin/src/Features/RemotePaymentMethods/DefaultPaymentGateways.php @@ -92,6 +92,15 @@ class DefaultPaymentGateways { self::get_rules_for_cbd( false ), ), ), + array( + 'key' => 'bacs', + 'title' => __( 'Direct bank transfer', 'woocommerce-admin' ), + 'content' => __( 'Take payments via bank transfer.', 'woocommerce-admin' ), + 'image' => plugins_url( 'images/onboarding/bacs.svg', WC_ADMIN_PLUGIN_FILE ), + 'is_visible' => array( + self::get_rules_for_cbd( false ), + ), + ), ); }