diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureDescription.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureDescription.js
new file mode 100644
index 000000000..9bf754d13
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureDescription.js
@@ -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 (
+ <>
+
+ { __(
+ 'Enable additional features and capabilities on your WooCommerce store.',
+ 'woocommerce-paypal-payments'
+ ) }
+
+
+ { __(
+ 'Click Refresh to update your current features after making changes.',
+ 'woocommerce-paypal-payments'
+ ) }
+
+
+ >
+ );
+};
+
+export default FeatureDescription;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureItem.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureItem.js
new file mode 100644
index 000000000..1659f961f
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/FeatureItem.js
@@ -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 (
+
+
+
+ );
+};
+
+export default FeatureItem;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/Features.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/Features.js
new file mode 100644
index 000000000..c8997979a
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Features/Features.js
@@ -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 (
+
+ }
+ contentContainer={ false }
+ >
+
+ { features.map( ( { id, isEligible, ...feature } ) => (
+
+ ) ) }
+
+
+ );
+};
+
+export default Features;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Help/Help.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Help/Help.js
new file mode 100644
index 000000000..afb1cc1f2
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Help/Help.js
@@ -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 (
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default Help;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Todos/Todos.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Todos/Todos.js
new file mode 100644
index 000000000..e7ff5fb4b
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/Todos/Todos.js
@@ -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 (
+
+
+ { __(
+ 'Complete these tasks to keep your store updated with the latest products and services.',
+ 'woocommerce-paypal-payments'
+ ) }
+
+
+ >
+ }
+ >
+
+
+ );
+};
+
+export default Todos;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/features-config.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/features-config.js
deleted file mode 100644
index 3a01b436f..000000000
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Overview/features-config.js
+++ /dev/null
@@ -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;
-};
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
index 089ad7150..e8cd2cd1b 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Settings/Tabs/TabOverview.js
@@ -1,356 +1,25 @@
-import { __, sprintf } from '@wordpress/i18n';
-import { useState, useEffect } 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,
- 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 Todos from '../Components/Overview/Todos/Todos';
+import Features from '../Components/Overview/Features/Features';
+import Help from '../Components/Overview/Help/Help';
+import { TodosHooks, CommonHooks, FeaturesHooks } from '../../../../data';
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 { isReady: areTodosReady } = TodosHooks.useTodos();
const { isReady: merchantIsReady } = CommonHooks.useMerchantInfo();
+ const { isReady: featuresIsReady } = FeaturesHooks.useFeatures();
- if ( ! areTodosReady || ! merchantIsReady ) {
+ if ( ! areTodosReady || ! merchantIsReady || ! featuresIsReady ) {
return ;
}
return (
-
-
-
+
+
+
);
};
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 (
-
-
- { __(
- 'Complete these tasks to keep your store updated with the latest products and services.',
- 'woocommerce-paypal-payments'
- ) }
-
-
- >
- }
- >
-
-
- );
-};
-
-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 (
-
- }
- contentContainer={ false }
- >
-
- { features.map( ( { id, ...feature } ) => (
-
- ) ) }
-
-
- );
-};
-
-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 (
-
-
-
- );
-};
-
-const OverviewFeatureDescription = ( { refreshHandler, isRefreshing } ) => {
- const buttonLabel = isRefreshing
- ? __( 'Refreshing…', 'woocommerce-paypal-payments' )
- : __( 'Refresh', 'woocommerce-paypal-payments' );
-
- return (
- <>
-
- { __(
- 'Enable additional features and capabilities on your WooCommerce store.',
- 'woocommerce-paypal-payments'
- ) }
-
-
- { __(
- 'Click Refresh to update your current features after making changes.',
- 'woocommerce-paypal-payments'
- ) }
-
-
- >
- );
-};
-
-const OverviewHelp = () => {
- return (
-
-
-
-
-
-
-
-
-
-
-
- );
-};
diff --git a/modules/ppcp-settings/resources/js/data/features/action-types.js b/modules/ppcp-settings/resources/js/data/features/action-types.js
index 309037f18..dc21c5110 100644
--- a/modules/ppcp-settings/resources/js/data/features/action-types.js
+++ b/modules/ppcp-settings/resources/js/data/features/action-types.js
@@ -8,8 +8,7 @@ export default {
// Transient data
SET_TRANSIENT: 'ppcp/features/SET_TRANSIENT',
- // Persistent data
- SET_PERSISTENT: 'ppcp/features/SET_PERSISTENT',
- RESET: 'ppcp/features/RESET',
+ // Persistant data
+ SET_FEATURES: 'ppcp/features/SET_FEATURES',
HYDRATE: 'ppcp/features/HYDRATE',
};
diff --git a/modules/ppcp-settings/resources/js/data/features/actions.js b/modules/ppcp-settings/resources/js/data/features/actions.js
index 664e7cbae..6dc43653f 100644
--- a/modules/ppcp-settings/resources/js/data/features/actions.js
+++ b/modules/ppcp-settings/resources/js/data/features/actions.js
@@ -2,16 +2,14 @@
* Action Creators: Define functions to create action objects.
*
* 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
*/
import apiFetch from '@wordpress/api-fetch';
-
import ACTION_TYPES from './action-types';
-import { REST_PERSIST_PATH } from './constants';
-import { dispatch } from '@wordpress/data';
+import { REST_PATH } from './constants';
/**
* @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.
- *
- * @return {Action} The action.
- */
-export const reset = () => ( { type: ACTION_TYPES.RESET } );
-
-/**
- * Persistent. Set the full store details during app initialization.
+ * Set the full store details during app initialization.
*
* @param {{data: {}, flags?: {}}} payload
* @return {Action} The action.
@@ -49,18 +40,6 @@ export const setTransient = ( 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.
*
@@ -70,24 +49,39 @@ export const setPersistent = ( prop, value ) => ( {
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() {
- return async ( { select } ) => {
- await apiFetch( {
- path: REST_PERSIST_PATH,
- method: 'POST',
- data: select.persistentData(),
- } );
- };
-}
+export const setFeatures = ( features ) => ( {
+ type: ACTION_TYPES.SET_FEATURES,
+ payload: features,
+} );
-export function fetchFeatures() {
- return async () => {
- const response = await apiFetch( { path: REST_PERSIST_PATH } );
- const features = response?.data || [];
- dispatch( setFeatures( features ) );
- };
-}
+/**
+ * Fetches features from the server.
+ *
+ * @return {Promise} The features data.
+ */
+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,
+ };
+ }
+};
diff --git a/modules/ppcp-settings/resources/js/data/features/constants.js b/modules/ppcp-settings/resources/js/data/features/constants.js
index 64b1b5251..88961407a 100644
--- a/modules/ppcp-settings/resources/js/data/features/constants.js
+++ b/modules/ppcp-settings/resources/js/data/features/constants.js
@@ -5,23 +5,4 @@
*/
export const STORE_NAME = 'wc/paypal/features';
-
-/**
- * REST path to hydrate data of this module by loading data from the WP DB.
- *
- * Used by: Resolvers
- * See: .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: .php
- *
- * @type {string}
- */
-export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/features';
+export const REST_PATH = '/wc/v3/wc_paypal/features';
diff --git a/modules/ppcp-settings/resources/js/data/features/hooks.js b/modules/ppcp-settings/resources/js/data/features/hooks.js
index 286d31518..476aab163 100644
--- a/modules/ppcp-settings/resources/js/data/features/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/features/hooks.js
@@ -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.
* Hooks simplify data access and manipulation for components.
@@ -7,49 +7,61 @@
* @file
*/
-import { useMemo } from '@wordpress/element';
-import { useDispatch, useSelect } from '@wordpress/data';
-
-import { createHooksForStore } from '../utils';
-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 };
-};
+import { useSelect, useDispatch } from '@wordpress/data';
+import { useEffect } from '@wordpress/element';
+import apiFetch from '@wordpress/api-fetch';
+import { STORE_NAME, REST_PATH } from './constants';
export const useFeatures = () => {
- const { usePersistent } = useStoreData();
- const [ features, fetchFeatures ] = usePersistent( 'features' );
+ const { features, isReady } = useSelect( ( select ) => {
+ 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 {
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 };
+ }
+ },
};
};
diff --git a/modules/ppcp-settings/resources/js/data/features/reducer.js b/modules/ppcp-settings/resources/js/data/features/reducer.js
index 11e261ebe..d3932fca4 100644
--- a/modules/ppcp-settings/resources/js/data/features/reducer.js
+++ b/modules/ppcp-settings/resources/js/data/features/reducer.js
@@ -22,7 +22,7 @@ const defaultTransient = Object.freeze( {
/**
* 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( {
features: [],
@@ -50,10 +50,10 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
changeTransient( state, payload ),
/**
- * Updates todos list
+ * Updates features list
*
* @param {Object} state Current state
- * @param {Object} payload Update payload
+ * @param {Object} payload Update payload containing features array
* @return {Object} Updated state
*/
[ ACTION_TYPES.SET_FEATURES ]: ( state, payload ) => {
@@ -65,7 +65,7 @@ const reducer = createReducer( defaultTransient, defaultPersistent, {
*
* @param {Object} state Current state
* @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
*/
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
diff --git a/modules/ppcp-settings/resources/js/data/features/resolvers.js b/modules/ppcp-settings/resources/js/data/features/resolvers.js
index 5e79d8de7..4d9de5d2c 100644
--- a/modules/ppcp-settings/resources/js/data/features/resolvers.js
+++ b/modules/ppcp-settings/resources/js/data/features/resolvers.js
@@ -11,26 +11,24 @@
import { __ } from '@wordpress/i18n';
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() {
- return async ( { dispatch, registry } ) => {
+export function getFeatures() {
+ return async ( { dispatch } ) => {
try {
- const result = await apiFetch( { path: REST_HYDRATE_PATH } );
- await dispatch.hydrate( result );
- await dispatch.setIsReady( true );
- } catch ( e ) {
- await registry
- .dispatch( 'core/notices' )
- .createErrorNotice(
- __(
- 'Error retrieving features details.',
- 'woocommerce-paypal-payments'
- )
- );
+ const response = await apiFetch( { path: REST_PATH } );
+
+ if ( response?.features ) {
+ dispatch.setFeatures( response.features );
+ dispatch.setIsReady( true );
+ }
+ } catch ( error ) {
+ console.error( 'Error fetching features:', error );
}
};
}
diff --git a/modules/ppcp-settings/resources/js/data/features/selectors.js b/modules/ppcp-settings/resources/js/data/features/selectors.js
index 14334fcf3..98100dec9 100644
--- a/modules/ppcp-settings/resources/js/data/features/selectors.js
+++ b/modules/ppcp-settings/resources/js/data/features/selectors.js
@@ -8,6 +8,7 @@
*/
const EMPTY_OBJ = Object.freeze( {} );
+const EMPTY_ARR = Object.freeze( [] );
const getState = ( state ) => state || EMPTY_OBJ;
@@ -19,3 +20,8 @@ export const transientData = ( state ) => {
const { data, ...transientState } = getState( state );
return transientState || EMPTY_OBJ;
};
+
+export const getFeatures = ( state ) => {
+ const features = state?.features || persistentData( state ).features;
+ return features || EMPTY_ARR;
+};
diff --git a/modules/ppcp-settings/services.php b/modules/ppcp-settings/services.php
index 443dbaf7e..e67cdacc0 100644
--- a/modules/ppcp-settings/services.php
+++ b/modules/ppcp-settings/services.php
@@ -378,25 +378,25 @@ return array(
$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(
$container->get( 'settings.data.definition.features' ),
$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(
$container->get( 'settings.service.features_eligibilities' ),
$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(
'woocommerce_paypal_payments_rest_common_merchant_features',
array()
);
- $payment_endpoint = $container->get('settings.rest.payment');
+ $payment_endpoint = $container->get( 'settings.rest.payment' );
$settings = $payment_endpoint->get_details()->get_data();
// Settings status.
@@ -418,8 +418,8 @@ return array(
$capabilities['save_paypal'], // Save PayPal and Venmo eligibility.
$capabilities['acdc'] && ! $gateways['card-button'], // Advanced credit and debit cards eligibility.
$capabilities['apm'], // Alternative payment methods eligibility.
- $capabilities['acdc'] && ! $capabilities['google_pay'], // Google Pay eligibility.
- $capabilities['acdc'] && ! $capabilities['apple_pay'], // Apple Pay eligibility.
+ $capabilities['acdc'] && $capabilities['google_pay'], // Google Pay eligibility.
+ $capabilities['acdc'] && $capabilities['apple_pay'], // Apple Pay eligibility.
$capabilities['paylater'], // Pay Later eligibility.
);
},
diff --git a/modules/ppcp-settings/src/Data/Definition/FeaturesDefinition.php b/modules/ppcp-settings/src/Data/Definition/FeaturesDefinition.php
index a4c9ca3b4..bbe105d9c 100644
--- a/modules/ppcp-settings/src/Data/Definition/FeaturesDefinition.php
+++ b/modules/ppcp-settings/src/Data/Definition/FeaturesDefinition.php
@@ -18,8 +18,8 @@ use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
* Provides the definitions for all available features in the system.
* Each feature has a title, description, eligibility condition, and associated action.
*/
-class FeaturesDefinition
-{
+class FeaturesDefinition {
+
/**
* The features eligibility service.
@@ -39,15 +39,14 @@ class FeaturesDefinition
* Constructor.
*
* @param FeaturesEligibilityService $eligibilities The features eligibility service.
- * @param GeneralSettings $settings The general settings service.
+ * @param GeneralSettings $settings The general settings service.
*/
public function __construct(
FeaturesEligibilityService $eligibilities,
- GeneralSettings $settings
- )
- {
+ GeneralSettings $settings
+ ) {
$this->eligibilities = $eligibilities;
- $this->settings = $settings;
+ $this->settings = $settings;
}
/**
@@ -55,10 +54,9 @@ class FeaturesDefinition
*
* @return array The array of feature definitions.
*/
- public function get(): array
- {
+ public function get(): array {
$eligibility_checks = $this->eligibilities->get_eligibility_checks();
- $paylaterCountries = [
+ $paylater_countries = array(
'UK',
'ES',
'IT',
@@ -66,216 +64,216 @@ class FeaturesDefinition
'US',
'DE',
'AU',
- ];
- $storeCountry = $this->settings->get_woo_settings()['country'];
- $countryLocation = in_array($storeCountry, $paylaterCountries) ? strtolower($storeCountry) : 'us';
+ );
+ $store_country = $this->settings->get_woo_settings()['country'];
+ $country_location = in_array( $store_country, $paylater_countries, true ) ? strtolower( $store_country ) : 'us';
return array(
- 'save_paypal_and_venmo' => array(
- 'title' => __('Save PayPal and Venmo', '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'],
- 'buttons' => array(
+ 'save_paypal_and_venmo' => array(
+ 'title' => __( 'Save PayPal and Venmo', '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'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
- 'type' => 'tab',
- 'tab' => 'settings',
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
+ 'type' => 'tab',
+ 'tab' => 'settings',
'section' => 'ppcp--save-payment-methods',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Sign up', 'woocommerce-paypal-payments'),
- 'urls' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
+ 'urls' => array(
'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',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => 'https://www.paypal.com/us/enterprise/payment-processing/accept-venmo',
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://www.paypal.com/us/enterprise/payment-processing/accept-venmo',
'class' => 'small-button',
),
),
),
'advanced_credit_and_debit_cards' => array(
- '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'),
- 'isEligible' => $eligibility_checks['advanced_credit_and_debit_cards'],
- 'buttons' => array(
+ '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' ),
+ 'isEligible' => $eligibility_checks['advanced_credit_and_debit_cards'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
- 'type' => 'tab',
- 'tab' => 'payment_methods',
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
+ 'type' => 'tab',
+ 'tab' => 'payment_methods',
'section' => 'ppcp-card-payments-card',
- 'modal' => 'ppcp-credit-card-gateway',
+ 'modal' => 'ppcp-credit-card-gateway',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Sign up', 'woocommerce-paypal-payments'),
- 'urls' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
+ 'urls' => array(
'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',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => 'https://developer.paypal.com/studio/checkout/advanced',
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://developer.paypal.com/studio/checkout/advanced',
'class' => 'small-button',
),
),
),
- 'alternative_payment_methods' => array(
- 'title' => __('Alternative Payment Methods', 'woocommerce-paypal-payments'),
- 'description' => __('Offer global, country-specific payment options for your customers.', 'woocommerce-paypal-payments'),
- 'isEligible' => $eligibility_checks['alternative_payment_methods'],
- 'buttons' => array(
+ 'alternative_payment_methods' => array(
+ 'title' => __( 'Alternative Payment Methods', 'woocommerce-paypal-payments' ),
+ 'description' => __( 'Offer global, country-specific payment options for your customers.', 'woocommerce-paypal-payments' ),
+ 'isEligible' => $eligibility_checks['alternative_payment_methods'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
- 'type' => 'tab',
- 'tab' => 'payment_methods',
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
+ 'type' => 'tab',
+ 'tab' => 'payment_methods',
'section' => 'ppcp-alternative-payments-card',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Sign up', 'woocommerce-paypal-payments'),
- 'url' => 'https://developer.paypal.com/docs/checkout/apm/',
+ 'type' => 'secondary',
+ 'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://developer.paypal.com/docs/checkout/apm/',
'showWhen' => 'disabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => 'https://developer.paypal.com/docs/checkout/apm/',
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://developer.paypal.com/docs/checkout/apm/',
'class' => 'small-button',
),
),
),
- 'google_pay' => array(
- 'title' => __('Google Pay', 'woocommerce-paypal-payments'),
- 'description' => __('Let customers pay using their Google Pay wallet.', 'woocommerce-paypal-payments'),
- 'isEligible' => $eligibility_checks['google_pay'],
- 'buttons' => array(
+ 'google_pay' => array(
+ 'title' => __( 'Google Pay', 'woocommerce-paypal-payments' ),
+ 'description' => __( 'Let customers pay using their Google Pay wallet.', 'woocommerce-paypal-payments' ),
+ 'isEligible' => $eligibility_checks['google_pay'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
- 'type' => 'tab',
- 'tab' => 'payment_methods',
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
+ 'type' => 'tab',
+ 'tab' => 'payment_methods',
'section' => 'ppcp-card-payments-card',
- 'modal' => 'ppcp-googlepay',
+ 'modal' => 'ppcp-googlepay',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Sign up', 'woocommerce-paypal-payments'),
- 'urls' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
+ 'urls' => array(
'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',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => 'https://developer.paypal.com/docs/checkout/apm/google-pay/',
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://developer.paypal.com/docs/checkout/apm/google-pay/',
'class' => 'small-button',
),
),
- 'notes' => array(
- __('¹PayPal Q2 Earnings-2021.', 'woocommerce-paypal-payments'),
+ 'notes' => array(
+ __( '¹PayPal Q2 Earnings-2021.', 'woocommerce-paypal-payments' ),
),
),
- 'apple_pay' => array(
- 'title' => __('Apple Pay', 'woocommerce-paypal-payments'),
- 'description' => __('Let customers pay using their Apple Pay wallet.', 'woocommerce-paypal-payments'),
- 'isEligible' => $eligibility_checks['apple_pay'],
- 'buttons' => array(
+ 'apple_pay' => array(
+ 'title' => __( 'Apple Pay', 'woocommerce-paypal-payments' ),
+ 'description' => __( 'Let customers pay using their Apple Pay wallet.', 'woocommerce-paypal-payments' ),
+ 'isEligible' => $eligibility_checks['apple_pay'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
- 'type' => 'tab',
- 'tab' => 'payment_methods',
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
+ 'type' => 'tab',
+ 'tab' => 'payment_methods',
'section' => 'ppcp-card-payments-card',
- 'modal' => 'ppcp-applepay',
+ 'modal' => 'ppcp-applepay',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Domain registration', 'woocommerce-paypal-payments'),
- 'urls' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Domain registration', 'woocommerce-paypal-payments' ),
+ 'urls' => array(
'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',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'secondary',
- 'text' => __('Sign up', 'woocommerce-paypal-payments'),
- 'urls' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Sign up', 'woocommerce-paypal-payments' ),
+ 'urls' => array(
'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',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => 'https://developer.paypal.com/docs/checkout/apm/apple-pay/',
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => 'https://developer.paypal.com/docs/checkout/apm/apple-pay/',
'class' => 'small-button',
),
),
),
- 'pay_later' => array(
- 'title' => __('Pay Later Messaging', 'woocommerce-paypal-payments'),
+ 'pay_later' => array(
+ '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'
),
- 'isEligible' => $eligibility_checks['pay_later'],
- 'buttons' => array(
+ 'isEligible' => $eligibility_checks['pay_later'],
+ 'buttons' => array(
array(
- 'type' => 'secondary',
- 'text' => __('Configure', 'woocommerce-paypal-payments'),
- 'action' => array(
+ 'type' => 'secondary',
+ 'text' => __( 'Configure', 'woocommerce-paypal-payments' ),
+ 'action' => array(
'type' => 'tab',
'tab' => 'pay_later_messaging',
),
'showWhen' => 'enabled',
- 'class' => 'small-button',
+ 'class' => 'small-button',
),
array(
- 'type' => 'tertiary',
- 'text' => __('Learn more', 'woocommerce-paypal-payments'),
- 'url' => "https://www.paypal.com/$countryLocation/business/accept-payments/checkout/installments",
+ 'type' => 'tertiary',
+ 'text' => __( 'Learn more', 'woocommerce-paypal-payments' ),
+ 'url' => "https://www.paypal.com/{$country_location}/business/accept-payments/checkout/installments",
'class' => 'small-button',
),
),
diff --git a/modules/ppcp-settings/src/Endpoint/FeaturesRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/FeaturesRestEndpoint.php
index 6112a2804..6bb486fb9 100644
--- a/modules/ppcp-settings/src/Endpoint/FeaturesRestEndpoint.php
+++ b/modules/ppcp-settings/src/Endpoint/FeaturesRestEndpoint.php
@@ -1,9 +1,8 @@
features_definition->get() as $id => $feature ) {
- // Check eligibility and add to features if eligible.
- if ( $feature['isEligible']() ) {
- $features[] = array_merge(
- array( 'id' => $id ),
- array_diff_key( $feature, array( 'isEligible' => true ) )
- );
+ // Evaluate eligibility check.
+ if ( is_callable( $feature['isEligible'] ) ) {
+ $is_eligible = $feature['isEligible']();
+ } else {
+ $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(
diff --git a/modules/ppcp-settings/src/Service/FeaturesEligibilityService.php b/modules/ppcp-settings/src/Service/FeaturesEligibilityService.php
index 3475487df..9f3fe4db7 100644
--- a/modules/ppcp-settings/src/Service/FeaturesEligibilityService.php
+++ b/modules/ppcp-settings/src/Service/FeaturesEligibilityService.php
@@ -77,12 +77,12 @@ class FeaturesEligibilityService {
bool $is_apple_pay_eligible,
bool $is_pay_later_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_alternative_payment_methods_eligible = $is_alternative_payment_methods_eligible;
- $this->is_google_pay_eligible = $is_google_pay_eligible;
- $this->is_apple_pay_eligible = $is_apple_pay_eligible;
- $this->is_pay_later_eligible = $is_pay_later_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_alternative_payment_methods_eligible = $is_alternative_payment_methods_eligible;
+ $this->is_google_pay_eligible = $is_google_pay_eligible;
+ $this->is_apple_pay_eligible = $is_apple_pay_eligible;
+ $this->is_pay_later_eligible = $is_pay_later_eligible;
}
/**
@@ -92,12 +92,12 @@ class FeaturesEligibilityService {
*/
public function get_eligibility_checks(): array {
return array(
- '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,
- 'alternative_payment_methods' => fn() => $this->is_alternative_payment_methods_eligible,
- 'google_pay' => fn() => $this->is_google_pay_eligible,
- 'apple_pay' => fn() => $this->is_apple_pay_eligible,
- 'pay_later' => fn() => $this->is_pay_later_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,
+ 'alternative_payment_methods' => fn() => $this->is_alternative_payment_methods_eligible,
+ 'google_pay' => fn() => $this->is_google_pay_eligible,
+ 'apple_pay' => fn() => $this->is_apple_pay_eligible,
+ 'pay_later' => fn() => $this->is_pay_later_eligible,
);
}
}