mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 10:55:00 +08:00
Add Submit button and loading spinners
This commit is contained in:
parent
907b807122
commit
f86f6a3f5a
12 changed files with 430 additions and 542 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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,36 +13,54 @@ export const onEmailSubmit = async (
|
|||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeButtonClick
|
||||
onChangeCardButtonClick
|
||||
) => {
|
||||
return async ( email ) => {
|
||||
try {
|
||||
console.log( 'Email value being looked up:', email );
|
||||
|
||||
if ( ! fastlaneSdk ) {
|
||||
throw new Error( 'FastlaneSDK is not initialized' );
|
||||
}
|
||||
|
||||
if ( ! fastlaneSdk.identity ) {
|
||||
throw new Error(
|
||||
'FastlaneSDK identity object is not available'
|
||||
);
|
||||
}
|
||||
|
||||
const lookup =
|
||||
await fastlaneSdk.identity.lookupCustomerByEmail( email );
|
||||
|
||||
console.log( 'Lookup response:', lookup );
|
||||
|
||||
if ( ! lookup.customerContextId ) {
|
||||
if ( ! lookup || ! lookup.customerContextId ) {
|
||||
console.warn( 'No customerContextId found in the response' );
|
||||
return;
|
||||
}
|
||||
|
||||
const { authenticationState, profileData } =
|
||||
const authResponse =
|
||||
await fastlaneSdk.identity.triggerAuthenticationFlow(
|
||||
lookup.customerContextId
|
||||
);
|
||||
|
||||
console.log( 'authenticationState', authenticationState );
|
||||
if ( ! authResponse || ! authResponse.authenticationState ) {
|
||||
throw new Error( 'Invalid authentication response' );
|
||||
}
|
||||
|
||||
const { authenticationState, profileData } = authResponse;
|
||||
|
||||
if ( authenticationState === 'succeeded' ) {
|
||||
// Capture the existing WooCommerce data before updating it
|
||||
snapshotFields( wooShippingAddress, wooBillingAddress );
|
||||
|
||||
console.log( 'Setting isGuest to false' );
|
||||
setIsGuest( false );
|
||||
|
||||
if ( profileData && profileData.shippingAddress ) {
|
||||
setShippingAddress( profileData.shippingAddress );
|
||||
}
|
||||
if ( profileData && profileData.card ) {
|
||||
setCard( profileData.card );
|
||||
}
|
||||
|
||||
console.log( 'Profile Data:', profileData );
|
||||
|
||||
|
@ -55,11 +71,16 @@ export const onEmailSubmit = async (
|
|||
);
|
||||
|
||||
injectShippingChangeButton( onChangeShippingAddressClick );
|
||||
injectCardChangeButton( onChangeButtonClick );
|
||||
injectCardChangeButton( onChangeCardButtonClick );
|
||||
} else {
|
||||
console.warn( 'Authentication failed or did not succeed' );
|
||||
}
|
||||
} catch ( error ) {
|
||||
console.error( 'Error during email lookup or authentication:', error );
|
||||
console.error(
|
||||
'Error during email lookup or authentication:',
|
||||
error
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
|
@ -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 } ) => {
|
||||
|
|
|
@ -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 createWatermark = () => {
|
||||
const textInputContainer = document.querySelector(
|
||||
'.wp-block-woocommerce-checkout-contact-information-block .wc-block-components-text-input'
|
||||
);
|
||||
|
||||
if ( textInputContainer ) {
|
||||
if ( textInputContainer && ! watermarkReference.container ) {
|
||||
const emailInput = textInputContainer.querySelector(
|
||||
'input[type="email"]'
|
||||
);
|
||||
|
||||
if ( emailInput ) {
|
||||
if ( ! watermarkReference.container ) {
|
||||
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' );
|
||||
}
|
||||
} else {
|
||||
console.warn( 'Text input container not found' );
|
||||
};
|
||||
|
||||
const removeWatermark = () => {
|
||||
if ( watermarkReference.root ) {
|
||||
watermarkReference.root.unmount();
|
||||
}
|
||||
}, [ fastlaneSdk, isGuest, isAxoActive ] );
|
||||
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 {
|
||||
removeWatermark();
|
||||
}
|
||||
|
||||
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
|
||||
) {
|
||||
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 };
|
||||
};
|
||||
|
|
|
@ -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,11 +94,12 @@ const Axo = () => {
|
|||
|
||||
const onChangeCardButtonClick = useCardChange( fastlaneSdk, setCard );
|
||||
|
||||
const handleEmailInput = useCallback(
|
||||
async ( email ) => {
|
||||
if ( fastlaneSdk ) {
|
||||
await onEmailSubmit(
|
||||
email,
|
||||
useEffect( () => {
|
||||
setupWatermark( fastlaneSdk );
|
||||
if ( paypalLoaded && fastlaneSdk ) {
|
||||
setIsAxoScriptLoaded( true );
|
||||
setIsAxoActive( true );
|
||||
const emailLookupHandler = createEmailLookupHandler(
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
|
@ -121,60 +111,29 @@ const Axo = () => {
|
|||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick
|
||||
);
|
||||
} else {
|
||||
console.warn( 'FastLane SDK is not available' );
|
||||
setupEmailFunctionality( emailLookupHandler );
|
||||
}
|
||||
},
|
||||
[
|
||||
}, [
|
||||
paypalLoaded,
|
||||
fastlaneSdk,
|
||||
setShippingAddress,
|
||||
setCard,
|
||||
setIsAxoActive,
|
||||
setIsAxoScriptLoaded,
|
||||
wooShippingAddress,
|
||||
wooBillingAddress,
|
||||
setWooShippingAddress,
|
||||
setWooBillingAddress,
|
||||
onChangeShippingAddressClick,
|
||||
onChangeCardButtonClick,
|
||||
]
|
||||
);
|
||||
|
||||
useEffect( () => {
|
||||
handleEmailInputRef.current = handleEmailInput;
|
||||
}, [ handleEmailInput ] );
|
||||
|
||||
useEffect( () => {
|
||||
if ( paypalLoaded && fastlaneSdk ) {
|
||||
console.log( 'Enabling Axo' );
|
||||
setIsAxoActive( true );
|
||||
setupWatermark( fastlaneSdk );
|
||||
setupEmailSubmitButton( async ( email ) => {
|
||||
await onEmailSubmit( email );
|
||||
} );
|
||||
setupEmailEvent( handleEmailInputRef.current );
|
||||
}
|
||||
}, [ paypalLoaded, fastlaneSdk, setIsAxoActive ] );
|
||||
] );
|
||||
|
||||
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 );
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue