-
-
-
- { props.title }
-
-
-
- { props.description }
-
-
-
- { Modal && (
-
setModalIsVisible( true ) }
- >
- { data().getImage( 'icon-settings.svg' ) }
-
- ) }
-
+
+
+
-
- { Modal && modalIsVisible && (
-
- ) }
- >
+
+ { description }
+
+
+
+ { hasModal && onTriggerModal && (
+
+ { data().getImage( 'icon-settings.svg' ) }
+
+ ) }
+
+
+
);
};
diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js
index 3ffb91051..1caae6ce6 100644
--- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js
+++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsBlocks/PaymentMethodsBlock.js
@@ -2,7 +2,11 @@ import { useState, useCallback } from '@wordpress/element';
import SettingsBlock from './SettingsBlock';
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
-const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => {
+const PaymentMethodsBlock = ( {
+ paymentMethods,
+ className = '',
+ onTriggerModal,
+} ) => {
const [ selectedMethod, setSelectedMethod ] = useState( null );
const handleSelect = useCallback( ( methodId, isSelected ) => {
@@ -25,6 +29,9 @@ const PaymentMethodsBlock = ( { paymentMethods, className = '' } ) => {
onSelect={ ( checked ) =>
handleSelect( paymentMethod.id, checked )
}
+ onTriggerModal={ () =>
+ onTriggerModal?.( paymentMethod.id )
+ }
/>
) ) }
diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsCard.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsCard.js
index aeb0e3561..b7b6b8de4 100644
--- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsCard.js
+++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/SettingsCard.js
@@ -1,6 +1,7 @@
import { Content, ContentWrapper } from './SettingsBlocks';
const SettingsCard = ( {
+ id,
className: extraClassName,
title,
description,
@@ -33,7 +34,7 @@ const SettingsCard = ( {
};
return (
-
+
diff --git a/modules/ppcp-settings/resources/js/Components/ReusableComponents/TabNavigation.js b/modules/ppcp-settings/resources/js/Components/ReusableComponents/TabNavigation.js
index e22711255..e6561f56f 100644
--- a/modules/ppcp-settings/resources/js/Components/ReusableComponents/TabNavigation.js
+++ b/modules/ppcp-settings/resources/js/Components/ReusableComponents/TabNavigation.js
@@ -1,4 +1,6 @@
import { useCallback, useEffect, useState } from '@wordpress/element';
+
+// TODO: Migrate to Tabs (TabPanel v2) once its API is publicly available, as it provides programmatic tab switching support: https://github.com/WordPress/gutenberg/issues/52997
import { TabPanel } from '@wordpress/components';
import { getQuery, updateQueryString } from '../../utils/navigation';
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/Modals/Modal.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/Modals/Modal.js
new file mode 100644
index 000000000..a0c401d44
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/Modals/Modal.js
@@ -0,0 +1,51 @@
+import { __ } from '@wordpress/i18n';
+import ModalPayPal from './ModalPayPal';
+import ModalFastlane from './ModalFastlane';
+import ModalAcdc from './ModalAcdc';
+import { useActiveModal } from '../../../../data/common/hooks';
+
+export const MODAL_CONFIG = {
+ paypal: {
+ component: ModalPayPal,
+ icon: 'payment-method-paypal-big',
+ title: __( 'PayPal', 'woocommerce-paypal-payments' ),
+ },
+ fastlane: {
+ component: ModalFastlane,
+ icon: 'payment-method-fastlane-big',
+ title: __( 'Fastlane by PayPal', 'woocommerce-paypal-payments' ),
+ size: 'small',
+ },
+ advanced_credit_and_debit_card_payments: {
+ component: ModalAcdc,
+ icon: 'payment-method-cards-big',
+ title: __(
+ 'Advanced Credit and Debit Card Payments',
+ 'woocommerce-paypal-payments'
+ ),
+ },
+};
+
+const Modal = () => {
+ const { activeModal, setActiveModal } = useActiveModal();
+
+ const handleCloseModal = () => {
+ setActiveModal( '' );
+ };
+
+ if ( ! activeModal || ! MODAL_CONFIG[ activeModal ] ) {
+ return null;
+ }
+
+ const { component: ModalComponent, ...modalProps } =
+ MODAL_CONFIG[ activeModal ];
+
+ return (
+
+ );
+};
+
+export default Modal;
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabOverview.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabOverview.js
index f64095a8f..25e713bcd 100644
--- a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabOverview.js
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabOverview.js
@@ -1,5 +1,5 @@
import { __ } from '@wordpress/i18n';
-import { useState } from '@wordpress/element';
+import { useState, useMemo } from '@wordpress/element';
import { Button, Icon } from '@wordpress/components';
import { useDispatch } from '@wordpress/data';
import { reusableBlock } from '@wordpress/icons';
@@ -10,6 +10,7 @@ import FeatureSettingsBlock from '../../ReusableComponents/SettingsBlocks/Featur
import { TITLE_BADGE_POSITIVE } from '../../ReusableComponents/TitleBadge';
import { useMerchantInfo } from '../../../data/common/hooks';
import { STORE_NAME } from '../../../data/common';
+import Features from './TabSettingsElements/Blocks/Features';
const TabOverview = () => {
const [ todos, setTodos ] = useState( [] );
@@ -17,32 +18,39 @@ const TabOverview = () => {
const [ isRefreshing, setIsRefreshing ] = useState( false );
const { merchantFeatures } = useMerchantInfo();
- const { refreshFeatureStatuses } = useDispatch( STORE_NAME );
+ const { refreshFeatureStatuses, setActiveModal } =
+ useDispatch( STORE_NAME );
- const features = featuresDefault.map( ( feature ) => {
- const merchantFeature = merchantFeatures?.[ feature.id ];
- return {
- ...feature,
- enabled: merchantFeature?.enabled ?? false,
- };
- } );
+ // Get the features data with access to setActiveModal
+ const featuresData = useMemo(
+ () => Features.getFeatures( setActiveModal ),
+ [ setActiveModal ]
+ );
+
+ // Map merchant features status to our config
+ const features = useMemo( () => {
+ return featuresData.map( ( feature ) => {
+ const merchantFeature = merchantFeatures?.[ feature.id ];
+ return {
+ ...feature,
+ enabled: merchantFeature?.enabled ?? false,
+ };
+ } );
+ }, [ featuresData, merchantFeatures ] );
const refreshHandler = async () => {
setIsRefreshing( true );
-
- const result = await refreshFeatureStatuses();
-
- // TODO: Implement the refresh logic, remove this debug code -- PCP-4024
- if ( result && ! result.success ) {
- console.error(
- 'Failed to refresh features:',
- result.message || 'Unknown error'
- );
- } else {
- console.log( 'Features refreshed successfully.' );
+ try {
+ const result = await refreshFeatureStatuses();
+ if ( result && ! result.success ) {
+ console.error(
+ 'Failed to refresh features:',
+ result.message || 'Unknown error'
+ );
+ }
+ } finally {
+ setIsRefreshing( false );
}
-
- setIsRefreshing( false );
};
return (
@@ -103,27 +111,46 @@ const TabOverview = () => {
>
}
- contentItems={ features.map( ( feature ) => (
-
- ) ) }
+ contentItems={ features.map( ( feature ) => {
+ return (
+
+ ! button.showWhen || // Learn more buttons
+ ( feature.enabled &&
+ button.showWhen ===
+ 'enabled' ) ||
+ ( ! feature.enabled &&
+ button.showWhen === 'disabled' )
+ )
+ .map( ( button ) => ( {
+ ...button,
+ url: button.urls
+ ? merchant?.isSandbox
+ ? button.urls.sandbox
+ : button.urls.live
+ : button.url,
+ } ) ),
+ enabled: feature.enabled,
+ notes: feature.notes,
+ badge: feature.enabled
+ ? {
+ text: __(
+ 'Active',
+ 'woocommerce-paypal-payments'
+ ),
+ type: TITLE_BADGE_POSITIVE,
+ }
+ : undefined,
+ } }
+ />
+ );
+ } ) }
/>
{
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
+ const { setActiveModal } = useActiveModal();
const filteredPaymentMethods = useMemo( () => {
const contextProps = { storeCountry, storeCurrency };
@@ -33,6 +33,7 @@ const TabPaymentMethods = () => {
return (
);
};
@@ -98,7 +106,6 @@ const paymentMethodsPayPalCheckout = [
'woocommerce-paypal-payments'
),
icon: 'payment-method-paypal',
- modal: ModalPayPal,
},
{
id: 'venmo',
@@ -144,7 +151,6 @@ const paymentMethodsOnlineCardPayments = [
'woocommerce-paypal-payments'
),
icon: 'payment-method-advanced-cards',
- modal: ModalAcdc,
},
{
id: 'fastlane',
@@ -154,7 +160,6 @@ const paymentMethodsOnlineCardPayments = [
'woocommerce-paypal-payments'
),
icon: 'payment-method-fastlane',
- modal: ModalFastlane,
},
{
id: 'apply_pay',
diff --git a/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Features.js b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Features.js
new file mode 100644
index 000000000..0529cba66
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/Components/Screens/Overview/TabSettingsElements/Blocks/Features.js
@@ -0,0 +1,297 @@
+import { __ } from '@wordpress/i18n';
+import { TAB_IDS, selectTab } from '../../../../../utils/tabSelector';
+
+const Features = {
+ getFeatures: ( setActiveModal ) => [
+ {
+ id: 'save_paypal_and_venmo',
+ title: __( 'Save PayPal and Venmo', 'woocommerce-paypal-payments' ),
+ description: __(
+ 'Securely save PayPal and Venmo payment methods for subscriptions or return buyers.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-paypal-checkout-card'
+ ).then( () => {
+ setActiveModal( 'paypal' );
+ } );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox:
+ 'https://www.sandbox.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
+ live: 'https://www.paypal.com/bizsignup/entry?product=ADVANCED_VAULTING',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ },
+ {
+ id: 'advanced_credit_and_debit_cards',
+ title: __(
+ 'Advanced Credit and Debit Cards',
+ 'woocommerce-paypal-payments'
+ ),
+ description: __(
+ 'Process major credit and debit cards including Visa, Mastercard, American Express and Discover.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-card-payments-card'
+ ).then( () => {
+ setActiveModal(
+ 'advanced_credit_and_debit_card_payments'
+ );
+ } );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox:
+ 'https://www.sandbox.paypal.com/bizsignup/entry?product=ppcp',
+ live: 'https://www.paypal.com/bizsignup/entry?product=ppcp',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ },
+ {
+ id: 'alternative_payment_methods',
+ title: __(
+ 'Alternative Payment Methods',
+ 'woocommerce-paypal-payments'
+ ),
+ description: __(
+ 'Offer global, country-specific payment options for your customers.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-alternative-payments-card'
+ );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ },
+ {
+ id: 'google_pay',
+ title: __( 'Google Pay', 'woocommerce-paypal-payments' ),
+ description: __(
+ 'Let customers pay using their Google Pay wallet.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-card-payments-card'
+ ).then( () => {
+ setActiveModal( 'google_pay' );
+ } );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox:
+ 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
+ live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ notes: [
+ __(
+ '¹PayPal Q2 Earnings-2021.',
+ 'woocommerce-paypal-payments'
+ ),
+ ],
+ },
+ {
+ id: 'apple_pay',
+ title: __( 'Apple Pay', 'woocommerce-paypal-payments' ),
+ description: __(
+ 'Let customers pay using their Apple Pay wallet.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-card-payments-card'
+ ).then( () => {
+ setActiveModal( 'apple_pay' );
+ } );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __(
+ 'Domain registration',
+ 'woocommerce-paypal-payments'
+ ),
+ urls: {
+ sandbox:
+ 'https://www.sandbox.paypal.com/uccservicing/apm/applepay',
+ live: 'https://www.paypal.com/uccservicing/apm/applepay',
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox:
+ 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
+ live: 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ },
+ {
+ id: 'pay_later_messaging',
+ title: __( 'Pay Later Messaging', 'woocommerce-paypal-payments' ),
+ description: __(
+ 'Let customers know they can buy now and pay later with PayPal. Adding this messaging can boost conversion rates and increase cart sizes by 39%¹, with no extra cost to you—plus, you get paid up front.',
+ 'woocommerce-paypal-payments'
+ ),
+ buttons: [
+ {
+ type: 'secondary',
+ text: __( 'Configure', 'woocommerce-paypal-payments' ),
+ onClick: () => {
+ selectTab(
+ TAB_IDS.PAYMENT_METHODS,
+ 'ppcp-paypal-checkout-card'
+ ).then( () => {
+ setActiveModal( 'paypal' );
+ } );
+ },
+ showWhen: 'enabled',
+ class: 'small-button',
+ },
+ {
+ type: 'secondary',
+ text: __( 'Apply', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ showWhen: 'disabled',
+ class: 'small-button',
+ },
+ {
+ type: 'tertiary',
+ text: __( 'Learn more', 'woocommerce-paypal-payments' ),
+ urls: {
+ sandbox: '#',
+ live: '#',
+ },
+ class: 'small-button',
+ },
+ ],
+ },
+ ],
+};
+
+export default Features;
diff --git a/modules/ppcp-settings/resources/js/data/common/actions.js b/modules/ppcp-settings/resources/js/data/common/actions.js
index 0cdec5d31..c859fe0be 100644
--- a/modules/ppcp-settings/resources/js/data/common/actions.js
+++ b/modules/ppcp-settings/resources/js/data/common/actions.js
@@ -47,6 +47,17 @@ export const setIsReady = ( isReady ) => ( {
payload: { isReady },
} );
+/**
+ * Transient. Sets the active settings tab.
+ *
+ * @param {string} activeModal
+ * @return {Action} The action.
+ */
+export const setActiveModal = ( activeModal ) => ( {
+ type: ACTION_TYPES.SET_TRANSIENT,
+ payload: { activeModal },
+} );
+
/**
* Transient. Changes the "saving" flag.
*
diff --git a/modules/ppcp-settings/resources/js/data/common/hooks.js b/modules/ppcp-settings/resources/js/data/common/hooks.js
index e9a77b79b..4aea08caa 100644
--- a/modules/ppcp-settings/resources/js/data/common/hooks.js
+++ b/modules/ppcp-settings/resources/js/data/common/hooks.js
@@ -32,12 +32,14 @@ const useHooks = () => {
productionOnboardingUrl,
authenticateWithCredentials,
authenticateWithOAuth,
+ setActiveModal,
startWebhookSimulation,
checkWebhookSimulationState,
} = useDispatch( STORE_NAME );
// Transient accessors.
const isReady = useTransient( 'isReady' );
+ const activeModal = useTransient( 'activeModal' );
// Persistent accessors.
const isSandboxMode = usePersistent( 'useSandbox' );
@@ -68,6 +70,8 @@ const useHooks = () => {
return {
isReady,
+ activeModal,
+ setActiveModal,
isSandboxMode,
setSandboxMode: ( state ) => {
return savePersistent( setSandboxMode, state );
@@ -161,6 +165,11 @@ export const useMerchantInfo = () => {
};
};
+export const useActiveModal = () => {
+ const { activeModal, setActiveModal } = useHooks();
+ return { activeModal, setActiveModal };
+};
+
// -- Not using the `useHooks()` data provider --
export const useBusyState = () => {
diff --git a/modules/ppcp-settings/resources/js/data/common/reducer.js b/modules/ppcp-settings/resources/js/data/common/reducer.js
index 019d29911..e9ff90a42 100644
--- a/modules/ppcp-settings/resources/js/data/common/reducer.js
+++ b/modules/ppcp-settings/resources/js/data/common/reducer.js
@@ -15,6 +15,7 @@ import ACTION_TYPES from './action-types';
const defaultTransient = Object.freeze( {
isReady: false,
activities: new Map(),
+ activeModal: '',
// Read only values, provided by the server via hydrate.
merchant: Object.freeze( {
diff --git a/modules/ppcp-settings/resources/js/utils/tabSelector.js b/modules/ppcp-settings/resources/js/utils/tabSelector.js
new file mode 100644
index 000000000..c8b1c5350
--- /dev/null
+++ b/modules/ppcp-settings/resources/js/utils/tabSelector.js
@@ -0,0 +1,59 @@
+// Tab panel IDs
+export const TAB_IDS = {
+ OVERVIEW: 'tab-panel-0-overview',
+ PAYMENT_METHODS: 'tab-panel-0-payment-methods',
+ SETTINGS: 'tab-panel-0-settings',
+ STYLING: 'tab-panel-0-styling',
+};
+
+/**
+ * Select a tab by simulating a click event and scroll to specified element,
+ * accounting for navigation container height
+ *
+ * TODO: Once the TabPanel gets migrated to Tabs (TabPanel v2) we need to remove this in favor of programmatic tab switching: https://github.com/WordPress/gutenberg/issues/52997
+ *
+ * @param {string} tabId - The ID of the tab to select
+ * @param {string} [scrollToId] - Optional ID of the element to scroll to
+ * @return {Promise} - Resolves when tab switch and scroll are complete
+ */
+export const selectTab = ( tabId, scrollToId ) => {
+ return new Promise( ( resolve ) => {
+ const tab = document.getElementById( tabId );
+ if ( tab ) {
+ tab.click();
+ setTimeout( () => {
+ const scrollTarget = scrollToId
+ ? document.getElementById( scrollToId )
+ : document.getElementById( 'ppcp-settings-container' );
+
+ if ( scrollTarget ) {
+ const navContainer = document.querySelector(
+ '.ppcp-r-navigation-container'
+ );
+ const navHeight = navContainer
+ ? navContainer.offsetHeight
+ : 0;
+
+ // Get the current scroll position and element's position relative to viewport
+ const rect = scrollTarget.getBoundingClientRect();
+
+ // Calculate the final position with offset
+ const scrollPosition =
+ rect.top + window.scrollY - ( navHeight + 55 );
+
+ window.scrollTo( {
+ top: scrollPosition,
+ behavior: 'smooth',
+ } );
+
+ // Resolve after scroll animation
+ setTimeout( resolve, 300 );
+ } else {
+ resolve();
+ }
+ }, 100 );
+ } else {
+ resolve();
+ }
+ } );
+};
diff --git a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php
index 6f249006a..761743817 100644
--- a/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php
+++ b/modules/ppcp-settings/src/Endpoint/CommonRestEndpoint.php
@@ -187,6 +187,40 @@ class CommonRestEndpoint extends RestEndpoint {
return $this->return_success( $js_data, $extra_data );
}
+ /**
+ * Returns mocked merchant data until real data fetching is implemented.
+ *
+ * @return array Mocked merchant details including connection status, features, etc.
+ */
+ protected function get_mocked_merchant_data(): array {
+ return array(
+ 'isConnected' => true,
+ 'isSandbox' => false,
+ 'id' => '',
+ 'email' => '',
+ 'features' => array(
+ 'save_paypal_and_venmo' => array(
+ 'enabled' => true,
+ ),
+ 'advanced_credit_and_debit_cards' => array(
+ 'enabled' => true,
+ ),
+ 'alternative_payment_methods' => array(
+ 'enabled' => true,
+ ),
+ 'google_pay' => array(
+ 'enabled' => true,
+ ),
+ 'apple_pay' => array(
+ 'enabled' => true,
+ ),
+ 'pay_later_messaging' => array(
+ 'enabled' => true,
+ ),
+ ),
+ );
+ }
+
/**
* Appends the "merchant" attribute to the extra_data collection, which
* contains details about the merchant's PayPal account, like the merchant ID.
@@ -195,7 +229,7 @@ class CommonRestEndpoint extends RestEndpoint {
*
* @return array Updated extra_data collection.
*/
- protected function add_merchant_info( array $extra_data ) : array {
+ protected function add_merchant_info( array $extra_data ): array {
$extra_data['merchant'] = $this->sanitize_for_javascript(
$this->settings->to_array(),
$this->merchant_info_map
@@ -208,6 +242,11 @@ class CommonRestEndpoint extends RestEndpoint {
);
}
+ // If no real data is available yet, use mock data.
+ if ( empty( $extra_data['merchant'] ) || ( empty( $extra_data['merchant']['id'] ) && empty( $extra_data['merchant']['email'] ) ) ) {
+ $extra_data['merchant'] = $this->get_mocked_merchant_data();
+ }
+
return $extra_data;
}