Refactor the Overview tab > Features > Buttons

This commit is contained in:
Daniel Dudzic 2025-01-02 13:55:32 +01:00
parent 7a223de4a7
commit e4e95de5f6
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
15 changed files with 602 additions and 239 deletions

View file

@ -119,8 +119,6 @@
background-color: $color-white;
&::before {
transform: translate(3px, 3px);
border-width: 6px;
border-color: $color-blueberry;
}
}

View file

@ -19,6 +19,26 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
);
};
const renderButton = ( button ) => {
const buttonElement = (
<Button
key={ button.text }
variant={ button.type }
onClick={ button.onClick }
>
{ button.text }
</Button>
);
return button.urls ? (
<a href={ button.urls.live } key={ button.text }>
{ buttonElement }
</a>
) : (
buttonElement
);
};
return (
<SettingsBlock { ...props } className="ppcp-r-settings-block__feature">
<Header>
@ -35,15 +55,7 @@ const FeatureSettingsBlock = ( { title, description, ...props } ) => {
</Header>
<Action>
<div className="ppcp-r-feature-item__buttons">
{ props.actionProps?.buttons.map( ( button ) => (
<Button
href={ button.url }
key={ button.text }
variant={ button.type }
>
{ button.text }
</Button>
) ) }
{ props.actionProps?.buttons.map( renderButton ) }
</div>
</Action>
</SettingsBlock>

View file

@ -1,51 +1,50 @@
import { useState } from '@wordpress/element';
import { ToggleControl } from '@wordpress/components';
import SettingsBlock from './SettingsBlock';
import PaymentMethodIcon from '../PaymentMethodIcon';
import data from '../../../utils/data';
import { MODAL_CONFIG } from '../../Screens/Overview/Modals/Modal';
const PaymentMethodItemBlock = ( props ) => {
const [ toggleIsChecked, setToggleIsChecked ] = useState( false );
const [ modalIsVisible, setModalIsVisible ] = useState( false );
const Modal = props?.modal;
const PaymentMethodItemBlock = ( {
id,
title,
description,
icon,
onTriggerModal,
onSelect,
isSelected,
} ) => {
// Only show settings icon if this method has a modal configured
const hasModal = Boolean( MODAL_CONFIG[ id ] );
return (
<>
<SettingsBlock className="ppcp-r-settings-block__payment-methods__item">
<div className="ppcp-r-settings-block__payment-methods__item__inner">
<div className="ppcp-r-settings-block__payment-methods__item__title-wrapper">
<PaymentMethodIcon
icons={ [ props.icon ] }
type={ props.icon }
/>
<span className="ppcp-r-settings-block__payment-methods__item__title">
{ props.title }
</span>
</div>
<p className="ppcp-r-settings-block__payment-methods__item__description">
{ props.description }
</p>
<div className="ppcp-r-settings-block__payment-methods__item__footer">
<ToggleControl
__nextHasNoMarginBottom={ true }
checked={ toggleIsChecked }
onChange={ setToggleIsChecked }
/>
{ Modal && (
<div
className="ppcp-r-settings-block__payment-methods__item__settings"
onClick={ () => setModalIsVisible( true ) }
>
{ data().getImage( 'icon-settings.svg' ) }
</div>
) }
</div>
<SettingsBlock className="ppcp-r-settings-block__payment-methods__item">
<div className="ppcp-r-settings-block__payment-methods__item__inner">
<div className="ppcp-r-settings-block__payment-methods__item__title-wrapper">
<PaymentMethodIcon icons={ [ icon ] } type={ icon } />
<span className="ppcp-r-settings-block__payment-methods__item__title">
{ title }
</span>
</div>
</SettingsBlock>
{ Modal && modalIsVisible && (
<Modal setModalIsVisible={ setModalIsVisible } />
) }
</>
<p className="ppcp-r-settings-block__payment-methods__item__description">
{ description }
</p>
<div className="ppcp-r-settings-block__payment-methods__item__footer">
<ToggleControl
__nextHasNoMarginBottom={ true }
checked={ isSelected }
onChange={ onSelect }
/>
{ hasModal && onTriggerModal && (
<div
className="ppcp-r-settings-block__payment-methods__item__settings"
onClick={ onTriggerModal }
>
{ data().getImage( 'icon-settings.svg' ) }
</div>
) }
</div>
</div>
</SettingsBlock>
);
};

View file

@ -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 )
}
/>
) ) }
</SettingsBlock>

View file

@ -1,6 +1,7 @@
import { Content, ContentWrapper } from './SettingsBlocks';
const SettingsCard = ( {
id,
className: extraClassName,
title,
description,
@ -33,7 +34,7 @@ const SettingsCard = ( {
};
return (
<div className={ className }>
<div id={ id } className={ className }>
<div className="ppcp-r-settings-card__header">
<div className="ppcp-r-settings-card__content-inner">
<span className="ppcp-r-settings-card__title">

View file

@ -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';

View file

@ -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 (
<ModalComponent
setModalIsVisible={ handleCloseModal }
{ ...modalProps }
/>
);
};
export default Modal;

View file

@ -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 { merchant } = useMerchantInfo();
const { refreshFeatureStatuses } = useDispatch( STORE_NAME );
const { refreshFeatureStatuses, setActiveModal } =
useDispatch( STORE_NAME );
const features = featuresDefault.map( ( feature ) => {
const merchantFeature = merchant?.features?.[ 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 = merchant?.features?.[ feature.id ];
return {
...feature,
enabled: merchantFeature?.enabled ?? false,
};
} );
}, [ featuresData, merchant?.features ] );
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 = () => {
</Button>
</>
}
contentItems={ features.map( ( feature ) => (
<FeatureSettingsBlock
key={ feature.id }
title={ feature.title }
description={ feature.description }
actionProps={ {
buttons: feature.buttons,
enabled: feature.enabled,
notes: feature.notes,
badge: feature.enabled
? {
text: __(
'Active',
'woocommerce-paypal-payments'
),
type: TITLE_BADGE_POSITIVE,
}
: undefined,
} }
/>
) ) }
contentItems={ features.map( ( feature ) => {
return (
<FeatureSettingsBlock
key={ feature.id }
title={ feature.title }
description={ feature.description }
actionProps={ {
buttons: feature.buttons
.filter(
( button ) =>
! 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,
} }
/>
);
} ) }
/>
<SettingsCard
@ -219,140 +246,4 @@ const todosDataDefault = [
},
];
// TODO: Hardcoding this list here is not the best idea. Can we move this to a REST API response?
const featuresDefault = [
{
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' ),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
},
{
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' ),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
},
{
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: __( 'Apply', 'woocommerce-paypal-payments' ),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
},
{
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' ),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
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: __(
'Domain registration',
'woocommerce-paypal-payments'
),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
},
{
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' ),
url: '#',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
url: '#',
},
],
},
];
export default TabOverview;

View file

@ -4,12 +4,12 @@ import { useMemo } from '@wordpress/element';
import SettingsCard from '../../ReusableComponents/SettingsCard';
import PaymentMethodsBlock from '../../ReusableComponents/SettingsBlocks/PaymentMethodsBlock';
import { CommonHooks } from '../../../data';
import ModalPayPal from './Modals/ModalPayPal';
import ModalFastlane from './Modals/ModalFastlane';
import ModalAcdc from './Modals/ModalAcdc';
import { useActiveModal } from '../../../data/common/hooks';
import Modal from './Modals/Modal';
const TabPaymentMethods = () => {
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
const { setActiveModal } = useActiveModal();
const filteredPaymentMethods = useMemo( () => {
const contextProps = { storeCountry, storeCurrency };
@ -33,6 +33,7 @@ const TabPaymentMethods = () => {
return (
<div className="ppcp-r-payment-methods">
<SettingsCard
id="ppcp-paypal-checkout-card"
title={ __( 'PayPal Checkout', 'woocommerce-paypal-payments' ) }
description={ __(
'Select your preferred checkout option with PayPal for easy payment processing.',
@ -43,9 +44,11 @@ const TabPaymentMethods = () => {
>
<PaymentMethodsBlock
paymentMethods={ filteredPaymentMethods.payPalCheckout }
onTriggerModal={ setActiveModal }
/>
</SettingsCard>
<SettingsCard
id="ppcp-card-payments-card"
title={ __(
'Online Card Payments',
'woocommerce-paypal-payments'
@ -59,9 +62,11 @@ const TabPaymentMethods = () => {
>
<PaymentMethodsBlock
paymentMethods={ filteredPaymentMethods.onlineCardPayments }
onTriggerModal={ setActiveModal }
/>
</SettingsCard>
<SettingsCard
id="ppcp-alternative-payments-card"
title={ __(
'Alternative Payment Methods',
'woocommerce-paypal-payments'
@ -75,8 +80,11 @@ const TabPaymentMethods = () => {
>
<PaymentMethodsBlock
paymentMethods={ filteredPaymentMethods.alternative }
onTriggerModal={ setActiveModal }
/>
</SettingsCard>
<Modal />
</div>
);
};
@ -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',

View file

@ -0,0 +1,278 @@
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',
},
{
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',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
},
{
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',
},
{
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',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
},
{
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',
},
{
type: 'secondary',
text: __( 'Apply', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
showWhen: 'disabled',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
},
{
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',
},
{
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',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
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',
},
{
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',
},
{
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',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
},
{
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',
},
{
type: 'secondary',
text: __( 'Apply', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
showWhen: 'disabled',
},
{
type: 'tertiary',
text: __( 'Learn more', 'woocommerce-paypal-payments' ),
urls: {
sandbox: '#',
live: '#',
},
},
],
},
],
};
export default Features;

View file

@ -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.
*

View file

@ -34,10 +34,12 @@ const useHooks = () => {
connectToSandbox,
connectToProduction,
connectViaIdAndSecret,
setActiveModal,
} = useDispatch( STORE_NAME );
// Transient accessors.
const isReady = useTransient( 'isReady' );
const activeModal = useTransient( 'activeModal' );
// Persistent accessors.
const clientId = usePersistent( 'clientId' );
@ -61,6 +63,8 @@ const useHooks = () => {
return {
isReady,
activeModal,
setActiveModal,
isSandboxMode,
setSandboxMode: ( state ) => {
return savePersistent( setSandboxMode, state );
@ -146,6 +150,11 @@ export const useMerchantInfo = () => {
};
};
export const useActiveModal = () => {
const { activeModal, setActiveModal } = useHooks();
return { activeModal, setActiveModal };
};
// -- Not using the `useHooks()` data provider --
export const useBusyState = () => {

View file

@ -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( {

View file

@ -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();
}
} );
};

View file

@ -192,6 +192,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.
@ -200,7 +234,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
@ -211,6 +245,11 @@ class CommonRestEndpoint extends RestEndpoint {
$extra_data['merchant'],
);
// 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;
}