Add Submit button and loading spinners

This commit is contained in:
Daniel Dudzic 2024-09-11 00:39:09 +02:00
parent 907b807122
commit f86f6a3f5a
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
12 changed files with 430 additions and 542 deletions

View file

@ -78,9 +78,9 @@
} }
.wp-block-woocommerce-checkout-express-payment-block { .wp-block-woocommerce-checkout-express-payment-block {
transition: opacity .2s ease-in, transition: opacity .3s ease-in,
scale .2s ease-in, scale .3s ease-in,
display .4s ease-in; display .3s ease-in;
/* key to transitioning out */ /* key to transitioning out */
transition-behavior: allow-discrete; transition-behavior: allow-discrete;
@ -99,7 +99,7 @@
display: none !important; display: none !important;
/* faster leaving the stage then entering */ /* faster leaving the stage then entering */
transition-duration: .2s; transition-duration: .5s;
transition-timing-function: var(--ease-out-5); transition-timing-function: var(--ease-out-5);
} }
} }
@ -153,20 +153,72 @@
margin-top: 4px; margin-top: 4px;
} }
/* Ensure the button doesn't stretch */
.wc-block-axo-email-submit-button-container .wc-block-components-button { .wc-block-axo-email-submit-button-container .wc-block-components-button {
white-space: nowrap; white-space: nowrap;
} }
}
/* Responsive adjustments */ a.wc-block-axo-change-link {
@media (max-width: 768px) { & {
.wc-block-components-text-input { color: var(--wp--preset--color--secondary);
grid-template-areas: text-decoration: underline;
"input" }
"button"
"watermark" &:hover {
"error"; text-decoration: none;
grid-template-columns: 1fr; }
}
&:focus {
text-decoration: underline dashed;
}
&:active {
color: var(--wp--preset--color--secondary);
text-decoration: none;
} }
} }
.wc-block-checkout-axo-block-watermark-container {
height: 25px;
}
.wp-block-woocommerce-checkout-contact-information-block:not( .wc-block-axo-is-loaded ) .wc-block-checkout-axo-block-watermark-container {
display: flex;
justify-content: left;
margin-left: 10px;
align-items: center;
position: relative;
.wc-block-components-spinner {
box-sizing: content-box;
color: inherit;
font-size: 1em;
height: auto;
width: auto;
position: relative;
margin-top: 12px;
}
}
.wp-block-woocommerce-checkout-contact-information-block.wc-block-axo-is-loaded {
.wc-block-checkout-axo-block-watermark-container .wc-block-components-spinner {
display: none;
visibility: hidden;
opacity: 0;
}
}
.wc-block-axo-email-submit-button-container,
.wc-block-checkout-axo-block-watermark-container #fastlane-watermark-email,
a.wc-block-axo-change-link{
transition: opacity 0.5s ease-in-out;
/* stage enter */
/* key to transitioning in */
@starting-style {
opacity: 0;
scale: 1.1;
}
}

View file

@ -1,197 +0,0 @@
import { useEffect, useState } from '@wordpress/element';
import { useCustomerData } from './useCustomerData';
import { ShippingChangeButton } from './shippingChangeButtonManager';
import { loadPaypalScript } from '../utils/ScriptLoading';
import Payment from './Payment';
import useAxoBlockManager from './useAxoBlockManager';
const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
if ( typeof window.PayPalCommerceGateway === 'undefined' ) {
window.PayPalCommerceGateway = ppcpConfig;
}
const axoConfig = window.wc_ppcp_axo;
// AxoBlock Component
const AxoBlock = () => {
const [ paypalLoaded, setPaypalLoaded ] = useState( false );
const [ isGuest, setIsGuest ] = useState( true );
const [ shippingAddress, setShippingAddress ] = useState( null );
const [ card, setCard ] = useState( null );
const fastlaneSdk = useAxoBlockManager( axoConfig, ppcpConfig );
// WooCommerce customer data hooks
const {
shippingAddress: wooShippingAddress,
billingAddress: wooBillingAddress,
setShippingAddress: updateWooShippingAddress,
setBillingAddress: updateWooBillingAddress,
} = useCustomerData();
// Snapshot and restore original checkout fields from localStorage
const snapshotFields = () => {
const originalData = {
shippingAddress: wooShippingAddress,
billingAddress: wooBillingAddress,
};
localStorage.setItem(
'originalCheckoutFields',
JSON.stringify( originalData )
);
console.log( 'originalFields saved to localStorage', originalData );
};
const restoreOriginalFields = () => {
const savedData = JSON.parse(
localStorage.getItem( 'originalCheckoutFields' )
);
if ( savedData ) {
if ( savedData.shippingAddress ) {
updateWooShippingAddress( savedData.shippingAddress );
}
if ( savedData.billingAddress ) {
updateWooBillingAddress( savedData.billingAddress );
}
console.log(
'originalFields restored from localStorage',
savedData
);
}
};
// Cleanup function to handle component unmounting
useEffect( () => {
// Perform cleanup when the component unmounts
return () => {
console.log( 'Axo component unmounted, restoring original fields' );
restoreOriginalFields(); // Restore original fields when Axo is unmounted
};
}, [] );
useEffect( () => {
console.log( 'ppcpConfig', ppcpConfig );
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setPaypalLoaded( true );
} );
}, [] );
const onEmailSubmit = async ( email ) => {
try {
console.log( 'Email value being looked up:', email );
const lookup =
await fastlaneSdk.identity.lookupCustomerByEmail( email );
if ( ! lookup.customerContextId ) {
console.warn( 'No customerContextId found in the response' );
return;
}
const { authenticationState, profileData } =
await fastlaneSdk.identity.triggerAuthenticationFlow(
lookup.customerContextId
);
if ( authenticationState === 'succeeded' ) {
// Snapshot original fields before updating with Fastlane data
snapshotFields();
// Update WooCommerce fields with Fastlane data
setIsGuest( false );
setShippingAddress( profileData.shippingAddress );
setCard( profileData.card );
const { address, name, phoneNumber } =
profileData.shippingAddress;
updateWooShippingAddress( {
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;
updateWooBillingAddress( {
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,
} );
} else {
console.warn( 'Authentication failed or did not succeed' );
}
} catch ( error ) {
console.error(
'Error during email lookup or authentication:',
error
);
}
};
const onChangeShippingAddressClick = async () => {
if ( fastlaneSdk ) {
const { selectionChanged, selectedAddress } =
await fastlaneSdk.profile.showShippingAddressSelector();
if ( selectionChanged ) {
setShippingAddress( selectedAddress );
const { address, name, phoneNumber } = selectedAddress;
updateWooShippingAddress( {
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 onChangeButtonClick = async () => {
const { selectionChanged, selectedCard } =
await fastlaneSdk.profile.showCardSelector();
if ( selectionChanged ) {
setCard( selectedCard );
}
};
const handlePaymentLoad = ( paymentComponent ) => {
console.log( 'Payment component loaded', paymentComponent );
};
return fastlaneSdk ? (
<div>
<Payment
fastlaneSdk={ fastlaneSdk }
card={ card }
shippingAddress={ shippingAddress }
isGuestFlow={ isGuest }
onPaymentLoad={ handlePaymentLoad }
onChangeButtonClick={ onChangeButtonClick }
/>
<ShippingChangeButton
onChangeShippingAddressClick={ onChangeShippingAddressClick }
/>
</div>
) : (
<div>Loading Fastlane...</div>
);
};
export default AxoBlock;

View file

@ -1,102 +0,0 @@
import { createElement, createRoot } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { STORE_NAME } from '../stores/axoStore';
const EmailSubmitButton = ( { onEmailSubmit } ) => {
const { isGuest, isAxoActive } = useSelect( ( select ) => ( {
isGuest: select( STORE_NAME ).getIsGuest(),
isAxoActive: select( STORE_NAME ).getIsAxoActive(),
} ) );
const handleSubmit = () => {
const emailInput = document.getElementById( 'email' );
if ( emailInput && emailInput.value ) {
onEmailSubmit( emailInput.value );
}
};
if ( ! isGuest || ! isAxoActive ) {
return null;
}
return (
<button
type="button"
onClick={ handleSubmit }
className="wc-block-components-button wp-element-button"
>
Submit
</button>
);
};
// Setup and removal functions
let submitButtonReference = {
container: null,
root: null,
};
export const setupEmailSubmitButton = ( onEmailSubmit ) => {
const emailInput = document.getElementById( 'email' );
if ( emailInput ) {
if ( ! submitButtonReference.container ) {
submitButtonReference.container = document.createElement( 'div' );
submitButtonReference.container.setAttribute(
'class',
'wc-block-axo-email-submit-button-container'
);
emailInput.parentNode.insertBefore(
submitButtonReference.container,
emailInput.nextSibling
);
submitButtonReference.root = createRoot(
submitButtonReference.container
);
}
if ( submitButtonReference.root ) {
const renderButton = () => {
submitButtonReference.root.render(
createElement( EmailSubmitButton, { onEmailSubmit } )
);
};
renderButton(); // Initial render
// Subscribe to state changes
const unsubscribe = wp.data.subscribe( () => {
renderButton();
} );
// Store the unsubscribe function for cleanup
submitButtonReference.unsubscribe = unsubscribe;
} else {
console.warn( 'Submit button root not found' );
}
} else {
console.warn( 'Email input not found' );
}
};
export const removeEmailSubmitButton = () => {
if ( submitButtonReference.root ) {
submitButtonReference.root.unmount();
}
if ( submitButtonReference.unsubscribe ) {
submitButtonReference.unsubscribe();
}
if (
submitButtonReference.container &&
submitButtonReference.container.parentNode
) {
submitButtonReference.container.parentNode.removeChild(
submitButtonReference.container
);
}
submitButtonReference = { container: null, root: null, unsubscribe: null };
};
export default EmailSubmitButton;

View file

@ -26,8 +26,6 @@ export const FastlaneWatermark = ( {
watermarkRef.current = watermark; watermarkRef.current = watermark;
watermark.render( `#${ name }` ); watermark.render( `#${ name }` );
console.log( 'Watermark rendered successfully' );
} catch ( error ) { } catch ( error ) {
console.error( 'Error rendering watermark:', error ); console.error( 'Error rendering watermark:', error );
} }

View file

@ -3,9 +3,7 @@ import { injectShippingChangeButton } from '../helpers/shippingChangeButtonManag
import { injectCardChangeButton } from '../helpers/cardChangeButtonManager'; import { injectCardChangeButton } from '../helpers/cardChangeButtonManager';
import { setIsGuest } from '../stores/axoStore'; import { setIsGuest } from '../stores/axoStore';
// Handle the logic for email submission and customer data retrieval export const createEmailLookupHandler = (
export const onEmailSubmit = async (
email,
fastlaneSdk, fastlaneSdk,
setShippingAddress, setShippingAddress,
setCard, setCard,
@ -15,51 +13,74 @@ export const onEmailSubmit = async (
setWooShippingAddress, setWooShippingAddress,
setWooBillingAddress, setWooBillingAddress,
onChangeShippingAddressClick, onChangeShippingAddressClick,
onChangeButtonClick onChangeCardButtonClick
) => { ) => {
try { return async ( email ) => {
console.log( 'Email value being looked up:', email ); try {
const lookup = console.log( 'Email value being looked up:', email );
await fastlaneSdk.identity.lookupCustomerByEmail( email );
console.log( 'Lookup response:', lookup ); if ( ! fastlaneSdk ) {
throw new Error( 'FastlaneSDK is not initialized' );
}
if ( ! lookup.customerContextId ) { if ( ! fastlaneSdk.identity ) {
console.warn( 'No customerContextId found in the response' ); throw new Error(
return; 'FastlaneSDK identity object is not available'
} );
}
const { authenticationState, profileData } = const lookup =
await fastlaneSdk.identity.triggerAuthenticationFlow( await fastlaneSdk.identity.lookupCustomerByEmail( email );
lookup.customerContextId
console.log( 'Lookup response:', lookup );
if ( ! lookup || ! lookup.customerContextId ) {
console.warn( 'No customerContextId found in the response' );
return;
}
const authResponse =
await fastlaneSdk.identity.triggerAuthenticationFlow(
lookup.customerContextId
);
if ( ! authResponse || ! authResponse.authenticationState ) {
throw new Error( 'Invalid authentication response' );
}
const { authenticationState, profileData } = authResponse;
if ( authenticationState === 'succeeded' ) {
snapshotFields( wooShippingAddress, wooBillingAddress );
setIsGuest( false );
if ( profileData && profileData.shippingAddress ) {
setShippingAddress( profileData.shippingAddress );
}
if ( profileData && profileData.card ) {
setCard( profileData.card );
}
console.log( 'Profile Data:', profileData );
populateWooFields(
profileData,
setWooShippingAddress,
setWooBillingAddress
);
injectShippingChangeButton( onChangeShippingAddressClick );
injectCardChangeButton( onChangeCardButtonClick );
} else {
console.warn( 'Authentication failed or did not succeed' );
}
} catch ( error ) {
console.error(
'Error during email lookup or authentication:',
error
); );
throw error;
console.log( 'authenticationState', authenticationState );
if ( authenticationState === 'succeeded' ) {
// Capture the existing WooCommerce data before updating it
snapshotFields( wooShippingAddress, wooBillingAddress );
console.log( 'Setting isGuest to false' );
setIsGuest( false );
setShippingAddress( profileData.shippingAddress );
setCard( profileData.card );
console.log( 'Profile Data:', profileData );
populateWooFields(
profileData,
setWooShippingAddress,
setWooBillingAddress
);
injectShippingChangeButton( onChangeShippingAddressClick );
injectCardChangeButton( onChangeButtonClick );
} else {
console.warn( 'Authentication failed or did not succeed' );
} }
} catch ( error ) { };
console.error( 'Error during email lookup or authentication:', error );
}
}; };

View file

@ -2,14 +2,17 @@ import { createElement, useEffect, createRoot } from '@wordpress/element';
const CardChangeButton = ( { onChangeButtonClick } ) => const CardChangeButton = ( { onChangeButtonClick } ) =>
createElement( createElement(
'button', 'a',
{ {
className: 'wc-block-checkout-axo-block-card__edit', className:
'aria-label': 'Change billing details', 'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link',
type: 'button', role: 'button',
onClick: onChangeButtonClick, onClick: ( event ) => {
event.preventDefault();
onChangeButtonClick();
},
}, },
'Change' 'Choose a different card'
); );
const CardChangeButtonManager = ( { onChangeButtonClick } ) => { const CardChangeButtonManager = ( { onChangeButtonClick } ) => {
@ -56,7 +59,6 @@ export const injectCardChangeButton = ( onChangeButtonClick ) => {
}; };
export const removeCardChangeButton = () => { export const removeCardChangeButton = () => {
console.log('removeCardChangeButton running');
const button = document.querySelector( const button = document.querySelector(
'.wc-block-checkout-axo-block-card__edit' '.wc-block-checkout-axo-block-card__edit'
); );

View file

@ -1,57 +0,0 @@
let emailInput = null;
let currentHandler = null;
const getEmailInput = () => {
if ( ! emailInput ) {
emailInput = document.getElementById( 'email' );
}
return emailInput;
};
export const setupEmailEvent = ( onEmailSubmit ) => {
const input = getEmailInput();
if ( ! input ) {
console.warn(
'Email input element not found. Event listener not added.'
);
return;
}
if ( currentHandler ) {
console.warn(
'Email event listener already exists. Removing old listener before adding new one.'
);
removeEmailEvent();
}
const handleEmailInput = async ( event ) => {
const email = event.target.value;
if ( email ) {
await onEmailSubmit( email );
}
};
input.addEventListener( 'keyup', handleEmailInput );
currentHandler = handleEmailInput;
console.log( 'Email event listener added' );
};
export const removeEmailEvent = () => {
const input = getEmailInput();
if ( input && currentHandler ) {
input.removeEventListener( 'keyup', currentHandler );
currentHandler = null;
console.log( 'Email event listener removed' );
} else {
console.log(
'Could not remove email event listener. Input:',
input,
'Handler:',
currentHandler
);
}
};
export const isEmailEventSetup = () => {
return !! currentHandler;
};

View file

@ -0,0 +1,165 @@
// EmailSubmissionManager.js
import { createElement, createRoot } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { STORE_NAME } from '../stores/axoStore';
let emailInput = null;
let submitButtonReference = {
container: null,
root: null,
unsubscribe: null,
};
let isLoading = false;
const getEmailInput = () => {
if ( ! emailInput ) {
emailInput = document.getElementById( 'email' );
}
return emailInput;
};
const EmailSubmitButton = ( { handleSubmit } ) => {
const { isGuest, isAxoActive } = useSelect( ( select ) => ( {
isGuest: select( STORE_NAME ).getIsGuest(),
isAxoActive: select( STORE_NAME ).getIsAxoActive(),
} ) );
if ( ! isGuest || ! isAxoActive ) {
return null;
}
return (
<button
type="button"
onClick={ handleSubmit }
className={ `wc-block-components-button wp-element-button ${
isLoading ? 'is-loading' : ''
}` }
disabled={ isLoading }
>
<span
className="wc-block-components-button__text"
style={ { visibility: isLoading ? 'hidden' : 'visible' } }
>
Submit
</span>
{ isLoading && (
<span
className="wc-block-components-spinner"
aria-hidden="true"
style={ {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
} }
/>
) }
</button>
);
};
export const setupEmailFunctionality = ( onEmailSubmit ) => {
const input = getEmailInput();
if ( ! input ) {
console.warn(
'Email input element not found. Functionality not added.'
);
return;
}
const handleEmailSubmit = async () => {
if ( isLoading || ! input.value ) {
return;
}
isLoading = true;
renderButton(); // Re-render button to show loading state
try {
await onEmailSubmit( input.value );
} catch ( error ) {
console.error( 'Error during email submission:', error );
// Here you might want to show an error message to the user
} finally {
isLoading = false;
renderButton(); // Re-render button to remove loading state
}
};
const keydownHandler = ( event ) => {
if ( event.key === 'Enter' ) {
event.preventDefault();
handleEmailSubmit();
}
};
input.addEventListener( 'keydown', keydownHandler );
// Set up submit button
if ( ! submitButtonReference.container ) {
submitButtonReference.container = document.createElement( 'div' );
submitButtonReference.container.setAttribute(
'class',
'wc-block-axo-email-submit-button-container'
);
input.parentNode.insertBefore(
submitButtonReference.container,
input.nextSibling
);
submitButtonReference.root = createRoot(
submitButtonReference.container
);
}
const renderButton = () => {
if ( submitButtonReference.root ) {
submitButtonReference.root.render(
createElement( EmailSubmitButton, {
handleSubmit: handleEmailSubmit,
} )
);
} else {
console.warn( 'Submit button root not found' );
}
};
renderButton(); // Initial render
// Subscribe to state changes
submitButtonReference.unsubscribe = wp.data.subscribe( () => {
renderButton();
} );
};
export const removeEmailFunctionality = () => {
const input = getEmailInput();
if ( input ) {
input.removeEventListener( 'keydown', input.onkeydown );
}
if ( submitButtonReference.root ) {
submitButtonReference.root.unmount();
}
if ( submitButtonReference.unsubscribe ) {
submitButtonReference.unsubscribe();
}
if (
submitButtonReference.container &&
submitButtonReference.container.parentNode
) {
submitButtonReference.container.parentNode.removeChild(
submitButtonReference.container
);
}
submitButtonReference = { container: null, root: null, unsubscribe: null };
};
export const isEmailFunctionalitySetup = () => {
return !! submitButtonReference.root;
};
export default EmailSubmitButton;

View file

@ -2,17 +2,17 @@ import { createElement, useEffect, createRoot } from '@wordpress/element';
const ShippingChangeButton = ( { onChangeShippingAddressClick } ) => const ShippingChangeButton = ( { onChangeShippingAddressClick } ) =>
createElement( createElement(
'button', 'a',
{ {
className: 'wc-block-checkout-axo-block-card__edit', className:
'aria-label': 'Change shipping details', 'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link',
type: 'button', role: 'button',
onClick: ( event ) => { onClick: ( event ) => {
event.preventDefault(); event.preventDefault();
onChangeShippingAddressClick(); onChangeShippingAddressClick();
}, },
}, },
'Change' 'Choose a different shipping address'
); );
const ShippingChangeButtonManager = ( { onChangeShippingAddressClick } ) => { const ShippingChangeButtonManager = ( { onChangeShippingAddressClick } ) => {

View file

@ -8,26 +8,29 @@ let watermarkReference = {
root: null, root: null,
}; };
const WatermarkManager = ( { fastlaneSdk } ) => { const WatermarkManager = ( { fastlaneSdk, isLoaded } ) => {
const isGuest = useSelect( ( select ) => const isGuest = useSelect( ( select ) =>
select( STORE_NAME ).getIsGuest() select( STORE_NAME ).getIsGuest()
); );
const isAxoActive = useSelect( ( select ) => const isAxoActive = useSelect( ( select ) =>
select( STORE_NAME ).getIsAxoActive() select( STORE_NAME ).getIsAxoActive()
); );
const isAxoScriptLoaded = useSelect( ( select ) =>
select( STORE_NAME ).isAxoScriptLoaded()
);
useEffect( () => { useEffect( () => {
const textInputContainer = document.querySelector( const createWatermark = () => {
'.wp-block-woocommerce-checkout-contact-information-block .wc-block-components-text-input' const textInputContainer = document.querySelector(
); '.wp-block-woocommerce-checkout-contact-information-block .wc-block-components-text-input'
if ( textInputContainer ) {
const emailInput = textInputContainer.querySelector(
'input[type="email"]'
); );
if ( emailInput ) { if ( textInputContainer && ! watermarkReference.container ) {
if ( ! watermarkReference.container ) { const emailInput = textInputContainer.querySelector(
'input[type="email"]'
);
if ( emailInput ) {
watermarkReference.container = watermarkReference.container =
document.createElement( 'div' ); document.createElement( 'div' );
watermarkReference.container.setAttribute( watermarkReference.container.setAttribute(
@ -35,7 +38,6 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
'wc-block-checkout-axo-block-watermark-container' 'wc-block-checkout-axo-block-watermark-container'
); );
// Insert the watermark container after the email input
emailInput.parentNode.insertBefore( emailInput.parentNode.insertBefore(
watermarkReference.container, watermarkReference.container,
emailInput.nextSibling emailInput.nextSibling
@ -45,8 +47,17 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
watermarkReference.container watermarkReference.container
); );
} }
}
if ( watermarkReference.root && isAxoActive ) { if ( watermarkReference.root ) {
if ( ! isAxoActive && ! isAxoScriptLoaded ) {
watermarkReference.root.render(
createElement( 'span', {
className: 'wc-block-components-spinner',
'aria-hidden': 'true',
} )
);
} else if ( isAxoActive ) {
watermarkReference.root.render( watermarkReference.root.render(
createElement( FastlaneWatermark, { createElement( FastlaneWatermark, {
fastlaneSdk, fastlaneSdk,
@ -54,16 +65,41 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
includeAdditionalInfo: isGuest, includeAdditionalInfo: isGuest,
} ) } )
); );
} else if ( ! isAxoActive && watermarkReference.root ) { } else {
watermarkReference.root.render( null ); watermarkReference.root.render( null );
} }
} else {
console.warn( 'Email input not found' );
} }
};
const removeWatermark = () => {
if ( watermarkReference.root ) {
watermarkReference.root.unmount();
}
if ( watermarkReference.container ) {
if ( watermarkReference.container.parentNode ) {
watermarkReference.container.parentNode.removeChild(
watermarkReference.container
);
} else {
const detachedContainer = document.querySelector(
'.wc-block-checkout-axo-block-watermark-container'
);
if ( detachedContainer ) {
detachedContainer.remove();
}
}
}
watermarkReference = { container: null, root: null };
};
if ( isAxoActive || ( ! isAxoActive && ! isAxoScriptLoaded ) ) {
createWatermark();
} else { } else {
console.warn( 'Text input container not found' ); removeWatermark();
} }
}, [ fastlaneSdk, isGuest, isAxoActive ] );
return removeWatermark;
}, [ fastlaneSdk, isGuest, isAxoActive, isLoaded, isAxoScriptLoaded ] );
return null; return null;
}; };
@ -71,22 +107,34 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
export const setupWatermark = ( fastlaneSdk ) => { export const setupWatermark = ( fastlaneSdk ) => {
const container = document.createElement( 'div' ); const container = document.createElement( 'div' );
document.body.appendChild( container ); document.body.appendChild( container );
createRoot( container ).render( const root = createRoot( container );
createElement( WatermarkManager, { fastlaneSdk } ) root.render( createElement( WatermarkManager, { fastlaneSdk } ) );
);
return () => {
root.unmount();
if ( container && container.parentNode ) {
container.parentNode.removeChild( container );
}
};
}; };
export const removeWatermark = () => { export const removeWatermark = () => {
if ( watermarkReference.root ) { if ( watermarkReference.root ) {
watermarkReference.root.unmount(); watermarkReference.root.unmount();
} }
if ( if ( watermarkReference.container ) {
watermarkReference.container && if ( watermarkReference.container.parentNode ) {
watermarkReference.container.parentNode watermarkReference.container.parentNode.removeChild(
) { watermarkReference.container
watermarkReference.container.parentNode.removeChild( );
watermarkReference.container } else {
); const detachedContainer = document.querySelector(
'.wc-block-checkout-axo-block-watermark-container'
);
if ( detachedContainer ) {
detachedContainer.remove();
}
}
} }
watermarkReference = { container: null, root: null }; watermarkReference = { container: null, root: null };
}; };

View file

@ -27,13 +27,12 @@ import { initializeClassToggles } from './helpers/classnamesManager';
import { STORE_NAME } from './stores/axoStore'; import { STORE_NAME } from './stores/axoStore';
// Event handlers // Event handlers
import { onEmailSubmit } from './events/emailLookupManager'; import { createEmailLookupHandler } from './events/emailLookupManager';
import { import {
setupEmailEvent, setupEmailFunctionality,
removeEmailEvent, removeEmailFunctionality,
isEmailEventSetup, isEmailFunctionalitySetup,
} from './helpers/emailHelpers'; } from './helpers/emailSubmissionManager';
import { setupEmailSubmitButton } from './components/EmailSubmitButton';
const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' ); const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
@ -49,12 +48,8 @@ const Axo = () => {
const [ card, setCard ] = useState( null ); const [ card, setCard ] = useState( null );
const fastlaneSdk = useAxoBlockManager( axoConfig, ppcpConfig ); const fastlaneSdk = useAxoBlockManager( axoConfig, ppcpConfig );
const isAxoActive = useSelect( ( select ) => const { setIsAxoActive, setIsGuest, setIsAxoScriptLoaded } =
select( STORE_NAME ).getIsAxoActive() useDispatch( STORE_NAME );
);
const { setIsAxoActive, setIsGuest } = useDispatch( STORE_NAME );
const handleEmailInputRef = useRef( null );
// Access WooCommerce customer data // Access WooCommerce customer data
const { const {
@ -64,10 +59,6 @@ const Axo = () => {
setBillingAddress: updateWooBillingAddress, setBillingAddress: updateWooBillingAddress,
} = useCustomerData(); } = useCustomerData();
useEffect( () => {
console.log( 'isAxoActive updated:', isAxoActive );
}, [ isAxoActive ] );
useEffect( () => { useEffect( () => {
initializeClassToggles(); initializeClassToggles();
}, [] ); }, [] );
@ -88,10 +79,8 @@ const Axo = () => {
} = useCustomerData(); } = useCustomerData();
useEffect( () => { useEffect( () => {
console.log( 'ppcpConfig', ppcpConfig );
if ( ! paypalLoaded ) { if ( ! paypalLoaded ) {
loadPaypalScript( ppcpConfig, () => { loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setPaypalLoaded( true ); setPaypalLoaded( true );
} ); } );
} }
@ -105,76 +94,46 @@ const Axo = () => {
const onChangeCardButtonClick = useCardChange( fastlaneSdk, setCard ); const onChangeCardButtonClick = useCardChange( fastlaneSdk, setCard );
const handleEmailInput = useCallback(
async ( email ) => {
if ( fastlaneSdk ) {
await onEmailSubmit(
email,
fastlaneSdk,
setShippingAddress,
setCard,
snapshotFields,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
);
} else {
console.warn( 'FastLane SDK is not available' );
}
},
[
fastlaneSdk,
setShippingAddress,
setCard,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick,
]
);
useEffect( () => {
handleEmailInputRef.current = handleEmailInput;
}, [ handleEmailInput ] );
useEffect( () => { useEffect( () => {
setupWatermark( fastlaneSdk );
if ( paypalLoaded && fastlaneSdk ) { if ( paypalLoaded && fastlaneSdk ) {
console.log( 'Enabling Axo' ); setIsAxoScriptLoaded( true );
setIsAxoActive( true ); setIsAxoActive( true );
setupWatermark( fastlaneSdk ); const emailLookupHandler = createEmailLookupHandler(
setupEmailSubmitButton( async ( email ) => { fastlaneSdk,
await onEmailSubmit( email ); setShippingAddress,
} ); setCard,
setupEmailEvent( handleEmailInputRef.current ); snapshotFields,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
);
setupEmailFunctionality( emailLookupHandler );
} }
}, [ paypalLoaded, fastlaneSdk, setIsAxoActive ] ); }, [
paypalLoaded,
fastlaneSdk,
setIsAxoActive,
setIsAxoScriptLoaded,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick,
] );
useEffect( () => { useEffect( () => {
return () => { return () => {
console.log( 'Disabling Axo' );
console.log( 'Axo component unmounting' );
setIsAxoActive( false ); setIsAxoActive( false );
setIsGuest( true ); setIsGuest( true );
console.log( 'isAxoActive', isAxoActive );
console.log( 'isEmailEventSetup', isEmailEventSetup() );
removeShippingChangeButton(); removeShippingChangeButton();
removeCardChangeButton(); removeCardChangeButton();
removeWatermark(); removeWatermark();
if ( isEmailEventSetup() ) {
console.log(
'Axo became inactive, removing email event listener'
);
removeEmailEvent( handleEmailInputRef.current );
}
}; };
}, [ }, [
setIsAxoActive, setIsAxoActive,
@ -185,23 +144,15 @@ const Axo = () => {
useEffect( () => { useEffect( () => {
return () => { return () => {
console.log( 'Disabling Axo' );
setIsAxoActive( false ); setIsAxoActive( false );
setIsGuest( true ); setIsGuest( true );
console.log( 'isAxoActive', isAxoActive );
console.log( 'isEmailEventSetup', isEmailEventSetup() );
removeShippingChangeButton(); removeShippingChangeButton();
removeCardChangeButton(); removeCardChangeButton();
removeWatermark(); removeWatermark();
if ( isEmailEventSetup() ) { if ( isEmailFunctionalitySetup() ) {
console.log( removeEmailFunctionality();
'Axo became inactive, removing email event listener'
);
removeEmailEvent( handleEmailInputRef.current );
} }
}; };
}, [] ); }, [] );
@ -214,7 +165,6 @@ const Axo = () => {
); );
const handleChange = ( selectedCard ) => { const handleChange = ( selectedCard ) => {
console.log( 'Selected card changed', selectedCard );
setCard( selectedCard ); setCard( selectedCard );
}; };

View file

@ -8,6 +8,7 @@ export const STORE_NAME = 'woocommerce-paypal-payments/axo-block';
const DEFAULT_STATE = { const DEFAULT_STATE = {
isGuest: true, isGuest: true,
isAxoActive: false, isAxoActive: false,
isAxoScriptLoaded: false,
}; };
// Actions // Actions
@ -20,6 +21,10 @@ const actions = {
type: 'SET_IS_AXO_ACTIVE', type: 'SET_IS_AXO_ACTIVE',
payload: isAxoActive, payload: isAxoActive,
} ), } ),
setIsAxoScriptLoaded: ( isAxoScriptLoaded ) => ( {
type: 'SET_IS_AXO_SCRIPT_LOADED',
payload: isAxoScriptLoaded,
} ),
}; };
// Reducer // Reducer
@ -29,6 +34,8 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
return { ...state, isGuest: action.payload }; return { ...state, isGuest: action.payload };
case 'SET_IS_AXO_ACTIVE': case 'SET_IS_AXO_ACTIVE':
return { ...state, isAxoActive: action.payload }; return { ...state, isAxoActive: action.payload };
case 'SET_IS_AXO_SCRIPT_LOADED':
return { ...state, isAxoScriptLoaded: action.payload };
default: default:
return state; return state;
} }
@ -38,6 +45,7 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
const selectors = { const selectors = {
getIsGuest: ( state ) => state.isGuest, getIsGuest: ( state ) => state.isGuest,
getIsAxoActive: ( state ) => state.isAxoActive, getIsAxoActive: ( state ) => state.isAxoActive,
isAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
}; };
// Create and register the store // Create and register the store