Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Axo: Add support for card icons in the Block Checkout and add card type limiting for both block and classic checkouts (3783) #2704

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions modules/ppcp-axo-block/resources/css/gateway.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,19 @@ $fast-transition-duration: 0.5s;
}

// 1. AXO Block Radio Label
#ppcp-axo-block-radio-label {
@include flex-space-between;
.wc-block-checkout__payment-method label[for="radio-control-wc-payment-method-options-ppcp-axo-gateway"] {
padding-right: .875em;
}

#radio-control-wc-payment-method-options-ppcp-axo-gateway__label {
display: flex;
align-items: center;
width: 100%;
padding-right: 1em;

.wc-block-components-payment-method-icons {
margin: 0;
}
}

// 2. AXO Block Card
Expand Down Expand Up @@ -70,15 +79,16 @@ $fast-transition-duration: 0.5s;
}

&__edit {
background-color: transparent;
flex-grow: 1;
margin-left: auto;
text-align: right;
border: 0;
color: inherit;
cursor: pointer;
display: block;
font-family: inherit;
margin: 0 0 0 auto;
font-size: 0.875em;
font-weight: normal;
color: inherit;
background-color: transparent;
cursor: pointer;

&:hover {
text-decoration: underline;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { createElement } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { STORE_NAME } from '../../stores/axoStore';

/**
* Renders a button to change the selected card in the checkout process.
*
* @param {Object} props
* @param {Function} props.onChangeButtonClick - Callback function to handle the click event.
* @return {JSX.Element} The rendered button as an anchor tag.
* @return {JSX.Element|null} The rendered button as an anchor tag, or null if conditions aren't met.
*/
const CardChangeButton = ( { onChangeButtonClick } ) =>
createElement(
const CardChangeButton = () => {
const { isGuest, cardDetails, cardChangeHandler } = useSelect(
( select ) => ( {
isGuest: select( STORE_NAME ).getIsGuest(),
cardDetails: select( STORE_NAME ).getCardDetails(),
cardChangeHandler: select( STORE_NAME ).getCardChangeHandler(),
} ),
[]
);

if ( isGuest || ! cardDetails || ! cardChangeHandler ) {
return null;
}

return createElement(
'a',
{
className:
Expand All @@ -19,10 +32,11 @@ const CardChangeButton = ( { onChangeButtonClick } ) =>
// Prevent default anchor behavior
event.preventDefault();
// Call the provided click handler
onChangeButtonClick();
cardChangeHandler();
},
},
__( 'Choose a different card', 'woocommerce-paypal-payments' )
);
};

export default CardChangeButton;

This file was deleted.

2 changes: 0 additions & 2 deletions modules/ppcp-axo-block/resources/js/components/Card/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
export { default as Card } from './Card';
export { default as CardChangeButton } from './CardChangeButton';
export { default as CardChangeButtonManager } from './CardChangeButtonManager';
export { injectCardChangeButton, removeCardChangeButton } from './utils';
32 changes: 0 additions & 32 deletions modules/ppcp-axo-block/resources/js/components/Card/utils.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import CardChangeButton from './../Card/CardChangeButton';

/**
* TitleLabel component for displaying a payment method title with icons and a change card button.
*
* @param {Object} props - Component props
* @param {Object} props.components - Object containing WooCommerce components
* @param {Object} props.config - Configuration object for the payment method
* @return {JSX.Element} WordPress element
*/
const TitleLabel = ( { components, config } ) => {
const axoConfig = window.wc_ppcp_axo;
const { PaymentMethodIcons } = components;

return (
<>
<span dangerouslySetInnerHTML={ { __html: config.title } } />
<PaymentMethodIcons icons={ axoConfig?.card_icons } />
<CardChangeButton />
</>
);
};

export default TitleLabel;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as TitleLabel } from './TitleLabel';
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { populateWooFields } from '../helpers/fieldHelpers';
import { injectShippingChangeButton } from '../components/Shipping';
import { injectCardChangeButton } from '../components/Card';
import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';

/**
Expand All @@ -16,7 +15,6 @@ import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
* @param {Function} setWooShippingAddress - Function to update WooCommerce shipping address.
* @param {Function} setWooBillingAddress - Function to update WooCommerce billing address.
* @param {Function} onChangeShippingAddressClick - Handler for shipping address change.
* @param {Function} onChangeCardButtonClick - Handler for card change.
* @return {Function} The email lookup handler function.
*/
export const createEmailLookupHandler = (
Expand All @@ -28,8 +26,7 @@ export const createEmailLookupHandler = (
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
onChangeShippingAddressClick
) => {
return async ( email ) => {
try {
Expand Down Expand Up @@ -102,9 +99,8 @@ export const createEmailLookupHandler = (
setWooBillingAddress
);

// Inject change buttons for shipping and card
// Inject the change button for shipping
injectShippingChangeButton( onChangeShippingAddressClick );
injectCardChangeButton( onChangeCardButtonClick );
} else {
log( 'Authentication failed or did not succeed', 'warn' );
}
Expand Down
2 changes: 0 additions & 2 deletions modules/ppcp-axo-block/resources/js/hooks/useAxoCleanup.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { useDispatch } from '@wordpress/data';
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { STORE_NAME } from '../stores/axoStore';
import { removeShippingChangeButton } from '../components/Shipping';
import { removeCardChangeButton } from '../components/Card';
import { removeWatermark } from '../components/Watermark';
import {
removeEmailFunctionality,
Expand Down Expand Up @@ -50,7 +49,6 @@ const useAxoCleanup = () => {

// Remove AXO UI elements
removeShippingChangeButton();
removeCardChangeButton();
removeWatermark();

// Remove email functionality if it was set up
Expand Down
5 changes: 3 additions & 2 deletions modules/ppcp-axo-block/resources/js/hooks/useAxoSetup.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const useAxoSetup = (
setIsAxoScriptLoaded,
setShippingAddress,
setCardDetails,
setCardChangeHandler,
} = useDispatch( STORE_NAME );

// Check if PayPal script has loaded
Expand Down Expand Up @@ -73,6 +74,7 @@ const useAxoSetup = (
if ( paypalLoaded && fastlaneSdk ) {
setIsAxoScriptLoaded( true );
setIsAxoActive( true );
setCardChangeHandler( onChangeCardButtonClick );

// Create and set up email lookup handler
const emailLookupHandler = createEmailLookupHandler(
Expand All @@ -84,8 +86,7 @@ const useAxoSetup = (
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
onChangeShippingAddressClick
);
setupEmailFunctionality( emailLookupHandler );
}
Expand Down
36 changes: 36 additions & 0 deletions modules/ppcp-axo-block/resources/js/hooks/useCardOptions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useMemo } from '@wordpress/element';

const DEFAULT_ALLOWED_CARDS = [ 'VISA', 'MASTERCARD', 'AMEX', 'DISCOVER' ];

/**
* Custom hook to determine the allowed card options based on configuration.
*
* @param {Object} axoConfig - The AXO configuration object.
* @return {Array} The final list of allowed card options.
*/
const useCardOptions = ( axoConfig ) => {
const merchantCountry = axoConfig.merchant_country || 'US';

return useMemo( () => {
const allowedCards = new Set(
axoConfig.allowed_cards?.[ merchantCountry ] ||
DEFAULT_ALLOWED_CARDS
);

// Create a Set of disabled cards, converting each to uppercase
const disabledCards = new Set(
( axoConfig.disable_cards || [] ).map( ( card ) =>
card.toUpperCase()
)
);

// Filter out disabled cards from the allowed cards
const finalCardOptions = [ ...allowedCards ].filter(
( card ) => ! disabledCards.has( card )
);

return finalCardOptions;
}, [ axoConfig.allowed_cards, axoConfig.disable_cards, merchantCountry ] );
};

export default useCardOptions;
9 changes: 8 additions & 1 deletion modules/ppcp-axo-block/resources/js/hooks/useFastlaneSdk.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useSelect } from '@wordpress/data';
import Fastlane from '../../../../ppcp-axo/resources/js/Connection/Fastlane';
import { log } from '../../../../ppcp-axo/resources/js/Helper/Debug';
import { useDeleteEmptyKeys } from './useDeleteEmptyKeys';
import useCardOptions from './useCardOptions';
import useAllowedLocations from './useAllowedLocations';
import { STORE_NAME } from '../stores/axoStore';

Expand All @@ -27,6 +28,8 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
[]
);

const cardOptions = useCardOptions( axoConfig );

const styleOptions = useMemo( () => {
return deleteEmptyKeys( configRef.current.axoConfig.style_options );
}, [ deleteEmptyKeys ] );
Expand All @@ -51,10 +54,13 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
window.localStorage.setItem( 'axoEnv', 'sandbox' );
}

// Connect to Fastlane with locale and style options
// Connect to Fastlane with locale, style options, and allowed card brands
await fastlane.connect( {
locale: configRef.current.ppcpConfig.locale,
styles: styleOptions,
cardOptions: {
allowedBrands: cardOptions,
},
shippingAddressOptions: {
allowedLocations,
},
Expand All @@ -77,6 +83,7 @@ const useFastlaneSdk = ( namespace, axoConfig, ppcpConfig ) => {
styleOptions,
isPayPalLoaded,
namespace,
cardOptions,
allowedLocations,
] );

Expand Down
8 changes: 2 additions & 6 deletions modules/ppcp-axo-block/resources/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import usePayPalCommerceGateway from './hooks/usePayPalCommerceGateway';

// Components
import { Payment } from './components/Payment/Payment';
import { TitleLabel } from './components/TitleLabel';

const gatewayHandle = 'ppcp-axo-gateway';
const namespace = 'ppcpBlocksPaypalAxo';
Expand Down Expand Up @@ -89,12 +90,7 @@ const Axo = ( props ) => {

registerPaymentMethod( {
name: initialConfig.id,
label: (
<div
id="ppcp-axo-block-radio-label"
dangerouslySetInnerHTML={ { __html: initialConfig.title } }
/>
),
label: <TitleLabel config={ initialConfig } />,
content: <Axo />,
edit: createElement( initialConfig.title ),
ariaLabel: initialConfig.title,
Expand Down
Loading
Loading