mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-30 05:00:51 +08:00
Merge remote-tracking branch 'origin/trunk' into PCP-3882-Create-settings-placeholder-page-in-new-settings-module
# Conflicts: # modules/ppcp-settings/resources/css/_global.scss # modules/ppcp-settings/resources/js/Components/ReusableComponents/OnboardingSettingsToggleBlock.js # modules/ppcp-settings/resources/js/Components/Screens/Onboarding/StepWelcome.js # yarn.lock
This commit is contained in:
commit
cf543bb6a1
50 changed files with 1702 additions and 7606 deletions
|
@ -0,0 +1,45 @@
|
|||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
|
||||
import { useState } from 'react';
|
||||
|
||||
const Accordion = ( {
|
||||
title,
|
||||
initiallyOpen = false,
|
||||
className = '',
|
||||
children,
|
||||
} ) => {
|
||||
const [ isOpen, setIsOpen ] = useState( initiallyOpen );
|
||||
|
||||
const toggleOpen = ( ev ) => {
|
||||
setIsOpen( ! isOpen );
|
||||
ev?.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
const wrapperClasses = [ 'ppcp-r-accordion' ];
|
||||
if ( className ) {
|
||||
wrapperClasses.push( className );
|
||||
}
|
||||
if ( isOpen ) {
|
||||
wrapperClasses.push( 'ppcp--is-open' );
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ wrapperClasses.join( ' ' ) }>
|
||||
<button
|
||||
onClick={ toggleOpen }
|
||||
className="ppcp-r-accordion--title"
|
||||
type="button"
|
||||
>
|
||||
<span>{ title }</span>
|
||||
<Icon icon={ isOpen ? chevronUp : chevronDown } />
|
||||
</button>
|
||||
{ isOpen && (
|
||||
<div className="ppcp-r-accordion--content">{ children }</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Accordion;
|
|
@ -12,47 +12,53 @@ import { debounce } from '../../../../../ppcp-blocks/resources/js/Helper/debounc
|
|||
* @param {Function} props.onChange Change handler
|
||||
* @param {number} [props.delay=300] Debounce delay in milliseconds
|
||||
*/
|
||||
const DataStoreControl = ( {
|
||||
control: ControlComponent,
|
||||
value: externalValue,
|
||||
onChange,
|
||||
delay = 300,
|
||||
...props
|
||||
} ) => {
|
||||
const [ internalValue, setInternalValue ] = useState( externalValue );
|
||||
const onChangeRef = useRef( onChange );
|
||||
onChangeRef.current = onChange;
|
||||
|
||||
const debouncedUpdate = useRef(
|
||||
debounce( ( value ) => {
|
||||
onChangeRef.current( value );
|
||||
}, delay )
|
||||
).current;
|
||||
|
||||
useEffect( () => {
|
||||
setInternalValue( externalValue );
|
||||
debouncedUpdate?.cancel();
|
||||
}, [ externalValue ] );
|
||||
|
||||
useEffect( () => {
|
||||
return () => debouncedUpdate?.cancel();
|
||||
}, [ debouncedUpdate ] );
|
||||
|
||||
const handleChange = useCallback(
|
||||
( newValue ) => {
|
||||
setInternalValue( newValue );
|
||||
debouncedUpdate( newValue );
|
||||
const DataStoreControl = React.forwardRef(
|
||||
(
|
||||
{
|
||||
control: ControlComponent,
|
||||
value: externalValue,
|
||||
onChange,
|
||||
delay = 300,
|
||||
...props
|
||||
},
|
||||
[ debouncedUpdate ]
|
||||
);
|
||||
ref
|
||||
) => {
|
||||
const [ internalValue, setInternalValue ] = useState( externalValue );
|
||||
const onChangeRef = useRef( onChange );
|
||||
onChangeRef.current = onChange;
|
||||
|
||||
return (
|
||||
<ControlComponent
|
||||
{ ...props }
|
||||
value={ internalValue }
|
||||
onChange={ handleChange }
|
||||
/>
|
||||
);
|
||||
};
|
||||
const debouncedUpdate = useRef(
|
||||
debounce( ( value ) => {
|
||||
onChangeRef.current( value );
|
||||
}, delay )
|
||||
).current;
|
||||
|
||||
useEffect( () => {
|
||||
setInternalValue( externalValue );
|
||||
debouncedUpdate?.cancel();
|
||||
}, [ externalValue ] );
|
||||
|
||||
useEffect( () => {
|
||||
return () => debouncedUpdate?.cancel();
|
||||
}, [ debouncedUpdate ] );
|
||||
|
||||
const handleChange = useCallback(
|
||||
( newValue ) => {
|
||||
setInternalValue( newValue );
|
||||
debouncedUpdate( newValue );
|
||||
},
|
||||
[ debouncedUpdate ]
|
||||
);
|
||||
|
||||
return (
|
||||
<ControlComponent
|
||||
ref={ ref }
|
||||
{ ...props }
|
||||
value={ internalValue }
|
||||
onChange={ handleChange }
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default DataStoreControl;
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import {useOnboardingStepBusiness, useOnboardingStepProducts} from "../../data";
|
||||
import data from "../../utils/data";
|
||||
|
||||
const Navigation = ( {
|
||||
setStep,
|
||||
setCompleted,
|
||||
currentStep,
|
||||
stepperOrder,
|
||||
canProceeedCallback = () => true,
|
||||
stepperOrder
|
||||
} ) => {
|
||||
const isLastStep = () => currentStep + 1 === stepperOrder.length;
|
||||
const isFistStep = () => currentStep === 0;
|
||||
const navigateBy = ( stepDirection ) => {
|
||||
let newStep = currentStep + stepDirection;
|
||||
|
||||
|
@ -23,20 +26,77 @@ const Navigation = ( {
|
|||
}
|
||||
};
|
||||
|
||||
const { products, toggleProduct } = useOnboardingStepProducts();
|
||||
const { isCasualSeller, setIsCasualSeller } = useOnboardingStepBusiness();
|
||||
|
||||
let navigationTitle = '';
|
||||
let disabled = false;
|
||||
|
||||
switch ( currentStep ) {
|
||||
case 1:
|
||||
navigationTitle = __( 'Set up store type', 'woocommerce-paypal-payments' );
|
||||
disabled = isCasualSeller === null
|
||||
break;
|
||||
case 2:
|
||||
navigationTitle = __( 'Select product types', 'woocommerce-paypal-payments' );
|
||||
disabled = products.length < 1
|
||||
break;
|
||||
case 3:
|
||||
navigationTitle = __( 'Choose checkout options', 'woocommerce-paypal-payments' );
|
||||
case 4:
|
||||
navigationTitle = __( 'Connect your PayPal account', 'woocommerce-paypal-payments' );
|
||||
break;
|
||||
default:
|
||||
navigationTitle = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-navigation">
|
||||
<Button variant="tertiary" onClick={ () => navigateBy( -1 ) }>
|
||||
{ __( 'Back', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={ ! canProceeedCallback() }
|
||||
onClick={ () => navigateBy( 1 ) }
|
||||
>
|
||||
{ __( 'Next', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
<div className="ppcp-r-navigation-container">
|
||||
<div className="ppcp-r-navigation">
|
||||
<div className="ppcp-r-navigation--left">
|
||||
<span>{data().getImage('icon-arrow-left.svg')}</span>
|
||||
{!isFistStep() ? (
|
||||
<Button variant="tertiary" onClick={() => navigateBy(-1)}>
|
||||
{navigationTitle}
|
||||
</Button>
|
||||
) : (
|
||||
<a
|
||||
className="ppcp-r-navigation--left__link"
|
||||
href={global.ppcpSettings.wcPaymentsTabUrl}
|
||||
aria-label={__('Return to payments', 'woocommerce-paypal-payments')}
|
||||
>
|
||||
{navigationTitle}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
{!isFistStep() && (
|
||||
<div className="ppcp-r-navigation--right">
|
||||
<a
|
||||
href={ global.ppcpSettings.wcPaymentsTabUrl }
|
||||
aria-label={ __( 'Return to payments', 'woocommerce-paypal-payments' ) }
|
||||
>
|
||||
{ __( 'Save and exit', 'woocommerce-paypal-payments' ) }
|
||||
</a>
|
||||
{!isLastStep() && (
|
||||
<Button
|
||||
variant="primary"
|
||||
disabled={ disabled }
|
||||
onClick={ () => navigateBy( 1 ) }
|
||||
>
|
||||
{ __( 'Continue', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="ppcp-r-navigation--progress-bar"
|
||||
style={{
|
||||
width: `${ ( currentStep / ( stepperOrder.length - 1 ) ) * 90 }%`
|
||||
}}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Navigation;
|
||||
|
|
|
@ -1,18 +1,42 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import { useRef } from '@wordpress/element';
|
||||
|
||||
const OnboardingSettingsToggleBlock = ( {
|
||||
import SpinnerOverlay from './SpinnerOverlay';
|
||||
|
||||
const SettingsToggleBlock = ( {
|
||||
isToggled,
|
||||
setToggled,
|
||||
isLoading = false,
|
||||
...props
|
||||
} ) => {
|
||||
const toggleRef = useRef( null );
|
||||
const blockClasses = [ 'ppcp-r-toggle-block' ];
|
||||
|
||||
if ( isLoading ) {
|
||||
blockClasses.push( 'ppcp--is-loading' );
|
||||
}
|
||||
|
||||
const handleLabelClick = () => {
|
||||
if ( ! toggleRef.current || isLoading ) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleRef.current.click();
|
||||
toggleRef.current.focus();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-toggle-block">
|
||||
<div className={ blockClasses.join( ' ' ) }>
|
||||
<div className="ppcp-r-toggle-block__wrapper">
|
||||
<div className="ppcp-r-toggle-block__content">
|
||||
{ props?.label && (
|
||||
<span className="ppcp-r-toggle-block__content-label">
|
||||
// eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions -- keyboard element is ToggleControl
|
||||
<div
|
||||
className="ppcp-r-toggle-block__content-label"
|
||||
onClick={ handleLabelClick }
|
||||
>
|
||||
{ props.label }
|
||||
</span>
|
||||
</div>
|
||||
) }
|
||||
{ props?.description && (
|
||||
<p
|
||||
|
@ -25,15 +49,16 @@ const OnboardingSettingsToggleBlock = ( {
|
|||
</div>
|
||||
<div className="ppcp-r-toggle-block__switch">
|
||||
<ToggleControl
|
||||
ref={ toggleRef }
|
||||
checked={ isToggled }
|
||||
onChange={ ( newValue ) => {
|
||||
setToggled( newValue );
|
||||
} }
|
||||
onChange={ ( newState ) => setToggled( newState ) }
|
||||
disabled={ isLoading }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{ props.children && isToggled && (
|
||||
<div className="ppcp-r-toggle-block__toggled-content">
|
||||
{ isLoading && <SpinnerOverlay /> }
|
||||
{ props.children }
|
||||
</div>
|
||||
) }
|
||||
|
@ -41,4 +66,4 @@ const OnboardingSettingsToggleBlock = ( {
|
|||
);
|
||||
};
|
||||
|
||||
export default OnboardingSettingsToggleBlock;
|
||||
export default SettingsToggleBlock;
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
import { Spinner } from '@wordpress/components';
|
||||
|
||||
const SpinnerOverlay = () => {
|
||||
return (
|
||||
<div className="ppcp-r-spinner-overlay">
|
||||
<Spinner />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SpinnerOverlay;
|
|
@ -0,0 +1,327 @@
|
|||
import BadgeBox, { BADGE_BOX_TITLE_BIG } from "../BadgeBox";
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import Separator from '../Separator';
|
||||
|
||||
const AcdcFlow = ( { isFastlane, isPayLater, storeCountry } ) => {
|
||||
if (isFastlane && isPayLater && storeCountry === 'us') {
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs__wrapper">
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={__(
|
||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||
'woocommerce-paypal-payments'
|
||||
)}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
||||
<BadgeBox
|
||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-paypal.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Venmo', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-venmo.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Crypto', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-crypto.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-fastlane-small.svg']}
|
||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Speed up guest checkout with Fatslane. Link a customer\'s email address to their payment details. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (isPayLater && storeCountry === 'uk') {
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs__wrapper">
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
textBadge={__('from 2.90% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={__(
|
||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||
'woocommerce-paypal-payments'
|
||||
)}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
||||
<BadgeBox
|
||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-paypal.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Pay in 3', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
||||
textBadge={__('from 1.20% + £0.30 GBP<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs__wrapper">
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={__(
|
||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||
'woocommerce-paypal-payments'
|
||||
)}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
||||
<BadgeBox
|
||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-paypal.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Custom Card Fields', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Style the credit card fields to match your own style. Includes advanced processing with risk management, 3D Secure, fraud protection options, and chargeback protection. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Digital Wallets', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-apple-pay.svg', 'icon-button-google-pay.svg']}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Accept Apple Pay on eligible devices and Google Pay through mobile and web. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Alternative Payment Methods', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-sepa.svg', 'icon-button-ideal.svg', 'icon-button-blik.svg', 'icon-button-bancontact.svg']}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Seamless payments for customers across the globe using their preferred payment methods. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default AcdcFlow;
|
|
@ -0,0 +1,160 @@
|
|||
import BadgeBox, { BADGE_BOX_TITLE_BIG } from "../BadgeBox";
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import Separator from '../Separator';
|
||||
|
||||
const BcdcFlow = ( { isPayLater, storeCountry } ) => {
|
||||
if (isPayLater && storeCountry === 'us') {
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs__wrapper">
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
textBadge={__('from 3.49% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={__(
|
||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||
'woocommerce-paypal-payments'
|
||||
)}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
||||
<BadgeBox
|
||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-paypal.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Venmo', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-venmo.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Automatically offer Venmo checkout to millions of active users. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Crypto', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-crypto.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Let customers checkout with Crypto while you get paid in cash. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
<div className="ppcp-r-welcome-docs__col">
|
||||
<BadgeBox
|
||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Credit and Debit Cards', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
||||
textBadge={__('from 2.59% + $0.49 USD<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs__wrapper ppcp-r-welcome-docs__wrapper--one-col">
|
||||
<BadgeBox
|
||||
title={__('PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={__(
|
||||
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximise conversion',
|
||||
'woocommerce-paypal-payments'
|
||||
)}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Included in PayPal Checkout', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}/>
|
||||
<BadgeBox
|
||||
title={__('Pay with PayPal', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-paypal.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Our brand recognition helps give customers the confidence to buy. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Pay Later', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-payment-method-paypal-small.svg']}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Offer installment payment options and get paid upfront - at no extra cost to you. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator"/>
|
||||
<BadgeBox
|
||||
title={__('Optional payment methods', 'woocommerce-paypal-payments')}
|
||||
titleType={BADGE_BOX_TITLE_BIG}
|
||||
description={__('with additional application', 'woocommerce-paypal-payments')}
|
||||
/>
|
||||
<BadgeBox
|
||||
title={__('Credit and Debit Cards', 'woocommerce-paypal-payments')}
|
||||
imageBadge={['icon-button-visa.svg', 'icon-button-mastercard.svg', 'icon-button-amex.svg', 'icon-button-discover.svg']}
|
||||
textBadge={__('from 3.40% + €0.35 EUR<sup>1</sup>', 'woocommerce-paypal-payments')}
|
||||
description={sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'Process major credit and debit cards through PayPal’s card fields. <a target="_blank" href="%s">Learn more</a>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BcdcFlow;
|
|
@ -0,0 +1,32 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import AcdcFlow from "./AcdcFlow";
|
||||
import BcdcFlow from "./BcdcFlow";
|
||||
import {Button} from "@wordpress/components";
|
||||
|
||||
const WelcomeDocs = ( { useAcdc, isFastlane, isPayLater, storeCountry, storeCurrency } ) => {
|
||||
const pricesBasedDescription = sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'<sup>1</sup>Prices based on domestic transactions as of October 25th, 2024. <a target="_blank" href="%s">Click here</a> for full pricing details.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-welcome-docs">
|
||||
<h2 className="ppcp-r-welcome-docs__title">{__(`Want to know more about PayPal Payments?`, 'woocommerce-paypal-payments')}</h2>
|
||||
{useAcdc ? (
|
||||
<AcdcFlow isFastlane={ isFastlane } isPayLater={ isPayLater } storeCountry={ storeCountry } />
|
||||
) : (
|
||||
<BcdcFlow isPayLater={ isPayLater } storeCountry={ storeCountry } />
|
||||
)}
|
||||
<p
|
||||
className="ppcp-r-welcome-docs__description"
|
||||
dangerouslySetInnerHTML={{__html: pricesBasedDescription,}}
|
||||
></p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default WelcomeDocs;
|
|
@ -0,0 +1,180 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Button, TextControl } from '@wordpress/components';
|
||||
import { useRef } from '@wordpress/element';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { store as noticesStore } from '@wordpress/notices';
|
||||
|
||||
import SettingsToggleBlock from '../../../ReusableComponents/SettingsToggleBlock';
|
||||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import DataStoreControl from '../../../ReusableComponents/DataStoreControl';
|
||||
import { useManualConnect, useOnboardingStepWelcome } from '../../../../data';
|
||||
|
||||
const AdvancedOptionsForm = ( { setCompleted } ) => {
|
||||
const {
|
||||
isManualConnectionBusy,
|
||||
isSandboxMode,
|
||||
setSandboxMode,
|
||||
isManualConnectionMode,
|
||||
setManualConnectionMode,
|
||||
clientId,
|
||||
setClientId,
|
||||
clientSecret,
|
||||
setClientSecret,
|
||||
} = useOnboardingStepWelcome();
|
||||
|
||||
const { createSuccessNotice, createErrorNotice } =
|
||||
useDispatch( noticesStore );
|
||||
const { connectManual } = useManualConnect();
|
||||
const refClientId = useRef( null );
|
||||
const refClientSecret = useRef( null );
|
||||
|
||||
const handleFormValidation = () => {
|
||||
const fields = [
|
||||
{
|
||||
ref: refClientId,
|
||||
value: clientId,
|
||||
errorMessage: __(
|
||||
'Please enter your Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
ref: refClientSecret,
|
||||
value: clientSecret,
|
||||
errorMessage: __(
|
||||
'Please enter your Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
for ( const { ref, value, errorMessage } of fields ) {
|
||||
if ( value ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ref?.current?.focus();
|
||||
createErrorNotice( errorMessage );
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleServerError = ( res ) => {
|
||||
if ( res.message ) {
|
||||
createErrorNotice( res.message );
|
||||
} else {
|
||||
createErrorNotice(
|
||||
__(
|
||||
'Could not connect to PayPal. Please make sure your Client ID and Secret Key are correct.',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const handleServerSuccess = () => {
|
||||
createSuccessNotice(
|
||||
__( 'Connected to PayPal', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
|
||||
setCompleted( true );
|
||||
};
|
||||
|
||||
const handleConnect = async () => {
|
||||
if ( ! handleFormValidation() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await connectManual();
|
||||
|
||||
if ( res.success ) {
|
||||
handleServerSuccess();
|
||||
} else {
|
||||
handleServerError( res );
|
||||
}
|
||||
};
|
||||
|
||||
const advancedUsersDescription = sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'For advanced users: Connect a custom PayPal REST app for full control over your integration. For more information on creating a PayPal REST application, <a target="_blank" href="%s">click here</a>.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input'
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingsToggleBlock
|
||||
label={ __(
|
||||
'Enable Sandbox Mode',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Activate Sandbox mode to safely test PayPal with sample data. Once your store is ready to go live, you can easily switch to your production account.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
isToggled={ !! isSandboxMode }
|
||||
setToggled={ setSandboxMode }
|
||||
>
|
||||
<Button variant="secondary">
|
||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</SettingsToggleBlock>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||
<SettingsToggleBlock
|
||||
label={ __(
|
||||
'Manually Connect',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ advancedUsersDescription }
|
||||
isToggled={ !! isManualConnectionMode }
|
||||
setToggled={ setManualConnectionMode }
|
||||
isLoading={ isManualConnectionBusy }
|
||||
>
|
||||
<DataStoreControl
|
||||
control={ TextControl }
|
||||
ref={ refClientId }
|
||||
label={
|
||||
isSandboxMode
|
||||
? __(
|
||||
'Sandbox Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
: __(
|
||||
'Live Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
}
|
||||
value={ clientId }
|
||||
onChange={ setClientId }
|
||||
/>
|
||||
<DataStoreControl
|
||||
control={ TextControl }
|
||||
ref={ refClientSecret }
|
||||
label={
|
||||
isSandboxMode
|
||||
? __(
|
||||
'Sandbox Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
: __(
|
||||
'Live Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
}
|
||||
value={ clientSecret }
|
||||
onChange={ setClientSecret }
|
||||
type="password"
|
||||
/>
|
||||
<Button variant="secondary" onClick={ handleConnect }>
|
||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</SettingsToggleBlock>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default AdvancedOptionsForm;
|
|
@ -1,6 +1,7 @@
|
|||
import Container from '../../ReusableComponents/Container';
|
||||
import { useOnboardingStep } from '../../../data';
|
||||
import { getSteps } from './availableSteps';
|
||||
import Navigation from '../../ReusableComponents/Navigation';
|
||||
|
||||
const getCurrentStep = ( requestedStep, steps ) => {
|
||||
const isValidStep = ( step ) =>
|
||||
|
@ -20,16 +21,24 @@ const Onboarding = () => {
|
|||
const CurrentStepComponent = getCurrentStep( step, steps );
|
||||
|
||||
return (
|
||||
<Container page="onboarding">
|
||||
<div className="ppcp-r-card">
|
||||
<CurrentStepComponent
|
||||
setStep={ setStep }
|
||||
currentStep={ step }
|
||||
setCompleted={ setCompleted }
|
||||
stepperOrder={ steps }
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
<>
|
||||
<Navigation
|
||||
setStep={ setStep }
|
||||
currentStep={ step }
|
||||
setCompleted={ setCompleted }
|
||||
stepperOrder={ steps }
|
||||
/>
|
||||
<Container page="onboarding">
|
||||
<div className="ppcp-r-card">
|
||||
<CurrentStepComponent
|
||||
setStep={ setStep }
|
||||
currentStep={ step }
|
||||
setCompleted={ setCompleted }
|
||||
stepperOrder={ steps }
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import SelectBox from '../../ReusableComponents/SelectBox';
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||
import { useOnboardingStepBusiness } from '../../../data';
|
||||
import Navigation from '../../ReusableComponents/Navigation';
|
||||
import { BUSINESS_TYPES } from '../../../data/constants';
|
||||
|
||||
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
||||
|
@ -101,13 +100,6 @@ const StepBusiness = ( {
|
|||
/>
|
||||
</SelectBox>
|
||||
</SelectBoxWrapper>
|
||||
<Navigation
|
||||
setStep={ setStep }
|
||||
currentStep={ currentStep }
|
||||
stepperOrder={ stepperOrder }
|
||||
setCompleted={ setCompleted }
|
||||
canProceeedCallback={ () => isCasualSeller !== null }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
|
||||
const StepCompleteSetup = ( {
|
||||
setStep,
|
||||
currentStep,
|
||||
stepperOrder,
|
||||
setCompleted,
|
||||
} ) => {
|
||||
const ButtonIcon = () => (
|
||||
<Icon
|
||||
icon={ () => (
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19.5001 4.5H12.5001V6H16.9394L10.9697 11.9697L12.0304 13.0303L18.0001 7.06066V11.5H19.5001V4.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
<path
|
||||
d="M6.5 5.5C5.39543 5.5 4.5 6.39543 4.5 7.5V17.5C4.5 18.6046 5.39543 19.5 6.5 19.5H16.5C17.6046 19.5 18.5 18.6046 18.5 17.5V14.5H17V17.5C17 17.7761 16.7761 18 16.5 18H6.5C6.22386 18 6 17.7761 6 17.5V7.5C6 7.22386 6.22386 7 6.5 7H9.5V5.5H6.5Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
) }
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-page-products">
|
||||
<OnboardingHeader
|
||||
title={ __(
|
||||
'Complete Your Payment Setup',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'To finalize your payment setup, please log in to PayPal. If you don’t have an account yet, don’t worry - we’ll guide you through the easy process of creating one.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
<div className="ppcp-r-inner-container">
|
||||
<div className="ppcp-r-onboarding-header__description">
|
||||
<Button
|
||||
variant="primary"
|
||||
icon={ ButtonIcon }
|
||||
onClick={ () => {} }
|
||||
>
|
||||
{ __(
|
||||
'Connect to PayPal',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepCompleteSetup;
|
|
@ -1,5 +1,4 @@
|
|||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||
import Navigation from '../../ReusableComponents/Navigation';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import SelectBox from '../../ReusableComponents/SelectBox';
|
||||
import SelectBoxWrapper from '../../ReusableComponents/SelectBoxWrapper';
|
||||
|
@ -121,13 +120,6 @@ const StepProducts = ( {
|
|||
</a>
|
||||
</SelectBox>
|
||||
</SelectBoxWrapper>
|
||||
<Navigation
|
||||
setStep={ setStep }
|
||||
currentStep={ currentStep }
|
||||
stepperOrder={ stepperOrder }
|
||||
setCompleted={ setCompleted }
|
||||
canProceeedCallback={ () => products.length > 0 }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Button, TextControl } from '@wordpress/components';
|
||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||
import OnboardingSettingsToggleBlock from '../../ReusableComponents/OnboardingSettingsToggleBlock';
|
||||
import Separator from '../../ReusableComponents/Separator';
|
||||
import { useOnboardingStepWelcome, useManualConnect } from '../../../data';
|
||||
import { Button } from '@wordpress/components';
|
||||
|
||||
import DataStoreControl from '../../ReusableComponents/DataStoreControl';
|
||||
import BadgeBox, {
|
||||
BADGE_BOX_TITLE_BIG,
|
||||
} from '../../ReusableComponents/BadgeBox';
|
||||
import OnboardingHeader from '../../ReusableComponents/OnboardingHeader';
|
||||
import PaymentMethodIcons from '../../ReusableComponents/PaymentMethodIcons';
|
||||
import Separator from '../../ReusableComponents/Separator';
|
||||
import WelcomeDocs from '../../ReusableComponents/WelcomeDocs/WelcomeDocs';
|
||||
|
||||
import AdvancedOptionsForm from './Components/AdvancedOptionsForm';
|
||||
import AccordionSection from '../../ReusableComponents/AccordionSection';
|
||||
|
||||
const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
||||
return (
|
||||
|
@ -20,7 +18,7 @@ const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
|||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Your all-in-one integration for PayPal checkout solutions that enable buyers<br/> to pay via PayPal, Pay Later, all major credit/debit cards, Apple Pay, Google Pay, and more.',
|
||||
'Your all-in-one integration for PayPal checkout solutions that enable buyers to pay via PayPal, Pay Later, all major credit/debit cards, Apple Pay, Google Pay, and more.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
|
@ -45,8 +43,24 @@ const StepWelcome = ( { setStep, currentStep, setCompleted } ) => {
|
|||
</Button>
|
||||
</div>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||
<WelcomeDocs />
|
||||
<WelcomeForm setCompleted={ setCompleted } />
|
||||
<WelcomeDocs
|
||||
useAcdc = { true }
|
||||
isFastlane = { true }
|
||||
isPayLater = { true }
|
||||
storeCountry = { 'us' }
|
||||
storeCurrency = { 'usd' }
|
||||
/>
|
||||
<Separator text={ __( 'or', 'woocommerce-paypal-payments' ) } />
|
||||
<AccordionSection
|
||||
title={ __(
|
||||
'See advanced options',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
className="onboarding-advanced-options"
|
||||
initiallyOpen={ false }
|
||||
>
|
||||
<AdvancedOptionsForm setCompleted={ setCompleted } />
|
||||
</AccordionSection>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -296,118 +310,4 @@ const WelcomeDocs = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const WelcomeForm = ( { setCompleted } ) => {
|
||||
const {
|
||||
isSandboxMode,
|
||||
setSandboxMode,
|
||||
isManualConnectionMode,
|
||||
setManualConnectionMode,
|
||||
clientId,
|
||||
setClientId,
|
||||
clientSecret,
|
||||
setClientSecret,
|
||||
} = useOnboardingStepWelcome();
|
||||
|
||||
const { connectManual } = useManualConnect();
|
||||
|
||||
const handleConnect = async () => {
|
||||
try {
|
||||
const res = await connectManual(
|
||||
clientId,
|
||||
clientSecret,
|
||||
isSandboxMode
|
||||
);
|
||||
if ( ! res.success ) {
|
||||
throw new Error( 'Request failed.' );
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Merchant ID: ${ res.merchantId }, email: ${ res.email }`
|
||||
);
|
||||
|
||||
setCompleted( true );
|
||||
} catch ( exc ) {
|
||||
console.error( exc );
|
||||
alert( 'Connection failed.' );
|
||||
}
|
||||
};
|
||||
|
||||
const advancedUsersDescription = sprintf(
|
||||
// translators: %s: Link to PayPal REST application guide
|
||||
__(
|
||||
'For advanced users: Connect a custom PayPal REST app for full control over your integration. For more information on creating a PayPal REST application, <a target="_blank" href="%s">click here</a>.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#manual-credential-input '
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<OnboardingSettingsToggleBlock
|
||||
label={ __(
|
||||
'Enable Sandbox Mode',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Activate Sandbox mode to safely test PayPal with sample data. Once your store is ready to go live, you can easily switch to your production account.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
isToggled={ !! isSandboxMode }
|
||||
setToggled={ setSandboxMode }
|
||||
>
|
||||
<Button variant="secondary">
|
||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</OnboardingSettingsToggleBlock>
|
||||
<Separator className="ppcp-r-page-welcome-mode-separator" />
|
||||
<OnboardingSettingsToggleBlock
|
||||
label={ __(
|
||||
'Manually Connect',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ advancedUsersDescription }
|
||||
isToggled={ !! isManualConnectionMode }
|
||||
setToggled={ setManualConnectionMode }
|
||||
>
|
||||
<DataStoreControl
|
||||
control={ TextControl }
|
||||
label={
|
||||
isSandboxMode
|
||||
? __(
|
||||
'Sandbox Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
: __(
|
||||
'Live Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
}
|
||||
value={ clientId }
|
||||
onChange={ setClientId }
|
||||
/>
|
||||
<DataStoreControl
|
||||
control={ TextControl }
|
||||
label={
|
||||
isSandboxMode
|
||||
? __(
|
||||
'Sandbox Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
: __(
|
||||
'Live Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
}
|
||||
value={ clientSecret }
|
||||
onChange={ setClientSecret }
|
||||
type="password"
|
||||
/>
|
||||
<Button variant="secondary" onClick={ handleConnect }>
|
||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</OnboardingSettingsToggleBlock>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepWelcome;
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
import StepWelcome from './StepWelcome';
|
||||
import StepBusiness from './StepBusiness';
|
||||
import StepProducts from './StepProducts';
|
||||
import StepCompleteSetup from './StepCompleteSetup';
|
||||
|
||||
export const getSteps = ( flags ) => {
|
||||
const allSteps = [ StepWelcome, StepBusiness, StepProducts ];
|
||||
const allSteps = [
|
||||
StepWelcome,
|
||||
StepBusiness,
|
||||
StepProducts,
|
||||
StepCompleteSetup,
|
||||
];
|
||||
|
||||
if ( ! flags.canUseCasualSelling ) {
|
||||
return allSteps.filter( ( step ) => step !== StepBusiness );
|
||||
|
|
|
@ -4,6 +4,7 @@ export default {
|
|||
// Transient data.
|
||||
SET_ONBOARDING_IS_READY: 'SET_ONBOARDING_IS_READY',
|
||||
SET_IS_SAVING_ONBOARDING: 'SET_IS_SAVING_ONBOARDING',
|
||||
SET_MANUAL_CONNECTION_BUSY: 'SET_MANUAL_CONNECTION_BUSY',
|
||||
|
||||
// Persistent data.
|
||||
SET_ONBOARDING_COMPLETED: 'SET_ONBOARDING_COMPLETED',
|
||||
|
|
|
@ -38,6 +38,19 @@ export const setIsSaving = ( isSaving ) => {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Non-persistent. Changes the "manual connection is busy" flag.
|
||||
*
|
||||
* @param {boolean} isBusy
|
||||
* @return {{type: string, isBusy}} The action.
|
||||
*/
|
||||
export const setManualConnectionIsBusy = ( isBusy ) => {
|
||||
return {
|
||||
type: ACTION_TYPES.SET_MANUAL_CONNECTION_BUSY,
|
||||
isBusy,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Persistent. Set the full onboarding details, usually during app initialization.
|
||||
*
|
||||
|
@ -155,10 +168,47 @@ export const setProducts = ( products ) => {
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Attempts to establish a connection using client ID and secret via the server-side
|
||||
* connection endpoint.
|
||||
*
|
||||
* @return {Object} The server response object
|
||||
*/
|
||||
export function* connectViaIdAndSecret() {
|
||||
let result = null;
|
||||
|
||||
try {
|
||||
const path = `${ NAMESPACE }/connect_manual`;
|
||||
const { clientId, clientSecret, useSandbox } =
|
||||
yield select( STORE_NAME ).getPersistentData();
|
||||
|
||||
yield setManualConnectionIsBusy( true );
|
||||
|
||||
result = yield apiFetch( {
|
||||
path,
|
||||
method: 'POST',
|
||||
data: {
|
||||
clientId,
|
||||
clientSecret,
|
||||
useSandbox,
|
||||
},
|
||||
} );
|
||||
} catch ( e ) {
|
||||
result = {
|
||||
success: false,
|
||||
error: e,
|
||||
};
|
||||
} finally {
|
||||
yield setManualConnectionIsBusy( false );
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the persistent details to the WP database.
|
||||
*
|
||||
* @return {any} A generator function that handles the saving process.
|
||||
* @return {boolean} True, if the values were successfully saved.
|
||||
*/
|
||||
export function* persist() {
|
||||
let error = null;
|
||||
|
|
|
@ -25,6 +25,10 @@ const useOnboardingDetails = () => {
|
|||
return select( STORE_NAME ).getTransientData().isReady;
|
||||
} );
|
||||
|
||||
const isManualConnectionBusy = useSelect( ( select ) => {
|
||||
return select( STORE_NAME ).getTransientData().isManualConnectionBusy;
|
||||
}, [] );
|
||||
|
||||
// Read-only flags.
|
||||
const flags = useSelect( ( select ) => {
|
||||
return select( STORE_NAME ).getFlags();
|
||||
|
@ -78,6 +82,7 @@ const useOnboardingDetails = () => {
|
|||
return {
|
||||
isSaving,
|
||||
isReady,
|
||||
isManualConnectionBusy,
|
||||
step,
|
||||
setStep: ( value ) => setDetailAndPersist( setOnboardingStep, value ),
|
||||
completed,
|
||||
|
@ -105,6 +110,7 @@ const useOnboardingDetails = () => {
|
|||
export const useOnboardingStepWelcome = () => {
|
||||
const {
|
||||
isSaving,
|
||||
isManualConnectionBusy,
|
||||
isSandboxMode,
|
||||
setSandboxMode,
|
||||
isManualConnectionMode,
|
||||
|
@ -117,6 +123,7 @@ export const useOnboardingStepWelcome = () => {
|
|||
|
||||
return {
|
||||
isSaving,
|
||||
isManualConnectionBusy,
|
||||
isSandboxMode,
|
||||
setSandboxMode,
|
||||
isManualConnectionMode,
|
||||
|
@ -148,19 +155,9 @@ export const useOnboardingStep = () => {
|
|||
};
|
||||
|
||||
export const useManualConnect = () => {
|
||||
const connectManual = async ( clientId, clientSecret, isSandboxMode ) => {
|
||||
return await apiFetch( {
|
||||
path: `${ NAMESPACE }/connect_manual`,
|
||||
method: 'POST',
|
||||
data: {
|
||||
clientId,
|
||||
clientSecret,
|
||||
useSandbox: isSandboxMode,
|
||||
},
|
||||
} );
|
||||
};
|
||||
const { connectViaIdAndSecret } = useDispatch( STORE_NAME );
|
||||
|
||||
return {
|
||||
connectManual,
|
||||
connectManual: connectViaIdAndSecret,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -3,6 +3,7 @@ import ACTION_TYPES from './action-types';
|
|||
const defaultState = {
|
||||
isReady: false,
|
||||
isSaving: false,
|
||||
isManualConnectionBusy: false,
|
||||
|
||||
// Data persisted to the server.
|
||||
data: {
|
||||
|
@ -59,6 +60,9 @@ export const onboardingReducer = (
|
|||
case ACTION_TYPES.SET_IS_SAVING_ONBOARDING:
|
||||
return setTransient( { isSaving: action.isSaving } );
|
||||
|
||||
case ACTION_TYPES.SET_MANUAL_CONNECTION_BUSY:
|
||||
return setTransient( { isManualConnectionBusy: action.isBusy } );
|
||||
|
||||
// Persistent data.
|
||||
case ACTION_TYPES.SET_ONBOARDING_DETAILS:
|
||||
const newState = setPersistent( action.payload.data );
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue