mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Clean up the Features store a bit and split the TabOverview into separate files
This commit is contained in:
parent
1497cbae52
commit
84854e737a
18 changed files with 643 additions and 901 deletions
|
@ -0,0 +1,36 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { Button, Icon } from '@wordpress/components';
|
||||||
|
import { reusableBlock } from '@wordpress/icons';
|
||||||
|
|
||||||
|
const FeatureDescription = ( { refreshHandler, isRefreshing } ) => {
|
||||||
|
const buttonLabel = isRefreshing
|
||||||
|
? __( 'Refreshing…', 'woocommerce-paypal-payments' )
|
||||||
|
: __( 'Refresh', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'Enable additional features and capabilities on your WooCommerce store.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'Click Refresh to update your current features after making changes.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={ refreshHandler }
|
||||||
|
disabled={ isRefreshing }
|
||||||
|
>
|
||||||
|
<Icon icon={ reusableBlock } size={ 18 } />
|
||||||
|
{ buttonLabel }
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeatureDescription;
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { FeatureSettingsBlock } from '../../../../../ReusableComponents/SettingsBlocks';
|
||||||
|
import { Content } from '../../../../../ReusableComponents/Elements';
|
||||||
|
import { TITLE_BADGE_POSITIVE } from '../../../../../ReusableComponents/TitleBadge';
|
||||||
|
import { selectTab, TAB_IDS } from '../../../../../../utils/tabSelector';
|
||||||
|
import { setActiveModal } from '../../../../../../data/common/actions';
|
||||||
|
|
||||||
|
const FeatureItem = ( {
|
||||||
|
isBusy,
|
||||||
|
isSandbox,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
buttons,
|
||||||
|
enabled,
|
||||||
|
notes,
|
||||||
|
} ) => {
|
||||||
|
const getButtonUrl = ( button ) => {
|
||||||
|
if ( button.urls ) {
|
||||||
|
return isSandbox ? button.urls.sandbox : button.urls.live;
|
||||||
|
}
|
||||||
|
|
||||||
|
return button.url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const visibleButtons = buttons.filter(
|
||||||
|
( button ) =>
|
||||||
|
! button.showWhen || // Learn more buttons
|
||||||
|
( enabled && button.showWhen === 'enabled' ) ||
|
||||||
|
( ! enabled && button.showWhen === 'disabled' )
|
||||||
|
);
|
||||||
|
const handleClick = async ( feature ) => {
|
||||||
|
if ( feature.action?.type === 'tab' ) {
|
||||||
|
const tabId = TAB_IDS[ feature.action.tab.toUpperCase() ];
|
||||||
|
await selectTab( tabId, feature.action.section );
|
||||||
|
}
|
||||||
|
if ( feature.action?.modal ) {
|
||||||
|
setActiveModal( feature.action.modal );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const actionProps = {
|
||||||
|
isBusy,
|
||||||
|
enabled,
|
||||||
|
notes,
|
||||||
|
buttons: visibleButtons.map( ( button ) => ( {
|
||||||
|
...button,
|
||||||
|
url: getButtonUrl( button ),
|
||||||
|
onClick: () => handleClick( button ),
|
||||||
|
} ) ),
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( enabled ) {
|
||||||
|
actionProps.badge = {
|
||||||
|
text: __( 'Active', 'woocommerce-paypal-payments' ),
|
||||||
|
type: TITLE_BADGE_POSITIVE,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Content>
|
||||||
|
<FeatureSettingsBlock
|
||||||
|
title={ title }
|
||||||
|
description={ description }
|
||||||
|
actionProps={ actionProps }
|
||||||
|
/>
|
||||||
|
</Content>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default FeatureItem;
|
|
@ -0,0 +1,95 @@
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { useState } from '@wordpress/element';
|
||||||
|
import { useDispatch } from '@wordpress/data';
|
||||||
|
import { store as noticesStore } from '@wordpress/notices';
|
||||||
|
import FeatureItem from './FeatureItem';
|
||||||
|
import FeatureDescription from './FeatureDescription';
|
||||||
|
import { ContentWrapper } from '../../../../../ReusableComponents/Elements';
|
||||||
|
import SettingsCard from '../../../../../ReusableComponents/SettingsCard';
|
||||||
|
import { useMerchantInfo } from '../../../../../../data/common/hooks';
|
||||||
|
import { STORE_NAME as COMMON_STORE_NAME } from '../../../../../../data/common';
|
||||||
|
import {
|
||||||
|
NOTIFICATION_ERROR,
|
||||||
|
NOTIFICATION_SUCCESS,
|
||||||
|
} from '../../../../../ReusableComponents/Icons';
|
||||||
|
import { useFeatures } from '../../../../../../data/features/hooks';
|
||||||
|
|
||||||
|
const Features = () => {
|
||||||
|
const [ isRefreshing, setIsRefreshing ] = useState( false );
|
||||||
|
const { merchant } = useMerchantInfo();
|
||||||
|
const { features, fetchFeatures } = useFeatures();
|
||||||
|
const { refreshFeatureStatuses } = useDispatch( COMMON_STORE_NAME );
|
||||||
|
const { createSuccessNotice, createErrorNotice } =
|
||||||
|
useDispatch( noticesStore );
|
||||||
|
|
||||||
|
if ( ! features || features.length === 0 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const refreshHandler = async () => {
|
||||||
|
setIsRefreshing( true );
|
||||||
|
try {
|
||||||
|
const statusResult = await refreshFeatureStatuses();
|
||||||
|
if ( ! statusResult?.success ) {
|
||||||
|
throw new Error(
|
||||||
|
statusResult?.message || 'Failed to refresh status'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const featuresResult = await fetchFeatures();
|
||||||
|
if ( featuresResult.success ) {
|
||||||
|
createSuccessNotice(
|
||||||
|
__(
|
||||||
|
'Features refreshed successfully.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
{ icon: NOTIFICATION_SUCCESS }
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error(
|
||||||
|
featuresResult?.message || 'Failed to fetch features'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch ( error ) {
|
||||||
|
createErrorNotice(
|
||||||
|
sprintf(
|
||||||
|
/* translators: %s: error message */
|
||||||
|
__( 'Operation failed: %s', 'woocommerce-paypal-payments' ),
|
||||||
|
error.message ||
|
||||||
|
__( 'Unknown error', 'woocommerce-paypal-payments' )
|
||||||
|
),
|
||||||
|
{ icon: NOTIFICATION_ERROR }
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsRefreshing( false );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-features"
|
||||||
|
title={ __( 'Features', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={
|
||||||
|
<FeatureDescription
|
||||||
|
refreshHandler={ refreshHandler }
|
||||||
|
isRefreshing={ isRefreshing }
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
contentContainer={ false }
|
||||||
|
>
|
||||||
|
<ContentWrapper>
|
||||||
|
{ features.map( ( { id, isEligible, ...feature } ) => (
|
||||||
|
<FeatureItem
|
||||||
|
key={ id }
|
||||||
|
isBusy={ isRefreshing }
|
||||||
|
isSandbox={ merchant.isSandbox }
|
||||||
|
enabled={ isEligible }
|
||||||
|
{ ...feature }
|
||||||
|
/>
|
||||||
|
) ) }
|
||||||
|
</ContentWrapper>
|
||||||
|
</SettingsCard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Features;
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { FeatureSettingsBlock } from '../../../../../ReusableComponents/SettingsBlocks';
|
||||||
|
import {
|
||||||
|
Content,
|
||||||
|
ContentWrapper,
|
||||||
|
} from '../../../../../ReusableComponents/Elements';
|
||||||
|
import SettingsCard from '../../../../../ReusableComponents/SettingsCard';
|
||||||
|
|
||||||
|
const Help = () => {
|
||||||
|
return (
|
||||||
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-help"
|
||||||
|
title={ __( 'Help Center', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={ __(
|
||||||
|
'Access detailed guides and responsive support to streamline setup and enhance your experience.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
contentContainer={ false }
|
||||||
|
>
|
||||||
|
<ContentWrapper>
|
||||||
|
<Content>
|
||||||
|
<FeatureSettingsBlock
|
||||||
|
title={ __(
|
||||||
|
'Documentation',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
description={ __(
|
||||||
|
'Find detailed guides and resources to help you set up, manage, and optimize your PayPal integration.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
actionProps={ {
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'tertiary',
|
||||||
|
text: __(
|
||||||
|
'View full documentation',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} }
|
||||||
|
/>
|
||||||
|
</Content>
|
||||||
|
|
||||||
|
<Content>
|
||||||
|
<FeatureSettingsBlock
|
||||||
|
title={ __( 'Support', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={ __(
|
||||||
|
'Need help? Access troubleshooting tips or contact our support team for personalized assistance.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
actionProps={ {
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'tertiary',
|
||||||
|
text: __(
|
||||||
|
'View support options',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/#get-help ',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} }
|
||||||
|
/>
|
||||||
|
</Content>
|
||||||
|
</ContentWrapper>
|
||||||
|
</SettingsCard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Help;
|
|
@ -0,0 +1,86 @@
|
||||||
|
import { __ } from '@wordpress/i18n';
|
||||||
|
import { useState } 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 { TodoSettingsBlock } from '../../../../../ReusableComponents/SettingsBlocks';
|
||||||
|
import SettingsCard from '../../../../../ReusableComponents/SettingsCard';
|
||||||
|
import { useTodos } from '../../../../../../data/todos/hooks';
|
||||||
|
import { STORE_NAME as COMMON_STORE_NAME } from '../../../../../../data/common';
|
||||||
|
import { STORE_NAME as TODOS_STORE_NAME } from '../../../../../../data/todos';
|
||||||
|
import { NOTIFICATION_SUCCESS } from '../../../../../ReusableComponents/Icons';
|
||||||
|
|
||||||
|
const Todos = () => {
|
||||||
|
const [ isResetting, setIsResetting ] = useState( false );
|
||||||
|
const { todos, isReady: areTodosReady, dismissTodo } = useTodos();
|
||||||
|
// eslint-disable-next-line no-shadow
|
||||||
|
const { setActiveModal, setActiveHighlight } =
|
||||||
|
useDispatch( COMMON_STORE_NAME );
|
||||||
|
const { resetDismissedTodos, setDismissedTodos } =
|
||||||
|
useDispatch( TODOS_STORE_NAME );
|
||||||
|
const { createSuccessNotice } = useDispatch( noticesStore );
|
||||||
|
|
||||||
|
const showTodos = areTodosReady && todos.length > 0;
|
||||||
|
|
||||||
|
const resetHandler = async () => {
|
||||||
|
setIsResetting( true );
|
||||||
|
try {
|
||||||
|
await setDismissedTodos( [] );
|
||||||
|
await resetDismissedTodos();
|
||||||
|
|
||||||
|
createSuccessNotice(
|
||||||
|
__(
|
||||||
|
'Dismissed items restored successfully.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
{ icon: NOTIFICATION_SUCCESS }
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setIsResetting( false );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( ! showTodos ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SettingsCard
|
||||||
|
className="ppcp-r-tab-overview-todo"
|
||||||
|
title={ __( 'Things to do next', 'woocommerce-paypal-payments' ) }
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
{ __(
|
||||||
|
'Complete these tasks to keep your store updated with the latest products and services.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
variant="tertiary"
|
||||||
|
onClick={ resetHandler }
|
||||||
|
disabled={ isResetting }
|
||||||
|
>
|
||||||
|
<Icon icon={ reusableBlock } size={ 18 } />
|
||||||
|
{ isResetting
|
||||||
|
? __( 'Restoring…', 'woocommerce-paypal-payments' )
|
||||||
|
: __(
|
||||||
|
'Restore dismissed Things To Do',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
) }
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<TodoSettingsBlock
|
||||||
|
todosData={ todos }
|
||||||
|
setActiveModal={ setActiveModal }
|
||||||
|
setActiveHighlight={ setActiveHighlight }
|
||||||
|
onDismissTodo={ dismissTodo }
|
||||||
|
/>
|
||||||
|
</SettingsCard>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Todos;
|
|
@ -1,278 +0,0 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
|
||||||
import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
|
|
||||||
import { payLaterMessaging } from './pay-later-messaging';
|
|
||||||
|
|
||||||
export const getFeatures = ( setActiveModal ) => {
|
|
||||||
const storeCountry = ppcpSettings?.storeCountry;
|
|
||||||
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.SETTINGS,
|
|
||||||
'ppcp--save-payment-methods'
|
|
||||||
);
|
|
||||||
},
|
|
||||||
showWhen: 'enabled',
|
|
||||||
class: 'small-button',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'secondary',
|
|
||||||
text: __( 'Sign up', '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://www.paypal.com/us/enterprise/payment-processing/accept-venmo',
|
|
||||||
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( 'ppcp-credit-card-gateway' );
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
showWhen: 'enabled',
|
|
||||||
class: 'small-button',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'secondary',
|
|
||||||
text: __( 'Sign up', '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: __( 'Sign up', '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( 'ppcp-googlepay' );
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
showWhen: 'enabled',
|
|
||||||
class: 'small-button',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'secondary',
|
|
||||||
text: __( 'Sign up', '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( 'ppcp-applepay' );
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
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: __( 'Sign up', '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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const countryData = payLaterMessaging[ storeCountry ] || {};
|
|
||||||
|
|
||||||
if (
|
|
||||||
!! window.ppcpSettings?.isPayLaterConfiguratorAvailable &&
|
|
||||||
countryData
|
|
||||||
) {
|
|
||||||
const countryLocation = [
|
|
||||||
'UK',
|
|
||||||
'ES',
|
|
||||||
'IT',
|
|
||||||
'FR',
|
|
||||||
'US',
|
|
||||||
'DE',
|
|
||||||
'AU',
|
|
||||||
].includes( storeCountry )
|
|
||||||
? storeCountry.toLowerCase()
|
|
||||||
: 'us';
|
|
||||||
features.push( {
|
|
||||||
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.PAY_LATER_MESSAGING );
|
|
||||||
},
|
|
||||||
showWhen: 'enabled',
|
|
||||||
class: 'small-button',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'tertiary',
|
|
||||||
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
|
|
||||||
url: `https://www.paypal.com/${ countryLocation }/business/accept-payments/checkout/installments`,
|
|
||||||
class: 'small-button',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
return features;
|
|
||||||
};
|
|
|
@ -1,356 +1,25 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import Todos from '../Components/Overview/Todos/Todos';
|
||||||
import { useState, useEffect } from '@wordpress/element';
|
import Features from '../Components/Overview/Features/Features';
|
||||||
import { Button, Icon } from '@wordpress/components';
|
import Help from '../Components/Overview/Help/Help';
|
||||||
import { useDispatch } from '@wordpress/data';
|
import { TodosHooks, CommonHooks, FeaturesHooks } from '../../../../data';
|
||||||
import { reusableBlock } from '@wordpress/icons';
|
|
||||||
import { store as noticesStore } from '@wordpress/notices';
|
|
||||||
|
|
||||||
import {
|
|
||||||
TodoSettingsBlock,
|
|
||||||
FeatureSettingsBlock,
|
|
||||||
} from '../../../ReusableComponents/SettingsBlocks';
|
|
||||||
import { Content, ContentWrapper } from '../../../ReusableComponents/Elements';
|
|
||||||
import SettingsCard from '../../../ReusableComponents/SettingsCard';
|
|
||||||
import { TITLE_BADGE_POSITIVE } from '../../../ReusableComponents/TitleBadge';
|
|
||||||
import { useTodos } from '../../../../data/todos/hooks';
|
|
||||||
import { useMerchantInfo } from '../../../../data/common/hooks';
|
|
||||||
import { STORE_NAME as COMMON_STORE_NAME } from '../../../../data/common';
|
|
||||||
import { STORE_NAME as TODOS_STORE_NAME } from '../../../../data/todos';
|
|
||||||
import { CommonHooks, TodosHooks } from '../../../../data';
|
|
||||||
|
|
||||||
import {
|
|
||||||
NOTIFICATION_ERROR,
|
|
||||||
NOTIFICATION_SUCCESS,
|
|
||||||
} from '../../../ReusableComponents/Icons';
|
|
||||||
import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
|
import SpinnerOverlay from '../../../ReusableComponents/SpinnerOverlay';
|
||||||
import { useFeatures } from '../../../../data/features/hooks';
|
|
||||||
import { selectTab, TAB_IDS } from '../../../../utils/tabSelector';
|
|
||||||
import { setActiveModal } from '../../../../data/common/actions';
|
|
||||||
|
|
||||||
const TabOverview = () => {
|
const TabOverview = () => {
|
||||||
const { isReady: areTodosReady } = TodosHooks.useTodos();
|
const { isReady: areTodosReady } = TodosHooks.useTodos();
|
||||||
const { isReady: merchantIsReady } = CommonHooks.useMerchantInfo();
|
const { isReady: merchantIsReady } = CommonHooks.useMerchantInfo();
|
||||||
|
const { isReady: featuresIsReady } = FeaturesHooks.useFeatures();
|
||||||
|
|
||||||
if ( ! areTodosReady || ! merchantIsReady ) {
|
if ( ! areTodosReady || ! merchantIsReady || ! featuresIsReady ) {
|
||||||
return <SpinnerOverlay asModal={ true } />;
|
return <SpinnerOverlay asModal={ true } />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ppcp-r-tab-overview">
|
<div className="ppcp-r-tab-overview">
|
||||||
<OverviewTodos />
|
<Todos />
|
||||||
<OverviewFeatures />
|
<Features />
|
||||||
<OverviewHelp />
|
<Help />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default TabOverview;
|
export default TabOverview;
|
||||||
|
|
||||||
const OverviewTodos = () => {
|
|
||||||
const [ isResetting, setIsResetting ] = useState( false );
|
|
||||||
const { todos, isReady: areTodosReady, dismissTodo } = useTodos();
|
|
||||||
// eslint-disable-next-line no-shadow
|
|
||||||
const { setActiveModal, setActiveHighlight } =
|
|
||||||
useDispatch( COMMON_STORE_NAME );
|
|
||||||
const { resetDismissedTodos, setDismissedTodos } =
|
|
||||||
useDispatch( TODOS_STORE_NAME );
|
|
||||||
const { createSuccessNotice } = useDispatch( noticesStore );
|
|
||||||
|
|
||||||
const showTodos = areTodosReady && todos.length > 0;
|
|
||||||
|
|
||||||
const resetHandler = async () => {
|
|
||||||
setIsResetting( true );
|
|
||||||
try {
|
|
||||||
await setDismissedTodos( [] );
|
|
||||||
await resetDismissedTodos();
|
|
||||||
|
|
||||||
createSuccessNotice(
|
|
||||||
__(
|
|
||||||
'Dismissed items restored successfully.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
{ icon: NOTIFICATION_SUCCESS }
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
setIsResetting( false );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( ! showTodos ) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SettingsCard
|
|
||||||
className="ppcp-r-tab-overview-todo"
|
|
||||||
title={ __( 'Things to do next', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={
|
|
||||||
<>
|
|
||||||
<p>
|
|
||||||
{ __(
|
|
||||||
'Complete these tasks to keep your store updated with the latest products and services.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
variant="tertiary"
|
|
||||||
onClick={ resetHandler }
|
|
||||||
disabled={ isResetting }
|
|
||||||
>
|
|
||||||
<Icon icon={ reusableBlock } size={ 18 } />
|
|
||||||
{ isResetting
|
|
||||||
? __( 'Restoring…', 'woocommerce-paypal-payments' )
|
|
||||||
: __(
|
|
||||||
'Restore dismissed Things To Do',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<TodoSettingsBlock
|
|
||||||
todosData={ todos }
|
|
||||||
setActiveModal={ setActiveModal }
|
|
||||||
setActiveHighlight={ setActiveHighlight }
|
|
||||||
onDismissTodo={ dismissTodo }
|
|
||||||
/>
|
|
||||||
</SettingsCard>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewFeatures = () => {
|
|
||||||
const [ isRefreshing, setIsRefreshing ] = useState( false );
|
|
||||||
const { merchant } = useMerchantInfo();
|
|
||||||
const { refreshFeatureStatuses } = useDispatch( COMMON_STORE_NAME );
|
|
||||||
const { createSuccessNotice, createErrorNotice } =
|
|
||||||
useDispatch( noticesStore );
|
|
||||||
const { features, fetchFeatures } = useFeatures();
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
fetchFeatures();
|
|
||||||
}, [ fetchFeatures ] );
|
|
||||||
|
|
||||||
const refreshHandler = async () => {
|
|
||||||
setIsRefreshing( true );
|
|
||||||
|
|
||||||
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' )
|
|
||||||
);
|
|
||||||
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
setIsRefreshing( false );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SettingsCard
|
|
||||||
className="ppcp-r-tab-overview-features"
|
|
||||||
title={ __( 'Features', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={
|
|
||||||
<OverviewFeatureDescription
|
|
||||||
refreshHandler={ refreshHandler }
|
|
||||||
isRefreshing={ isRefreshing }
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
contentContainer={ false }
|
|
||||||
>
|
|
||||||
<ContentWrapper>
|
|
||||||
{ features.map( ( { id, ...feature } ) => (
|
|
||||||
<OverviewFeatureItem
|
|
||||||
key={ id }
|
|
||||||
isBusy={ isRefreshing }
|
|
||||||
isSandbox={ merchant.isSandbox }
|
|
||||||
title={ feature.title }
|
|
||||||
description={ feature.description }
|
|
||||||
buttons={ feature.buttons }
|
|
||||||
enabled={ feature.isEligible }
|
|
||||||
notes={ feature.notes }
|
|
||||||
/>
|
|
||||||
) ) }
|
|
||||||
</ContentWrapper>
|
|
||||||
</SettingsCard>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewFeatureItem = ( {
|
|
||||||
isBusy,
|
|
||||||
isSandbox,
|
|
||||||
title,
|
|
||||||
description,
|
|
||||||
buttons,
|
|
||||||
enabled,
|
|
||||||
notes,
|
|
||||||
} ) => {
|
|
||||||
const getButtonUrl = ( button ) => {
|
|
||||||
if ( button.urls ) {
|
|
||||||
return isSandbox ? button.urls.sandbox : button.urls.live;
|
|
||||||
}
|
|
||||||
|
|
||||||
return button.url;
|
|
||||||
};
|
|
||||||
|
|
||||||
const visibleButtons = buttons.filter(
|
|
||||||
( button ) =>
|
|
||||||
! button.showWhen || // Learn more buttons
|
|
||||||
( enabled && button.showWhen === 'enabled' ) ||
|
|
||||||
( ! enabled && button.showWhen === 'disabled' )
|
|
||||||
);
|
|
||||||
const handleClick = async ( feature ) => {
|
|
||||||
if ( feature.action?.type === 'tab' ) {
|
|
||||||
const tabId = TAB_IDS[ feature.action.tab.toUpperCase() ];
|
|
||||||
await selectTab( tabId, feature.action.section );
|
|
||||||
}
|
|
||||||
if ( feature.action?.modal ) {
|
|
||||||
setActiveModal( feature.action.modal );
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const actionProps = {
|
|
||||||
isBusy,
|
|
||||||
enabled,
|
|
||||||
notes,
|
|
||||||
buttons: visibleButtons.map( ( button ) => ( {
|
|
||||||
...button,
|
|
||||||
url: getButtonUrl( button ),
|
|
||||||
onClick: () => handleClick( button ),
|
|
||||||
} ) ),
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( enabled ) {
|
|
||||||
actionProps.badge = {
|
|
||||||
text: __( 'Active', 'woocommerce-paypal-payments' ),
|
|
||||||
type: TITLE_BADGE_POSITIVE,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Content>
|
|
||||||
<FeatureSettingsBlock
|
|
||||||
title={ title }
|
|
||||||
description={ description }
|
|
||||||
actionProps={ actionProps }
|
|
||||||
/>
|
|
||||||
</Content>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewFeatureDescription = ( { refreshHandler, isRefreshing } ) => {
|
|
||||||
const buttonLabel = isRefreshing
|
|
||||||
? __( 'Refreshing…', 'woocommerce-paypal-payments' )
|
|
||||||
: __( 'Refresh', 'woocommerce-paypal-payments' );
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>
|
|
||||||
{ __(
|
|
||||||
'Enable additional features and capabilities on your WooCommerce store.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{ __(
|
|
||||||
'Click Refresh to update your current features after making changes.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
variant="tertiary"
|
|
||||||
onClick={ refreshHandler }
|
|
||||||
disabled={ isRefreshing }
|
|
||||||
>
|
|
||||||
<Icon icon={ reusableBlock } size={ 18 } />
|
|
||||||
{ buttonLabel }
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const OverviewHelp = () => {
|
|
||||||
return (
|
|
||||||
<SettingsCard
|
|
||||||
className="ppcp-r-tab-overview-help"
|
|
||||||
title={ __( 'Help Center', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={ __(
|
|
||||||
'Access detailed guides and responsive support to streamline setup and enhance your experience.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
contentContainer={ false }
|
|
||||||
>
|
|
||||||
<ContentWrapper>
|
|
||||||
<Content>
|
|
||||||
<FeatureSettingsBlock
|
|
||||||
title={ __(
|
|
||||||
'Documentation',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
description={ __(
|
|
||||||
'Find detailed guides and resources to help you set up, manage, and optimize your PayPal integration.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
actionProps={ {
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
type: 'tertiary',
|
|
||||||
text: __(
|
|
||||||
'View full documentation',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
</Content>
|
|
||||||
|
|
||||||
<Content>
|
|
||||||
<FeatureSettingsBlock
|
|
||||||
title={ __( 'Support', 'woocommerce-paypal-payments' ) }
|
|
||||||
description={ __(
|
|
||||||
'Need help? Access troubleshooting tips or contact our support team for personalized assistance.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
) }
|
|
||||||
actionProps={ {
|
|
||||||
buttons: [
|
|
||||||
{
|
|
||||||
type: 'tertiary',
|
|
||||||
text: __(
|
|
||||||
'View support options',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
),
|
|
||||||
url: 'https://woocommerce.com/document/woocommerce-paypal-payments/#get-help ',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
} }
|
|
||||||
/>
|
|
||||||
</Content>
|
|
||||||
</ContentWrapper>
|
|
||||||
</SettingsCard>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ export default {
|
||||||
// Transient data
|
// Transient data
|
||||||
SET_TRANSIENT: 'ppcp/features/SET_TRANSIENT',
|
SET_TRANSIENT: 'ppcp/features/SET_TRANSIENT',
|
||||||
|
|
||||||
// Persistent data
|
// Persistant data
|
||||||
SET_PERSISTENT: 'ppcp/features/SET_PERSISTENT',
|
SET_FEATURES: 'ppcp/features/SET_FEATURES',
|
||||||
RESET: 'ppcp/features/RESET',
|
|
||||||
HYDRATE: 'ppcp/features/HYDRATE',
|
HYDRATE: 'ppcp/features/HYDRATE',
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,16 +2,14 @@
|
||||||
* Action Creators: Define functions to create action objects.
|
* Action Creators: Define functions to create action objects.
|
||||||
*
|
*
|
||||||
* These functions update state or trigger side effects (e.g., async operations).
|
* These functions update state or trigger side effects (e.g., async operations).
|
||||||
* Actions are categorized as Transient, Persistent, or Side effect.
|
* Actions are categorized as Transient or Side effect.
|
||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import apiFetch from '@wordpress/api-fetch';
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
|
||||||
import ACTION_TYPES from './action-types';
|
import ACTION_TYPES from './action-types';
|
||||||
import { REST_PERSIST_PATH } from './constants';
|
import { REST_PATH } from './constants';
|
||||||
import { dispatch } from '@wordpress/data';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} Action An action object that is handled by a reducer or control.
|
* @typedef {Object} Action An action object that is handled by a reducer or control.
|
||||||
|
@ -20,14 +18,7 @@ import { dispatch } from '@wordpress/data';
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Special. Resets all values in the store to initial defaults.
|
* Set the full store details during app initialization.
|
||||||
*
|
|
||||||
* @return {Action} The action.
|
|
||||||
*/
|
|
||||||
export const reset = () => ( { type: ACTION_TYPES.RESET } );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persistent. Set the full store details during app initialization.
|
|
||||||
*
|
*
|
||||||
* @param {{data: {}, flags?: {}}} payload
|
* @param {{data: {}, flags?: {}}} payload
|
||||||
* @return {Action} The action.
|
* @return {Action} The action.
|
||||||
|
@ -49,18 +40,6 @@ export const setTransient = ( prop, value ) => ( {
|
||||||
payload: { [ prop ]: value },
|
payload: { [ prop ]: value },
|
||||||
} );
|
} );
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic persistent-data updater.
|
|
||||||
*
|
|
||||||
* @param {string} prop Name of the property to update.
|
|
||||||
* @param {any} value The new value of the property.
|
|
||||||
* @return {Action} The action.
|
|
||||||
*/
|
|
||||||
export const setPersistent = ( prop, value ) => ( {
|
|
||||||
type: ACTION_TYPES.SET_PERSISTENT,
|
|
||||||
payload: { [ prop ]: value },
|
|
||||||
} );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transient. Marks the store as "ready", i.e., fully initialized.
|
* Transient. Marks the store as "ready", i.e., fully initialized.
|
||||||
*
|
*
|
||||||
|
@ -70,24 +49,39 @@ export const setPersistent = ( prop, value ) => ( {
|
||||||
export const setIsReady = ( isReady ) => setTransient( 'isReady', isReady );
|
export const setIsReady = ( isReady ) => setTransient( 'isReady', isReady );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thunk action creator. Triggers the persistence of store data to the server.
|
* Sets the features in the store.
|
||||||
*
|
*
|
||||||
* @return {Function} The thunk function.
|
* @param {Array} features The features to set.
|
||||||
|
* @return {Action} The action.
|
||||||
*/
|
*/
|
||||||
export function persist() {
|
export const setFeatures = ( features ) => ( {
|
||||||
return async ( { select } ) => {
|
type: ACTION_TYPES.SET_FEATURES,
|
||||||
await apiFetch( {
|
payload: features,
|
||||||
path: REST_PERSIST_PATH,
|
} );
|
||||||
method: 'POST',
|
|
||||||
data: select.persistentData(),
|
|
||||||
} );
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function fetchFeatures() {
|
/**
|
||||||
return async () => {
|
* Fetches features from the server.
|
||||||
const response = await apiFetch( { path: REST_PERSIST_PATH } );
|
*
|
||||||
const features = response?.data || [];
|
* @return {Promise<Array>} The features data.
|
||||||
dispatch( setFeatures( features ) );
|
*/
|
||||||
};
|
export const fetchFeatures = async () => {
|
||||||
}
|
try {
|
||||||
|
const response = await apiFetch( { path: REST_PATH } );
|
||||||
|
if ( response?.data ) {
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
features: response.data.features,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
features: [],
|
||||||
|
};
|
||||||
|
} catch ( e ) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: e,
|
||||||
|
message: e.message,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
@ -5,23 +5,4 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const STORE_NAME = 'wc/paypal/features';
|
export const STORE_NAME = 'wc/paypal/features';
|
||||||
|
export const REST_PATH = '/wc/v3/wc_paypal/features';
|
||||||
/**
|
|
||||||
* REST path to hydrate data of this module by loading data from the WP DB.
|
|
||||||
*
|
|
||||||
* Used by: Resolvers
|
|
||||||
* See: <UNKNOWN>.php
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/features';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* REST path to persist data of this module to the WP DB.
|
|
||||||
*
|
|
||||||
* Used by: Controls
|
|
||||||
* See: <UNKNOWN>.php
|
|
||||||
*
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/features';
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Hooks: Provide the main API for components to interact with the store.
|
* Hooks: Provide the main API for components to interact with the features store.
|
||||||
*
|
*
|
||||||
* These encapsulate store interactions, offering a consistent interface.
|
* These encapsulate store interactions, offering a consistent interface.
|
||||||
* Hooks simplify data access and manipulation for components.
|
* Hooks simplify data access and manipulation for components.
|
||||||
|
@ -7,49 +7,61 @@
|
||||||
* @file
|
* @file
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useMemo } from '@wordpress/element';
|
import { useSelect, useDispatch } from '@wordpress/data';
|
||||||
import { useDispatch, useSelect } from '@wordpress/data';
|
import { useEffect } from '@wordpress/element';
|
||||||
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
import { createHooksForStore } from '../utils';
|
import { STORE_NAME, REST_PATH } from './constants';
|
||||||
import { STORE_NAME } from './constants';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Single source of truth for access Redux details.
|
|
||||||
*
|
|
||||||
* This hook returns a stable API to access actions, selectors and special hooks to generate
|
|
||||||
* getter- and setters for transient or persistent properties.
|
|
||||||
*
|
|
||||||
* @return {{select, dispatch, useTransient, usePersistent}} Store data API.
|
|
||||||
*/
|
|
||||||
const useStoreData = () => {
|
|
||||||
const select = useSelect( ( selectors ) => selectors( STORE_NAME ), [] );
|
|
||||||
const dispatch = useDispatch( STORE_NAME );
|
|
||||||
const { useTransient, usePersistent } = createHooksForStore( STORE_NAME );
|
|
||||||
|
|
||||||
return useMemo(
|
|
||||||
() => ( {
|
|
||||||
select,
|
|
||||||
dispatch,
|
|
||||||
useTransient,
|
|
||||||
usePersistent,
|
|
||||||
} ),
|
|
||||||
[ select, dispatch, useTransient, usePersistent ]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useStore = () => {
|
|
||||||
const { dispatch, useTransient } = useStoreData();
|
|
||||||
const [ isReady ] = useTransient( 'isReady' );
|
|
||||||
|
|
||||||
return { persist: dispatch.persist, isReady };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useFeatures = () => {
|
export const useFeatures = () => {
|
||||||
const { usePersistent } = useStoreData();
|
const { features, isReady } = useSelect( ( select ) => {
|
||||||
const [ features, fetchFeatures ] = usePersistent( 'features' );
|
const store = select( STORE_NAME );
|
||||||
|
|
||||||
|
return {
|
||||||
|
features: store.getFeatures() || [],
|
||||||
|
isReady: select( STORE_NAME ).transientData()?.isReady || false,
|
||||||
|
};
|
||||||
|
}, [] );
|
||||||
|
|
||||||
|
const { setFeatures, setIsReady } = useDispatch( STORE_NAME );
|
||||||
|
|
||||||
|
useEffect( () => {
|
||||||
|
const loadInitialFeatures = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiFetch( { path: REST_PATH } );
|
||||||
|
|
||||||
|
if ( response?.data?.features ) {
|
||||||
|
const featuresData = response.data.features;
|
||||||
|
|
||||||
|
if ( featuresData.length > 0 ) {
|
||||||
|
await setFeatures( featuresData );
|
||||||
|
await setIsReady( true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch ( error ) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( ! isReady ) {
|
||||||
|
loadInitialFeatures();
|
||||||
|
}
|
||||||
|
}, [ isReady, setFeatures, setIsReady ] );
|
||||||
|
|
||||||
return {
|
return {
|
||||||
features,
|
features,
|
||||||
fetchFeatures,
|
isReady,
|
||||||
|
fetchFeatures: async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiFetch( { path: REST_PATH } );
|
||||||
|
const featuresData = response.data?.features || [];
|
||||||
|
|
||||||
|
if ( featuresData.length > 0 ) {
|
||||||
|
await setFeatures( featuresData );
|
||||||
|
await setIsReady( true );
|
||||||
|
return { success: true, features: featuresData };
|
||||||
|
}
|
||||||
|
return { success: false, features: [] };
|
||||||
|
} catch ( error ) {
|
||||||
|
return { success: false, error, message: error.message };
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,7 @@ const defaultTransient = Object.freeze( {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Persistent: Values that are loaded from and saved to the DB.
|
* Persistent: Values that are loaded from and saved to the DB.
|
||||||
* These represent the core todos configuration.
|
* These represent the core features configuration.
|
||||||
*/
|
*/
|
||||||
const defaultPersistent = Object.freeze( {
|
const defaultPersistent = Object.freeze( {
|
||||||
features: [],
|
features: [],
|
||||||
|
@ -50,10 +50,10 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
|
||||||
changeTransient( state, payload ),
|
changeTransient( state, payload ),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates todos list
|
* Updates features list
|
||||||
*
|
*
|
||||||
* @param {Object} state Current state
|
* @param {Object} state Current state
|
||||||
* @param {Object} payload Update payload
|
* @param {Object} payload Update payload containing features array
|
||||||
* @return {Object} Updated state
|
* @return {Object} Updated state
|
||||||
*/
|
*/
|
||||||
[ ACTION_TYPES.SET_FEATURES ]: ( state, payload ) => {
|
[ ACTION_TYPES.SET_FEATURES ]: ( state, payload ) => {
|
||||||
|
@ -65,7 +65,7 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
|
||||||
*
|
*
|
||||||
* @param {Object} state Current state
|
* @param {Object} state Current state
|
||||||
* @param {Object} payload Hydration payload containing server data
|
* @param {Object} payload Hydration payload containing server data
|
||||||
* @param {Object} payload.data The todos data to hydrate
|
* @param {Object} payload.data The features data to hydrate
|
||||||
* @return {Object} Hydrated state
|
* @return {Object} Hydrated state
|
||||||
*/
|
*/
|
||||||
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
|
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
|
||||||
|
|
|
@ -11,26 +11,24 @@
|
||||||
import { __ } from '@wordpress/i18n';
|
import { __ } from '@wordpress/i18n';
|
||||||
import apiFetch from '@wordpress/api-fetch';
|
import apiFetch from '@wordpress/api-fetch';
|
||||||
|
|
||||||
import { REST_HYDRATE_PATH } from './constants';
|
import { REST_PATH } from './constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve settings from the site's REST API.
|
* Hydrates the features data from the API.
|
||||||
|
*
|
||||||
|
* @return {Object} Action to dispatch.
|
||||||
*/
|
*/
|
||||||
export function persistentData() {
|
export function getFeatures() {
|
||||||
return async ( { dispatch, registry } ) => {
|
return async ( { dispatch } ) => {
|
||||||
try {
|
try {
|
||||||
const result = await apiFetch( { path: REST_HYDRATE_PATH } );
|
const response = await apiFetch( { path: REST_PATH } );
|
||||||
await dispatch.hydrate( result );
|
|
||||||
await dispatch.setIsReady( true );
|
if ( response?.features ) {
|
||||||
} catch ( e ) {
|
dispatch.setFeatures( response.features );
|
||||||
await registry
|
dispatch.setIsReady( true );
|
||||||
.dispatch( 'core/notices' )
|
}
|
||||||
.createErrorNotice(
|
} catch ( error ) {
|
||||||
__(
|
console.error( 'Error fetching features:', error );
|
||||||
'Error retrieving features details.',
|
|
||||||
'woocommerce-paypal-payments'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const EMPTY_OBJ = Object.freeze( {} );
|
const EMPTY_OBJ = Object.freeze( {} );
|
||||||
|
const EMPTY_ARR = Object.freeze( [] );
|
||||||
|
|
||||||
const getState = ( state ) => state || EMPTY_OBJ;
|
const getState = ( state ) => state || EMPTY_OBJ;
|
||||||
|
|
||||||
|
@ -19,3 +20,8 @@ export const transientData = ( state ) => {
|
||||||
const { data, ...transientState } = getState( state );
|
const { data, ...transientState } = getState( state );
|
||||||
return transientState || EMPTY_OBJ;
|
return transientState || EMPTY_OBJ;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getFeatures = ( state ) => {
|
||||||
|
const features = state?.features || persistentData( state ).features;
|
||||||
|
return features || EMPTY_ARR;
|
||||||
|
};
|
||||||
|
|
|
@ -378,25 +378,25 @@ return array(
|
||||||
$capabilities['google_pay'] && ! $gateways['google_pay'], // Enable Google Pay.
|
$capabilities['google_pay'] && ! $gateways['google_pay'], // Enable Google Pay.
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'settings.rest.features' => static function ( ContainerInterface $container ) : FeaturesRestEndpoint {
|
'settings.rest.features' => static function ( ContainerInterface $container ) : FeaturesRestEndpoint {
|
||||||
return new FeaturesRestEndpoint(
|
return new FeaturesRestEndpoint(
|
||||||
$container->get( 'settings.data.definition.features' ),
|
$container->get( 'settings.data.definition.features' ),
|
||||||
$container->get( 'settings.rest.settings' )
|
$container->get( 'settings.rest.settings' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'settings.data.definition.features' => static function ( ContainerInterface $container ) : FeaturesDefinition {
|
'settings.data.definition.features' => static function ( ContainerInterface $container ) : FeaturesDefinition {
|
||||||
return new FeaturesDefinition(
|
return new FeaturesDefinition(
|
||||||
$container->get( 'settings.service.features_eligibilities' ),
|
$container->get( 'settings.service.features_eligibilities' ),
|
||||||
$container->get( 'settings.data.general' )
|
$container->get( 'settings.data.general' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'settings.service.features_eligibilities' => static function( ContainerInterface $container ): FeaturesEligibilityService {
|
'settings.service.features_eligibilities' => static function( ContainerInterface $container ): FeaturesEligibilityService {
|
||||||
$features = apply_filters(
|
$features = apply_filters(
|
||||||
'woocommerce_paypal_payments_rest_common_merchant_features',
|
'woocommerce_paypal_payments_rest_common_merchant_features',
|
||||||
array()
|
array()
|
||||||
);
|
);
|
||||||
|
|
||||||
$payment_endpoint = $container->get('settings.rest.payment');
|
$payment_endpoint = $container->get( 'settings.rest.payment' );
|
||||||
$settings = $payment_endpoint->get_details()->get_data();
|
$settings = $payment_endpoint->get_details()->get_data();
|
||||||
|
|
||||||
// Settings status.
|
// Settings status.
|
||||||
|
@ -418,8 +418,8 @@ return array(
|
||||||
$capabilities['save_paypal'], // Save PayPal and Venmo eligibility.
|
$capabilities['save_paypal'], // Save PayPal and Venmo eligibility.
|
||||||
$capabilities['acdc'] && ! $gateways['card-button'], // Advanced credit and debit cards eligibility.
|
$capabilities['acdc'] && ! $gateways['card-button'], // Advanced credit and debit cards eligibility.
|
||||||
$capabilities['apm'], // Alternative payment methods eligibility.
|
$capabilities['apm'], // Alternative payment methods eligibility.
|
||||||
$capabilities['acdc'] && ! $capabilities['google_pay'], // Google Pay eligibility.
|
$capabilities['acdc'] && $capabilities['google_pay'], // Google Pay eligibility.
|
||||||
$capabilities['acdc'] && ! $capabilities['apple_pay'], // Apple Pay eligibility.
|
$capabilities['acdc'] && $capabilities['apple_pay'], // Apple Pay eligibility.
|
||||||
$capabilities['paylater'], // Pay Later eligibility.
|
$capabilities['paylater'], // Pay Later eligibility.
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,8 +18,8 @@ use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
|
||||||
* Provides the definitions for all available features in the system.
|
* Provides the definitions for all available features in the system.
|
||||||
* Each feature has a title, description, eligibility condition, and associated action.
|
* Each feature has a title, description, eligibility condition, and associated action.
|
||||||
*/
|
*/
|
||||||
class FeaturesDefinition
|
class FeaturesDefinition {
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The features eligibility service.
|
* The features eligibility service.
|
||||||
|
@ -39,15 +39,14 @@ class FeaturesDefinition
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param FeaturesEligibilityService $eligibilities The features eligibility service.
|
* @param FeaturesEligibilityService $eligibilities The features eligibility service.
|
||||||
* @param GeneralSettings $settings The general settings service.
|
* @param GeneralSettings $settings The general settings service.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
FeaturesEligibilityService $eligibilities,
|
FeaturesEligibilityService $eligibilities,
|
||||||
GeneralSettings $settings
|
GeneralSettings $settings
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
$this->eligibilities = $eligibilities;
|
$this->eligibilities = $eligibilities;
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,10 +54,9 @@ class FeaturesDefinition
|
||||||
*
|
*
|
||||||
* @return array The array of feature definitions.
|
* @return array The array of feature definitions.
|
||||||
*/
|
*/
|
||||||
public function get(): array
|
public function get(): array {
|
||||||
{
|
|
||||||
$eligibility_checks = $this->eligibilities->get_eligibility_checks();
|
$eligibility_checks = $this->eligibilities->get_eligibility_checks();
|
||||||
$paylaterCountries = [
|
$paylater_countries = array(
|
||||||
'UK',
|
'UK',
|
||||||
'ES',
|
'ES',
|
||||||
'IT',
|
'IT',
|
||||||
|
@ -66,216 +64,216 @@ class FeaturesDefinition
|
||||||
'US',
|
'US',
|
||||||
'DE',
|
'DE',
|
||||||
'AU',
|
'AU',
|
||||||
];
|
);
|
||||||
$storeCountry = $this->settings->get_woo_settings()['country'];
|
$store_country = $this->settings->get_woo_settings()['country'];
|
||||||
$countryLocation = in_array($storeCountry, $paylaterCountries) ? strtolower($storeCountry) : 'us';
|
$country_location = in_array( $store_country, $paylater_countries, true ) ? strtolower( $store_country ) : 'us';
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'save_paypal_and_venmo' => array(
|
'save_paypal_and_venmo' => array(
|
||||||
'title' => __('Save PayPal and Venmo', 'woocommerce-paypal-payments'),
|
'title' => __( 'Save PayPal and Venmo', 'woocommerce-paypal-payments' ),
|
||||||
'description' => __('Securely save PayPal and Venmo payment methods for subscriptions or return buyers.', 'woocommerce-paypal-payments'),
|
'description' => __( 'Securely save PayPal and Venmo payment methods for subscriptions or return buyers.', 'woocommerce-paypal-payments' ),
|
||||||
'isEligible' => $eligibility_checks['save_paypal_and_venmo'],
|
'isEligible' => $eligibility_checks['save_paypal_and_venmo'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'settings',
|
'tab' => 'settings',
|
||||||
'section' => 'ppcp--save-payment-methods',
|
'section' => 'ppcp--save-payment-methods',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Sign up', 'woocommerce-paypal-payments'),
|
'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
|
||||||
'urls' => array(
|
'urls' => array(
|
||||||
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||||
'live' => 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
'live' => 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
|
||||||
),
|
),
|
||||||
'showWhen' => 'disabled',
|
'showWhen' => 'disabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://www.paypal.com/us/enterprise/payment-processing/accept-venmo',
|
'url' => 'https://www.paypal.com/us/enterprise/payment-processing/accept-venmo',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'advanced_credit_and_debit_cards' => array(
|
'advanced_credit_and_debit_cards' => array(
|
||||||
'title' => __('Advanced Credit and Debit Cards', 'woocommerce-paypal-payments'),
|
'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'),
|
'description' => __( 'Process major credit and debit cards including Visa, Mastercard, American Express and Discover.', 'woocommerce-paypal-payments' ),
|
||||||
'isEligible' => $eligibility_checks['advanced_credit_and_debit_cards'],
|
'isEligible' => $eligibility_checks['advanced_credit_and_debit_cards'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'payment_methods',
|
'tab' => 'payment_methods',
|
||||||
'section' => 'ppcp-card-payments-card',
|
'section' => 'ppcp-card-payments-card',
|
||||||
'modal' => 'ppcp-credit-card-gateway',
|
'modal' => 'ppcp-credit-card-gateway',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Sign up', 'woocommerce-paypal-payments'),
|
'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
|
||||||
'urls' => array(
|
'urls' => array(
|
||||||
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp',
|
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp',
|
||||||
'live' => 'https://www.paypal.com/bizsignup/entry?product=ppcp',
|
'live' => 'https://www.paypal.com/bizsignup/entry?product=ppcp',
|
||||||
),
|
),
|
||||||
'showWhen' => 'disabled',
|
'showWhen' => 'disabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://developer.paypal.com/studio/checkout/advanced',
|
'url' => 'https://developer.paypal.com/studio/checkout/advanced',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'alternative_payment_methods' => array(
|
'alternative_payment_methods' => array(
|
||||||
'title' => __('Alternative Payment Methods', 'woocommerce-paypal-payments'),
|
'title' => __( 'Alternative Payment Methods', 'woocommerce-paypal-payments' ),
|
||||||
'description' => __('Offer global, country-specific payment options for your customers.', 'woocommerce-paypal-payments'),
|
'description' => __( 'Offer global, country-specific payment options for your customers.', 'woocommerce-paypal-payments' ),
|
||||||
'isEligible' => $eligibility_checks['alternative_payment_methods'],
|
'isEligible' => $eligibility_checks['alternative_payment_methods'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'payment_methods',
|
'tab' => 'payment_methods',
|
||||||
'section' => 'ppcp-alternative-payments-card',
|
'section' => 'ppcp-alternative-payments-card',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Sign up', 'woocommerce-paypal-payments'),
|
'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://developer.paypal.com/docs/checkout/apm/',
|
'url' => 'https://developer.paypal.com/docs/checkout/apm/',
|
||||||
'showWhen' => 'disabled',
|
'showWhen' => 'disabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://developer.paypal.com/docs/checkout/apm/',
|
'url' => 'https://developer.paypal.com/docs/checkout/apm/',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'google_pay' => array(
|
'google_pay' => array(
|
||||||
'title' => __('Google Pay', 'woocommerce-paypal-payments'),
|
'title' => __( 'Google Pay', 'woocommerce-paypal-payments' ),
|
||||||
'description' => __('Let customers pay using their Google Pay wallet.', 'woocommerce-paypal-payments'),
|
'description' => __( 'Let customers pay using their Google Pay wallet.', 'woocommerce-paypal-payments' ),
|
||||||
'isEligible' => $eligibility_checks['google_pay'],
|
'isEligible' => $eligibility_checks['google_pay'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'payment_methods',
|
'tab' => 'payment_methods',
|
||||||
'section' => 'ppcp-card-payments-card',
|
'section' => 'ppcp-card-payments-card',
|
||||||
'modal' => 'ppcp-googlepay',
|
'modal' => 'ppcp-googlepay',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Sign up', 'woocommerce-paypal-payments'),
|
'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
|
||||||
'urls' => array(
|
'urls' => array(
|
||||||
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
'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',
|
'live' => 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
|
||||||
),
|
),
|
||||||
'showWhen' => 'disabled',
|
'showWhen' => 'disabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://developer.paypal.com/docs/checkout/apm/google-pay/',
|
'url' => 'https://developer.paypal.com/docs/checkout/apm/google-pay/',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'notes' => array(
|
'notes' => array(
|
||||||
__('¹PayPal Q2 Earnings-2021.', 'woocommerce-paypal-payments'),
|
__( '¹PayPal Q2 Earnings-2021.', 'woocommerce-paypal-payments' ),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'apple_pay' => array(
|
'apple_pay' => array(
|
||||||
'title' => __('Apple Pay', 'woocommerce-paypal-payments'),
|
'title' => __( 'Apple Pay', 'woocommerce-paypal-payments' ),
|
||||||
'description' => __('Let customers pay using their Apple Pay wallet.', 'woocommerce-paypal-payments'),
|
'description' => __( 'Let customers pay using their Apple Pay wallet.', 'woocommerce-paypal-payments' ),
|
||||||
'isEligible' => $eligibility_checks['apple_pay'],
|
'isEligible' => $eligibility_checks['apple_pay'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'payment_methods',
|
'tab' => 'payment_methods',
|
||||||
'section' => 'ppcp-card-payments-card',
|
'section' => 'ppcp-card-payments-card',
|
||||||
'modal' => 'ppcp-applepay',
|
'modal' => 'ppcp-applepay',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Domain registration', 'woocommerce-paypal-payments'),
|
'text' => __( 'Domain registration', 'woocommerce-paypal-payments' ),
|
||||||
'urls' => array(
|
'urls' => array(
|
||||||
'sandbox' => 'https://www.sandbox.paypal.com/uccservicing/apm/applepay',
|
'sandbox' => 'https://www.sandbox.paypal.com/uccservicing/apm/applepay',
|
||||||
'live' => 'https://www.paypal.com/uccservicing/apm/applepay',
|
'live' => 'https://www.paypal.com/uccservicing/apm/applepay',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Sign up', 'woocommerce-paypal-payments'),
|
'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
|
||||||
'urls' => array(
|
'urls' => array(
|
||||||
'sandbox' => 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
'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',
|
'live' => 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
|
||||||
),
|
),
|
||||||
'showWhen' => 'disabled',
|
'showWhen' => 'disabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => 'https://developer.paypal.com/docs/checkout/apm/apple-pay/',
|
'url' => 'https://developer.paypal.com/docs/checkout/apm/apple-pay/',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'pay_later' => array(
|
'pay_later' => array(
|
||||||
'title' => __('Pay Later Messaging', 'woocommerce-paypal-payments'),
|
'title' => __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
|
||||||
'description' => __(
|
'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.',
|
'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'
|
'woocommerce-paypal-payments'
|
||||||
),
|
),
|
||||||
'isEligible' => $eligibility_checks['pay_later'],
|
'isEligible' => $eligibility_checks['pay_later'],
|
||||||
'buttons' => array(
|
'buttons' => array(
|
||||||
array(
|
array(
|
||||||
'type' => 'secondary',
|
'type' => 'secondary',
|
||||||
'text' => __('Configure', 'woocommerce-paypal-payments'),
|
'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
|
||||||
'action' => array(
|
'action' => array(
|
||||||
'type' => 'tab',
|
'type' => 'tab',
|
||||||
'tab' => 'pay_later_messaging',
|
'tab' => 'pay_later_messaging',
|
||||||
),
|
),
|
||||||
'showWhen' => 'enabled',
|
'showWhen' => 'enabled',
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'type' => 'tertiary',
|
'type' => 'tertiary',
|
||||||
'text' => __('Learn more', 'woocommerce-paypal-payments'),
|
'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
|
||||||
'url' => "https://www.paypal.com/$countryLocation/business/accept-payments/checkout/installments",
|
'url' => "https://www.paypal.com/{$country_location}/business/accept-payments/checkout/installments",
|
||||||
'class' => 'small-button',
|
'class' => 'small-button',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* REST endpoint to manage the features items.
|
* REST endpoint to manage features.
|
||||||
*
|
*
|
||||||
* Provides endpoints for retrieving features
|
* Provides endpoints for retrieving features via WP REST API routes.
|
||||||
* via WP REST API routes.
|
|
||||||
*
|
*
|
||||||
* @package WooCommerce\PayPalCommerce\Settings\Endpoint
|
* @package WooCommerce\PayPalCommerce\Settings\Endpoint
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +16,7 @@ use WP_REST_Response;
|
||||||
use WooCommerce\PayPalCommerce\Settings\Data\Definition\FeaturesDefinition;
|
use WooCommerce\PayPalCommerce\Settings\Data\Definition\FeaturesDefinition;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* REST controller for the features items in the Overview tab.
|
* REST controller for the features in the Overview tab.
|
||||||
*
|
*
|
||||||
* This API acts as the intermediary between the "external world" and our
|
* This API acts as the intermediary between the "external world" and our
|
||||||
* internal data model. It's responsible for checking eligibility and
|
* internal data model. It's responsible for checking eligibility and
|
||||||
|
@ -48,8 +47,8 @@ class FeaturesRestEndpoint extends RestEndpoint {
|
||||||
/**
|
/**
|
||||||
* FeaturesRestEndpoint constructor.
|
* FeaturesRestEndpoint constructor.
|
||||||
*
|
*
|
||||||
* @param FeaturesDefinition $features_definition The features definition instance.
|
* @param FeaturesDefinition $features_definition The features definition instance.
|
||||||
* @param SettingsRestEndpoint $settings The settings endpoint instance.
|
* @param SettingsRestEndpoint $settings The settings endpoint instance.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
FeaturesDefinition $features_definition,
|
FeaturesDefinition $features_definition,
|
||||||
|
@ -83,16 +82,21 @@ class FeaturesRestEndpoint extends RestEndpoint {
|
||||||
* @return WP_REST_Response The response containing features data.
|
* @return WP_REST_Response The response containing features data.
|
||||||
*/
|
*/
|
||||||
public function get_features(): WP_REST_Response {
|
public function get_features(): WP_REST_Response {
|
||||||
|
|
||||||
$features = array();
|
$features = array();
|
||||||
foreach ( $this->features_definition->get() as $id => $feature ) {
|
foreach ( $this->features_definition->get() as $id => $feature ) {
|
||||||
// Check eligibility and add to features if eligible.
|
// Evaluate eligibility check.
|
||||||
if ( $feature['isEligible']() ) {
|
if ( is_callable( $feature['isEligible'] ) ) {
|
||||||
$features[] = array_merge(
|
$is_eligible = $feature['isEligible']();
|
||||||
array( 'id' => $id ),
|
} else {
|
||||||
array_diff_key( $feature, array( 'isEligible' => true ) )
|
$is_eligible = (bool) $feature['isEligible'];
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Include all features with their eligibility state.
|
||||||
|
$features[] = array_merge(
|
||||||
|
array( 'id' => $id ),
|
||||||
|
array_diff_key( $feature, array( 'isEligible' => true ) ),
|
||||||
|
array( 'isEligible' => $is_eligible )
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->return_success(
|
return $this->return_success(
|
||||||
|
|
|
@ -77,12 +77,12 @@ class FeaturesEligibilityService {
|
||||||
bool $is_apple_pay_eligible,
|
bool $is_apple_pay_eligible,
|
||||||
bool $is_pay_later_eligible
|
bool $is_pay_later_eligible
|
||||||
) {
|
) {
|
||||||
$this->is_save_paypal_and_venmo_eligible = $is_save_paypal_and_venmo_eligible;
|
$this->is_save_paypal_and_venmo_eligible = $is_save_paypal_and_venmo_eligible;
|
||||||
$this->is_advanced_credit_and_debit_cards_eligible = $is_advanced_credit_and_debit_cards_eligible;
|
$this->is_advanced_credit_and_debit_cards_eligible = $is_advanced_credit_and_debit_cards_eligible;
|
||||||
$this->is_alternative_payment_methods_eligible = $is_alternative_payment_methods_eligible;
|
$this->is_alternative_payment_methods_eligible = $is_alternative_payment_methods_eligible;
|
||||||
$this->is_google_pay_eligible = $is_google_pay_eligible;
|
$this->is_google_pay_eligible = $is_google_pay_eligible;
|
||||||
$this->is_apple_pay_eligible = $is_apple_pay_eligible;
|
$this->is_apple_pay_eligible = $is_apple_pay_eligible;
|
||||||
$this->is_pay_later_eligible = $is_pay_later_eligible;
|
$this->is_pay_later_eligible = $is_pay_later_eligible;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,12 +92,12 @@ class FeaturesEligibilityService {
|
||||||
*/
|
*/
|
||||||
public function get_eligibility_checks(): array {
|
public function get_eligibility_checks(): array {
|
||||||
return array(
|
return array(
|
||||||
'save_paypal_and_venmo' => fn() => $this->is_save_paypal_and_venmo_eligible,
|
'save_paypal_and_venmo' => fn() => $this->is_save_paypal_and_venmo_eligible,
|
||||||
'advanced_credit_and_debit_cards' => fn() => $this->is_advanced_credit_and_debit_cards_eligible,
|
'advanced_credit_and_debit_cards' => fn() => $this->is_advanced_credit_and_debit_cards_eligible,
|
||||||
'alternative_payment_methods' => fn() => $this->is_alternative_payment_methods_eligible,
|
'alternative_payment_methods' => fn() => $this->is_alternative_payment_methods_eligible,
|
||||||
'google_pay' => fn() => $this->is_google_pay_eligible,
|
'google_pay' => fn() => $this->is_google_pay_eligible,
|
||||||
'apple_pay' => fn() => $this->is_apple_pay_eligible,
|
'apple_pay' => fn() => $this->is_apple_pay_eligible,
|
||||||
'pay_later' => fn() => $this->is_pay_later_eligible,
|
'pay_later' => fn() => $this->is_pay_later_eligible,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue