diff --git a/modules.php b/modules.php index 3672dc515..aa73fb6ad 100644 --- a/modules.php +++ b/modules.php @@ -73,12 +73,12 @@ return function ( string $root_dir ): iterable { $modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )(); } - if ( PayLaterWCBlocksModule::is_module_loading_required() ) { - $modules[] = ( require "$modules_dir/ppcp-paylater-wc-blocks/module.php" )(); - } - if ( PayLaterConfiguratorModule::is_enabled() ) { $modules[] = ( require "$modules_dir/ppcp-paylater-configurator/module.php" )(); + + if ( PayLaterWCBlocksModule::is_module_loading_required() ) { + $modules[] = ( require "$modules_dir/ppcp-paylater-wc-blocks/module.php" )(); + } } if ( apply_filters( diff --git a/modules/ppcp-axo/resources/css/styles.scss b/modules/ppcp-axo/resources/css/styles.scss index 3513d0642..3c879dcb6 100644 --- a/modules/ppcp-axo/resources/css/styles.scss +++ b/modules/ppcp-axo/resources/css/styles.scss @@ -12,6 +12,39 @@ } } +#ppcp-axo-billing-email-field-wrapper { + display: flex; + gap: 0.5rem; +} + +#ppcp-axo-billing-email-submit-button { + margin-top: 0; + position: relative; + transition: opacity 0.3s ease; + flex: 0 1 auto; + align-self: flex-start; + + .loader:before { + display: inline; + height: 12px; + width: 12px; + margin-left: -6px; + margin-top: -6px; + left: auto; + right: auto; + } +} + +.ppcp-axo-billing-email-submit-button { + &-hidden { + opacity: 0; + } + + &-loaded:not([disabled]) { + opacity: 1; + } +} + .ppcp-axo-payment-container { padding: 1rem 0; background-color: #ffffff; @@ -89,3 +122,22 @@ max-height: 25px; } } + +.ppcp-axo-customer-details #billing_email_field .woocommerce-input-wrapper { + flex: 1 1 auto; +} + +@media screen and (max-width: 719px) { + #ppcp-axo-billing-email { + &-field-wrapper { + flex-direction: column; + } + + &-submit-button { + align-self: auto; + } + } +} + + + diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 960da7f26..8299dc51c 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -167,12 +167,15 @@ class AxoManager { ev.preventDefault(); log(`Enter key attempt - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); + this.validateEmail(this.el.fieldBillingEmail.selector); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { await this.onChangeEmail(); } } }); + this.reEnableEmailInput(); + // Clear last email checked identity when email field is focused. this.$('#billing_email_field input').on('focus', (ev) => { log(`Clear the last email checked: ${this.lastEmailCheckedIdentity}`); @@ -219,8 +222,10 @@ class AxoManager { if (scenario.defaultSubmitButton) { this.el.defaultSubmitButton.show(); + this.el.billingEmailSubmitButton.hide(); } else { this.el.defaultSubmitButton.hide(); + this.el.billingEmailSubmitButton.show(); } if (scenario.defaultEmailField) { @@ -246,8 +251,8 @@ class AxoManager { this.el.watermarkContainer.show(); // Move watermark to after email. - this.$(this.el.fieldBillingEmail.selector).append( - this.$(this.el.watermarkContainer.selector) + document.querySelector('#billing_email_field .woocommerce-input-wrapper').append( + document.querySelector(this.el.watermarkContainer.selector) ); } else { this.el.emailWidgetContainer.hide(); @@ -280,6 +285,8 @@ class AxoManager { if (scenario.axoPaymentContainer) { this.el.paymentContainer.show(); + this.el.gatewayDescription.hide(); + document.querySelector(this.el.billingEmailSubmitButton.selector).setAttribute('disabled', 'disabled'); } else { this.el.paymentContainer.hide(); } @@ -425,10 +432,18 @@ class AxoManager { `); } + // billingEmailFieldWrapper + const befw = this.el.billingEmailFieldWrapper; + if (!document.querySelector(befw.selector)) { + document.querySelector('#billing_email_field .woocommerce-input-wrapper').insertAdjacentHTML('afterend', ` +
+ `); + } + // Watermark container const wc = this.el.watermarkContainer; if (!document.querySelector(wc.selector)) { - this.emailInput.insertAdjacentHTML('afterend', ` + document.querySelector(befw.selector).insertAdjacentHTML('beforeend', `
`); } @@ -458,10 +473,10 @@ class AxoManager { } } else { - // Move email to the AXO container. let emailRow = document.querySelector(this.el.fieldBillingEmail.selector); wrapperElement.prepend(emailRow); + document.querySelector(this.el.billingEmailFieldWrapper.selector).prepend(document.querySelector('#billing_email_field .woocommerce-input-wrapper')); } } @@ -472,7 +487,8 @@ class AxoManager { this.initialized = true; await this.connect(); - this.renderWatermark(); + await this.renderWatermark(); + this.renderEmailSubmitButton(); this.watchEmail(); } @@ -501,6 +517,24 @@ class AxoManager { this.toggleWatermarkLoading(this.el.watermarkContainer, 'ppcp-axo-watermark-loading', 'loader'); } + renderEmailSubmitButton() { + const billingEmailSubmitButton = this.el.billingEmailSubmitButton; + const billingEmailSubmitButtonSpinner = this.el.billingEmailSubmitButtonSpinner; + + if (!document.querySelector(billingEmailSubmitButton.selector)) { + document.querySelector(this.el.billingEmailFieldWrapper.selector).insertAdjacentHTML('beforeend', ` + + `); + + document.querySelector(this.el.billingEmailSubmitButton.selector).offsetHeight; + document.querySelector(this.el.billingEmailSubmitButton.selector).classList.remove('ppcp-axo-billing-email-submit-button-hidden'); + document.querySelector(this.el.billingEmailSubmitButton.selector).classList.add('ppcp-axo-billing-email-submit-button-loaded'); + } + } + watchEmail() { if (this.useEmailWidget()) { @@ -512,6 +546,7 @@ class AxoManager { log(`Change event attempt - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { + this.validateEmail(this.el.fieldBillingEmail.selector); this.onChangeEmail(); } }); @@ -549,7 +584,7 @@ class AxoManager { this.lastEmailCheckedIdentity = this.emailInput.value; - if (!this.emailInput.value || !this.emailInput.checkValidity()) { + if (!this.emailInput.value || !this.emailInput.checkValidity() || !this.validateEmailFormat(this.emailInput.value)) { log('The email address is not valid.'); return; } @@ -566,8 +601,11 @@ class AxoManager { page_type: 'checkout' }); + this.disableGatewaySelection(); + this.spinnerToggleLoaderAndOverlay(this.el.billingEmailSubmitButtonSpinner, 'loader', 'ppcp-axo-overlay'); await this.lookupCustomerByEmail(); + this.spinnerToggleLoaderAndOverlay(this.el.billingEmailSubmitButtonSpinner, 'loader', 'ppcp-axo-overlay'); this.enableGatewaySelection(); } @@ -878,6 +916,14 @@ class AxoManager { } } + spinnerToggleLoaderAndOverlay(element, loaderClass, overlayClass) { + const spinner = document.querySelector(`${element.selector}`); + if (spinner) { + spinner.classList.toggle(loaderClass); + spinner.classList.toggle(overlayClass); + } + } + toggleWatermarkLoading(container, loadingClass, loaderClass) { const watermarkLoading = document.querySelector(`${container.selector}.${loadingClass}`); const watermarkLoader = document.querySelector(`${container.selector}.${loaderClass}`); @@ -888,6 +934,39 @@ class AxoManager { watermarkLoader.classList.toggle(loaderClass); } } + + validateEmailFormat(value) { + const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailPattern.test(value); + } + + validateEmail(billingEmail) { + const billingEmailSelector = document.querySelector(billingEmail); + const value = document.querySelector(billingEmail + ' input').value; + + if (this.validateEmailFormat(value)) { + billingEmailSelector.classList.remove('woocommerce-invalid'); + billingEmailSelector.classList.add('woocommerce-validated'); + this.setStatus('validEmail', true); + } else { + billingEmailSelector.classList.remove('woocommerce-validated'); + billingEmailSelector.classList.add('woocommerce-invalid'); + this.setStatus('validEmail', false); + } + } + + reEnableEmailInput() { + const reEnableInput = (ev) => { + const submitButton = document.querySelector(this.el.billingEmailSubmitButton.selector); + if (submitButton.hasAttribute('disabled')) { + submitButton.removeAttribute('disabled'); + } + }; + + this.$('#billing_email_field input').on('focus', reEnableInput); + this.$('#billing_email_field input').on('input', reEnableInput); + this.$('#billing_email_field input').on('click', reEnableInput); + } } export default AxoManager; diff --git a/modules/ppcp-axo/resources/js/Components/DomElementCollection.js b/modules/ppcp-axo/resources/js/Components/DomElementCollection.js index 35f19ec6d..b6ab77177 100644 --- a/modules/ppcp-axo/resources/js/Components/DomElementCollection.js +++ b/modules/ppcp-axo/resources/js/Components/DomElementCollection.js @@ -7,6 +7,10 @@ class DomElementCollection { selector: '#payment_method_ppcp-axo-gateway', }); + this.gatewayDescription = new DomElement({ + selector: '.payment_box.payment_method_ppcp-axo-gateway', + }); + this.defaultSubmitButton = new DomElement({ selector: '#place_order', }); @@ -56,6 +60,23 @@ class DomElementCollection { selector: '#billing_email_field' }); + this.billingEmailFieldWrapper = new DomElement({ + id: 'ppcp-axo-billing-email-field-wrapper', + selector: '#ppcp-axo-billing-email-field-wrapper', + }); + + this.billingEmailSubmitButton = new DomElement({ + id: 'ppcp-axo-billing-email-submit-button', + selector: '#ppcp-axo-billing-email-submit-button', + className: 'ppcp-axo-billing-email-submit-button-hidden button alt wp-element-button wc-block-components-button' + }); + + this.billingEmailSubmitButtonSpinner = new DomElement({ + id: 'ppcp-axo-billing-email-submit-button-spinner', + selector: '#ppcp-axo-billing-email-submit-button-spinner', + className: 'loader ppcp-axo-overlay' + }); + this.submitButtonContainer = new DomElement({ selector: '#ppcp-axo-submit-button-container', }); diff --git a/modules/ppcp-axo/src/Assets/AxoManager.php b/modules/ppcp-axo/src/Assets/AxoManager.php index bef207ea6..e74cfa5d7 100644 --- a/modules/ppcp-axo/src/Assets/AxoManager.php +++ b/modules/ppcp-axo/src/Assets/AxoManager.php @@ -162,13 +162,13 @@ class AxoManager { */ private function script_data() { return array( - 'environment' => array( + 'environment' => array( 'is_sandbox' => $this->environment->current_environment() === 'sandbox', ), - 'widgets' => array( + 'widgets' => array( 'email' => 'render', ), - 'insights' => array( + 'insights' => array( 'enabled' => true, 'client_id' => ( $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : null ), 'session_id' => @@ -182,7 +182,7 @@ class AxoManager { 'value' => WC()->cart->get_total( 'numeric' ), ), ), - 'style_options' => array( + 'style_options' => array( 'root' => array( 'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '', 'errorColor' => $this->settings->has( 'axo_style_root_error_color' ) ? $this->settings->get( 'axo_style_root_error_color' ) : '', @@ -201,22 +201,23 @@ class AxoManager { 'focusBorderColor' => $this->settings->has( 'axo_style_input_focus_border_color' ) ? $this->settings->get( 'axo_style_input_focus_border_color' ) : '', ), ), - 'name_on_card' => $this->settings->has( 'axo_name_on_card' ) ? $this->settings->get( 'axo_name_on_card' ) : '', - 'woocommerce' => array( + 'name_on_card' => $this->settings->has( 'axo_name_on_card' ) ? $this->settings->get( 'axo_name_on_card' ) : '', + 'woocommerce' => array( 'states' => array( 'US' => WC()->countries->get_states( 'US' ), 'CA' => WC()->countries->get_states( 'CA' ), ), ), - 'icons_directory' => esc_url( $this->wcgateway_module_url ) . 'assets/images/axo/', - 'module_url' => untrailingslashit( $this->module_url ), - 'ajax' => array( + 'icons_directory' => esc_url( $this->wcgateway_module_url ) . 'assets/images/axo/', + 'module_url' => untrailingslashit( $this->module_url ), + 'ajax' => array( 'frontend_logger' => array( 'endpoint' => \WC_AJAX::get_endpoint( FrontendLoggerEndpoint::ENDPOINT ), 'nonce' => wp_create_nonce( FrontendLoggerEndpoint::nonce() ), ), ), 'wp_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG, + 'billing_email_button_text' => __( 'Continue', 'woocommerce-paypal-payments' ), ); } diff --git a/modules/ppcp-axo/src/Gateway/AxoGateway.php b/modules/ppcp-axo/src/Gateway/AxoGateway.php index 13e81b74c..8d50b6253 100644 --- a/modules/ppcp-axo/src/Gateway/AxoGateway.php +++ b/modules/ppcp-axo/src/Gateway/AxoGateway.php @@ -168,7 +168,7 @@ class AxoGateway extends WC_Payment_Gateway { ? $this->ppcp_settings->get( 'axo_gateway_title' ) : $this->get_option( 'title', $this->method_title ); - $this->description = $this->get_option( 'description', '' ); + $this->description = __( 'Enter your email address to continue.', 'woocommerce-paypal-payments' ); $this->init_form_fields(); $this->init_settings();