mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Merge trunk
This commit is contained in:
commit
bef1c92f3f
165 changed files with 3796 additions and 3028 deletions
|
@ -1,20 +1,15 @@
|
|||
import { useEffect, useMemo } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { OnboardingHooks, CommonHooks } from '../data';
|
||||
import SpinnerOverlay from './ReusableComponents/SpinnerOverlay';
|
||||
import SendOnlyMessage from './Screens/SendOnlyMessage';
|
||||
import OnboardingScreen from './Screens/Onboarding';
|
||||
import SettingsScreen from './Screens/Settings';
|
||||
import { initStore as initSettingsStore } from '../data/settings-tab';
|
||||
import { useSettingsState } from '../data/settings-tab/hooks';
|
||||
|
||||
// Initialize the settings store
|
||||
initSettingsStore();
|
||||
|
||||
const SettingsApp = () => {
|
||||
const onboardingProgress = OnboardingHooks.useSteps();
|
||||
const { isReady: settingsIsReady } = useSettingsState();
|
||||
const { isReady: onboardingIsReady, completed: onboardingCompleted } =
|
||||
OnboardingHooks.useSteps();
|
||||
const {
|
||||
isReady: merchantIsReady,
|
||||
merchant: { isSendOnlyCountry },
|
||||
|
@ -33,34 +28,28 @@ const SettingsApp = () => {
|
|||
}, [] );
|
||||
|
||||
const wrapperClass = classNames( 'ppcp-r-app', {
|
||||
loading: ! onboardingProgress.isReady || ! settingsIsReady,
|
||||
loading: ! onboardingIsReady,
|
||||
} );
|
||||
|
||||
const Content = useMemo( () => {
|
||||
if (
|
||||
! onboardingProgress.isReady ||
|
||||
! merchantIsReady ||
|
||||
! settingsIsReady
|
||||
) {
|
||||
return (
|
||||
<SpinnerOverlay
|
||||
message={ __( 'Loading…', 'woocommerce-paypal-payments' ) }
|
||||
/>
|
||||
);
|
||||
if ( ! onboardingIsReady || ! merchantIsReady ) {
|
||||
return <SpinnerOverlay />;
|
||||
}
|
||||
|
||||
if ( isSendOnlyCountry ) {
|
||||
return <SendOnlyMessage />;
|
||||
}
|
||||
if ( ! onboardingProgress.completed ) {
|
||||
|
||||
if ( ! onboardingCompleted ) {
|
||||
return <OnboardingScreen />;
|
||||
}
|
||||
|
||||
return <SettingsScreen />;
|
||||
}, [
|
||||
isSendOnlyCountry,
|
||||
merchantIsReady,
|
||||
onboardingProgress.completed,
|
||||
onboardingProgress.isReady,
|
||||
settingsIsReady,
|
||||
onboardingCompleted,
|
||||
onboardingIsReady,
|
||||
] );
|
||||
|
||||
return <div className={ wrapperClass }>{ Content }</div>;
|
||||
|
|
|
@ -1,53 +1,33 @@
|
|||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { useAccordionState } from '../../hooks/useAccordionState';
|
||||
|
||||
// Provide defaults for all layout components so the generic version just works.
|
||||
const DefaultHeader = ( { children, className = '' } ) => (
|
||||
<div className={ `ppcp-r-accordion__header ${ className }`.trim() }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
const DefaultTitleWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-accordion__title-wrapper">{ children }</div>
|
||||
);
|
||||
const DefaultTitle = ( { children } ) => (
|
||||
<span className="ppcp-r-accordion__title">{ children }</span>
|
||||
);
|
||||
const DefaultAction = ( { children } ) => (
|
||||
<span className="ppcp-r-accordion__action">{ children }</span>
|
||||
);
|
||||
const DefaultDescription = ( { children } ) => (
|
||||
<div className="ppcp-r-accordion__description">{ children }</div>
|
||||
);
|
||||
|
||||
const AccordionContent = ( { isOpen, children } ) => {
|
||||
if ( ! isOpen || ! children ) {
|
||||
return null;
|
||||
}
|
||||
return <div className="ppcp-r-accordion__content">{ children }</div>;
|
||||
};
|
||||
import {
|
||||
Content,
|
||||
Description,
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
TitleWrapper,
|
||||
} from './Elements';
|
||||
|
||||
const Accordion = ( {
|
||||
title,
|
||||
id = '',
|
||||
noCaps = false,
|
||||
initiallyOpen = null,
|
||||
description = '',
|
||||
children = null,
|
||||
className = '',
|
||||
|
||||
// Layout components can be overridden by the caller
|
||||
Header = DefaultHeader,
|
||||
TitleWrapper = DefaultTitleWrapper,
|
||||
Title = DefaultTitle,
|
||||
Action = DefaultAction,
|
||||
Description = DefaultDescription,
|
||||
} ) => {
|
||||
const { isOpen, toggleOpen } = useAccordionState( { id, initiallyOpen } );
|
||||
const wrapperClasses = classNames( 'ppcp-r-accordion', className, {
|
||||
'ppcp--is-open': isOpen,
|
||||
} );
|
||||
const contentClass = classNames( 'ppcp--accordion-content', {
|
||||
'ppcp--is-open': isOpen,
|
||||
} );
|
||||
|
||||
const icon = isOpen ? chevronUp : chevronDown;
|
||||
|
||||
|
@ -55,22 +35,22 @@ const Accordion = ( {
|
|||
<div className={ wrapperClasses } { ...( id && { id } ) }>
|
||||
<button
|
||||
type="button"
|
||||
className="ppcp-r-accordion__toggler"
|
||||
className="ppcp--toggler"
|
||||
onClick={ toggleOpen }
|
||||
>
|
||||
<Header>
|
||||
<TitleWrapper>
|
||||
<Title>{ title }</Title>
|
||||
<Title noCaps={ noCaps }>{ title }</Title>
|
||||
<Action>
|
||||
<Icon icon={ icon } />
|
||||
</Action>
|
||||
</TitleWrapper>
|
||||
{ description && (
|
||||
<Description>{ description }</Description>
|
||||
) }
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
</button>
|
||||
<AccordionContent isOpen={ isOpen }>{ children }</AccordionContent>
|
||||
<div className={ contentClass }>
|
||||
<Content asCard={ false }>{ children }</Content>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { CommonHooks } from '../../data';
|
||||
|
||||
const ConnectionInfo = () => {
|
||||
const { merchant } = CommonHooks.useMerchantInfo();
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-connection-status__data">
|
||||
<StatusRow
|
||||
label={ __( 'Merchant ID', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.id }
|
||||
/>
|
||||
<StatusRow
|
||||
label={ __( 'Email address', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.email }
|
||||
/>
|
||||
<StatusRow
|
||||
label={ __( 'Client ID', 'woocommerce-paypal-payments' ) }
|
||||
value={ merchant.clientId }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
export default ConnectionInfo;
|
||||
|
||||
const StatusRow = ( { label, value } ) => (
|
||||
<div className="ppcp-r-connection-status__status-row">
|
||||
<span className="ppcp-r-connection-status__status-label">
|
||||
{ label }
|
||||
</span>
|
||||
<span className="ppcp-r-connection-status__status-value">
|
||||
{ value }
|
||||
</span>
|
||||
</div>
|
||||
);
|
|
@ -0,0 +1,18 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
|
||||
import { Action } from '../Elements';
|
||||
|
||||
const ControlButton = ( {
|
||||
type = 'secondary',
|
||||
isBusy,
|
||||
onClick,
|
||||
buttonLabel,
|
||||
} ) => (
|
||||
<Action>
|
||||
<Button isBusy={ isBusy } variant={ type } onClick={ onClick }>
|
||||
{ buttonLabel }
|
||||
</Button>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlButton;
|
|
@ -0,0 +1,14 @@
|
|||
import { Action } from '../Elements';
|
||||
import { RadioGroup } from '../Fields';
|
||||
|
||||
const ControlRadioGroup = ( { options, value, onChange } ) => (
|
||||
<Action>
|
||||
<RadioGroup
|
||||
options={ options }
|
||||
selected={ value }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlRadioGroup;
|
|
@ -0,0 +1,22 @@
|
|||
import { Select } from '../Fields';
|
||||
import { Action } from '../Elements';
|
||||
|
||||
const ControlSelect = ( {
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
placeholder,
|
||||
isMulti = false,
|
||||
} ) => (
|
||||
<Action>
|
||||
<Select
|
||||
isMulti={ isMulti }
|
||||
options={ options }
|
||||
value={ value }
|
||||
placeholder={ placeholder }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlSelect;
|
|
@ -0,0 +1,9 @@
|
|||
import { Action } from '../Elements';
|
||||
|
||||
const ControlStaticValue = ( { value } ) => (
|
||||
<Action>
|
||||
<div className="ppcp--static-value">{ value }</div>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlStaticValue;
|
|
@ -0,0 +1,22 @@
|
|||
import { TextControl } from '@wordpress/components';
|
||||
|
||||
import { Action, Description } from '../Elements';
|
||||
|
||||
const ControlTextInput = ( {
|
||||
value,
|
||||
description,
|
||||
onChange,
|
||||
placeholder = '',
|
||||
} ) => (
|
||||
<Action>
|
||||
<TextControl
|
||||
className="ppcp-r-vertical-text-control"
|
||||
placeholder={ placeholder }
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
/>
|
||||
<Description>{ description }</Description>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlTextInput;
|
|
@ -0,0 +1,19 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import { Action, Description } from '../Elements';
|
||||
|
||||
const ControlToggleButton = ( { label, description, value, onChange } ) => (
|
||||
<Action>
|
||||
<ToggleControl
|
||||
className="ppcp--control-toggle"
|
||||
__nextHasNoMarginBottom={ true }
|
||||
checked={ value }
|
||||
onChange={ onChange }
|
||||
label={ label }
|
||||
help={
|
||||
description ? <Description>{ description }</Description> : null
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
);
|
||||
|
||||
export default ControlToggleButton;
|
|
@ -0,0 +1,6 @@
|
|||
export { default as ControlStaticValue } from './ControlStaticValue';
|
||||
export { default as ControlTextInput } from './ControlTextInput';
|
||||
export { default as ControlToggleButton } from './ControlToggleButton';
|
||||
export { default as ControlButton } from './ControlButton';
|
||||
export { default as ControlRadioGroup } from './ControlRadioGroup';
|
||||
export { default as ControlSelect } from './ControlSelect';
|
|
@ -0,0 +1,5 @@
|
|||
const Action = ( { children } ) => (
|
||||
<div className="ppcp--action">{ children }</div>
|
||||
);
|
||||
|
||||
export default Action;
|
|
@ -0,0 +1,15 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Content = ( { children, asCard = true, className = '', id = '' } ) => {
|
||||
const elementClasses = classNames( 'ppcp--content', className, {
|
||||
'ppcp--is-card': asCard,
|
||||
} );
|
||||
|
||||
return (
|
||||
<div id={ id } className={ elementClasses }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Content;
|
|
@ -0,0 +1,5 @@
|
|||
const ContentWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-card__content-wrapper">{ children }</div>
|
||||
);
|
||||
|
||||
export default ContentWrapper;
|
|
@ -0,0 +1,23 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Description = ( { children, className = '' } ) => {
|
||||
// Don't output anything if description is empty.
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--description', className );
|
||||
|
||||
if ( 'string' !== typeof children ) {
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className={ elementClasses }
|
||||
dangerouslySetInnerHTML={ { __html: children } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Description;
|
|
@ -0,0 +1,13 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Header = ( { children, className = '' } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--header', className );
|
||||
|
||||
return <div className={ elementClasses }>{ children }</div>;
|
||||
};
|
||||
|
||||
export default Header;
|
|
@ -0,0 +1,16 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const Title = ( { children, noCaps = false, big = false, className = '' } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames( 'ppcp--title', className, {
|
||||
'ppcp--no-caps': noCaps,
|
||||
'ppcp--big': big,
|
||||
} );
|
||||
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
};
|
||||
|
||||
export default Title;
|
|
@ -0,0 +1,9 @@
|
|||
const TitleExtra = ( { children } ) => {
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <span className="ppcp--title-extra">{ children }</span>;
|
||||
};
|
||||
|
||||
export default TitleExtra;
|
|
@ -0,0 +1,5 @@
|
|||
const TitleWrapper = ( { children } ) => (
|
||||
<span className="ppcp--title-wrapper">{ children }</span>
|
||||
);
|
||||
|
||||
export default TitleWrapper;
|
|
@ -0,0 +1,13 @@
|
|||
/**
|
||||
* Static elements used to build UI layouts.
|
||||
*/
|
||||
|
||||
export { default as Action } from './Action';
|
||||
export { default as Content } from './Content';
|
||||
export { default as ContentWrapper } from './ContentWrapper';
|
||||
export { default as Description } from './Description';
|
||||
export { default as Header } from './Header';
|
||||
export { default as Title } from './Title';
|
||||
export { default as TitleExtra } from './TitleExtra';
|
||||
export { default as TitleWrapper } from './TitleWrapper';
|
||||
export { default as Separator } from './Separator';
|
|
@ -1,138 +0,0 @@
|
|||
import { CheckboxControl } from '@wordpress/components';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export const PayPalCheckbox = ( {
|
||||
currentValue,
|
||||
label,
|
||||
value,
|
||||
checked = null,
|
||||
disabled = null,
|
||||
changeCallback,
|
||||
} ) => {
|
||||
let isChecked = checked;
|
||||
|
||||
if ( null === isChecked ) {
|
||||
if ( Array.isArray( currentValue ) ) {
|
||||
isChecked = currentValue.includes( value );
|
||||
} else {
|
||||
isChecked = currentValue;
|
||||
}
|
||||
}
|
||||
|
||||
const className = classNames( { 'is-disabled': disabled } );
|
||||
|
||||
const onChange = ( newState ) => {
|
||||
let newValue;
|
||||
|
||||
if ( ! Array.isArray( currentValue ) ) {
|
||||
newValue = newState;
|
||||
} else if ( newState ) {
|
||||
newValue = [ ...currentValue, value ];
|
||||
} else {
|
||||
newValue = currentValue.filter(
|
||||
( optionValue ) => optionValue !== value
|
||||
);
|
||||
}
|
||||
|
||||
changeCallback( newValue );
|
||||
};
|
||||
|
||||
return (
|
||||
<CheckboxControl
|
||||
label={ label }
|
||||
value={ value }
|
||||
checked={ isChecked }
|
||||
disabled={ disabled }
|
||||
onChange={ onChange }
|
||||
className={ className }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const CheckboxGroup = ( { options, value, onChange } ) => (
|
||||
<>
|
||||
{ options.map( ( checkbox ) => (
|
||||
<PayPalCheckbox
|
||||
key={ checkbox.value }
|
||||
label={ checkbox.label }
|
||||
value={ checkbox.value }
|
||||
checked={ checkbox.checked }
|
||||
disabled={ checkbox.disabled }
|
||||
description={ checkbox.description }
|
||||
tooltip={ checkbox.tooltip }
|
||||
currentValue={ value }
|
||||
changeCallback={ onChange }
|
||||
/>
|
||||
) ) }
|
||||
</>
|
||||
);
|
||||
|
||||
export const PayPalRdb = ( {
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
} ) => {
|
||||
return (
|
||||
<div className="ppcp-r__radio">
|
||||
{ /* todo: Can we remove the wrapper div? */ }
|
||||
<input
|
||||
className="ppcp-r__radio-value"
|
||||
type="radio"
|
||||
id={ id }
|
||||
checked={ value === currentValue }
|
||||
name={ name }
|
||||
value={ value }
|
||||
onChange={ () => handleRdbState( value ) }
|
||||
/>
|
||||
<span className="ppcp-r__radio-presentation"></span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const PayPalRdbWithContent = ( {
|
||||
className,
|
||||
id,
|
||||
name,
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
toggleAdditionalContent,
|
||||
children,
|
||||
} ) => {
|
||||
const wrapperClasses = classNames( 'ppcp-r__radio-wrapper', className );
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio-outer-wrapper">
|
||||
<div className={ wrapperClasses }>
|
||||
<PayPalRdb
|
||||
id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
currentValue={ currentValue }
|
||||
handleRdbState={ handleRdbState }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r__radio-content">
|
||||
<label htmlFor={ id }>{ label }</label>
|
||||
{ description && (
|
||||
<p
|
||||
className="ppcp-r__radio-description"
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: description,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
{ toggleAdditionalContent && children && value === currentValue && (
|
||||
<div className="ppcp-r__radio-content-additional">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,37 @@
|
|||
import { CheckboxControl } from '@wordpress/components';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const Checkbox = ( {
|
||||
label,
|
||||
value,
|
||||
checked = null,
|
||||
disabled = null,
|
||||
onChange,
|
||||
changeCallback, // deprecated.
|
||||
} ) => {
|
||||
const className = classNames( { 'ppcp--is-disabled': disabled } );
|
||||
|
||||
const handleChange = ( isChecked ) => {
|
||||
if ( onChange ) {
|
||||
onChange( value, isChecked );
|
||||
} else if ( changeCallback ) {
|
||||
console.warn(
|
||||
'Deprecated prop, use "onChange" instead of "changeCallback"'
|
||||
);
|
||||
changeCallback( value, isChecked );
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<CheckboxControl
|
||||
label={ label }
|
||||
value={ value }
|
||||
checked={ checked }
|
||||
disabled={ disabled }
|
||||
onChange={ handleChange }
|
||||
className={ className }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkbox;
|
|
@ -0,0 +1,42 @@
|
|||
import { PayPalCheckbox } from './index';
|
||||
|
||||
const CheckboxGroup = ( { options, value, onChange } ) => {
|
||||
const handleChange = ( key, checked ) => {
|
||||
const getNewValue = () => {
|
||||
if ( checked ) {
|
||||
return [ ...value, key ];
|
||||
}
|
||||
return value.filter( ( val ) => val !== key );
|
||||
};
|
||||
|
||||
onChange( getNewValue() );
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{ options.map(
|
||||
( {
|
||||
value: itemValue,
|
||||
label,
|
||||
checked,
|
||||
disabled,
|
||||
description,
|
||||
tooltip,
|
||||
} ) => (
|
||||
<PayPalCheckbox
|
||||
key={ itemValue }
|
||||
value={ itemValue }
|
||||
label={ label }
|
||||
checked={ checked }
|
||||
disabled={ disabled }
|
||||
description={ description }
|
||||
tooltip={ tooltip }
|
||||
changeCallback={ handleChange }
|
||||
/>
|
||||
)
|
||||
) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default CheckboxGroup;
|
|
@ -0,0 +1,100 @@
|
|||
import classNames from 'classnames';
|
||||
import { PayPalCheckbox, PayPalRdb } from './index';
|
||||
|
||||
const OptionSelector = ( {
|
||||
multiSelect = false,
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
} ) => (
|
||||
<div className="ppcp-r-select-box-wrapper">
|
||||
{ options.map(
|
||||
( { value: itemValue, title, description, contents } ) => {
|
||||
let isSelected;
|
||||
|
||||
if ( Array.isArray( value ) ) {
|
||||
isSelected = value.includes( itemValue );
|
||||
} else {
|
||||
isSelected = value === itemValue;
|
||||
}
|
||||
|
||||
return (
|
||||
<OptionItem
|
||||
key={ itemValue }
|
||||
itemTitle={ title }
|
||||
itemDescription={ description }
|
||||
itemValue={ itemValue }
|
||||
onChange={ onChange }
|
||||
isMulti={ multiSelect }
|
||||
isSelected={ isSelected }
|
||||
>
|
||||
{ contents }
|
||||
</OptionItem>
|
||||
);
|
||||
}
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
|
||||
export default OptionSelector;
|
||||
|
||||
const OptionItem = ( {
|
||||
itemTitle,
|
||||
itemDescription,
|
||||
itemValue,
|
||||
onChange,
|
||||
isMulti,
|
||||
isSelected,
|
||||
children,
|
||||
} ) => {
|
||||
const boxClassName = classNames( 'ppcp-r-select-box', {
|
||||
'ppcp--selected': isSelected,
|
||||
} );
|
||||
|
||||
return (
|
||||
<div className={ boxClassName }>
|
||||
<InputField
|
||||
value={ itemValue }
|
||||
isRadio={ ! isMulti }
|
||||
onChange={ onChange }
|
||||
isSelected={ isSelected }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r-select-box__content">
|
||||
<div className="ppcp-r-select-box__content-inner">
|
||||
<span className="ppcp-r-select-box__title">
|
||||
{ itemTitle }
|
||||
</span>
|
||||
<p className="ppcp-r-select-box__description">
|
||||
{ itemDescription }
|
||||
</p>
|
||||
{ children && (
|
||||
<div className="ppcp-r-select-box__additional-content">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const InputField = ( { value, onChange, isRadio, isSelected } ) => {
|
||||
if ( isRadio ) {
|
||||
return (
|
||||
<PayPalRdb
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
checked={ isSelected }
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PayPalCheckbox
|
||||
value={ value }
|
||||
onChange={ onChange }
|
||||
checked={ isSelected }
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,42 @@
|
|||
import { useCallback } from '@wordpress/element';
|
||||
|
||||
const RadioButton = ( {
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
currentValue,
|
||||
checked = null, // alternative to currentValue.
|
||||
onChange,
|
||||
handleRdbState, // deprecated
|
||||
} ) => {
|
||||
const handleChange = useCallback( () => {
|
||||
if ( onChange ) {
|
||||
onChange( value );
|
||||
} else if ( handleRdbState ) {
|
||||
console.warn(
|
||||
'Deprecated prop, use "onChange" instead of "handleRdbState"'
|
||||
);
|
||||
handleRdbState( value );
|
||||
}
|
||||
}, [ handleRdbState, onChange, value ] );
|
||||
|
||||
const radioProps = {
|
||||
className: 'ppcp-r__radio-value',
|
||||
type: 'radio',
|
||||
onChange: handleChange,
|
||||
checked: null === checked ? value === currentValue : checked,
|
||||
id,
|
||||
name,
|
||||
value,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio">
|
||||
{ /* todo: Can we remove the wrapper div? */ }
|
||||
<input { ...radioProps } />
|
||||
<span className="ppcp-r__radio-presentation"></span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButton;
|
|
@ -0,0 +1,50 @@
|
|||
import classNames from 'classnames';
|
||||
import { PayPalRdb } from './index';
|
||||
|
||||
const RadioButtonWithContent = ( {
|
||||
className,
|
||||
id,
|
||||
name,
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
currentValue,
|
||||
handleRdbState,
|
||||
toggleAdditionalContent,
|
||||
children,
|
||||
} ) => {
|
||||
const wrapperClasses = classNames( 'ppcp-r__radio-wrapper', className );
|
||||
|
||||
return (
|
||||
<div className="ppcp-r__radio-outer-wrapper">
|
||||
<div className={ wrapperClasses }>
|
||||
<PayPalRdb
|
||||
id={ id }
|
||||
name={ name }
|
||||
value={ value }
|
||||
currentValue={ currentValue }
|
||||
handleRdbState={ handleRdbState }
|
||||
/>
|
||||
|
||||
<div className="ppcp-r__radio-content">
|
||||
<label htmlFor={ id }>{ label }</label>
|
||||
{ description && (
|
||||
<p
|
||||
className="ppcp-r__radio-description"
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: description,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
{ toggleAdditionalContent && children && value === currentValue && (
|
||||
<div className="ppcp-r__radio-content-additional">
|
||||
{ children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButtonWithContent;
|
|
@ -0,0 +1,13 @@
|
|||
import { RadioControl } from '@wordpress/components';
|
||||
|
||||
const RadioGroup = ( { options, selected, onChange } ) => {
|
||||
return (
|
||||
<RadioControl
|
||||
options={ options }
|
||||
onChange={ onChange }
|
||||
selected={ selected }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioGroup;
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* TODO: Replace this with the WordPress select control once V2 with multi-select is ready.
|
||||
*
|
||||
* This component has a lot of compatibility logic to (a) make the ReactSelect component look like
|
||||
* a WordPress select component, and (b) convert values from Redux-format (value-strings) to
|
||||
* ReactSelect values (objects containing value and label). When switching to the
|
||||
* SelectControl from `@wordpress/components`, we can remove a lot of this code.
|
||||
*
|
||||
* @see https://wordpress.github.io/gutenberg/?path=/story/components-customselectcontrol-v2--multiple-selection
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { default as ReactSelect, components } from 'react-select';
|
||||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import { useCallback, useEffect, useState } from '@wordpress/element';
|
||||
|
||||
const DropdownIndicator = ( props ) => (
|
||||
<components.DropdownIndicator { ...props }>
|
||||
<Icon icon={ props.selectProps.menuIsOpen ? chevronUp : chevronDown } />
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
|
||||
const IndicatorSeparator = () => null;
|
||||
|
||||
// Convert a plain value string/array to react-select objects.
|
||||
const toInternalValue = ( selected, options ) => {
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return selected.map( ( value ) =>
|
||||
options.find( ( option ) => option.value === value )
|
||||
);
|
||||
}
|
||||
|
||||
return options.find( ( option ) => option.value === selected );
|
||||
};
|
||||
|
||||
// Convert react-select object(s) to a plain value string/array.
|
||||
const toStoreValue = ( selected ) => {
|
||||
if ( ! selected ) {
|
||||
return null;
|
||||
}
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return selected.map( ( value ) => value.value );
|
||||
}
|
||||
return selected.value;
|
||||
};
|
||||
|
||||
const Select = ( { options, value, onChange, isMulti, placeholder } ) => {
|
||||
const [ internalValue, setInternalValue ] = useState(
|
||||
toInternalValue( value, options )
|
||||
);
|
||||
|
||||
const onInternalValueChange = useCallback(
|
||||
( selected ) => {
|
||||
setInternalValue( selected );
|
||||
|
||||
if ( Array.isArray( selected ) ) {
|
||||
return onChange( selected.map( ( option ) => option.id ) );
|
||||
}
|
||||
return onChange( selected.id );
|
||||
},
|
||||
[ onChange ]
|
||||
);
|
||||
|
||||
// Forward changes of the internal ReactSelect value to the onChange callback.
|
||||
useEffect( () => {
|
||||
onChange( toStoreValue( internalValue ) );
|
||||
}, [ internalValue, onChange ] );
|
||||
|
||||
return (
|
||||
<ReactSelect
|
||||
className="ppcp-r-select"
|
||||
classNamePrefix="ppcp"
|
||||
isMulti={ isMulti }
|
||||
options={ options }
|
||||
value={ internalValue }
|
||||
onChange={ onInternalValueChange }
|
||||
placeholder={ placeholder }
|
||||
components={ { DropdownIndicator, IndicatorSeparator } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Select;
|
|
@ -0,0 +1,11 @@
|
|||
/**
|
||||
* Generic input fields.
|
||||
*/
|
||||
|
||||
export { default as PayPalCheckbox } from './Checkbox';
|
||||
export { default as CheckboxGroup } from './CheckboxGroup';
|
||||
export { default as RadioGroup } from './RadioGroup';
|
||||
export { default as PayPalRdb } from './RadioButton';
|
||||
export { default as PayPalRdbWithContent } from './RadioContent';
|
||||
export { default as OptionSelector } from './OptionSelector';
|
||||
export { default as Select } from './Select';
|
|
@ -1,49 +0,0 @@
|
|||
import data from '../../utils/data';
|
||||
import { PayPalCheckbox, PayPalRdb } from './Fields';
|
||||
|
||||
const SelectBox = ( props ) => {
|
||||
let boxClassName = 'ppcp-r-select-box';
|
||||
|
||||
if (
|
||||
props.value === props.currentValue ||
|
||||
( Array.isArray( props.currentValue ) &&
|
||||
props.currentValue.includes( props.value ) )
|
||||
) {
|
||||
boxClassName += ' selected';
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ boxClassName }>
|
||||
{ props.type === 'radio' && (
|
||||
<PayPalRdb
|
||||
{ ...{
|
||||
...props,
|
||||
handleRdbState: props.changeCallback,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
{ props.type === 'checkbox' && (
|
||||
<PayPalCheckbox
|
||||
{ ...props }
|
||||
/>
|
||||
) }
|
||||
<div className="ppcp-r-select-box__content">
|
||||
<div className="ppcp-r-select-box__content-inner">
|
||||
<span className="ppcp-r-select-box__title">
|
||||
{ props.title }
|
||||
</span>
|
||||
<p className="ppcp-r-select-box__description">
|
||||
{ props.description }
|
||||
</p>
|
||||
{ props.children && (
|
||||
<div className="ppcp-r-select-box__additional-content">
|
||||
{ props.children }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectBox;
|
|
@ -1,5 +0,0 @@
|
|||
const SelectBoxWrapper = ( props ) => {
|
||||
return <div className="ppcp-r-select-box-wrapper">{ props.children }</div>;
|
||||
};
|
||||
|
||||
export default SelectBoxWrapper;
|
|
@ -0,0 +1,47 @@
|
|||
import classNames from 'classnames';
|
||||
import { Description, Header, Title, TitleExtra, Content } from './Elements';
|
||||
|
||||
const SettingsBlock = ( {
|
||||
className,
|
||||
children,
|
||||
title,
|
||||
titleSuffix,
|
||||
description,
|
||||
horizontalLayout = false,
|
||||
separatorAndGap = true,
|
||||
} ) => {
|
||||
const blockClassName = classNames( 'ppcp-r-settings-block', className, {
|
||||
'ppcp--no-gap': ! separatorAndGap,
|
||||
'ppcp--horizontal': horizontalLayout,
|
||||
} );
|
||||
|
||||
const BlockTitle = ( { blockTitle, blockSuffix, blockDescription } ) => {
|
||||
if ( ! blockTitle && ! blockDescription ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Header>
|
||||
<Title>
|
||||
{ blockTitle }
|
||||
<TitleExtra>{ blockSuffix }</TitleExtra>
|
||||
</Title>
|
||||
<Description>{ blockDescription }</Description>
|
||||
</Header>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={ blockClassName }>
|
||||
<BlockTitle
|
||||
blockTitle={ title }
|
||||
blockSuffix={ titleSuffix }
|
||||
blockDescription={ description }
|
||||
/>
|
||||
|
||||
<Content asCard={ false }>{ children }</Content>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SettingsBlock;
|
|
@ -1,27 +0,0 @@
|
|||
import Accordion from '../AccordionSection';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import {
|
||||
Header,
|
||||
Title,
|
||||
Action,
|
||||
Description,
|
||||
TitleWrapper,
|
||||
} from './SettingsBlockElements';
|
||||
|
||||
const SettingsAccordion = ( { title, description, children, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__accordion">
|
||||
<Accordion
|
||||
title={ title }
|
||||
description={ description }
|
||||
Header={ Header }
|
||||
TitleWrapper={ TitleWrapper }
|
||||
Title={ Title }
|
||||
Action={ Action }
|
||||
Description={ Description }
|
||||
>
|
||||
{ children }
|
||||
</Accordion>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default SettingsAccordion;
|
|
@ -1,27 +0,0 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Action, Description, Header, Title } from './SettingsBlockElements';
|
||||
|
||||
const ButtonSettingsBlock = ( { title, description, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__button">
|
||||
<Header>
|
||||
<Title>{ title }</Title>
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
<Action>
|
||||
<Button
|
||||
isBusy={ props.actionProps?.isBusy }
|
||||
variant={ props.actionProps?.buttonType }
|
||||
onClick={
|
||||
props.actionProps?.callback
|
||||
? () => props.actionProps.callback()
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{ props?.actionProps?.value }
|
||||
</Button>
|
||||
</Action>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default ButtonSettingsBlock;
|
|
@ -1,6 +1,7 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
import { Header, Title, Action, Description } from '../Elements';
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import TitleBadge from '../TitleBadge';
|
||||
|
||||
const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
||||
|
@ -41,13 +42,17 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
|
|||
</Button>
|
||||
);
|
||||
|
||||
return button.urls ? (
|
||||
<a href={ button.urls.live } key={ button.text }>
|
||||
{ buttonElement }
|
||||
</a>
|
||||
) : (
|
||||
buttonElement
|
||||
);
|
||||
// If there's a URL (either direct or in urls object), wrap in anchor tag
|
||||
if ( button.url || button.urls ) {
|
||||
const href = button.urls ? button.urls.live : button.url;
|
||||
return (
|
||||
<a href={ href } key={ button.text }>
|
||||
{ buttonElement }
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return buttonElement;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import { TextControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import {
|
||||
Title,
|
||||
Action,
|
||||
Description,
|
||||
SupplementaryLabel,
|
||||
} from './SettingsBlockElements';
|
||||
|
||||
const DEFAULT_ELEMENT_ORDER = [ 'title', 'action', 'description' ];
|
||||
|
||||
const ELEMENT_RENDERERS = {
|
||||
title: ( { title, supplementaryLabel } ) => (
|
||||
<Title>
|
||||
{ title }
|
||||
{ supplementaryLabel && (
|
||||
<SupplementaryLabel>{ supplementaryLabel }</SupplementaryLabel>
|
||||
) }
|
||||
</Title>
|
||||
),
|
||||
action: ( { actionProps } ) => (
|
||||
<Action>
|
||||
<TextControl
|
||||
className="ppcp-r-vertical-text-control"
|
||||
placeholder={ actionProps?.placeholder }
|
||||
value={ actionProps?.value }
|
||||
onChange={ ( newValue ) =>
|
||||
actionProps?.callback( actionProps?.key, newValue )
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
),
|
||||
description: ( { description } ) => (
|
||||
<Description>{ description }</Description>
|
||||
),
|
||||
};
|
||||
|
||||
const InputSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
supplementaryLabel,
|
||||
order = DEFAULT_ELEMENT_ORDER,
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__input">
|
||||
{ order.map( ( elementKey ) => {
|
||||
const RenderElement = ELEMENT_RENDERERS[ elementKey ];
|
||||
return RenderElement ? (
|
||||
<RenderElement
|
||||
key={ elementKey }
|
||||
title={ title }
|
||||
description={ description }
|
||||
supplementaryLabel={ supplementaryLabel }
|
||||
actionProps={ props.actionProps }
|
||||
/>
|
||||
) : null;
|
||||
} ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default InputSettingsBlock;
|
|
@ -1,32 +1,29 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import PaymentMethodIcon from '../PaymentMethodIcon';
|
||||
import data from '../../../utils/data';
|
||||
import { hasSettings } from '../../Screens/Overview/TabSettingsElements/Blocks/PaymentMethods';
|
||||
|
||||
const PaymentMethodItemBlock = ( {
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
icon,
|
||||
paymentMethod,
|
||||
onTriggerModal,
|
||||
onSelect,
|
||||
isSelected,
|
||||
} ) => {
|
||||
// Only show settings icon if this method has fields configured
|
||||
const hasModal = hasSettings( id );
|
||||
|
||||
return (
|
||||
<SettingsBlock className="ppcp-r-settings-block__payment-methods__item">
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__inner">
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__title-wrapper">
|
||||
<PaymentMethodIcon icons={ [ icon ] } type={ icon } />
|
||||
<PaymentMethodIcon
|
||||
icons={ [ paymentMethod.icon ] }
|
||||
type={ paymentMethod.icon }
|
||||
/>
|
||||
<span className="ppcp-r-settings-block__payment-methods__item__title">
|
||||
{ title }
|
||||
{ paymentMethod.itemTitle }
|
||||
</span>
|
||||
</div>
|
||||
<p className="ppcp-r-settings-block__payment-methods__item__description">
|
||||
{ description }
|
||||
{ paymentMethod.itemDescription }
|
||||
</p>
|
||||
<div className="ppcp-r-settings-block__payment-methods__item__footer">
|
||||
<ToggleControl
|
||||
|
@ -34,7 +31,7 @@ const PaymentMethodItemBlock = ( {
|
|||
checked={ isSelected }
|
||||
onChange={ onSelect }
|
||||
/>
|
||||
{ hasModal && onTriggerModal && (
|
||||
{ paymentMethod?.fields && onTriggerModal && (
|
||||
<div
|
||||
className="ppcp-r-settings-block__payment-methods__item__settings"
|
||||
onClick={ onTriggerModal }
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import SettingsBlock from './SettingsBlock';
|
||||
import SettingsBlock from '../SettingsBlock';
|
||||
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
|
||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
||||
|
||||
|
@ -27,7 +27,7 @@ const PaymentMethodsBlock = ( {
|
|||
{ paymentMethods.map( ( paymentMethod ) => (
|
||||
<PaymentMethodItemBlock
|
||||
key={ paymentMethod.id }
|
||||
{ ...paymentMethod }
|
||||
paymentMethod={ paymentMethod }
|
||||
isSelected={ paymentMethod.enabled }
|
||||
onSelect={ ( checked ) =>
|
||||
handleSelect( paymentMethod, checked )
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Description } from './SettingsBlockElements';
|
||||
import { PayPalRdbWithContent } from '../Fields';
|
||||
|
||||
const RadioSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
options = [],
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock
|
||||
{ ...props }
|
||||
className="ppcp-r-settings-block__radio ppcp-r-settings-block--expert-rdb"
|
||||
>
|
||||
<Header>
|
||||
<Title>{ title }</Title>
|
||||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
{ options.map( ( option ) => (
|
||||
<PayPalRdbWithContent
|
||||
key={ option.id }
|
||||
id={ option.id }
|
||||
name={ props.actionProps?.name }
|
||||
value={ option.value }
|
||||
currentValue={ props.actionProps?.currentValue }
|
||||
handleRdbState={ ( newValue ) =>
|
||||
props.actionProps?.callback(
|
||||
props.actionProps?.key,
|
||||
newValue
|
||||
)
|
||||
}
|
||||
label={ option.label }
|
||||
description={ option.description }
|
||||
toggleAdditionalContent={ true }
|
||||
>
|
||||
{ option.additionalContent }
|
||||
</PayPalRdbWithContent>
|
||||
) ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default RadioSettingsBlock;
|
|
@ -1,53 +0,0 @@
|
|||
import Select, { components } from 'react-select';
|
||||
import data from '../../../utils/data';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
const DEFAULT_ELEMENT_ORDER = [ 'title', 'action', 'description' ];
|
||||
|
||||
const DropdownIndicator = ( props ) => (
|
||||
<components.DropdownIndicator { ...props }>
|
||||
{ data().getImage( 'icon-arrow-down.svg' ) }
|
||||
</components.DropdownIndicator>
|
||||
);
|
||||
|
||||
const ELEMENT_RENDERERS = {
|
||||
title: ( { title } ) => <Title>{ title }</Title>,
|
||||
action: ( { actionProps } ) => (
|
||||
<Action>
|
||||
<Select
|
||||
className="ppcp-r-multiselect"
|
||||
classNamePrefix="ppcp-r"
|
||||
isMulti={ actionProps?.isMulti }
|
||||
options={ actionProps?.options }
|
||||
components={ { DropdownIndicator } }
|
||||
/>
|
||||
</Action>
|
||||
),
|
||||
description: ( { description } ) => (
|
||||
<Description>{ description }</Description>
|
||||
),
|
||||
};
|
||||
|
||||
const SelectSettingsBlock = ( {
|
||||
title,
|
||||
description,
|
||||
order = DEFAULT_ELEMENT_ORDER,
|
||||
...props
|
||||
} ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__select">
|
||||
{ order.map( ( elementKey ) => {
|
||||
const RenderElement = ELEMENT_RENDERERS[ elementKey ];
|
||||
return RenderElement ? (
|
||||
<RenderElement
|
||||
key={ elementKey }
|
||||
title={ title }
|
||||
description={ description }
|
||||
actionProps={ props.actionProps }
|
||||
/>
|
||||
) : null;
|
||||
} ) }
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default SelectSettingsBlock;
|
|
@ -1,11 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
const SettingsBlock = ( { className, children, separatorAndGap = true } ) => {
|
||||
const blockClassName = classNames( 'ppcp-r-settings-block', className, {
|
||||
'no-gap': ! separatorAndGap,
|
||||
} );
|
||||
|
||||
return <div className={ blockClassName }>{ children }</div>;
|
||||
};
|
||||
|
||||
export default SettingsBlock;
|
|
@ -1,81 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
// Block Elements
|
||||
export const Title = ( {
|
||||
children,
|
||||
altStyle = false,
|
||||
big = false,
|
||||
className = '',
|
||||
} ) => {
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-block__title',
|
||||
className,
|
||||
{
|
||||
'style-alt': altStyle,
|
||||
'style-big': big,
|
||||
}
|
||||
);
|
||||
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
};
|
||||
|
||||
export const TitleWrapper = ( { children } ) => (
|
||||
<span className="ppcp-r-settings-block__title-wrapper">{ children }</span>
|
||||
);
|
||||
|
||||
export const SupplementaryLabel = ( { children } ) => (
|
||||
<span className="ppcp-r-settings-block__supplementary-title-label">
|
||||
{ children }
|
||||
</span>
|
||||
);
|
||||
|
||||
export const Description = ( { children, asHtml = false, className = '' } ) => {
|
||||
// Don't output anything if description is empty.
|
||||
if ( ! children ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-block__description',
|
||||
className
|
||||
);
|
||||
|
||||
if ( ! asHtml ) {
|
||||
return <span className={ elementClasses }>{ children }</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className={ elementClasses }
|
||||
dangerouslySetInnerHTML={ { __html: children } }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const Action = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-block__action">{ children }</div>
|
||||
);
|
||||
|
||||
export const Header = ( { children, className = '' } ) => (
|
||||
<div className={ `ppcp-r-settings-block__header ${ className }`.trim() }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
|
||||
// Card Elements
|
||||
export const Content = ( { children, className = '', id = '' } ) => {
|
||||
const elementClasses = classNames(
|
||||
'ppcp-r-settings-card__content',
|
||||
className
|
||||
);
|
||||
|
||||
return (
|
||||
<div id={ id } className={ elementClasses }>
|
||||
{ children }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ContentWrapper = ( { children } ) => (
|
||||
<div className="ppcp-r-settings-card__content-wrapper">{ children }</div>
|
||||
);
|
|
@ -1,27 +0,0 @@
|
|||
import { ToggleControl } from '@wordpress/components';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import { Header, Title, Action, Description } from './SettingsBlockElements';
|
||||
|
||||
const ToggleSettingsBlock = ( { title, description, ...props } ) => (
|
||||
<SettingsBlock { ...props } className="ppcp-r-settings-block__toggle">
|
||||
<Action>
|
||||
<ToggleControl
|
||||
className="ppcp-r-settings-block__toggle-control"
|
||||
__nextHasNoMarginBottom={ true }
|
||||
checked={ props.actionProps?.value }
|
||||
onChange={ ( newValue ) =>
|
||||
props.actionProps?.callback(
|
||||
props.actionProps?.key,
|
||||
newValue
|
||||
)
|
||||
}
|
||||
/>
|
||||
</Action>
|
||||
<Header>
|
||||
{ title && <Title>{ title }</Title> }
|
||||
{ description && <Description>{ description }</Description> }
|
||||
</Header>
|
||||
</SettingsBlock>
|
||||
);
|
||||
|
||||
export default ToggleSettingsBlock;
|
|
@ -1,20 +1,4 @@
|
|||
export { default as SettingsBlock } from './SettingsBlock';
|
||||
export { default as ButtonSettingsBlock } from './ButtonSettingsBlock';
|
||||
export { default as InputSettingsBlock } from './InputSettingsBlock';
|
||||
export { default as SelectSettingsBlock } from './SelectSettingsBlock';
|
||||
export { default as AccordionSettingsBlock } from './AccordionSettingsBlock';
|
||||
export { default as ToggleSettingsBlock } from './ToggleSettingsBlock';
|
||||
export { default as RadioSettingsBlock } from './RadioSettingsBlock';
|
||||
export { default as PaymentMethodsBlock } from './PaymentMethodsBlock';
|
||||
export { default as PaymentMethodItemBlock } from './PaymentMethodItemBlock';
|
||||
|
||||
export {
|
||||
Title,
|
||||
TitleWrapper,
|
||||
SupplementaryLabel,
|
||||
Description,
|
||||
Action,
|
||||
Content,
|
||||
ContentWrapper,
|
||||
Header,
|
||||
} from './SettingsBlockElements';
|
||||
export { default as TodoSettingsBlock } from './TodoSettingsBlock';
|
||||
export { default as FeatureSettingsBlock } from './FeatureSettingsBlock';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import classNames from 'classnames';
|
||||
|
||||
import { Content, ContentWrapper } from './SettingsBlocks';
|
||||
import { Content, ContentWrapper } from './Elements';
|
||||
|
||||
const SettingsCard = ( {
|
||||
id,
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { Spinner } from '@wordpress/components';
|
||||
|
||||
const SpinnerOverlay = ( { message = '' } ) => {
|
||||
const SpinnerOverlay = ( { message = null } ) => {
|
||||
if ( null === message ) {
|
||||
message = __( 'Loading…', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-spinner-overlay">
|
||||
{ message && (
|
||||
|
|
|
@ -20,10 +20,10 @@ const TopNavigation = ( {
|
|||
const { isScrolled } = useIsScrolled();
|
||||
|
||||
const className = classNames( 'ppcp-r-navigation-container', {
|
||||
'is-scrolled': isScrolled,
|
||||
'ppcp--is-scrolled': isScrolled,
|
||||
} );
|
||||
const titleClassName = classNames( 'title', {
|
||||
big: isMainTitle,
|
||||
const titleClassName = classNames( 'ppcp--nav-title', {
|
||||
'ppcp--big': isMainTitle,
|
||||
} );
|
||||
|
||||
const handleTitleClick = useCallback( () => {
|
||||
|
|
|
@ -3,7 +3,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|||
import BadgeBox, {
|
||||
BADGE_BOX_TITLE_BIG,
|
||||
} from '../../../ReusableComponents/BadgeBox';
|
||||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import { Separator } from '../../../ReusableComponents/Elements';
|
||||
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
|
||||
import OptionalPaymentMethods from './OptionalPaymentMethods';
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
import BadgeBox from '../../../ReusableComponents/BadgeBox';
|
||||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import { Separator } from '../../../ReusableComponents/Elements';
|
||||
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
|
||||
|
||||
const AcdcOptionalPaymentMethods = ( {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import { Separator } from '../../../ReusableComponents/Elements';
|
||||
import SandboxConnectionForm from './SandboxConnectionForm';
|
||||
import ManualConnectionForm from './ManualConnectionForm';
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import { __, sprintf } from '@wordpress/i18n';
|
|||
import BadgeBox, {
|
||||
BADGE_BOX_TITLE_BIG,
|
||||
} from '../../../ReusableComponents/BadgeBox';
|
||||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import { Separator } from '../../../ReusableComponents/Elements';
|
||||
import PricingTitleBadge from '../../../ReusableComponents/PricingTitleBadge';
|
||||
import OptionalPaymentMethods from './OptionalPaymentMethods';
|
||||
|
||||
|
|
|
@ -54,8 +54,8 @@ const ConnectionButton = ( {
|
|||
removeCompleteHandler,
|
||||
} = useHandleOnboardingButton( isSandbox );
|
||||
const buttonClassName = classNames( 'ppcp-r-connection-button', className, {
|
||||
'sandbox-mode': isSandbox,
|
||||
'live-mode': ! isSandbox,
|
||||
'ppcp--mode-sandbox': isSandbox,
|
||||
'ppcp--mode-live': ! isSandbox,
|
||||
} );
|
||||
const environment = isSandbox ? 'sandbox' : 'production';
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ const ManualConnectionForm = () => {
|
|||
value={ manualClientId }
|
||||
onChange={ setManualClientId }
|
||||
className={ classNames( {
|
||||
'has-error': ! clientValid,
|
||||
'ppcp--has-error': ! clientValid,
|
||||
} ) }
|
||||
/>
|
||||
{ clientValid || (
|
||||
|
|
|
@ -1,27 +1,29 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { useEffect, useState } from '@wordpress/element';
|
||||
|
||||
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
|
||||
import SelectBox from '../../../ReusableComponents/SelectBox';
|
||||
import { OptionSelector } from '../../../ReusableComponents/Fields';
|
||||
import { OnboardingHooks, BUSINESS_TYPES } from '../../../../data';
|
||||
import OnboardingHeader from '../Components/OnboardingHeader';
|
||||
|
||||
const BUSINESS_RADIO_GROUP_NAME = 'business';
|
||||
const getBusinessType = ( isCasualSeller ) => {
|
||||
if ( isCasualSeller === null ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return isCasualSeller
|
||||
? BUSINESS_TYPES.CASUAL_SELLER
|
||||
: BUSINESS_TYPES.BUSINESS;
|
||||
};
|
||||
|
||||
const StepBusiness = ( {} ) => {
|
||||
const { isCasualSeller, setIsCasualSeller } = OnboardingHooks.useBusiness();
|
||||
const [ businessChoice, setBusinessChoice ] = useState(
|
||||
getBusinessType( isCasualSeller )
|
||||
);
|
||||
|
||||
const handleSellerTypeChange = ( value ) =>
|
||||
setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === value );
|
||||
|
||||
const getCurrentValue = () => {
|
||||
if ( isCasualSeller === null ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return isCasualSeller
|
||||
? BUSINESS_TYPES.CASUAL_SELLER
|
||||
: BUSINESS_TYPES.BUSINESS;
|
||||
};
|
||||
useEffect( () => {
|
||||
setIsCasualSeller( BUSINESS_TYPES.CASUAL_SELLER === businessChoice );
|
||||
}, [ businessChoice, setIsCasualSeller ] );
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-page-business">
|
||||
|
@ -32,43 +34,34 @@ const StepBusiness = ( {} ) => {
|
|||
) }
|
||||
/>
|
||||
<div className="ppcp-r-inner-container">
|
||||
<SelectBoxWrapper>
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'Business',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Recommended for individuals and organizations that primarily use PayPal to sell goods or services or receive donations, even if your business is not incorporated.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ BUSINESS_RADIO_GROUP_NAME }
|
||||
value={ BUSINESS_TYPES.BUSINESS }
|
||||
changeCallback={ handleSellerTypeChange }
|
||||
currentValue={ getCurrentValue() }
|
||||
checked={ isCasualSeller === false }
|
||||
type="radio"
|
||||
></SelectBox>
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'Personal Account',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Ideal for those who primarily make purchases or send personal transactions to family and friends.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ BUSINESS_RADIO_GROUP_NAME }
|
||||
value={ BUSINESS_TYPES.CASUAL_SELLER }
|
||||
changeCallback={ handleSellerTypeChange }
|
||||
currentValue={ getCurrentValue() }
|
||||
checked={ isCasualSeller === true }
|
||||
type="radio"
|
||||
></SelectBox>
|
||||
</SelectBoxWrapper>
|
||||
<OptionSelector
|
||||
multiSelect={ false }
|
||||
options={ businessChoices }
|
||||
onChange={ setBusinessChoice }
|
||||
value={ businessChoice }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const businessChoices = [
|
||||
{
|
||||
value: BUSINESS_TYPES.BUSINESS,
|
||||
title: __( 'Business', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Recommended for individuals and organizations that primarily use PayPal to sell goods or services or receive donations, even if your business is not incorporated.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: BUSINESS_TYPES.CASUAL_SELLER,
|
||||
title: __( 'Personal Account', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Ideal for those who primarily make purchases or send personal transactions to family and friends.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export default StepBusiness;
|
||||
|
|
|
@ -1,71 +1,26 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { CommonHooks, OnboardingHooks } from '../../../../data';
|
||||
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
|
||||
import SelectBox from '../../../ReusableComponents/SelectBox';
|
||||
import { OptionSelector } from '../../../ReusableComponents/Fields';
|
||||
import PricingDescription from '../../../ReusableComponents/PricingDescription';
|
||||
import OnboardingHeader from '../Components/OnboardingHeader';
|
||||
import OptionalPaymentMethods from '../Components/OptionalPaymentMethods';
|
||||
|
||||
const OPM_RADIO_GROUP_NAME = 'optional-payment-methods';
|
||||
|
||||
const StepPaymentMethods = ( {} ) => {
|
||||
const {
|
||||
areOptionalPaymentMethodsEnabled,
|
||||
setAreOptionalPaymentMethodsEnabled,
|
||||
} = OnboardingHooks.useOptionalPaymentMethods();
|
||||
|
||||
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
|
||||
|
||||
let screenTitle = __(
|
||||
'Add optional payment methods to your Checkout',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
|
||||
if ( 'US' === storeCountry ) {
|
||||
screenTitle = __(
|
||||
'Add Expanded Checkout for More Ways to Pay',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
}
|
||||
const { optionalMethods, setOptionalMethods } =
|
||||
OnboardingHooks.useOptionalPaymentMethods();
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-page-optional-payment-methods">
|
||||
<OnboardingHeader title={ screenTitle } />
|
||||
<OnboardingHeader title={ <PaymentStepTitle /> } />
|
||||
<div className="ppcp-r-inner-container">
|
||||
<SelectBoxWrapper>
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'Available with additional application',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={
|
||||
<OptionalPaymentMethods
|
||||
useAcdc={ true }
|
||||
isFastlane={ true }
|
||||
isPayLater={ true }
|
||||
storeCountry={ storeCountry }
|
||||
storeCurrency={ storeCurrency }
|
||||
/>
|
||||
}
|
||||
name={ OPM_RADIO_GROUP_NAME }
|
||||
value={ true }
|
||||
changeCallback={ setAreOptionalPaymentMethodsEnabled }
|
||||
currentValue={ areOptionalPaymentMethodsEnabled }
|
||||
type="radio"
|
||||
></SelectBox>
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'No thanks, I prefer to use a different provider for processing credit cards, digital wallets, and local payment methods',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ OPM_RADIO_GROUP_NAME }
|
||||
value={ false }
|
||||
changeCallback={ setAreOptionalPaymentMethodsEnabled }
|
||||
currentValue={ areOptionalPaymentMethodsEnabled }
|
||||
type="radio"
|
||||
></SelectBox>
|
||||
</SelectBoxWrapper>
|
||||
<OptionSelector
|
||||
multiSelect={ false }
|
||||
options={ methodChoices }
|
||||
onChange={ setOptionalMethods }
|
||||
value={ optionalMethods }
|
||||
/>
|
||||
|
||||
<PricingDescription />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -73,3 +28,51 @@ const StepPaymentMethods = ( {} ) => {
|
|||
};
|
||||
|
||||
export default StepPaymentMethods;
|
||||
|
||||
const PaymentStepTitle = () => {
|
||||
const { storeCountry } = CommonHooks.useWooSettings();
|
||||
|
||||
if ( 'US' === storeCountry ) {
|
||||
return __(
|
||||
'Add Expanded Checkout for More Ways to Pay',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
}
|
||||
|
||||
return __(
|
||||
'Add optional payment methods to your Checkout',
|
||||
'woocommerce-paypal-payments'
|
||||
);
|
||||
};
|
||||
|
||||
const OptionalMethodDescription = () => {
|
||||
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
|
||||
|
||||
return (
|
||||
<OptionalPaymentMethods
|
||||
useAcdc={ true }
|
||||
isFastlane={ true }
|
||||
isPayLater={ true }
|
||||
storeCountry={ storeCountry }
|
||||
storeCurrency={ storeCurrency }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const methodChoices = [
|
||||
{
|
||||
value: true,
|
||||
title: __(
|
||||
'Available with additional application',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: <OptionalMethodDescription />,
|
||||
},
|
||||
{
|
||||
title: __(
|
||||
'No thanks, I prefer to use a different provider for processing credit cards, digital wallets, and local payment methods',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
value: false,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1,15 +1,53 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { useEffect, useState } from '@wordpress/element';
|
||||
|
||||
import SelectBox from '../../../ReusableComponents/SelectBox';
|
||||
import SelectBoxWrapper from '../../../ReusableComponents/SelectBoxWrapper';
|
||||
import { OptionSelector } from '../../../ReusableComponents/Fields';
|
||||
import { OnboardingHooks, PRODUCT_TYPES } from '../../../../data';
|
||||
import OnboardingHeader from '../Components/OnboardingHeader';
|
||||
|
||||
const PRODUCTS_CHECKBOX_GROUP_NAME = 'products';
|
||||
|
||||
const StepProducts = () => {
|
||||
const { products, setProducts } = OnboardingHooks.useProducts();
|
||||
const { canUseSubscriptions } = OnboardingHooks.useFlags();
|
||||
const [ optionState, setOptionState ] = useState( null );
|
||||
const [ productChoices, setProductChoices ] = useState( [] );
|
||||
|
||||
useEffect( () => {
|
||||
const initChoices = () => {
|
||||
if ( optionState === canUseSubscriptions ) {
|
||||
return;
|
||||
}
|
||||
|
||||
let choices = productChoicesFull;
|
||||
|
||||
// Remove subscription details, if not available.
|
||||
if ( ! canUseSubscriptions ) {
|
||||
choices = choices.filter(
|
||||
( { value } ) => value !== PRODUCT_TYPES.SUBSCRIPTIONS
|
||||
);
|
||||
setProducts(
|
||||
products.filter(
|
||||
( value ) => value !== PRODUCT_TYPES.SUBSCRIPTIONS
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
setProductChoices( choices );
|
||||
setOptionState( canUseSubscriptions );
|
||||
};
|
||||
|
||||
initChoices();
|
||||
}, [ canUseSubscriptions, optionState, products, setProducts ] );
|
||||
|
||||
const handleChange = ( key, checked ) => {
|
||||
const getNewValue = () => {
|
||||
if ( checked ) {
|
||||
return [ ...products, key ];
|
||||
}
|
||||
return products.filter( ( val ) => val !== key );
|
||||
};
|
||||
|
||||
setProducts( getNewValue() );
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-page-products">
|
||||
|
@ -20,104 +58,70 @@ const StepProducts = () => {
|
|||
) }
|
||||
/>
|
||||
<div className="ppcp-r-inner-container">
|
||||
<SelectBoxWrapper>
|
||||
<SelectBox
|
||||
title={ __( 'Virtual', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Items do not require shipping.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||
value={ PRODUCT_TYPES.VIRTUAL }
|
||||
changeCallback={ setProducts }
|
||||
currentValue={ products }
|
||||
type="checkbox"
|
||||
>
|
||||
<ul className="ppcp-r-services">
|
||||
<li>
|
||||
{ __(
|
||||
'Services',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</li>
|
||||
<li>
|
||||
{ __(
|
||||
'Downloadable',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</li>
|
||||
<li>
|
||||
{ __(
|
||||
'Bookings',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</li>
|
||||
<li>
|
||||
{ __(
|
||||
'Deposits',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</li>
|
||||
</ul>
|
||||
</SelectBox>
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'Physical Goods',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Items require shipping.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||
value={ PRODUCT_TYPES.PHYSICAL }
|
||||
changeCallback={ setProducts }
|
||||
currentValue={ products }
|
||||
type="checkbox"
|
||||
>
|
||||
<ul className="ppcp-r-services">
|
||||
<li>
|
||||
{ __( 'Goods', 'woocommerce-paypal-payments' ) }
|
||||
</li>
|
||||
<li>
|
||||
{ __(
|
||||
'Deliveries',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</li>
|
||||
</ul>
|
||||
</SelectBox>
|
||||
{ canUseSubscriptions && (
|
||||
<SelectBox
|
||||
title={ __(
|
||||
'Subscriptions',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Recurring payments for either physical goods or services.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
name={ PRODUCTS_CHECKBOX_GROUP_NAME }
|
||||
value={ PRODUCT_TYPES.SUBSCRIPTIONS }
|
||||
changeCallback={ setProducts }
|
||||
currentValue={ products }
|
||||
type="checkbox"
|
||||
>
|
||||
<a
|
||||
target="__blank"
|
||||
href="https://woocommerce.com/document/woocommerce-paypal-payments/#subscriptions-faq"
|
||||
>
|
||||
{ __(
|
||||
'WooCommerce Subscriptions',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</a>
|
||||
</SelectBox>
|
||||
) }
|
||||
</SelectBoxWrapper>
|
||||
<OptionSelector
|
||||
multiSelect={ true }
|
||||
options={ productChoices }
|
||||
onChange={ handleChange }
|
||||
value={ products }
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default StepProducts;
|
||||
|
||||
const DetailsVirtual = () => (
|
||||
<ul className="ppcp-r-services">
|
||||
<li>{ __( 'Services', 'woocommerce-paypal-payments' ) }</li>
|
||||
<li>{ __( 'Downloadable', 'woocommerce-paypal-payments' ) }</li>
|
||||
<li>{ __( 'Bookings', 'woocommerce-paypal-payments' ) }</li>
|
||||
<li>{ __( 'Deposits', 'woocommerce-paypal-payments' ) }</li>
|
||||
</ul>
|
||||
);
|
||||
|
||||
const DetailsPhysical = () => (
|
||||
<ul className="ppcp-r-services">
|
||||
<li>{ __( 'Goods', 'woocommerce-paypal-payments' ) }</li>
|
||||
<li>{ __( 'Deliveries', 'woocommerce-paypal-payments' ) }</li>
|
||||
</ul>
|
||||
);
|
||||
|
||||
const DetailsSubscriptions = () => (
|
||||
<a
|
||||
target="__blank"
|
||||
href="https://woocommerce.com/document/woocommerce-paypal-payments/#subscriptions-faq"
|
||||
>
|
||||
{ __( 'WooCommerce Subscriptions', 'woocommerce-paypal-payments' ) }
|
||||
</a>
|
||||
);
|
||||
|
||||
const productChoicesFull = [
|
||||
{
|
||||
value: PRODUCT_TYPES.VIRTUAL,
|
||||
title: __( 'Virtual', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Items do not require shipping.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
contents: <DetailsVirtual />,
|
||||
},
|
||||
{
|
||||
value: PRODUCT_TYPES.PHYSICAL,
|
||||
title: __( 'Physical Goods', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Items require shipping.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
contents: <DetailsPhysical />,
|
||||
},
|
||||
{
|
||||
value: PRODUCT_TYPES.SUBSCRIPTIONS,
|
||||
title: __( 'Subscriptions', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Recurring payments for either physical goods or services.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
contents: <DetailsSubscriptions />,
|
||||
},
|
||||
];
|
||||
|
|
|
@ -2,8 +2,8 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Button } from '@wordpress/components';
|
||||
|
||||
import PaymentMethodIcons from '../../../ReusableComponents/PaymentMethodIcons';
|
||||
import Separator from '../../../ReusableComponents/Separator';
|
||||
import AccordionSection from '../../../ReusableComponents/AccordionSection';
|
||||
import { Separator } from '../../../ReusableComponents/Elements';
|
||||
import Accordion from '../../../ReusableComponents/AccordionSection';
|
||||
import { CommonHooks } from '../../../../data';
|
||||
import BusyStateWrapper from '../../../ReusableComponents/BusyStateWrapper';
|
||||
import OnboardingHeader from '../Components/OnboardingHeader';
|
||||
|
@ -55,16 +55,17 @@ const StepWelcome = ( { setStep, currentStep } ) => {
|
|||
storeCountry={ storeCountry }
|
||||
/>
|
||||
<Separator text={ __( 'or', 'woocommerce-paypal-payments' ) } />
|
||||
<AccordionSection
|
||||
<Accordion
|
||||
title={ __(
|
||||
'See advanced options',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
className="onboarding-advanced-options"
|
||||
noCaps={ true }
|
||||
id="advanced-options"
|
||||
>
|
||||
<AdvancedOptionsForm />
|
||||
</AccordionSection>
|
||||
</Accordion>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -36,7 +36,8 @@ const ALL_STEPS = [
|
|||
id: 'methods',
|
||||
title: __( 'Choose checkout options', 'woocommerce-paypal-payments' ),
|
||||
StepComponent: StepPaymentMethods,
|
||||
canProceed: () => true,
|
||||
canProceed: ( { methods } ) =>
|
||||
methods.areOptionalPaymentMethodsEnabled !== null,
|
||||
},
|
||||
{
|
||||
id: 'complete',
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import SettingsCard from '../../ReusableComponents/SettingsCard';
|
||||
import PaymentMethodsBlock from '../../ReusableComponents/SettingsBlocks/PaymentMethodsBlock';
|
||||
import { PaymentMethodsBlock } from '../../ReusableComponents/SettingsBlocks';
|
||||
import { PaymentHooks } from '../../../data';
|
||||
import { useActiveModal } from '../../../data/common/hooks';
|
||||
import Modal from './TabSettingsElements/Blocks/Modal';
|
||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
||||
|
||||
const TabPaymentMethods = () => {
|
||||
const { paymentMethodsPayPalCheckout } =
|
||||
|
@ -14,6 +15,8 @@ const TabPaymentMethods = () => {
|
|||
const { paymentMethodsAlternative } =
|
||||
PaymentHooks.usePaymentMethodsAlternative();
|
||||
|
||||
const { setPersistent } = usePaymentMethods();
|
||||
|
||||
const { activeModal, setActiveModal } = useActiveModal();
|
||||
|
||||
const getActiveMethod = () => {
|
||||
|
@ -89,11 +92,37 @@ const TabPaymentMethods = () => {
|
|||
method={ getActiveMethod() }
|
||||
setModalIsVisible={ () => setActiveModal( null ) }
|
||||
onSave={ ( methodId, settings ) => {
|
||||
console.log(
|
||||
'Saving settings for:',
|
||||
methodId,
|
||||
settings
|
||||
);
|
||||
setPersistent( methodId, {
|
||||
...getActiveMethod(),
|
||||
title: settings.checkoutPageTitle,
|
||||
description: settings.checkoutPageDescription,
|
||||
} );
|
||||
|
||||
if ( 'paypalShowLogo' in settings ) {
|
||||
setPersistent(
|
||||
'paypalShowLogo',
|
||||
settings.paypalShowLogo
|
||||
);
|
||||
}
|
||||
if ( 'threeDSecure' in settings ) {
|
||||
setPersistent(
|
||||
'threeDSecure',
|
||||
settings.threeDSecure
|
||||
);
|
||||
}
|
||||
if ( 'fastlaneCardholderName' in settings ) {
|
||||
setPersistent(
|
||||
'fastlaneCardholderName',
|
||||
settings.fastlaneCardholderName
|
||||
);
|
||||
}
|
||||
if ( 'fastlaneDisplayWatermark' in settings ) {
|
||||
setPersistent(
|
||||
'fastlaneDisplayWatermark',
|
||||
settings.fastlaneDisplayWatermark
|
||||
);
|
||||
}
|
||||
|
||||
setActiveModal( null );
|
||||
} }
|
||||
/>
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
import ConnectionStatus from './TabSettingsElements/ConnectionStatus';
|
||||
import CommonSettings from './TabSettingsElements/CommonSettings';
|
||||
import ExpertSettings from './TabSettingsElements/ExpertSettings';
|
||||
import { useSettings } from '../../../data/settings-tab/hooks';
|
||||
|
||||
const TabSettings = () => {
|
||||
const { settings, setSettings } = useSettings();
|
||||
|
||||
const updateFormValue = ( key, value ) => {
|
||||
setSettings( {
|
||||
...settings,
|
||||
[ key ]: value,
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="ppcp-r-settings">
|
||||
<ConnectionStatus />
|
||||
<CommonSettings
|
||||
settings={ settings }
|
||||
updateFormValue={ updateFormValue }
|
||||
/>
|
||||
<ExpertSettings
|
||||
settings={ settings }
|
||||
updateFormValue={ updateFormValue }
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabSettings;
|
|
@ -1,14 +1,12 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Button } from '@wordpress/components';
|
||||
|
||||
import {
|
||||
AccordionSettingsBlock,
|
||||
RadioSettingsBlock,
|
||||
InputSettingsBlock,
|
||||
} from '../../../../ReusableComponents/SettingsBlocks';
|
||||
import {
|
||||
sandboxData,
|
||||
productionData,
|
||||
} from '../../../../../data/settings/connection-details-data';
|
||||
ControlTextInput,
|
||||
ControlRadioGroup,
|
||||
} from '../../../../ReusableComponents/Controls';
|
||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
||||
|
||||
const ConnectionDetails = ( { settings, updateFormValue } ) => {
|
||||
const isSandbox = settings.sandboxConnected;
|
||||
|
@ -20,22 +18,192 @@ const ConnectionDetails = ( { settings, updateFormValue } ) => {
|
|||
const modeKey = isSandbox ? 'productionMode' : 'sandboxMode';
|
||||
|
||||
return (
|
||||
<AccordionSettingsBlock
|
||||
<Accordion
|
||||
title={ modeConfig.title }
|
||||
description={ modeConfig.description }
|
||||
>
|
||||
<RadioSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ modeConfig.connectTitle }
|
||||
description={ modeConfig.connectDescription }
|
||||
options={ modeConfig.options }
|
||||
actionProps={ {
|
||||
key: modeKey,
|
||||
currentValue: settings[ modeKey ],
|
||||
callback: updateFormValue,
|
||||
} }
|
||||
/>
|
||||
</AccordionSettingsBlock>
|
||||
>
|
||||
<ControlRadioGroup
|
||||
options={ modeConfig.options }
|
||||
value={ settings[ modeKey ] }
|
||||
onChange={ updateFormValue }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionDetails;
|
||||
|
||||
// Helper logic, refactor this when possible.
|
||||
|
||||
/**
|
||||
* Generates options for the environment mode settings.
|
||||
*
|
||||
* @param {Object} config - Configuration for the mode.
|
||||
* @param {Object} settings - Current settings.
|
||||
* @param {Function} updateFormValue - Callback to update settings.
|
||||
* @return {Array} Options array.
|
||||
*/
|
||||
const generateOptions = ( config, settings, updateFormValue ) => [
|
||||
{
|
||||
id: `${ config.mode }_mode`,
|
||||
value: `${ config.mode }_mode`,
|
||||
label: config.labelTitle,
|
||||
description: config.labelDescription,
|
||||
additionalContent: (
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={ () => {
|
||||
updateFormValue( `${ config.mode }Connected`, true );
|
||||
if ( config.mode === 'production' ) {
|
||||
global.ppcpSettings.startOnboarding();
|
||||
}
|
||||
} }
|
||||
>
|
||||
{ config.buttonText }
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'manual_connect',
|
||||
value: 'manual_connect',
|
||||
label: __( 'Manual Connect', 'woocommerce-paypal-payments' ),
|
||||
description: sprintf(
|
||||
__(
|
||||
'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'
|
||||
),
|
||||
'#'
|
||||
),
|
||||
additionalContent: (
|
||||
<>
|
||||
<ControlTextInput
|
||||
title={ config.clientIdTitle }
|
||||
// Input field props.
|
||||
value={ settings[ `${ config.mode }ClientId` ] }
|
||||
onChange={ updateFormValue }
|
||||
placeholder={ __(
|
||||
'Enter Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
<ControlTextInput
|
||||
title={ config.secretKeyTitle }
|
||||
// Input field props.
|
||||
value={ settings[ `${ config.mode }SecretKey` ] }
|
||||
onChange={ updateFormValue }
|
||||
placeholder={ __(
|
||||
'Enter Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={ () =>
|
||||
updateFormValue(
|
||||
`${ config.mode }ManuallyConnected`,
|
||||
true
|
||||
)
|
||||
}
|
||||
>
|
||||
{ __( 'Connect Account', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* Generates data for a given mode (sandbox or production).
|
||||
*
|
||||
* @param {Object} config - Configuration for the mode.
|
||||
* @param {Object} settings - Current settings.
|
||||
* @param {Function} updateFormValue - Callback to update settings.
|
||||
* @return {Object} Mode configuration.
|
||||
*/
|
||||
const generateModeData = ( config, settings, updateFormValue ) => ( {
|
||||
title: config.title,
|
||||
description: config.description,
|
||||
connectTitle: __(
|
||||
`Connect ${ config.label } Account`, // TODO: Avoid variables inside __() translation literal.
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
connectDescription: config.connectDescription,
|
||||
options: generateOptions( config, settings, updateFormValue ),
|
||||
} );
|
||||
|
||||
const sandboxData = ( { settings = {}, updateFormValue = () => {} } ) =>
|
||||
generateModeData(
|
||||
{
|
||||
mode: 'sandbox',
|
||||
label: 'Sandbox',
|
||||
title: __( 'Sandbox', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
"Test your site in PayPal's Sandbox environment.",
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
connectDescription: __(
|
||||
'Connect a PayPal Sandbox account in order to test your website. Transactions made will not result in actual money movement. Do not fulfil orders completed in Sandbox mode.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
labelTitle: __( 'Sandbox Mode', 'woocommerce-paypal-payments' ),
|
||||
labelDescription: __(
|
||||
'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'
|
||||
),
|
||||
buttonText: __(
|
||||
'Connect Sandbox Account',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
clientIdTitle: __(
|
||||
'Sandbox Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
secretKeyTitle: __(
|
||||
'Sandbox Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
settings,
|
||||
updateFormValue
|
||||
);
|
||||
|
||||
const productionData = ( { settings = {}, updateFormValue = () => {} } ) =>
|
||||
generateModeData(
|
||||
{
|
||||
mode: 'production',
|
||||
label: 'Live',
|
||||
title: __( 'Live Payments', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Your site is currently configured in Sandbox mode to test payments. When you are ready, launch your site and receive live payments via PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
connectDescription: __(
|
||||
'Connect a live PayPal account to launch your site and receive live payments via PayPal. PayPal will guide you through the setup process.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
labelTitle: __( 'Production Mode', 'woocommerce-paypal-payments' ),
|
||||
labelDescription: __(
|
||||
'Activate Production mode to connect your live account and receive live payments via PayPal. Stay connected in Sandbox mode to continue testing payments before going live.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttonText: __(
|
||||
'Set up and connect live PayPal Account',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
clientIdTitle: __(
|
||||
'Live Account Client ID',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
secretKeyTitle: __(
|
||||
'Live Account Secret Key',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
settings,
|
||||
updateFormValue
|
||||
);
|
||||
|
|
|
@ -1,307 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
|
||||
import { CommonHooks } from '../../../../../data';
|
||||
import { payLaterMessagingComponentData } from '../../../../../data/settings/pay-later-messaging-component-data';
|
||||
|
||||
const Features = {
|
||||
getFeatures: ( setActiveModal ) => {
|
||||
const { storeCountry } = CommonHooks.useWooSettings();
|
||||
const features = [
|
||||
{
|
||||
id: 'save_paypal_and_venmo',
|
||||
title: __(
|
||||
'Save PayPal and Venmo',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Securely save PayPal and Venmo payment methods for subscriptions or return buyers.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-paypal-checkout-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'paypal' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||
live: 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'advanced_credit_and_debit_cards',
|
||||
title: __(
|
||||
'Advanced Credit and Debit Cards',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Process major credit and debit cards including Visa, Mastercard, American Express and Discover.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal(
|
||||
'advanced_credit_and_debit_card_payments'
|
||||
);
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp',
|
||||
live: 'https://www.paypal.com/bizsignup/entry?product=ppcp',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'alternative_payment_methods',
|
||||
title: __(
|
||||
'Alternative Payment Methods',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Offer global, country-specific payment options for your customers.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-alternative-payments-card'
|
||||
);
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'google_pay',
|
||||
title: __( 'Google Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Let customers pay using their Google Pay wallet.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'google_pay' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
||||
live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
notes: [
|
||||
__(
|
||||
'¹PayPal Q2 Earnings-2021.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'apple_pay',
|
||||
title: __( 'Apple Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Let customers pay using their Apple Pay wallet.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'apple_pay' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __(
|
||||
'Domain registration',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/uccservicing/apm/applepay',
|
||||
live: 'https://www.paypal.com/uccservicing/apm/applepay',
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
||||
live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const countryData =
|
||||
payLaterMessagingComponentData[ storeCountry ] || {};
|
||||
|
||||
if (
|
||||
!! window.ppcpSettings?.isPayLaterConfiguratorAvailable &&
|
||||
countryData
|
||||
) {
|
||||
features.push( {
|
||||
id: 'pay_later_messaging',
|
||||
title: __(
|
||||
'Pay Later Messaging',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: countryData?.description,
|
||||
notes: countryData?.notes,
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => selectTab( TAB_IDS.PAY_LATER_MESSAGING ),
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => selectTab( TAB_IDS.PAY_LATER_MESSAGING ),
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
} );
|
||||
}
|
||||
|
||||
return features;
|
||||
},
|
||||
};
|
||||
|
||||
export default Features;
|
|
@ -7,23 +7,49 @@ import {
|
|||
} from '@wordpress/components';
|
||||
import { useState } from '@wordpress/element';
|
||||
import PaymentMethodModal from '../../../../ReusableComponents/PaymentMethodModal';
|
||||
import { getPaymentMethods } from './PaymentMethods';
|
||||
import {
|
||||
usePaymentMethods,
|
||||
usePaymentMethodsModal,
|
||||
} from '../../../../../data/payment/hooks';
|
||||
|
||||
const Modal = ( { method, setModalIsVisible, onSave } ) => {
|
||||
const { paymentMethods } = usePaymentMethods();
|
||||
const {
|
||||
paypalShowLogo,
|
||||
threeDSecure,
|
||||
fastlaneCardholderName,
|
||||
fastlaneDisplayWatermark,
|
||||
} = usePaymentMethodsModal();
|
||||
|
||||
const [ settings, setSettings ] = useState( () => {
|
||||
if ( ! method?.id ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const methodConfig = getPaymentMethods( method );
|
||||
const methodConfig = paymentMethods.find( ( i ) => i.id === method.id );
|
||||
if ( ! methodConfig?.fields ) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const initialSettings = {};
|
||||
Object.entries( methodConfig.fields ).forEach( ( [ key, field ] ) => {
|
||||
initialSettings[ key ] = field.default;
|
||||
switch ( key ) {
|
||||
case 'checkoutPageTitle':
|
||||
initialSettings[ key ] = methodConfig.title;
|
||||
break;
|
||||
case 'checkoutPageDescription':
|
||||
initialSettings[ key ] = methodConfig.description;
|
||||
break;
|
||||
default:
|
||||
initialSettings[ key ] = field.default;
|
||||
}
|
||||
} );
|
||||
|
||||
initialSettings.paypalShowLogo = paypalShowLogo;
|
||||
initialSettings.threeDSecure = threeDSecure;
|
||||
initialSettings.fastlaneCardholderName = fastlaneCardholderName;
|
||||
initialSettings.fastlaneDisplayWatermark = fastlaneDisplayWatermark;
|
||||
|
||||
return initialSettings;
|
||||
} );
|
||||
|
||||
|
@ -31,7 +57,7 @@ const Modal = ( { method, setModalIsVisible, onSave } ) => {
|
|||
return null;
|
||||
}
|
||||
|
||||
const methodConfig = getPaymentMethods( method );
|
||||
const methodConfig = paymentMethods.find( ( i ) => i.id === method.id );
|
||||
if ( ! methodConfig?.fields ) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
Header,
|
||||
SettingsBlock,
|
||||
Title,
|
||||
Description,
|
||||
ToggleSettingsBlock,
|
||||
} from '../../../../ReusableComponents/SettingsBlocks';
|
||||
|
||||
const OrderIntent = ( { updateFormValue, settings } ) => {
|
||||
return (
|
||||
<SettingsBlock>
|
||||
<Header>
|
||||
<Title>
|
||||
{ __( 'Order Intent', 'woocommerce-paypal-payments' ) }
|
||||
</Title>
|
||||
<Description>
|
||||
{ __(
|
||||
'Choose between immediate capture or authorization-only, with manual capture in the Order section.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</Description>
|
||||
</Header>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __( 'Authorize Only', 'woocommerce-paypal-payments' ) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'authorizeOnly',
|
||||
value: settings.authorizeOnly,
|
||||
} }
|
||||
/>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __(
|
||||
'Capture Virtual-Only Orders',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'captureVirtualOnlyOrders',
|
||||
value: settings.captureVirtualOnlyOrders,
|
||||
} }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrderIntent;
|
|
@ -1,10 +1,48 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
AccordionSettingsBlock,
|
||||
SelectSettingsBlock,
|
||||
} from '../../../../ReusableComponents/SettingsBlocks';
|
||||
|
||||
const creditCardExamples = [
|
||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
||||
import { ControlSelect } from '../../../../ReusableComponents/Controls';
|
||||
import { SettingsHooks } from '../../../../../data';
|
||||
|
||||
const OtherSettings = () => {
|
||||
const { disabledCards, setDisabledCards } = SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
title={ __(
|
||||
'Other payment method settings',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Modify the checkout experience for alternative payment methods, credit cards, and digital wallets.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<SettingsBlock
|
||||
title={ __(
|
||||
'Disable specific credit cards',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
"If left blank, PayPal and other buttons will present in the user's detected language. Enter a language here to force all buttons to display in that language.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<ControlSelect
|
||||
options={ disabledCardChoices }
|
||||
value={ disabledCards }
|
||||
onChange={ setDisabledCards }
|
||||
isMulti={ true }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
export default OtherSettings;
|
||||
|
||||
const disabledCardChoices = [
|
||||
{ value: '', label: __( 'Select', 'woocommerce-paypal-payments' ) },
|
||||
{
|
||||
value: 'mastercard',
|
||||
|
@ -21,39 +59,3 @@ const creditCardExamples = [
|
|||
label: __( 'Diners Club', 'woocommerce-paypal-payments' ),
|
||||
},
|
||||
];
|
||||
|
||||
const OtherSettings = ( { settings, updateFormValue } ) => {
|
||||
return (
|
||||
<AccordionSettingsBlock
|
||||
title={ __(
|
||||
'Other payment method settings',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Modify the checkout experience for alternative payment methods, credit cards, and digital wallets.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<SelectSettingsBlock
|
||||
title={ __(
|
||||
'Disable specific credit cards',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
"If left blank, PayPal and other buttons will present in the user's detected language. Enter a language here to force all buttons to display in that language.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
options: creditCardExamples,
|
||||
value: settings.buttonLanguage,
|
||||
callback: updateFormValue,
|
||||
key: 'buttonLanguage',
|
||||
isMulti: true,
|
||||
} }
|
||||
order={ [ 'title', 'description', 'action' ] }
|
||||
/>
|
||||
</AccordionSettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default OtherSettings;
|
||||
|
|
|
@ -1,173 +0,0 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
const createStandardFields = ( methodId, defaultTitle ) => ( {
|
||||
checkoutPageTitle: {
|
||||
type: 'text',
|
||||
default: defaultTitle,
|
||||
label: __( 'Checkout page title', 'woocommerce-paypal-payments' ),
|
||||
},
|
||||
checkoutPageDescription: {
|
||||
type: 'text',
|
||||
default: sprintf(
|
||||
/* translators: %s: payment method title */
|
||||
__( 'Pay with %s', 'woocommerce-paypal-payments' ),
|
||||
defaultTitle
|
||||
),
|
||||
label: __( 'Checkout page description', 'woocommerce-paypal-payments' ),
|
||||
},
|
||||
} );
|
||||
|
||||
const paymentMethods = {
|
||||
// PayPal Checkout methods
|
||||
'ppcp-gateway': {
|
||||
fields: {
|
||||
...createStandardFields( 'paypal', 'PayPal' ),
|
||||
showLogo: {
|
||||
type: 'toggle',
|
||||
default: false,
|
||||
label: __( 'Show logo', 'woocommerce-paypal-payments' ),
|
||||
},
|
||||
},
|
||||
},
|
||||
credit_and_debit_card_payments: {
|
||||
fields: createStandardFields(
|
||||
'credit_and_debit_card_payments',
|
||||
__(
|
||||
'Credit and debit card payments',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
),
|
||||
},
|
||||
|
||||
// Online Card Payments
|
||||
advanced_credit_and_debit_card_payments: {
|
||||
fields: {
|
||||
...createStandardFields(
|
||||
'advanced_credit_and_debit_card_payments',
|
||||
__(
|
||||
'Advanced Credit and Debit Card Payments',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
),
|
||||
threeDSecure: {
|
||||
type: 'radio',
|
||||
default: 'no-3d-secure',
|
||||
label: __( '3D Secure', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Authenticate cardholders through their card issuers to reduce fraud and improve transaction security. Successful 3D Secure authentication can shift liability for fraudulent chargebacks to the card issuer.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
options: [
|
||||
{
|
||||
label: __(
|
||||
'No 3D Secure',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
value: 'no-3d-secure',
|
||||
},
|
||||
{
|
||||
label: __(
|
||||
'Only when required',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
value: 'only-required-3d-secure',
|
||||
},
|
||||
{
|
||||
label: __(
|
||||
'Always require 3D Secure',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
value: 'always-3d-secure',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
fastlane: {
|
||||
fields: {
|
||||
...createStandardFields( 'fastlane', 'Fastlane by PayPal' ),
|
||||
cardholderName: {
|
||||
type: 'toggle',
|
||||
default: false,
|
||||
label: __(
|
||||
'Display cardholder name',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
displayWatermark: {
|
||||
type: 'toggle',
|
||||
default: false,
|
||||
label: __(
|
||||
'Display Fastlane Watermark',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Digital Wallets
|
||||
apple_pay: {
|
||||
fields: createStandardFields( 'apple_pay', 'Apple Pay' ),
|
||||
},
|
||||
google_pay: {
|
||||
fields: createStandardFields( 'google_pay', 'Google Pay' ),
|
||||
},
|
||||
|
||||
// Alternative Payment Methods
|
||||
bancontact: {
|
||||
fields: createStandardFields( 'bancontact', 'Bancontact' ),
|
||||
},
|
||||
ideal: {
|
||||
fields: createStandardFields( 'ideal', 'iDEAL' ),
|
||||
},
|
||||
eps: {
|
||||
fields: createStandardFields( 'eps', 'eps' ),
|
||||
},
|
||||
blik: {
|
||||
fields: createStandardFields( 'blik', 'BLIK' ),
|
||||
},
|
||||
mybank: {
|
||||
fields: createStandardFields( 'mybank', 'MyBank' ),
|
||||
},
|
||||
przelewy24: {
|
||||
fields: createStandardFields( 'przelewy24', 'Przelewy24' ),
|
||||
},
|
||||
trustly: {
|
||||
fields: createStandardFields( 'trustly', 'Trustly' ),
|
||||
},
|
||||
multibanco: {
|
||||
fields: createStandardFields( 'multibanco', 'Multibanco' ),
|
||||
},
|
||||
pui: {
|
||||
fields: createStandardFields( 'pui', 'Pay upon Invoice' ),
|
||||
},
|
||||
oxxo: {
|
||||
fields: createStandardFields( 'oxxo', 'OXXO' ),
|
||||
},
|
||||
};
|
||||
|
||||
// Function to get configuration for a payment method
|
||||
export const getPaymentMethods = ( method ) => {
|
||||
if ( ! method?.id ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If method has specific config, return it
|
||||
if ( paymentMethods[ method.id ] ) {
|
||||
return {
|
||||
...paymentMethods[ method.id ],
|
||||
icon: method.icon,
|
||||
};
|
||||
}
|
||||
|
||||
// Return standard config for new payment methods
|
||||
return {
|
||||
fields: createStandardFields( method.id, method.title ),
|
||||
icon: method.icon,
|
||||
};
|
||||
};
|
||||
|
||||
// Function to check if a method has settings defined
|
||||
export const hasSettings = ( methodId ) => {
|
||||
return Boolean( methodId && paymentMethods[ methodId ] );
|
||||
};
|
|
@ -1,28 +1,41 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
AccordionSettingsBlock,
|
||||
RadioSettingsBlock,
|
||||
ToggleSettingsBlock,
|
||||
InputSettingsBlock,
|
||||
SelectSettingsBlock,
|
||||
} from '../../../../ReusableComponents/SettingsBlocks';
|
||||
|
||||
const PaypalSettings = ( { updateFormValue, settings } ) => {
|
||||
import {
|
||||
ControlRadioGroup,
|
||||
ControlToggleButton,
|
||||
ControlTextInput,
|
||||
ControlSelect,
|
||||
} from '../../../../ReusableComponents/Controls';
|
||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
||||
import Accordion from '../../../../ReusableComponents/AccordionSection';
|
||||
import { SettingsHooks } from '../../../../../data';
|
||||
|
||||
const PaypalSettings = () => {
|
||||
const {
|
||||
savePaypalAndVenmo,
|
||||
setSavePaypalAndVenmo,
|
||||
subtotalAdjustment,
|
||||
setSubtotalAdjustment,
|
||||
brandName,
|
||||
setBrandName,
|
||||
softDescriptor,
|
||||
setSoftDescriptor,
|
||||
landingPage,
|
||||
setLandingPage,
|
||||
buttonLanguage,
|
||||
setButtonLanguage,
|
||||
} = SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<AccordionSettingsBlock
|
||||
className="ppcp-r-settings-block--settings"
|
||||
<Accordion
|
||||
className="ppcp--paypal-settings"
|
||||
title={ __( 'PayPal Settings', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Modify the PayPal checkout experience.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'payNowExperience',
|
||||
value: settings.payNowExperience,
|
||||
} }
|
||||
>
|
||||
<RadioSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __(
|
||||
'Subtotal mismatch fallback',
|
||||
'woocommerce-paypal-payments'
|
||||
|
@ -31,93 +44,64 @@ const PaypalSettings = ( { updateFormValue, settings } ) => {
|
|||
'Due to differences in how WooCommerce and PayPal calculates taxes, some transactions may fail due to a rounding error. This settings determines the fallback behavior.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
options={ [
|
||||
{
|
||||
id: 'add_a_correction',
|
||||
value: 'add_a_correction',
|
||||
label: __(
|
||||
'Add a correction',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Adds an additional line item with the missing amount.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'do_not_send_line_items',
|
||||
value: 'do_not_send_line_items',
|
||||
label: __(
|
||||
'Do not send line items',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Resubmit the transaction without line item details.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
] }
|
||||
actionProps={ {
|
||||
name: 'paypal_settings_mismatch',
|
||||
key: 'subtotalMismatchFallback',
|
||||
currentValue: settings.subtotalMismatchFallback,
|
||||
callback: updateFormValue,
|
||||
} }
|
||||
/>
|
||||
>
|
||||
<ControlRadioGroup
|
||||
options={ subtotalAdjustmentChoices }
|
||||
value={ subtotalAdjustment }
|
||||
onChange={ setSubtotalAdjustment }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __(
|
||||
'Instant payments only',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'If enabled, PayPal will not allow buyers to use funding sources that take additional time to complete, such as eChecks.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
value: settings.savePaypalAndVenmo,
|
||||
callback: updateFormValue,
|
||||
key: 'savePaypalAndVenmo',
|
||||
} }
|
||||
/>
|
||||
<SettingsBlock>
|
||||
<ControlToggleButton
|
||||
label={ __(
|
||||
'Instant payments only',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'If enabled, PayPal will not allow buyers to use funding sources that take additional time to complete, such as eChecks.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
value={ savePaypalAndVenmo }
|
||||
onChange={ setSavePaypalAndVenmo }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<InputSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __( 'Brand name', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'What business name to show to your buyers during checkout and on receipts.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
value: settings.brandName,
|
||||
callback: updateFormValue,
|
||||
key: 'brandName',
|
||||
placeholder: __(
|
||||
>
|
||||
<ControlTextInput
|
||||
value={ brandName }
|
||||
onChange={ setBrandName }
|
||||
placeholder={ __(
|
||||
'Brand name',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
} }
|
||||
order={ [ 'title', 'description', 'action' ] }
|
||||
/>
|
||||
) }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<InputSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __( 'Soft Descriptor', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
"The dynamic text used to construct the statement descriptor that appears on a payer's card statement. Applies to PayPal and Credit Card transactions. Max value of 22 characters.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
value: settings.softDescriptor,
|
||||
callback: updateFormValue,
|
||||
key: 'softDescriptor',
|
||||
placeholder: __(
|
||||
>
|
||||
<ControlTextInput
|
||||
value={ softDescriptor }
|
||||
onChange={ setSoftDescriptor }
|
||||
placeholder={ __(
|
||||
'Soft Descriptor',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
} }
|
||||
order={ [ 'title', 'description', 'action' ] }
|
||||
/>
|
||||
) }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<RadioSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __(
|
||||
'PayPal landing page',
|
||||
'woocommerce-paypal-payments'
|
||||
|
@ -126,71 +110,32 @@ const PaypalSettings = ( { updateFormValue, settings } ) => {
|
|||
'Determine which experience a buyer sees when they click the PayPal button.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
options={ [
|
||||
{
|
||||
id: 'no_preference',
|
||||
value: 'no_reference',
|
||||
label: __(
|
||||
'No preference',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Shows the buyer the PayPal login for a recognized PayPal buyer.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'login_page',
|
||||
value: 'login_page',
|
||||
label: __(
|
||||
'Login page',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Always show the buyer the PayPal login screen.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'guest_checkout_page',
|
||||
value: 'guest_checkout_page',
|
||||
label: __(
|
||||
'Guest checkout page',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Always show the buyer the guest checkout fields first.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
] }
|
||||
actionProps={ {
|
||||
name: 'paypal_settings_landing',
|
||||
key: 'paypalLandingPage',
|
||||
currentValue: settings.paypalLandingPage,
|
||||
callback: updateFormValue,
|
||||
} }
|
||||
/>
|
||||
>
|
||||
<ControlRadioGroup
|
||||
options={ landingPageChoices }
|
||||
value={ landingPage }
|
||||
onChange={ setLandingPage }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<SelectSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __( 'Button Language', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
"If left blank, PayPal and other buttons will present in the user's detected language. Enter a language here to force all buttons to display in that language.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
value: settings.buttonLanguage,
|
||||
callback: updateFormValue,
|
||||
options: languagesExample,
|
||||
key: 'buttonLanguage',
|
||||
placeholder: __(
|
||||
>
|
||||
<ControlSelect
|
||||
options={ languagesExample }
|
||||
value={ buttonLanguage }
|
||||
onChange={ setButtonLanguage }
|
||||
placeholder={ __(
|
||||
'Browser language',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
} }
|
||||
order={ [ 'title', 'description', 'action' ] }
|
||||
/>
|
||||
</AccordionSettingsBlock>
|
||||
) }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -201,4 +146,50 @@ const languagesExample = [
|
|||
{ value: 'it', label: 'Italian' },
|
||||
];
|
||||
|
||||
const subtotalAdjustmentChoices = [
|
||||
{
|
||||
value: 'correction',
|
||||
label: __( 'Add a correction', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Adds an additional line item with the missing amount.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'no_details',
|
||||
label: __( 'Do not send line items', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Resubmit the transaction without line item details.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const landingPageChoices = [
|
||||
{
|
||||
value: 'any',
|
||||
label: __( 'No preference', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Shows the buyer the PayPal login for a recognized PayPal buyer.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'login',
|
||||
label: __( 'Login page', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Always show the buyer the PayPal login screen.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'guest_checkout',
|
||||
label: __( 'Guest checkout page', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Always show the buyer the guest checkout fields first.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
export default PaypalSettings;
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import {
|
||||
Header,
|
||||
SettingsBlock,
|
||||
ToggleSettingsBlock,
|
||||
Title,
|
||||
Description,
|
||||
} from '../../../../ReusableComponents/SettingsBlocks';
|
||||
|
||||
const SavePaymentMethods = ( { updateFormValue, settings } ) => {
|
||||
return (
|
||||
<SettingsBlock className="ppcp-r-settings-block--save-payment-methods">
|
||||
<Header>
|
||||
<Title>
|
||||
{ __(
|
||||
'Save payment methods',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</Title>
|
||||
<Description>
|
||||
{ __(
|
||||
"Securely store customers' payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</Description>
|
||||
</Header>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __(
|
||||
'Save PayPal and Venmo',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={
|
||||
<div
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: sprintf(
|
||||
/* translators: 1: URL to Pay Later documentation, 2: URL to Alternative Payment Methods documentation */
|
||||
__(
|
||||
'Securely store your customers\' PayPal accounts for a seamless checkout experience. <br />This will disable all <a target="_blank" rel="noreferrer" href="%1$s">Pay Later</a> features and <a target="_blank" rel="noreferrer" href="%2$s">Alternative Payment Methods</a> on your site.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#pay-later',
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#alternative-payment-methods'
|
||||
),
|
||||
} }
|
||||
/>
|
||||
}
|
||||
actionProps={ {
|
||||
value: settings.savePaypalAndVenmo,
|
||||
callback: updateFormValue,
|
||||
key: 'savePaypalAndVenmo',
|
||||
} }
|
||||
/>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __(
|
||||
'Save Credit and Debit Cards',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
"Securely store your customer's credit card.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'saveCreditCardAndDebitCard',
|
||||
value: settings.saveCreditCardAndDebitCard,
|
||||
} }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default SavePaymentMethods;
|
|
@ -1,9 +1,8 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { CommonHooks } from '../../../../../../data';
|
||||
import {
|
||||
SettingsBlock,
|
||||
Title,
|
||||
} from '../../../../../ReusableComponents/SettingsBlocks';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
import { Title } from '../../../../../ReusableComponents/Elements';
|
||||
|
||||
const HooksTableBlock = () => {
|
||||
const { webhooks } = CommonHooks.useWebhooks();
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import { useState } from '@wordpress/element';
|
||||
import { STORE_NAME } from '../../../../../../data/common';
|
||||
import { ButtonSettingsBlock } from '../../../../../ReusableComponents/SettingsBlocks';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { useState } from '@wordpress/element';
|
||||
import { store as noticesStore } from '@wordpress/notices';
|
||||
|
||||
import { STORE_NAME } from '../../../../../../data/common';
|
||||
import { ControlButton } from '../../../../../ReusableComponents/Controls';
|
||||
import {
|
||||
NOTIFICATION_ERROR,
|
||||
NOTIFICATION_SUCCESS,
|
||||
} from '../../../../../ReusableComponents/Icons';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
|
||||
const ResubscribeBlock = () => {
|
||||
const { createSuccessNotice, createErrorNotice } =
|
||||
|
@ -47,7 +49,7 @@ const ResubscribeBlock = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<ButtonSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __(
|
||||
'Resubscribe webhooks',
|
||||
'woocommerce-paypal-payments'
|
||||
|
@ -56,17 +58,18 @@ const ResubscribeBlock = () => {
|
|||
'Click to remove the current webhook subscription and subscribe again, for example, if the website domain or URL structure changed.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
separatorAndGap={ false }
|
||||
actionProps={ {
|
||||
buttonType: 'secondary',
|
||||
isBusy: resubscribing,
|
||||
callback: () => startResubscribingWebhooks(),
|
||||
value: __(
|
||||
horizontalLayout={ true }
|
||||
>
|
||||
<ControlButton
|
||||
type={ 'secondary' }
|
||||
isBusy={ resubscribing }
|
||||
onClick={ () => startResubscribingWebhooks() }
|
||||
buttonLabel={ __(
|
||||
'Resubscribe webhooks',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import { useState } from '@wordpress/element';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { ButtonSettingsBlock } from '../../../../../ReusableComponents/SettingsBlocks';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { store as noticesStore } from '@wordpress/notices';
|
||||
|
||||
import { ControlButton } from '../../../../../ReusableComponents/Controls';
|
||||
import { CommonHooks } from '../../../../../../data';
|
||||
import {
|
||||
NOTIFICATION_ERROR,
|
||||
NOTIFICATION_SUCCESS,
|
||||
} from '../../../../../ReusableComponents/Icons';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
|
||||
const SimulationBlock = () => {
|
||||
const {
|
||||
|
@ -107,20 +109,24 @@ const SimulationBlock = () => {
|
|||
};
|
||||
|
||||
return (
|
||||
<ButtonSettingsBlock
|
||||
<SettingsBlock
|
||||
title={ __( 'Test webhooks', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Send a test-webhook from PayPal to confirm that webhooks are being received and processed correctly.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
separatorAndGap={ false }
|
||||
actionProps={ {
|
||||
buttonType: 'secondary',
|
||||
isBusy: simulating,
|
||||
callback: () => startSimulation( 30 ),
|
||||
value: __( 'Simulate webhooks', 'woocommerce-paypal-payments' ),
|
||||
} }
|
||||
/>
|
||||
horizontalLayout={ true }
|
||||
>
|
||||
<ControlButton
|
||||
type={ 'secondary' }
|
||||
isBusy={ simulating }
|
||||
onClick={ () => startSimulation( 30 ) }
|
||||
buttonLabel={ __(
|
||||
'Simulate webhooks',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
export default SimulationBlock;
|
||||
|
|
|
@ -1,68 +1,53 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
AccordionSettingsBlock,
|
||||
Description,
|
||||
Header,
|
||||
Title,
|
||||
ToggleSettingsBlock,
|
||||
} from '../../../../../ReusableComponents/SettingsBlocks';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlocks/SettingsBlock';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
import { ControlToggleButton } from '../../../../../ReusableComponents/Controls';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
import Accordion from '../../../../../ReusableComponents/AccordionSection';
|
||||
|
||||
import SimulationBlock from './SimulationBlock';
|
||||
import ResubscribeBlock from './ResubscribeBlock';
|
||||
import HooksTableBlock from './HooksTableBlock';
|
||||
import { SettingsHooks } from '../../../../../../data';
|
||||
|
||||
const Troubleshooting = () => {
|
||||
const { logging, setLogging } = SettingsHooks.useSettings();
|
||||
|
||||
const Troubleshooting = ( { updateFormValue, settings } ) => {
|
||||
return (
|
||||
<AccordionSettingsBlock
|
||||
className="ppcp-r-settings-block--troubleshooting"
|
||||
<Accordion
|
||||
className="ppcp--troubleshooting"
|
||||
title={ __( 'Troubleshooting', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Access tools to help debug and resolve issues.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'payNowExperience',
|
||||
value: settings.payNowExperience,
|
||||
} }
|
||||
>
|
||||
<ToggleSettingsBlock
|
||||
title={ __( 'Logging', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Log additional debugging information in the WooCommerce logs that can assist technical staff to determine issues.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'logging',
|
||||
value: settings.logging,
|
||||
} }
|
||||
/>
|
||||
<SettingsBlock>
|
||||
<Header>
|
||||
<Title>
|
||||
{ __( 'Webhooks', 'woocommerce-paypal-payments' ) }
|
||||
</Title>
|
||||
<Description>
|
||||
{ __(
|
||||
'The following PayPal webhooks are subscribed. More information about the webhooks is available in the',
|
||||
'woocommerce-paypal-payments'
|
||||
) }{ ' ' }
|
||||
<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#webhook-status">
|
||||
{ __(
|
||||
'Webhook Status documentation',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
</a>
|
||||
.
|
||||
</Description>
|
||||
</Header>
|
||||
<ControlToggleButton
|
||||
label={ __( 'Logging', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Log additional debugging information in the WooCommerce logs that can assist technical staff to determine issues.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
value={ logging }
|
||||
onChange={ setLogging }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
|
||||
<SettingsBlock
|
||||
title={ __( 'Webhooks', 'woocommerce-paypal-payments' ) }
|
||||
description={ sprintf(
|
||||
__(
|
||||
'The following PayPal webhooks are subscribed. More information about the webhooks is available in the <a href="%s">Webhook Status documentation</a>.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#webhook-status'
|
||||
) }
|
||||
>
|
||||
<HooksTableBlock />
|
||||
<ResubscribeBlock />
|
||||
<SimulationBlock />
|
||||
</SettingsBlock>
|
||||
</AccordionSettingsBlock>
|
||||
</Accordion>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import {
|
||||
InputSettingsBlock,
|
||||
ToggleSettingsBlock,
|
||||
} from '../../../ReusableComponents/SettingsBlocks';
|
||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||
import OrderIntent from './Blocks/OrderIntent';
|
||||
import SavePaymentMethods from './Blocks/SavePaymentMethods';
|
||||
|
||||
const CommonSettings = ( { updateFormValue, settings } ) => {
|
||||
return (
|
||||
<SettingsCard
|
||||
icon="icon-settings-common.svg"
|
||||
title={ __( 'Common settings', 'woocommerce-paypal-payments' ) }
|
||||
className="ppcp-r-settings-card ppcp-r-settings-card--common-settings"
|
||||
description={ __(
|
||||
'Customize key features to tailor your PayPal experience.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<InputSettingsBlock
|
||||
title="Invoice Prefix"
|
||||
supplementaryLabel={ __(
|
||||
'(Recommended)',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description="Add a unique prefix to invoice numbers for site-specific tracking (recommended)."
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'invoicePrefix',
|
||||
value: settings.invoicePrefix,
|
||||
placeholder: __(
|
||||
'Input prefix',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
} }
|
||||
/>
|
||||
|
||||
<OrderIntent
|
||||
settings={ settings }
|
||||
updateFormValue={ updateFormValue }
|
||||
/>
|
||||
|
||||
<SavePaymentMethods
|
||||
updateFormValue={ updateFormValue }
|
||||
settings={ settings }
|
||||
/>
|
||||
|
||||
<ToggleSettingsBlock
|
||||
title={ __(
|
||||
'Pay Now Experience',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Let PayPal customers skip the Order Review page by selecting shipping options directly within PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
actionProps={ {
|
||||
callback: updateFormValue,
|
||||
key: 'payNowExperience',
|
||||
value: settings.payNowExperience,
|
||||
} }
|
||||
/>
|
||||
</SettingsCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default CommonSettings;
|
|
@ -1,49 +0,0 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||
import { CommonHooks } from '../../../../data';
|
||||
import TitleBadge, {
|
||||
TITLE_BADGE_NEGATIVE,
|
||||
TITLE_BADGE_POSITIVE,
|
||||
} from '../../../ReusableComponents/TitleBadge';
|
||||
import ConnectionInfo from '../../../ReusableComponents/ConnectionInfo';
|
||||
const ConnectionStatus = () => {
|
||||
const { merchant } = CommonHooks.useMerchantInfo();
|
||||
return (
|
||||
<SettingsCard
|
||||
className="ppcp-r-tab-overview-support"
|
||||
title={ __( 'Connection status', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Your PayPal account connection details',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<div className="ppcp-r-connection-status">
|
||||
<div className="ppcp-r-connection-status__status">
|
||||
<div className="ppcp-r-connection-status__status-status">
|
||||
{ merchant.isConnected ? (
|
||||
<TitleBadge
|
||||
type={ TITLE_BADGE_POSITIVE }
|
||||
text={ __(
|
||||
'Active',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
) : (
|
||||
<TitleBadge
|
||||
type={ TITLE_BADGE_NEGATIVE }
|
||||
text={ __(
|
||||
'Not Activated',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
{ merchant.isConnected && (
|
||||
<ConnectionInfo connectionStatusDataDefault={ merchant } />
|
||||
) }
|
||||
</div>
|
||||
</SettingsCard>
|
||||
);
|
||||
};
|
||||
export default ConnectionStatus;
|
|
@ -1,31 +1,19 @@
|
|||
import { Button } from '@wordpress/components';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { CommonHooks, StylingHooks } from '../../../../data';
|
||||
import TopNavigation from '../../../ReusableComponents/TopNavigation';
|
||||
import BusyStateWrapper from '../../../ReusableComponents/BusyStateWrapper';
|
||||
import { useSaveSettings } from '../../../../hooks/useSaveSettings';
|
||||
|
||||
const SettingsNavigation = () => {
|
||||
const { withActivity } = CommonHooks.useBusyState();
|
||||
|
||||
// Todo: Implement other stores here.
|
||||
const { persist: persistStyling } = StylingHooks.useStore();
|
||||
|
||||
const handleSaveClick = () => {
|
||||
// Todo: Add other stores here.
|
||||
withActivity(
|
||||
'persist-styling',
|
||||
'Save styling details',
|
||||
persistStyling
|
||||
);
|
||||
};
|
||||
const { persistAll } = useSaveSettings();
|
||||
|
||||
const title = __( 'PayPal Payments', 'woocommerce-paypal-payments' );
|
||||
|
||||
return (
|
||||
<TopNavigation title={ title } exitOnTitleClick={ true }>
|
||||
<BusyStateWrapper>
|
||||
<Button variant="primary" onClick={ handleSaveClick }>
|
||||
<Button variant="primary" onClick={ persistAll }>
|
||||
{ __( 'Save', 'woocommerce-paypal-payments' ) }
|
||||
</Button>
|
||||
</BusyStateWrapper>
|
||||
|
|
|
@ -0,0 +1,276 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
|
||||
|
||||
const Features = {
|
||||
getFeatures: ( setActiveModal ) => [
|
||||
{
|
||||
id: 'save_paypal_and_venmo',
|
||||
title: __( 'Save PayPal and Venmo', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Securely save PayPal and Venmo payment methods for subscriptions or return buyers.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-paypal-checkout-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'paypal' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||
live: 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/studio/checkout/standard',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'advanced_credit_and_debit_cards',
|
||||
title: __(
|
||||
'Advanced Credit and Debit Cards',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Process major credit and debit cards including Visa, Mastercard, American Express and Discover.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal(
|
||||
'advanced_credit_and_debit_card_payments'
|
||||
);
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp',
|
||||
live: 'https://www.paypal.com/bizsignup/entry?product=ppcp',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/studio/checkout/advanced',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'alternative_payment_methods',
|
||||
title: __(
|
||||
'Alternative Payment Methods',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Offer global, country-specific payment options for your customers.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-alternative-payments-card'
|
||||
);
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/docs/checkout/apm/',
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/docs/checkout/apm/',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'google_pay',
|
||||
title: __( 'Google Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Let customers pay using their Google Pay wallet.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'google_pay' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
||||
live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/docs/checkout/apm/google-pay/',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
notes: [
|
||||
__(
|
||||
'¹PayPal Q2 Earnings-2021.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'apple_pay',
|
||||
title: __( 'Apple Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Let customers pay using their Apple Pay wallet.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-card-payments-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'apple_pay' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __(
|
||||
'Domain registration',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/uccservicing/apm/applepay',
|
||||
live: 'https://www.paypal.com/uccservicing/apm/applepay',
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox:
|
||||
'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
||||
live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/docs/checkout/apm/apple-pay/',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'pay_later_messaging',
|
||||
title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Let customers know they can buy now and pay later with PayPal. Adding this messaging can boost conversion rates and increase cart sizes by 39%¹, with no extra cost to you—plus, you get paid up front.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
buttons: [
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||
onClick: () => {
|
||||
selectTab(
|
||||
TAB_IDS.PAYMENT_METHODS,
|
||||
'ppcp-paypal-checkout-card'
|
||||
).then( () => {
|
||||
setActiveModal( 'paypal' );
|
||||
} );
|
||||
},
|
||||
showWhen: 'enabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'secondary',
|
||||
text: __( 'Apply', 'woocommerce-paypal-payments' ),
|
||||
urls: {
|
||||
sandbox: '#',
|
||||
live: '#',
|
||||
},
|
||||
showWhen: 'disabled',
|
||||
class: 'small-button',
|
||||
},
|
||||
{
|
||||
type: 'tertiary',
|
||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||
url: 'https://developer.paypal.com/studio/checkout/pay-later/us',
|
||||
class: 'small-button',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default Features;
|
|
@ -0,0 +1,29 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { ControlTextInput } from '../../../../../ReusableComponents/Controls';
|
||||
import { SettingsHooks } from '../../../../../../data';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
|
||||
const InvoicePrefix = () => {
|
||||
const { invoicePrefix, setInvoicePrefix } = SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<SettingsBlock
|
||||
title="Invoice Prefix"
|
||||
titleSuffix={ __( '(Recommended)', 'woocommerce-paypal-payments' ) }
|
||||
className="ppcp--invoice-prefix"
|
||||
>
|
||||
<ControlTextInput
|
||||
placeholder={ __(
|
||||
'Input prefix',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
onChange={ setInvoicePrefix }
|
||||
value={ invoicePrefix }
|
||||
description="Add a unique prefix to invoice numbers for site-specific tracking (recommended)."
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default InvoicePrefix;
|
|
@ -0,0 +1,42 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { ControlToggleButton } from '../../../../../ReusableComponents/Controls';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
import { SettingsHooks } from '../../../../../../data';
|
||||
|
||||
const OrderIntent = () => {
|
||||
const {
|
||||
authorizeOnly,
|
||||
setAuthorizeOnly,
|
||||
captureVirtualOnlyOrders,
|
||||
setCaptureVirtualOnlyOrders,
|
||||
} = SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<SettingsBlock
|
||||
title={ __( 'Order Intent', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Choose between immediate capture or authorization-only, with manual capture in the Order section.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
className="ppcp--order-intent"
|
||||
>
|
||||
<ControlToggleButton
|
||||
label={ __( 'Authorize Only', 'woocommerce-paypal-payments' ) }
|
||||
onChange={ setAuthorizeOnly }
|
||||
value={ authorizeOnly }
|
||||
/>
|
||||
|
||||
<ControlToggleButton
|
||||
label={ __(
|
||||
'Capture Virtual-Only Orders',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
onChange={ setCaptureVirtualOnlyOrders }
|
||||
value={ captureVirtualOnlyOrders }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default OrderIntent;
|
|
@ -0,0 +1,29 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import { ControlToggleButton } from '../../../../../ReusableComponents/Controls';
|
||||
import { SettingsHooks } from '../../../../../../data';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
|
||||
const PayNowExperience = () => {
|
||||
const { payNowExperience, setPayNowExperience } =
|
||||
SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<SettingsBlock className="ppcp--pay-now-experience">
|
||||
<ControlToggleButton
|
||||
label={ __(
|
||||
'Pay Now Experience',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
'Let PayPal customers skip the Order Review page by selecting shipping options directly within PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
onChange={ setPayNowExperience }
|
||||
value={ payNowExperience }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default PayNowExperience;
|
|
@ -0,0 +1,61 @@
|
|||
import { __, sprintf } from '@wordpress/i18n';
|
||||
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
import { ControlToggleButton } from '../../../../../ReusableComponents/Controls';
|
||||
import { SettingsHooks } from '../../../../../../data';
|
||||
|
||||
const SavePaymentMethods = () => {
|
||||
const {
|
||||
savePaypalAndVenmo,
|
||||
setSavePaypalAndVenmo,
|
||||
saveCardDetails,
|
||||
setSaveCardDetails,
|
||||
} = SettingsHooks.useSettings();
|
||||
|
||||
return (
|
||||
<SettingsBlock
|
||||
title={ __(
|
||||
'Save payment methods',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
"Securely store customers' payment methods for future payments and subscriptions, simplifying checkout and enabling recurring transactions.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
className="ppcp--save-payment-methods"
|
||||
>
|
||||
<ControlToggleButton
|
||||
label={ __(
|
||||
'Save PayPal and Venmo',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ sprintf(
|
||||
/* translators: 1: URL to Pay Later documentation, 2: URL to Alternative Payment Methods documentation */
|
||||
__(
|
||||
'Securely store your customers\' PayPal accounts for a seamless checkout experience. <br />This will disable all <a target="_blank" rel="noreferrer" href="%1$s">Pay Later</a> features and <a target="_blank" rel="noreferrer" href="%2$s">Alternative Payment Methods</a> on your site.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#pay-later',
|
||||
'https://woocommerce.com/document/woocommerce-paypal-payments/#alternative-payment-methods'
|
||||
) }
|
||||
value={ savePaypalAndVenmo }
|
||||
onChange={ setSavePaypalAndVenmo }
|
||||
/>
|
||||
|
||||
<ControlToggleButton
|
||||
label={ __(
|
||||
'Save Credit and Debit Cards',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
description={ __(
|
||||
"Securely store your customer's credit card.",
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
onChange={ setSaveCardDetails }
|
||||
value={ saveCardDetails }
|
||||
/>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
||||
export default SavePaymentMethods;
|
|
@ -0,0 +1,26 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import SettingsCard from '../../../../ReusableComponents/SettingsCard';
|
||||
import OrderIntent from './Blocks/OrderIntent';
|
||||
import SavePaymentMethods from './Blocks/SavePaymentMethods';
|
||||
import InvoicePrefix from './Blocks/InvoicePrefix';
|
||||
import PayNowExperience from './Blocks/PayNowExperience';
|
||||
|
||||
const CommonSettings = () => (
|
||||
<SettingsCard
|
||||
icon="icon-settings-common.svg"
|
||||
title={ __( 'Common settings', 'woocommerce-paypal-payments' ) }
|
||||
className="ppcp-r-settings-card ppcp-r-settings-card--common-settings"
|
||||
description={ __(
|
||||
'Customize key features to tailor your PayPal experience.',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<InvoicePrefix />
|
||||
<OrderIntent />
|
||||
<SavePaymentMethods />
|
||||
<PayNowExperience />
|
||||
</SettingsCard>
|
||||
);
|
||||
|
||||
export default CommonSettings;
|
|
@ -0,0 +1,50 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import SettingsCard from '../../../../ReusableComponents/SettingsCard';
|
||||
import { CommonHooks } from '../../../../../data';
|
||||
import ConnectionStatusBadge from './Parts/ConnectionStatusBadge';
|
||||
import SettingsBlock from '../../../../ReusableComponents/SettingsBlock';
|
||||
import { ControlStaticValue } from '../../../../ReusableComponents/Controls';
|
||||
|
||||
const ConnectionStatus = () => {
|
||||
const { merchant } = CommonHooks.useMerchantInfo();
|
||||
|
||||
return (
|
||||
<SettingsCard
|
||||
className="ppcp-connection-details ppcp--value-list"
|
||||
title={ __( 'Connection status', 'woocommerce-paypal-payments' ) }
|
||||
description={ __(
|
||||
'Your PayPal account connection details',
|
||||
'woocommerce-paypal-payments'
|
||||
) }
|
||||
>
|
||||
<SettingsBlock>
|
||||
<ControlStaticValue
|
||||
value={
|
||||
<ConnectionStatusBadge
|
||||
isActive={ merchant.isConnected }
|
||||
isSandbox={ merchant.isSandbox }
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</SettingsBlock>
|
||||
<SettingsBlock
|
||||
title={ __( 'Merchant ID', 'woocommerce-paypal-payments' ) }
|
||||
>
|
||||
<ControlStaticValue value={ merchant.id } />
|
||||
</SettingsBlock>
|
||||
<SettingsBlock
|
||||
title={ __( 'Email address', 'woocommerce-paypal-payments' ) }
|
||||
>
|
||||
<ControlStaticValue value={ merchant.email } />
|
||||
</SettingsBlock>
|
||||
<SettingsBlock
|
||||
title={ __( 'Client ID', 'woocommerce-paypal-payments' ) }
|
||||
>
|
||||
<ControlStaticValue value={ merchant.clientId } />
|
||||
</SettingsBlock>
|
||||
</SettingsCard>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionStatus;
|
|
@ -1,15 +1,18 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||
import SettingsCard from '../../../../ReusableComponents/SettingsCard';
|
||||
import {
|
||||
Content,
|
||||
ContentWrapper,
|
||||
} from '../../../ReusableComponents/SettingsBlocks';
|
||||
import ConnectionDetails from './Blocks/ConnectionDetails';
|
||||
import Troubleshooting from './Blocks/Troubleshooting/Troubleshooting';
|
||||
import PaypalSettings from './Blocks/PaypalSettings';
|
||||
import OtherSettings from './Blocks/OtherSettings';
|
||||
} from '../../../../ReusableComponents/Elements';
|
||||
import ConnectionDetails from '../../../Overview/TabSettingsElements/Blocks/ConnectionDetails';
|
||||
import Troubleshooting from '../../../Overview/TabSettingsElements/Blocks/Troubleshooting/Troubleshooting';
|
||||
import PaypalSettings from '../../../Overview/TabSettingsElements/Blocks/PaypalSettings';
|
||||
import OtherSettings from '../../../Overview/TabSettingsElements/Blocks/OtherSettings';
|
||||
|
||||
const ExpertSettings = () => {
|
||||
const settings = {}; // dummy object
|
||||
const updateFormValue = () => {}; // dummy function
|
||||
|
||||
const ExpertSettings = ( { updateFormValue, settings } ) => {
|
||||
return (
|
||||
<SettingsCard
|
||||
icon="icon-settings-expert.svg"
|
|
@ -0,0 +1,25 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import TitleBadge, {
|
||||
TITLE_BADGE_NEGATIVE,
|
||||
TITLE_BADGE_POSITIVE,
|
||||
} from '../../../../../ReusableComponents/TitleBadge';
|
||||
|
||||
const ConnectionStatusBadge = ( { isActive, isSandbox } ) => {
|
||||
if ( isActive ) {
|
||||
const label = isSandbox
|
||||
? __( 'Sandbox Mode', 'woocommerce-paypal-payments' )
|
||||
: __( 'Active', 'woocommerce-paypal-payments' );
|
||||
|
||||
return <TitleBadge type={ TITLE_BADGE_POSITIVE } text={ label } />;
|
||||
}
|
||||
|
||||
return (
|
||||
<TitleBadge
|
||||
type={ TITLE_BADGE_NEGATIVE }
|
||||
text={ __( 'Not Connected', 'woocommerce-paypal-payments' ) }
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default ConnectionStatusBadge;
|
|
@ -1,10 +1,10 @@
|
|||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlocks/SettingsBlock';
|
||||
import SettingsBlock from '../../../../../ReusableComponents/SettingsBlock';
|
||||
import {
|
||||
Description,
|
||||
Header,
|
||||
Title,
|
||||
Content,
|
||||
} from '../../../../../ReusableComponents/SettingsBlocks';
|
||||
} from '../../../../../ReusableComponents/Elements';
|
||||
|
||||
const StylingSection = ( {
|
||||
title,
|
||||
|
@ -26,7 +26,9 @@ const StylingSection = ( {
|
|||
<Description>{ description }</Description>
|
||||
</Header>
|
||||
|
||||
<Content className="section-content">{ children }</Content>
|
||||
<Content asCard={ false } className="section-content">
|
||||
{ children }
|
||||
</Content>
|
||||
</SettingsBlock>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ const StylingSectionWithCheckboxes = ( {
|
|||
onChange,
|
||||
children,
|
||||
} ) => {
|
||||
className = classNames( 'has-checkboxes', className );
|
||||
className = classNames( 'ppcp--has-checkboxes', className );
|
||||
|
||||
return (
|
||||
<StylingSection
|
||||
|
|
|
@ -14,7 +14,7 @@ const StylingSectionWithRadiobuttons = ( {
|
|||
onChange,
|
||||
children,
|
||||
} ) => {
|
||||
className = classNames( 'has-radio-buttons', className );
|
||||
className = classNames( 'ppcp--has-radio-buttons', className );
|
||||
|
||||
return (
|
||||
<StylingSection
|
||||
|
|
|
@ -13,7 +13,7 @@ const StylingSectionWithSelect = ( {
|
|||
onChange,
|
||||
children,
|
||||
} ) => {
|
||||
className = classNames( 'has-select', className );
|
||||
className = classNames( 'ppcp--has-select', className );
|
||||
|
||||
return (
|
||||
<StylingSection
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { useState, useMemo } from '@wordpress/element';
|
||||
import { Button, Icon } from '@wordpress/components';
|
||||
import { useDispatch } from '@wordpress/data';
|
||||
import { reusableBlock } from '@wordpress/icons';
|
||||
import { store as noticesStore } from '@wordpress/notices';
|
||||
|
||||
import SettingsCard from '../../ReusableComponents/SettingsCard';
|
||||
import TodoSettingsBlock from '../../ReusableComponents/SettingsBlocks/TodoSettingsBlock';
|
||||
import FeatureSettingsBlock from '../../ReusableComponents/SettingsBlocks/FeatureSettingsBlock';
|
||||
import { TITLE_BADGE_POSITIVE } from '../../ReusableComponents/TitleBadge';
|
||||
import { useMerchantInfo } from '../../../data/common/hooks';
|
||||
import { STORE_NAME } from '../../../data/common';
|
||||
import Features from './TabSettingsElements/Blocks/Features';
|
||||
import { todosData } from '../../../data/settings/tab-overview-todos-data';
|
||||
import {
|
||||
TodoSettingsBlock,
|
||||
FeatureSettingsBlock,
|
||||
} from '../../../ReusableComponents/SettingsBlocks';
|
||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
||||
import { TITLE_BADGE_POSITIVE } from '../../../ReusableComponents/TitleBadge';
|
||||
import { useMerchantInfo } from '../../../../data/common/hooks';
|
||||
import { STORE_NAME } from '../../../../data/common';
|
||||
import Features from '../Components/Overview/Features';
|
||||
import { todosData } from '../todo-items';
|
||||
|
||||
import {
|
||||
NOTIFICATION_ERROR,
|
||||
NOTIFICATION_SUCCESS,
|
||||
} from '../../ReusableComponents/Icons';
|
||||
} from '../../../ReusableComponents/Icons';
|
||||
|
||||
const TabOverview = () => {
|
||||
const [ isRefreshing, setIsRefreshing ] = useState( false );
|
||||
|
||||
const { merchant, merchantFeatures } = useMerchantInfo();
|
||||
const { merchant, features: merchantFeatures } = useMerchantInfo();
|
||||
const { refreshFeatureStatuses, setActiveModal } =
|
||||
useDispatch( STORE_NAME );
|
||||
const { createSuccessNotice, createErrorNotice } =
|
||||
|
@ -49,35 +52,35 @@ const TabOverview = () => {
|
|||
try {
|
||||
const result = await refreshFeatureStatuses();
|
||||
if ( result && ! result.success ) {
|
||||
const errorMessage = sprintf(
|
||||
/* translators: %s: error message */
|
||||
__(
|
||||
'Operation failed: %s Check WooCommerce logs for more details.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
result.message ||
|
||||
__( 'Unknown error', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
const errorMessage = sprintf(
|
||||
/* translators: %s: error message */
|
||||
__(
|
||||
'Operation failed: %s Check WooCommerce logs for more details.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
result.message ||
|
||||
__( 'Unknown error', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
|
||||
createErrorNotice( errorMessage, {
|
||||
icon: NOTIFICATION_ERROR,
|
||||
} );
|
||||
console.error(
|
||||
'Failed to refresh features:',
|
||||
result.message || 'Unknown error'
|
||||
);
|
||||
createErrorNotice( errorMessage, {
|
||||
icon: NOTIFICATION_ERROR,
|
||||
} );
|
||||
console.error(
|
||||
'Failed to refresh features:',
|
||||
result.message || 'Unknown error'
|
||||
);
|
||||
} else {
|
||||
createSuccessNotice(
|
||||
__(
|
||||
'Features refreshed successfully.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
{
|
||||
icon: NOTIFICATION_SUCCESS,
|
||||
}
|
||||
);
|
||||
console.log( 'Features refreshed successfully.' );
|
||||
}
|
||||
createSuccessNotice(
|
||||
__(
|
||||
'Features refreshed successfully.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
{
|
||||
icon: NOTIFICATION_SUCCESS,
|
||||
}
|
||||
);
|
||||
console.log( 'Features refreshed successfully.' );
|
||||
}
|
||||
} finally {
|
||||
setIsRefreshing( false );
|
||||
}
|
||||
|
@ -161,7 +164,7 @@ const TabOverview = () => {
|
|||
: button.urls.live
|
||||
: button.url,
|
||||
} ) ),
|
||||
isBusy: isRefreshing,
|
||||
isBusy: isRefreshing,
|
||||
enabled: feature.enabled,
|
||||
notes: feature.notes,
|
||||
badge: feature.enabled
|
|
@ -0,0 +1,23 @@
|
|||
import ConnectionStatus from '../Components/Settings/ConnectionStatus';
|
||||
import CommonSettings from '../Components/Settings/CommonSettings';
|
||||
import ExpertSettings from '../Components/Settings/ExpertSettings';
|
||||
import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
|
||||
import { SettingsHooks } from '../../../../data';
|
||||
|
||||
const TabSettings = () => {
|
||||
const { isReady } = SettingsHooks.useStore();
|
||||
|
||||
if ( ! isReady ) {
|
||||
return <SpinnerOverlay />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-settings">
|
||||
<ConnectionStatus />
|
||||
<CommonSettings />
|
||||
<ExpertSettings />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TabSettings;
|
|
@ -1,10 +1,16 @@
|
|||
import { StylingHooks } from '../../../../data';
|
||||
import PreviewPanel from '../Components/Styling/PreviewPanel';
|
||||
import SettingsPanel from '../Components/Styling/SettingsPanel';
|
||||
import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
|
||||
|
||||
const TabStyling = () => {
|
||||
const { isReady } = StylingHooks.useStore();
|
||||
const { location, setLocation } = StylingHooks.useStylingLocation();
|
||||
|
||||
if ( ! isReady ) {
|
||||
return <SpinnerOverlay />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ppcp-r-styling">
|
||||
<SettingsPanel location={ location } setLocation={ setLocation } />
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
import TabOverview from '../../Overview/TabOverview';
|
||||
import TabOverview from './TabOverview';
|
||||
import TabPaymentMethods from '../../Overview/TabPaymentMethods';
|
||||
import TabSettings from '../../Overview/TabSettings';
|
||||
import TabSettings from './TabSettings';
|
||||
import TabStyling from './TabStyling';
|
||||
import TabPayLaterMessaging from '../../Overview/TabPayLaterMessaging';
|
||||
|
||||
|
|
|
@ -0,0 +1,160 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { selectTab, TAB_IDS } from '../../../utils/tabSelector';
|
||||
|
||||
export const todosData = [
|
||||
{
|
||||
id: 'enable_fastlane',
|
||||
title: __( 'Enable Fastlane', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Accelerate your guest checkout with Fastlane by PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () =>
|
||||
selectTab( TAB_IDS.PAYMENT_METHODS, 'ppcp-card-payments-card' ),
|
||||
},
|
||||
{
|
||||
id: 'enable_credit_debit_cards',
|
||||
title: __(
|
||||
'Enable Credit and Debit Cards on your checkout',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Credit and Debit Cards is now available for Blocks checkout pages.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () =>
|
||||
selectTab( TAB_IDS.PAYMENT_METHODS, 'ppcp-card-payments-card' ),
|
||||
},
|
||||
{
|
||||
id: 'enable_pay_later_messaging',
|
||||
title: __(
|
||||
'Enable Pay Later messaging',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Show Pay Later messaging to boost conversion rate and increase cart size.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => selectTab( TAB_IDS.OVERVIEW, 'pay_later_messaging' ),
|
||||
},
|
||||
{
|
||||
id: 'configure_paypal_subscription',
|
||||
title: __(
|
||||
'Configure a PayPal Subscription',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Connect a subscriptions-type product from WooCommerce with PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => {
|
||||
console.log(
|
||||
'Take merchant to product list, filtered with subscription-type products'
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'register_domain_apple_pay',
|
||||
title: __(
|
||||
'Register Domain for Apple Pay',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'To enable Apple Pay, you must register your domain with PayPal.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => selectTab( TAB_IDS.OVERVIEW, 'apple_pay' ),
|
||||
},
|
||||
{
|
||||
id: 'add_digital_wallets_to_account',
|
||||
title: __(
|
||||
'Add digital wallets to your account',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Add the ability to accept Apple Pay & Google Pay to your PayPal account.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => {
|
||||
console.log(
|
||||
'Take merchant to PayPal to enable Apple Pay & Google Pay'
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'add_apple_pay_to_account',
|
||||
title: __(
|
||||
'Add Apple Pay to your account',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Add the ability to accept Apple Pay to your PayPal account.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => {
|
||||
console.log( 'Take merchant to PayPal to enable Apple Pay' );
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'add_google_pay_to_account',
|
||||
title: __(
|
||||
'Add Google Pay to your account',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
description: __(
|
||||
'Add the ability to accept Google Pay to your PayPal account.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => {
|
||||
console.log( 'Take merchant to PayPal to enable Google Pay' );
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'enable_apple_pay',
|
||||
title: __( 'Enable Apple Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Allow your buyers to check out via Apple Pay.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => selectTab( TAB_IDS.OVERVIEW, 'apple_pay' ),
|
||||
},
|
||||
{
|
||||
id: 'enable_google_pay',
|
||||
title: __( 'Enable Google Pay', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Allow your buyers to check out via Google Pay.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
isCompleted: () => {
|
||||
return false;
|
||||
},
|
||||
onClick: () => selectTab( TAB_IDS.OVERVIEW, 'google_pay' ),
|
||||
},
|
||||
];
|
Loading…
Add table
Add a link
Reference in a new issue