Further separate code into hooks: useAxoCleanup, useAxoSetup, usePayPalScript and usePaymentSetup. Hide Shipping and Billing details on load.

This commit is contained in:
Daniel Dudzic 2024-09-13 19:24:23 +02:00
parent 90aa261c8b
commit 4bda191f0e
No known key found for this signature in database
GPG key ID: 31B40D33E3465483
13 changed files with 282 additions and 165 deletions

View file

@ -113,16 +113,18 @@
}
.wc-block-checkout-axo-block-watermark-container {
margin-top: 10px;
margin-left: 5px;
}
//.wc-block-axo-is-loaded:not(.wc-block-axo-is-authenticated) {
// #shipping-fields,
// #shipping-option,
// #order-notes {
// display: none;
// }
//}
.wc-block-axo-is-loaded:not(.wc-block-axo-email-lookup-completed) {
#shipping-fields,
#billing-fields,
#shipping-option,
#order-notes {
display: none;
}
}
.wc-block-axo-is-loaded {
&.wc-block-axo-is-authenticated .wc-block-components-text-input {

View file

@ -6,7 +6,7 @@ const EmailButton = ( { handleSubmit } ) => {
( select ) => ( {
isGuest: select( STORE_NAME ).getIsGuest(),
isAxoActive: select( STORE_NAME ).getIsAxoActive(),
isEmailSubmitted: select( STORE_NAME ).isEmailSubmitted(),
isEmailSubmitted: select( STORE_NAME ).getIsEmailSubmitted(),
} )
);

View file

@ -29,7 +29,7 @@ export const setupEmailFunctionality = ( onEmailSubmit ) => {
const handleEmailSubmit = async () => {
const isEmailSubmitted = wp.data
.select( STORE_NAME )
.isEmailSubmitted();
.getIsEmailSubmitted();
if ( isEmailSubmitted || ! input.value ) {
return;

View file

@ -19,7 +19,7 @@ const WatermarkManager = ( { fastlaneSdk } ) => {
select( STORE_NAME ).getIsAxoActive()
);
const isAxoScriptLoaded = useSelect( ( select ) =>
select( STORE_NAME ).isAxoScriptLoaded()
select( STORE_NAME ).getIsAxoScriptLoaded()
);
console.log( 'WatermarkManager state', {

View file

@ -1,7 +1,7 @@
import { populateWooFields } from '../helpers/fieldHelpers';
import { injectShippingChangeButton } from '../components/Shipping';
import { injectCardChangeButton } from '../components/Card';
import { setIsGuest } from '../stores/axoStore';
import { setIsGuest, setIsEmailLookupCompleted } from '../stores/axoStore';
export const createEmailLookupHandler = (
fastlaneSdk,
@ -34,6 +34,11 @@ export const createEmailLookupHandler = (
console.log( 'Lookup response:', lookup );
// Gary flow
if ( lookup && lookup.customerContextId === '' ) {
setIsEmailLookupCompleted( true );
}
if ( ! lookup || ! lookup.customerContextId ) {
console.warn( 'No customerContextId found in the response' );
return;
@ -50,9 +55,13 @@ export const createEmailLookupHandler = (
const { authenticationState, profileData } = authResponse;
// OTP success/fail/cancel flow
if ( authResponse ) {
setIsEmailLookupCompleted( true );
}
if ( authenticationState === 'succeeded' ) {
snapshotFields( wooShippingAddress, wooBillingAddress );
setIsGuest( false );
if ( profileData && profileData.shippingAddress ) {

View file

@ -37,16 +37,49 @@ export const setupAuthenticationClassToggle = () => {
return unsubscribe;
};
export const setupEmailLookupCompletedClassToggle = () => {
const targetSelector = '.wp-block-woocommerce-checkout-fields-block';
const emailLookupCompletedClass = 'wc-block-axo-email-lookup-completed';
const updateEmailLookupCompletedClass = () => {
const targetElement = document.querySelector( targetSelector );
if ( ! targetElement ) {
console.warn( `Target element not found: ${ targetSelector }` );
return;
}
const isEmailLookupCompleted =
select( STORE_NAME ).getIsEmailLookupCompleted();
if ( isEmailLookupCompleted ) {
targetElement.classList.add( emailLookupCompletedClass );
} else {
targetElement.classList.remove( emailLookupCompletedClass );
}
};
// Initial update
updateEmailLookupCompletedClass();
// Subscribe to state changes
const unsubscribe = subscribe( () => {
updateEmailLookupCompletedClass();
} );
return unsubscribe;
};
/**
* Sets up class toggles for the contact information block based on isAxoActive and isGuest states.
* @return {Function} Unsubscribe function for cleanup.
*/
export const setupContactInfoClassToggles = () => {
export const setupCheckoutBlockClassToggles = () => {
const targetSelector = '.wp-block-woocommerce-checkout-fields-block';
const axoLoadedClass = 'wc-block-axo-is-loaded';
const authClass = 'wc-block-axo-is-authenticated';
const emailLookupCompletedClass = 'wc-block-axo-email-lookup-completed';
const updateContactInfoClasses = () => {
const updateCheckoutBlockClassToggles = () => {
const targetElement = document.querySelector( targetSelector );
if ( ! targetElement ) {
console.warn( `Target element not found: ${ targetSelector }` );
@ -55,6 +88,8 @@ export const setupContactInfoClassToggles = () => {
const isAxoActive = select( STORE_NAME ).getIsAxoActive();
const isGuest = select( STORE_NAME ).getIsGuest();
const isEmailLookupCompleted =
select( STORE_NAME ).getIsEmailLookupCompleted();
if ( isAxoActive ) {
targetElement.classList.add( axoLoadedClass );
@ -67,14 +102,20 @@ export const setupContactInfoClassToggles = () => {
} else {
targetElement.classList.remove( authClass );
}
if ( isEmailLookupCompleted ) {
targetElement.classList.add( emailLookupCompletedClass );
} else {
targetElement.classList.remove( emailLookupCompletedClass );
}
};
// Initial update
updateContactInfoClasses();
updateCheckoutBlockClassToggles();
// Subscribe to state changes
const unsubscribe = subscribe( () => {
updateContactInfoClasses();
updateCheckoutBlockClassToggles();
} );
return unsubscribe;
@ -86,12 +127,17 @@ export const setupContactInfoClassToggles = () => {
*/
export const initializeClassToggles = () => {
const unsubscribeAuth = setupAuthenticationClassToggle();
const unsubscribeContactInfo = setupContactInfoClassToggles();
const unsubscribeEmailLookupCompleted =
setupEmailLookupCompletedClassToggle();
const unsubscribeContactInfo = setupCheckoutBlockClassToggles();
return () => {
if ( unsubscribeAuth ) {
unsubscribeAuth();
}
if ( unsubscribeEmailLookupCompleted ) {
unsubscribeEmailLookupCompleted();
}
if ( unsubscribeContactInfo ) {
unsubscribeContactInfo();
}

View file

@ -0,0 +1,9 @@
import { loadPaypalScript } from '../../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
export const payPalScriptLoader = ( ppcpConfig, callback ) => {
console.log( 'Loading PayPal script' );
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
callback();
} );
};

View file

@ -0,0 +1,44 @@
import { useEffect } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { STORE_NAME } from '../stores/axoStore';
import { removeShippingChangeButton } from '../components/Shipping';
import { removeCardChangeButton } from '../components/Card';
import { removeWatermark } from '../components/Watermark';
import {
removeEmailFunctionality,
isEmailFunctionalitySetup,
} from '../components/EmailButton';
import { restoreOriginalFields } from '../helpers/fieldHelpers';
const useAxoCleanup = ( updateWooShippingAddress, updateWooBillingAddress ) => {
const { setIsAxoActive, setIsGuest } = useDispatch( STORE_NAME );
useEffect( () => {
console.log( 'Setting up cleanup for WooCommerce fields' );
return () => {
console.log( 'Cleaning up: Restoring WooCommerce fields' );
restoreOriginalFields(
updateWooShippingAddress,
updateWooBillingAddress
);
};
}, [ updateWooShippingAddress, updateWooBillingAddress ] );
useEffect( () => {
console.log( 'Setting up cleanup for Axo component' );
return () => {
console.log( 'Cleaning up Axo component' );
setIsAxoActive( false );
setIsGuest( true );
removeShippingChangeButton();
removeCardChangeButton();
removeWatermark();
if ( isEmailFunctionalitySetup() ) {
console.log( 'Removing email functionality' );
removeEmailFunctionality();
}
};
}, [] );
};
export default useAxoCleanup;

View file

@ -0,0 +1,72 @@
import { useEffect } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { STORE_NAME } from '../stores/axoStore';
import usePayPalScript from './usePayPalScript';
import { setupWatermark } from '../components/Watermark';
import { setupEmailFunctionality } from '../components/EmailButton';
import { createEmailLookupHandler } from '../events/emailLookupManager';
import { initializeClassToggles } from '../helpers/classnamesManager';
import { snapshotFields } from '../helpers/fieldHelpers';
const useAxoSetup = (
ppcpConfig,
fastlaneSdk,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick,
setShippingAddress,
setCard
) => {
const { setIsAxoActive, setIsAxoScriptLoaded } = useDispatch( STORE_NAME );
const paypalLoaded = usePayPalScript( ppcpConfig );
useEffect( () => {
console.log( 'Initializing class toggles' );
initializeClassToggles();
}, [] );
useEffect( () => {
console.log( 'Setting up Axo functionality' );
setupWatermark( fastlaneSdk );
if ( paypalLoaded && fastlaneSdk ) {
console.log(
'PayPal loaded and FastlaneSDK available, setting up email functionality'
);
setIsAxoScriptLoaded( true );
setIsAxoActive( true );
const emailLookupHandler = createEmailLookupHandler(
fastlaneSdk,
setShippingAddress,
setCard,
snapshotFields,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
);
setupEmailFunctionality( emailLookupHandler );
}
}, [
paypalLoaded,
fastlaneSdk,
setIsAxoActive,
setIsAxoScriptLoaded,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick,
setShippingAddress,
setCard,
] );
return paypalLoaded;
};
export default useAxoSetup;

View file

@ -0,0 +1,20 @@
import { useState, useEffect } from '@wordpress/element';
import { loadPaypalScript } from '../../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
const usePayPalScript = ( ppcpConfig ) => {
const [ isLoaded, setIsLoaded ] = useState( false );
useEffect( () => {
if ( ! isLoaded ) {
console.log( 'Loading PayPal script' );
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setIsLoaded( true );
} );
}
}, [ ppcpConfig, isLoaded ] );
return isLoaded;
};
export default usePayPalScript;

View file

@ -0,0 +1,27 @@
import { useEffect } from '@wordpress/element';
const usePaymentSetup = ( onPaymentSetup, emitResponse, card ) => {
useEffect( () => {
const unsubscribe = onPaymentSetup( async () => {
return {
type: emitResponse.responseTypes.SUCCESS,
meta: {
paymentMethodData: {
axo_nonce: card?.id,
},
},
};
} );
return () => {
unsubscribe();
};
}, [
emitResponse.responseTypes.ERROR,
emitResponse.responseTypes.SUCCESS,
onPaymentSetup,
card,
] );
};
export default usePaymentSetup;

View file

@ -1,84 +1,28 @@
import { useCallback, useEffect, useState } from '@wordpress/element';
import { useDispatch } from '@wordpress/data';
import { useCallback, useState } from '@wordpress/element';
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading';
// Hooks
import useFastlaneSdk from './hooks/useFastlaneSdk';
import useCustomerData from './hooks/useCustomerData';
import useShippingAddressChange from './hooks/useShippingAddressChange';
import useCardChange from './hooks/useCardChange';
import useAxoSetup from './hooks/useAxoSetup';
import usePaymentSetup from './hooks/usePaymentSetup';
import useAxoCleanup from './hooks/useAxoCleanup';
// Components
import { Payment } from './components/Payment/Payment';
// Helpers
import { snapshotFields, restoreOriginalFields } from './helpers/fieldHelpers';
import { removeWatermark, setupWatermark } from './components/Watermark';
import { removeCardChangeButton } from './components/Card';
import { removeShippingChangeButton } from './components/Shipping';
import { initializeClassToggles } from './helpers/classnamesManager';
// Stores
import { STORE_NAME } from './stores/axoStore';
// Event handlers
import { createEmailLookupHandler } from './events/emailLookupManager';
import {
setupEmailFunctionality,
removeEmailFunctionality,
isEmailFunctionalitySetup,
} from './components/EmailButton';
const ppcpConfig = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
if ( typeof window.PayPalCommerceGateway === 'undefined' ) {
window.PayPalCommerceGateway = ppcpConfig;
}
const axoConfig = window.wc_ppcp_axo;
const Axo = ( props ) => {
const { eventRegistration, emitResponse } = props;
const { onPaymentSetup } = eventRegistration;
const [ paypalLoaded, setPaypalLoaded ] = useState( false );
const [ shippingAddress, setShippingAddress ] = useState( null );
const [ card, setCard ] = useState( null );
const fastlaneSdk = useFastlaneSdk( axoConfig, ppcpConfig );
console.log( 'Axo component rendering' );
useEffect( () => {
const unsubscribe = onPaymentSetup( async () => {
// Validate payment options and emit response.
// Note: This response supports the Ryan flow (payment via saved card-token)
return {
type: emitResponse.responseTypes.SUCCESS,
meta: {
paymentMethodData: {
axo_nonce: card?.id,
},
},
};
} );
// Unsubscribes when this component is unmounted.
return () => {
unsubscribe();
};
}, [
emitResponse.responseTypes.ERROR,
emitResponse.responseTypes.SUCCESS,
onPaymentSetup,
card,
] );
const { setIsAxoActive, setIsGuest, setIsAxoScriptLoaded } =
useDispatch( STORE_NAME );
const {
shippingAddress: wooShippingAddress,
billingAddress: wooBillingAddress,
@ -86,37 +30,6 @@ const Axo = ( props ) => {
setBillingAddress: updateWooBillingAddress,
} = useCustomerData();
useEffect( () => {
console.log( 'Initializing class toggles' );
initializeClassToggles();
}, [] );
useEffect( () => {
console.log( 'Setting up cleanup for WooCommerce fields' );
return () => {
console.log( 'Cleaning up: Restoring WooCommerce fields' );
restoreOriginalFields(
updateWooShippingAddress,
updateWooBillingAddress
);
};
}, [ updateWooShippingAddress, updateWooBillingAddress ] );
useEffect( () => {
if ( ! paypalLoaded ) {
console.log( 'Loading PayPal script' );
loadPaypalScript( ppcpConfig, () => {
console.log( 'PayPal script loaded' );
setPaypalLoaded( true );
} );
}
}, [ paypalLoaded, ppcpConfig ] );
const {
setShippingAddress: setWooShippingAddress,
setBillingAddress: setWooBillingAddress,
} = useCustomerData();
const onChangeShippingAddressClick = useShippingAddressChange(
fastlaneSdk,
setShippingAddress,
@ -128,63 +41,26 @@ const Axo = ( props ) => {
updateWooBillingAddress
);
useEffect( () => {
console.log( 'Setting up Axo functionality' );
setupWatermark( fastlaneSdk );
if ( paypalLoaded && fastlaneSdk ) {
console.log(
'PayPal loaded and FastlaneSDK available, setting up email functionality'
);
setIsAxoScriptLoaded( true );
setIsAxoActive( true );
const emailLookupHandler = createEmailLookupHandler(
fastlaneSdk,
setShippingAddress,
setCard,
snapshotFields,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick
);
setupEmailFunctionality( emailLookupHandler );
}
}, [
paypalLoaded,
useAxoSetup(
ppcpConfig,
fastlaneSdk,
setIsAxoActive,
setIsAxoScriptLoaded,
wooShippingAddress,
wooBillingAddress,
setWooShippingAddress,
setWooBillingAddress,
updateWooShippingAddress,
updateWooBillingAddress,
onChangeShippingAddressClick,
onChangeCardButtonClick,
] );
useEffect( () => {
console.log( 'Setting up cleanup for Axo component' );
return () => {
console.log( 'Cleaning up Axo component' );
setIsAxoActive( false );
setIsGuest( true );
removeShippingChangeButton();
removeCardChangeButton();
removeWatermark();
if ( isEmailFunctionalitySetup() ) {
console.log( 'Removing email functionality' );
removeEmailFunctionality();
}
};
}, [] );
setShippingAddress,
setCard
);
usePaymentSetup( onPaymentSetup, emitResponse, card );
useAxoCleanup( updateWooShippingAddress, updateWooBillingAddress );
const handlePaymentLoad = useCallback( ( paymentComponent ) => {
console.log( 'Payment component loaded', paymentComponent );
}, [] );
const handleChange = ( selectedCard ) => {
const handleCardChange = ( selectedCard ) => {
console.log( 'Card selection changed', selectedCard );
setCard( selectedCard );
};
@ -199,7 +75,7 @@ const Axo = ( props ) => {
<Payment
fastlaneSdk={ fastlaneSdk }
card={ card }
onChange={ handleChange }
onChange={ handleCardChange }
onPaymentLoad={ handlePaymentLoad }
onChangeButtonClick={ onChangeCardButtonClick }
/>
@ -208,7 +84,6 @@ const Axo = ( props ) => {
);
};
// Register the payment method
registerPaymentMethod( {
name: ppcpConfig.id,
label: (
@ -220,15 +95,11 @@ registerPaymentMethod( {
content: <Axo />,
edit: <h1>This is Axo Blocks in the editor</h1>,
ariaLabel: ppcpConfig.title,
canMakePayment: () => {
return true;
},
canMakePayment: () => true,
supports: {
showSavedCards: true,
features: ppcpConfig.supports,
},
} );
console.log( 'Axo module loaded' );
export default Axo;

View file

@ -10,6 +10,7 @@ const DEFAULT_STATE = {
isAxoActive: false,
isAxoScriptLoaded: false,
isEmailSubmitted: false,
isEmailLookupCompleted: false,
};
// Actions
@ -30,6 +31,10 @@ const actions = {
type: 'SET_IS_EMAIL_SUBMITTED',
payload: isEmailSubmitted,
} ),
setIsEmailLookupCompleted: ( isEmailLookupCompleted ) => ( {
type: 'SET_IS_EMAIL_LOOKUP_COMPLETED',
payload: isEmailLookupCompleted,
} ),
};
// Reducer
@ -43,6 +48,8 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
return { ...state, isAxoScriptLoaded: action.payload };
case 'SET_IS_EMAIL_SUBMITTED':
return { ...state, isEmailSubmitted: action.payload };
case 'SET_IS_EMAIL_LOOKUP_COMPLETED':
return { ...state, isEmailLookupCompleted: action.payload };
default:
return state;
}
@ -52,8 +59,9 @@ const reducer = ( state = DEFAULT_STATE, action ) => {
const selectors = {
getIsGuest: ( state ) => state.isGuest,
getIsAxoActive: ( state ) => state.isAxoActive,
isAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
isEmailSubmitted: ( state ) => state.isEmailSubmitted,
getIsAxoScriptLoaded: ( state ) => state.isAxoScriptLoaded,
getIsEmailSubmitted: ( state ) => state.isEmailSubmitted,
getIsEmailLookupCompleted: ( state ) => state.isEmailLookupCompleted,
};
// Create and register the store
@ -65,7 +73,6 @@ const store = createReduxStore( STORE_NAME, {
register( store );
// Utility functions
export const setIsGuest = ( isGuest ) => {
try {
dispatch( STORE_NAME ).setIsGuest( isGuest );
@ -73,3 +80,13 @@ export const setIsGuest = ( isGuest ) => {
console.error( 'Error updating isGuest state:', error );
}
};
export const setIsEmailLookupCompleted = ( isEmailLookupCompleted ) => {
try {
dispatch( STORE_NAME ).setIsEmailLookupCompleted(
isEmailLookupCompleted
);
} catch ( error ) {
console.error( 'Error updating isEmailLookupCompleted state:', error );
}
};