Add memoizing and improve the code quality of the card change button

This commit is contained in:
Daniel Dudzic 2024-09-06 03:21:27 +02:00
parent 67cbb83f33
commit 4b2da479f3
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
5 changed files with 120 additions and 134 deletions

View file

@ -1,4 +1,4 @@
import { useEffect } from '@wordpress/element';
import { useEffect, useCallback, useMemo } from '@wordpress/element';
const cardIcons = {
VISA: 'visa-light.svg',
@ -14,46 +14,54 @@ export const Payment = ( {
fastlaneSdk,
card,
shippingAddress,
isGuestFlow,
isGuest,
onPaymentLoad,
} ) => {
const { brand, lastDigits, expiry } = card?.paymentSource?.card ?? {};
const { fullName } = shippingAddress?.name ?? {};
useEffect( () => {
if ( isGuestFlow ) {
( async () => {
const paymentComponent =
await fastlaneSdk.FastlaneCardComponent( {} );
paymentComponent.render( `#fastlane-card` );
onPaymentLoad( paymentComponent );
} )();
// Memoized Fastlane card rendering
const loadPaymentComponent = useCallback( async () => {
if ( isGuest ) {
const paymentComponent = await fastlaneSdk.FastlaneCardComponent(
{}
);
paymentComponent.render( `#fastlane-card` );
onPaymentLoad( paymentComponent );
}
}, [ fastlaneSdk, onPaymentLoad, isGuestFlow ] );
}, [ isGuest, fastlaneSdk, onPaymentLoad ] );
const cardLogo = cardIcons[ brand ] ? (
<img
className="wc-block-axo-block-card__meta-icon"
title={ brand }
src={ `${ window.wc_ppcp_axo.icons_directory }${ cardIcons[ brand ] }` }
alt={ brand }
/>
) : (
<span>{ brand }</span>
);
useEffect( () => {
loadPaymentComponent();
}, [ loadPaymentComponent ] );
// Memoized card logo rendering
const cardLogo = useMemo( () => {
return cardIcons[ brand ] ? (
<img
className="wc-block-axo-block-card__meta-icon"
title={ brand }
src={ `${ window.wc_ppcp_axo.icons_directory }${ cardIcons[ brand ] }` }
alt={ brand }
/>
) : (
<span>{ brand }</span>
);
}, [ brand ] );
const formattedExpiry = expiry
? `${ expiry.split( '-' )[ 1 ] }/${ expiry.split( '-' )[ 0 ] }`
: '';
return isGuestFlow ? (
return isGuest ? (
<div id="fastlane-card" key="fastlane-card" />
) : (
<div key="custom-card" className="wc-block-checkout-axo-block-card">
<div className="wc-block-checkout-axo-block-card__meta-container">
<div className="wc-block-axo-block-card__meta">
<span className="wc-block-axo-block-card__meta__digits">{ `**** **** **** ${ lastDigits }` }</span>
<span className="wc-block-axo-block-card__meta__digits">
{ `**** **** **** ${ lastDigits }` }
</span>
{ cardLogo }
</div>
<div className="wc-block-axo-block-card__meta">

View file

@ -29,26 +29,10 @@ const injectShippingChangeButton = ( onChangeShippingAddressClick ) => {
}
};
// Cleanup function to remove the "Change" button when the payment gateway switches
const removeShippingChangeButton = () => {
const existingButton = document.querySelector(
'#shipping-fields .wc-block-checkout-axo-block-card__edit'
);
if ( existingButton ) {
existingButton.remove();
}
};
// ShippingChangeButton component that will handle injection and cleanup
// ShippingChangeButton component for injecting the button
const ShippingChangeButton = ( { onChangeShippingAddressClick } ) => {
useEffect( () => {
// Inject the button when the component mounts
injectShippingChangeButton( onChangeShippingAddressClick );
// Cleanup the button when the component unmounts or the payment gateway switches
return () => {
removeShippingChangeButton();
};
}, [ onChangeShippingAddressClick ] );
return null;

View file

@ -1,10 +1,12 @@
import ReactDOM from 'react-dom/client';
import { FastlaneWatermark } from '../components/FastlaneWatermark';
import { injectShippingChangeButton } from '../helpers/buttonHelpers';
import { populateWooFields } from '../helpers/fieldHelpers';
import { injectCardChangeButton } from '../helpers/gatewayRadioHelpers';
export const onEmailSubmit = async (
email,
fastlaneSdk,
setIsGuest,
isGuest,
setShippingAddress,
setCard,
snapshotFields,
@ -12,7 +14,6 @@ export const onEmailSubmit = async (
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
handlePaymentGatewaySwitch,
onChangeShippingAddressClick,
onChangeButtonClick,
shouldIncludeAdditionalInfo,
@ -41,68 +42,21 @@ export const onEmailSubmit = async (
// Capture the existing WooCommerce data before updating it
snapshotFields( wooShippingAddress, wooBillingAddress );
// Update WooCommerce fields with Fastlane data
setIsGuest( false );
setShippingAddress( profileData.shippingAddress );
injectShippingChangeButton( onChangeShippingAddressClick );
setCard( profileData.card );
setShouldIncludeAdditionalInfo( false );
console.log( 'Profile Data:', profileData );
const { address, name, phoneNumber } = profileData.shippingAddress;
setWooShippingAddress( {
first_name: name.firstName,
last_name: name.lastName,
address_1: address.addressLine1,
address_2: address.addressLine2 || '',
city: address.adminArea2,
state: address.adminArea1,
postcode: address.postalCode,
country: address.countryCode,
phone: phoneNumber.nationalNumber,
} );
const billingData =
profileData.card.paymentSource.card.billingAddress;
setWooBillingAddress( {
first_name: profileData.name.firstName,
last_name: profileData.name.lastName,
address_1: billingData.addressLine1,
address_2: billingData.addressLine2 || '',
city: billingData.adminArea2,
state: billingData.adminArea1,
postcode: billingData.postalCode,
country: billingData.countryCode,
} );
const radioLabelElement = document.getElementById(
'ppcp-axo-block-radio-label'
populateWooFields(
profileData,
setWooShippingAddress,
setWooBillingAddress
);
if ( radioLabelElement ) {
const watermarkRoot = ReactDOM.createRoot( radioLabelElement );
watermarkRoot.render(
<>
<FastlaneWatermark
fastlaneSdk={ fastlaneSdk }
name="fastlane-watermark-radio"
includeAdditionalInfo={
false
}
/>
<button
className="wc-block-checkout-axo-block-card__edit"
aria-label="Change billing details"
type="button"
onClick={ onChangeButtonClick }
>
Change
</button>
</>
);
}
handlePaymentGatewaySwitch( onChangeShippingAddressClick );
injectCardChangeButton( onChangeButtonClick );
} else {
console.warn( 'Authentication failed or did not succeed' );
}

View file

@ -7,7 +7,7 @@ export const snapshotFields = ( shippingAddress, billingAddress ) => {
}
const originalData = { shippingAddress, billingAddress };
console.log( 'Snapshot data:', originalData ); // Debug data
console.log( 'Snapshot data:', originalData );
localStorage.setItem(
'originalCheckoutFields',
JSON.stringify( originalData )
@ -37,3 +37,38 @@ export const restoreOriginalFields = (
);
}
};
export const populateWooFields = (
profileData,
setWooShippingAddress,
setWooBillingAddress
) => {
// Save shipping address
const { address, name, phoneNumber } = profileData.shippingAddress;
setWooShippingAddress( {
first_name: name.firstName,
last_name: name.lastName,
address_1: address.addressLine1,
address_2: address.addressLine2 || '',
city: address.adminArea2,
state: address.adminArea1,
postcode: address.postalCode,
country: address.countryCode,
phone: phoneNumber.nationalNumber,
} );
// Save billing address
const billingData = profileData.card.paymentSource.card.billingAddress;
setWooBillingAddress( {
first_name: profileData.name.firstName,
last_name: profileData.name.lastName,
address_1: billingData.addressLine1,
address_2: billingData.addressLine2 || '',
city: billingData.adminArea2,
state: billingData.adminArea1,
postcode: billingData.postalCode,
country: billingData.countryCode,
} );
};

View file

@ -1,4 +1,4 @@
import { useEffect, useState } from '@wordpress/element';
import { useCallback, useEffect, useState } from '@wordpress/element';
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
@ -11,10 +11,7 @@ import { useCustomerData } from './hooks/useCustomerData';
import { Payment } from './components/Payment';
// Helpers
import {
injectShippingChangeButton,
removeShippingChangeButton,
} from './helpers/buttonHelpers';
import { removeShippingChangeButton } from './helpers/buttonHelpers';
import { snapshotFields, restoreOriginalFields } from './helpers/fieldHelpers';
import { setupWatermark, cleanupWatermark } from './helpers/watermarkHelpers';
@ -29,13 +26,6 @@ if ( typeof window.PayPalCommerceGateway === 'undefined' ) {
const axoConfig = window.wc_ppcp_axo;
// Call this function when the payment gateway is loaded or switched
const handlePaymentGatewaySwitch = ( onChangeShippingAddressClick ) => {
removeShippingChangeButton();
injectShippingChangeButton( onChangeShippingAddressClick );
};
// Axo Component
const Axo = () => {
const [ paypalLoaded, setPaypalLoaded ] = useState( false );
const [ isGuest, setIsGuest ] = useState( true );
@ -53,16 +43,19 @@ const Axo = () => {
setBillingAddress: updateWooBillingAddress,
} = useCustomerData();
// Cleanup function to handle component unmounting
// Inject and cleanup logic for Change button
useEffect( () => {
return () => {
console.log( 'Axo component unmounted, restoring original fields' );
// Remove the shipping Change button on unmount
removeShippingChangeButton();
// Restore WooCommerce fields
restoreOriginalFields(
updateWooShippingAddress,
updateWooBillingAddress
); // Pass the correct arguments
);
};
}, [ updateWooShippingAddress, updateWooBillingAddress ] ); // Add the dependencies
}, [ updateWooShippingAddress, updateWooBillingAddress ] );
const {
setShippingAddress: setWooShippingAddress,
@ -71,14 +64,19 @@ const Axo = () => {
useEffect( () => {
console.log( 'ppcpConfig', ppcpConfig );
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setPaypalLoaded( true );
} );
}, [] );
if ( ! paypalLoaded ) {
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setPaypalLoaded( true );
} );
}
}, [ paypalLoaded, ppcpConfig ] );
useEffect( () => {
let watermarkHandlers = {};
const radioLabelElement = document.getElementById(
'ppcp-axo-block-radio-label'
);
if ( paypalLoaded && fastlaneSdk ) {
console.log( 'Fastlane SDK and PayPal loaded' );
@ -89,11 +87,6 @@ const Axo = () => {
);
const { emailInput } = watermarkHandlers;
console.log(
'shouldIncludeAdditionalInfo',
shouldIncludeAdditionalInfo
);
if ( emailInput ) {
emailInput.addEventListener( 'keyup', async ( event ) => {
const email = event.target.value;
@ -102,6 +95,7 @@ const Axo = () => {
email,
fastlaneSdk,
setIsGuest,
isGuest,
setShippingAddress,
setCard,
snapshotFields,
@ -109,11 +103,10 @@ const Axo = () => {
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
handlePaymentGatewaySwitch,
onChangeShippingAddressClick,
onChangeButtonClick,
shouldIncludeAdditionalInfo,
setShouldIncludeAdditionalInfo
setShouldIncludeAdditionalInfo
);
}
} );
@ -122,10 +115,19 @@ const Axo = () => {
return () => {
cleanupWatermark( watermarkHandlers );
if ( radioLabelElement ) {
const changeButton = radioLabelElement.querySelector(
'.wc-block-checkout-axo-block-card__edit'
);
if ( changeButton ) {
changeButton.remove();
}
}
};
}, [ paypalLoaded, fastlaneSdk, shouldIncludeAdditionalInfo ] );
const onChangeShippingAddressClick = async () => {
const onChangeShippingAddressClick = useCallback( async () => {
// Updated
if ( fastlaneSdk ) {
const { selectionChanged, selectedAddress } =
await fastlaneSdk.profile.showShippingAddressSelector();
@ -151,19 +153,22 @@ const Axo = () => {
} );
}
}
};
}, [ fastlaneSdk, setWooShippingAddress ] );
const onChangeButtonClick = async () => {
const onChangeButtonClick = useCallback( async () => {
const { selectionChanged, selectedCard } =
await fastlaneSdk.profile.showCardSelector();
if ( selectionChanged ) {
setCard( selectedCard );
}
};
}, [ fastlaneSdk ] );
const handlePaymentLoad = ( paymentComponent ) => {
console.log( 'Payment component loaded', paymentComponent );
};
const handlePaymentLoad = useCallback(
( paymentComponent ) => {
console.log( 'Payment component loaded', paymentComponent );
},
[] // Empty dependency array to avoid re-creating the function on every render
);
const handleChange = ( selectedCard ) => {
console.log( 'Selected card changed', selectedCard );
@ -176,7 +181,7 @@ const Axo = () => {
card={ card }
shippingAddress={ shippingAddress }
onChange={ handleChange }
isGuestFlow={ isGuest }
isGuest={ isGuest }
onPaymentLoad={ handlePaymentLoad }
onChangeButtonClick={ onChangeButtonClick }
/>