diff --git a/modules/ppcp-axo-block/resources/css/gateway.scss b/modules/ppcp-axo-block/resources/css/gateway.scss index dfb405606..543217bc1 100644 --- a/modules/ppcp-axo-block/resources/css/gateway.scss +++ b/modules/ppcp-axo-block/resources/css/gateway.scss @@ -78,9 +78,9 @@ } .wp-block-woocommerce-checkout-express-payment-block { - transition: opacity .2s ease-in, - scale .2s ease-in, - display .4s ease-in; + transition: opacity .3s ease-in, + scale .3s ease-in, + display .3s ease-in; /* key to transitioning out */ transition-behavior: allow-discrete; @@ -99,7 +99,7 @@ display: none !important; /* faster leaving the stage then entering */ - transition-duration: .2s; + transition-duration: .5s; transition-timing-function: var(--ease-out-5); } } @@ -153,20 +153,72 @@ margin-top: 4px; } - /* Ensure the button doesn't stretch */ .wc-block-axo-email-submit-button-container .wc-block-components-button { white-space: nowrap; } +} - /* Responsive adjustments */ - @media (max-width: 768px) { - .wc-block-components-text-input { - grid-template-areas: - "input" - "button" - "watermark" - "error"; - grid-template-columns: 1fr; - } +a.wc-block-axo-change-link { + & { + color: var(--wp--preset--color--secondary); + text-decoration: underline; + } + + &:hover { + text-decoration: none; + } + + &: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; + } +} + + diff --git a/modules/ppcp-axo-block/resources/js/components/AxoBlock.js b/modules/ppcp-axo-block/resources/js/components/AxoBlock.js deleted file mode 100644 index 3e243c4c8..000000000 --- a/modules/ppcp-axo-block/resources/js/components/AxoBlock.js +++ /dev/null @@ -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 ? ( -
- - -
- ) : ( -
Loading Fastlane...
- ); -}; - -export default AxoBlock; diff --git a/modules/ppcp-axo-block/resources/js/components/EmailSubmitButton.js b/modules/ppcp-axo-block/resources/js/components/EmailSubmitButton.js deleted file mode 100644 index 7f156ffef..000000000 --- a/modules/ppcp-axo-block/resources/js/components/EmailSubmitButton.js +++ /dev/null @@ -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 ( - - ); -}; - -// 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; diff --git a/modules/ppcp-axo-block/resources/js/components/FastlaneWatermark.js b/modules/ppcp-axo-block/resources/js/components/FastlaneWatermark.js index 8adaeb193..700832047 100644 --- a/modules/ppcp-axo-block/resources/js/components/FastlaneWatermark.js +++ b/modules/ppcp-axo-block/resources/js/components/FastlaneWatermark.js @@ -26,8 +26,6 @@ export const FastlaneWatermark = ( { watermarkRef.current = watermark; watermark.render( `#${ name }` ); - - console.log( 'Watermark rendered successfully' ); } catch ( error ) { console.error( 'Error rendering watermark:', error ); } diff --git a/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js b/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js index cd63ceeb0..f74eb0c7a 100644 --- a/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js +++ b/modules/ppcp-axo-block/resources/js/events/emailLookupManager.js @@ -3,9 +3,7 @@ import { injectShippingChangeButton } from '../helpers/shippingChangeButtonManag import { injectCardChangeButton } from '../helpers/cardChangeButtonManager'; import { setIsGuest } from '../stores/axoStore'; -// Handle the logic for email submission and customer data retrieval -export const onEmailSubmit = async ( - email, +export const createEmailLookupHandler = ( fastlaneSdk, setShippingAddress, setCard, @@ -15,51 +13,74 @@ export const onEmailSubmit = async ( setWooShippingAddress, setWooBillingAddress, onChangeShippingAddressClick, - onChangeButtonClick + onChangeCardButtonClick ) => { - try { - console.log( 'Email value being looked up:', email ); - const lookup = - await fastlaneSdk.identity.lookupCustomerByEmail( email ); + return async ( email ) => { + try { + console.log( 'Email value being looked up:', email ); - console.log( 'Lookup response:', lookup ); + if ( ! fastlaneSdk ) { + throw new Error( 'FastlaneSDK is not initialized' ); + } - if ( ! lookup.customerContextId ) { - console.warn( 'No customerContextId found in the response' ); - return; - } + if ( ! fastlaneSdk.identity ) { + throw new Error( + 'FastlaneSDK identity object is not available' + ); + } - const { authenticationState, profileData } = - await fastlaneSdk.identity.triggerAuthenticationFlow( - lookup.customerContextId + const lookup = + await fastlaneSdk.identity.lookupCustomerByEmail( email ); + + 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 ); - - 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' ); + throw error; } - } catch ( error ) { - console.error( 'Error during email lookup or authentication:', error ); - } + }; }; diff --git a/modules/ppcp-axo-block/resources/js/helpers/cardChangeButtonManager.js b/modules/ppcp-axo-block/resources/js/helpers/cardChangeButtonManager.js index 2e0b85361..e3b5268b6 100644 --- a/modules/ppcp-axo-block/resources/js/helpers/cardChangeButtonManager.js +++ b/modules/ppcp-axo-block/resources/js/helpers/cardChangeButtonManager.js @@ -2,14 +2,17 @@ import { createElement, useEffect, createRoot } from '@wordpress/element'; const CardChangeButton = ( { onChangeButtonClick } ) => createElement( - 'button', + 'a', { - className: 'wc-block-checkout-axo-block-card__edit', - 'aria-label': 'Change billing details', - type: 'button', - onClick: onChangeButtonClick, + className: + 'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link', + role: 'button', + onClick: ( event ) => { + event.preventDefault(); + onChangeButtonClick(); + }, }, - 'Change' + 'Choose a different card' ); const CardChangeButtonManager = ( { onChangeButtonClick } ) => { @@ -56,7 +59,6 @@ export const injectCardChangeButton = ( onChangeButtonClick ) => { }; export const removeCardChangeButton = () => { - console.log('removeCardChangeButton running'); const button = document.querySelector( '.wc-block-checkout-axo-block-card__edit' ); diff --git a/modules/ppcp-axo-block/resources/js/helpers/emailHelpers.js b/modules/ppcp-axo-block/resources/js/helpers/emailHelpers.js deleted file mode 100644 index 40e818410..000000000 --- a/modules/ppcp-axo-block/resources/js/helpers/emailHelpers.js +++ /dev/null @@ -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; -}; diff --git a/modules/ppcp-axo-block/resources/js/helpers/emailSubmissionManager.js b/modules/ppcp-axo-block/resources/js/helpers/emailSubmissionManager.js new file mode 100644 index 000000000..3d0724f75 --- /dev/null +++ b/modules/ppcp-axo-block/resources/js/helpers/emailSubmissionManager.js @@ -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 ( + + ); +}; + +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; diff --git a/modules/ppcp-axo-block/resources/js/helpers/shippingChangeButtonManager.js b/modules/ppcp-axo-block/resources/js/helpers/shippingChangeButtonManager.js index 26301189d..fc93bd675 100644 --- a/modules/ppcp-axo-block/resources/js/helpers/shippingChangeButtonManager.js +++ b/modules/ppcp-axo-block/resources/js/helpers/shippingChangeButtonManager.js @@ -2,17 +2,17 @@ import { createElement, useEffect, createRoot } from '@wordpress/element'; const ShippingChangeButton = ( { onChangeShippingAddressClick } ) => createElement( - 'button', + 'a', { - className: 'wc-block-checkout-axo-block-card__edit', - 'aria-label': 'Change shipping details', - type: 'button', + className: + 'wc-block-checkout-axo-block-card__edit wc-block-axo-change-link', + role: 'button', onClick: ( event ) => { event.preventDefault(); onChangeShippingAddressClick(); }, }, - 'Change' + 'Choose a different shipping address' ); const ShippingChangeButtonManager = ( { onChangeShippingAddressClick } ) => { diff --git a/modules/ppcp-axo-block/resources/js/helpers/watermarkHelpers.js b/modules/ppcp-axo-block/resources/js/helpers/watermarkHelpers.js index dfc69eb6e..6a59ffbc9 100644 --- a/modules/ppcp-axo-block/resources/js/helpers/watermarkHelpers.js +++ b/modules/ppcp-axo-block/resources/js/helpers/watermarkHelpers.js @@ -8,26 +8,29 @@ let watermarkReference = { root: null, }; -const WatermarkManager = ( { fastlaneSdk } ) => { +const WatermarkManager = ( { fastlaneSdk, isLoaded } ) => { const isGuest = useSelect( ( select ) => select( STORE_NAME ).getIsGuest() ); const isAxoActive = useSelect( ( select ) => select( STORE_NAME ).getIsAxoActive() ); + const isAxoScriptLoaded = useSelect( ( select ) => + select( STORE_NAME ).isAxoScriptLoaded() + ); useEffect( () => { - 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"]' + const createWatermark = () => { + const textInputContainer = document.querySelector( + '.wp-block-woocommerce-checkout-contact-information-block .wc-block-components-text-input' ); - if ( emailInput ) { - if ( ! watermarkReference.container ) { + if ( textInputContainer && ! watermarkReference.container ) { + const emailInput = textInputContainer.querySelector( + 'input[type="email"]' + ); + + if ( emailInput ) { watermarkReference.container = document.createElement( 'div' ); watermarkReference.container.setAttribute( @@ -35,7 +38,6 @@ const WatermarkManager = ( { fastlaneSdk } ) => { 'wc-block-checkout-axo-block-watermark-container' ); - // Insert the watermark container after the email input emailInput.parentNode.insertBefore( watermarkReference.container, emailInput.nextSibling @@ -45,8 +47,17 @@ const WatermarkManager = ( { fastlaneSdk } ) => { 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( createElement( FastlaneWatermark, { fastlaneSdk, @@ -54,16 +65,41 @@ const WatermarkManager = ( { fastlaneSdk } ) => { includeAdditionalInfo: isGuest, } ) ); - } else if ( ! isAxoActive && watermarkReference.root ) { + } else { 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 { - console.warn( 'Text input container not found' ); + removeWatermark(); } - }, [ fastlaneSdk, isGuest, isAxoActive ] ); + + return removeWatermark; + }, [ fastlaneSdk, isGuest, isAxoActive, isLoaded, isAxoScriptLoaded ] ); return null; }; @@ -71,22 +107,34 @@ const WatermarkManager = ( { fastlaneSdk } ) => { export const setupWatermark = ( fastlaneSdk ) => { const container = document.createElement( 'div' ); document.body.appendChild( container ); - createRoot( container ).render( - createElement( WatermarkManager, { fastlaneSdk } ) - ); + const root = createRoot( container ); + root.render( createElement( WatermarkManager, { fastlaneSdk } ) ); + + return () => { + root.unmount(); + if ( container && container.parentNode ) { + container.parentNode.removeChild( container ); + } + }; }; export const removeWatermark = () => { if ( watermarkReference.root ) { watermarkReference.root.unmount(); } - if ( - watermarkReference.container && - watermarkReference.container.parentNode - ) { - watermarkReference.container.parentNode.removeChild( - watermarkReference.container - ); + 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 }; }; diff --git a/modules/ppcp-axo-block/resources/js/index.js b/modules/ppcp-axo-block/resources/js/index.js index e629fe9bc..b94d74763 100644 --- a/modules/ppcp-axo-block/resources/js/index.js +++ b/modules/ppcp-axo-block/resources/js/index.js @@ -27,13 +27,12 @@ import { initializeClassToggles } from './helpers/classnamesManager'; import { STORE_NAME } from './stores/axoStore'; // Event handlers -import { onEmailSubmit } from './events/emailLookupManager'; +import { createEmailLookupHandler } from './events/emailLookupManager'; import { - setupEmailEvent, - removeEmailEvent, - isEmailEventSetup, -} from './helpers/emailHelpers'; -import { setupEmailSubmitButton } from './components/EmailSubmitButton'; + setupEmailFunctionality, + removeEmailFunctionality, + isEmailFunctionalitySetup, +} from './helpers/emailSubmissionManager'; const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' ); @@ -49,12 +48,8 @@ const Axo = () => { const [ card, setCard ] = useState( null ); const fastlaneSdk = useAxoBlockManager( axoConfig, ppcpConfig ); - const isAxoActive = useSelect( ( select ) => - select( STORE_NAME ).getIsAxoActive() - ); - const { setIsAxoActive, setIsGuest } = useDispatch( STORE_NAME ); - - const handleEmailInputRef = useRef( null ); + const { setIsAxoActive, setIsGuest, setIsAxoScriptLoaded } = + useDispatch( STORE_NAME ); // Access WooCommerce customer data const { @@ -64,10 +59,6 @@ const Axo = () => { setBillingAddress: updateWooBillingAddress, } = useCustomerData(); - useEffect( () => { - console.log( 'isAxoActive updated:', isAxoActive ); - }, [ isAxoActive ] ); - useEffect( () => { initializeClassToggles(); }, [] ); @@ -88,10 +79,8 @@ const Axo = () => { } = useCustomerData(); useEffect( () => { - console.log( 'ppcpConfig', ppcpConfig ); if ( ! paypalLoaded ) { loadPaypalScript( ppcpConfig, () => { - console.log( 'PayPal script loaded' ); setPaypalLoaded( true ); } ); } @@ -105,76 +94,46 @@ const Axo = () => { 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( () => { + setupWatermark( fastlaneSdk ); if ( paypalLoaded && fastlaneSdk ) { - console.log( 'Enabling Axo' ); + setIsAxoScriptLoaded( true ); setIsAxoActive( true ); - setupWatermark( fastlaneSdk ); - setupEmailSubmitButton( async ( email ) => { - await onEmailSubmit( email ); - } ); - setupEmailEvent( handleEmailInputRef.current ); + const emailLookupHandler = createEmailLookupHandler( + fastlaneSdk, + setShippingAddress, + setCard, + snapshotFields, + wooShippingAddress, + wooBillingAddress, + setWooShippingAddress, + setWooBillingAddress, + onChangeShippingAddressClick, + onChangeCardButtonClick + ); + setupEmailFunctionality( emailLookupHandler ); } - }, [ paypalLoaded, fastlaneSdk, setIsAxoActive ] ); + }, [ + paypalLoaded, + fastlaneSdk, + setIsAxoActive, + setIsAxoScriptLoaded, + wooShippingAddress, + wooBillingAddress, + setWooShippingAddress, + setWooBillingAddress, + onChangeShippingAddressClick, + onChangeCardButtonClick, + ] ); useEffect( () => { return () => { - console.log( 'Disabling Axo' ); - console.log( 'Axo component unmounting' ); setIsAxoActive( false ); setIsGuest( true ); - console.log( 'isAxoActive', isAxoActive ); - - console.log( 'isEmailEventSetup', isEmailEventSetup() ); - removeShippingChangeButton(); removeCardChangeButton(); removeWatermark(); - - if ( isEmailEventSetup() ) { - console.log( - 'Axo became inactive, removing email event listener' - ); - removeEmailEvent( handleEmailInputRef.current ); - } }; }, [ setIsAxoActive, @@ -185,23 +144,15 @@ const Axo = () => { useEffect( () => { return () => { - console.log( 'Disabling Axo' ); setIsAxoActive( false ); setIsGuest( true ); - console.log( 'isAxoActive', isAxoActive ); - - console.log( 'isEmailEventSetup', isEmailEventSetup() ); - removeShippingChangeButton(); removeCardChangeButton(); removeWatermark(); - if ( isEmailEventSetup() ) { - console.log( - 'Axo became inactive, removing email event listener' - ); - removeEmailEvent( handleEmailInputRef.current ); + if ( isEmailFunctionalitySetup() ) { + removeEmailFunctionality(); } }; }, [] ); @@ -214,7 +165,6 @@ const Axo = () => { ); const handleChange = ( selectedCard ) => { - console.log( 'Selected card changed', selectedCard ); setCard( selectedCard ); }; diff --git a/modules/ppcp-axo-block/resources/js/stores/axoStore.js b/modules/ppcp-axo-block/resources/js/stores/axoStore.js index a405b54f2..b945a784d 100644 --- a/modules/ppcp-axo-block/resources/js/stores/axoStore.js +++ b/modules/ppcp-axo-block/resources/js/stores/axoStore.js @@ -8,6 +8,7 @@ export const STORE_NAME = 'woocommerce-paypal-payments/axo-block'; const DEFAULT_STATE = { isGuest: true, isAxoActive: false, + isAxoScriptLoaded: false, }; // Actions @@ -20,6 +21,10 @@ const actions = { type: 'SET_IS_AXO_ACTIVE', payload: isAxoActive, } ), + setIsAxoScriptLoaded: ( isAxoScriptLoaded ) => ( { + type: 'SET_IS_AXO_SCRIPT_LOADED', + payload: isAxoScriptLoaded, + } ), }; // Reducer @@ -29,6 +34,8 @@ const reducer = ( state = DEFAULT_STATE, action ) => { return { ...state, isGuest: action.payload }; case 'SET_IS_AXO_ACTIVE': return { ...state, isAxoActive: action.payload }; + case 'SET_IS_AXO_SCRIPT_LOADED': + return { ...state, isAxoScriptLoaded: action.payload }; default: return state; } @@ -38,6 +45,7 @@ const reducer = ( state = DEFAULT_STATE, action ) => { const selectors = { getIsGuest: ( state ) => state.isGuest, getIsAxoActive: ( state ) => state.isAxoActive, + isAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded, }; // Create and register the store