mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-08-31 06:52:50 +08:00
Add memoizing and improve the code quality of the card change button
This commit is contained in:
parent
67cbb83f33
commit
4b2da479f3
5 changed files with 120 additions and 134 deletions
|
@ -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">
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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' );
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
} );
|
||||
};
|
||||
|
|
|
@ -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 }
|
||||
/>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue