import Fastlane from "./Connection/Fastlane"; import { log } from "./Helper/Debug"; import DomElementCollection from "./Components/DomElementCollection"; import ShippingView from "./Views/ShippingView"; import BillingView from "./Views/BillingView"; import CardView from "./Views/CardView"; import PayPalInsights from "./Insights/PayPalInsights"; import { disable, enable } from "../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler"; import { getCurrentPaymentMethod } from "../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState"; class AxoManager { constructor(axoConfig, ppcpConfig) { this.axoConfig = axoConfig; this.ppcpConfig = ppcpConfig; this.initialized = false; this.fastlane = new Fastlane(); this.$ = jQuery; this.hideGatewaySelection = false; this.status = { active: false, validEmail: false, hasProfile: false, useEmailWidget: this.useEmailWidget(), hasCard: false, }; this.data = { email: null, billing: null, shipping: null, card: null, }; this.states = this.axoConfig.woocommerce.states; this.el = new DomElementCollection(); this.emailInput = document.querySelector(this.el.fieldBillingEmail.selector + ' input'); this.styles = { root: { backgroundColorPrimary: '#ffffff' } }; this.locale = 'en_us'; this.registerEventHandlers(); this.shippingView = new ShippingView(this.el.shippingAddressContainer.selector, this.el, this.states); this.billingView = new BillingView(this.el.billingAddressContainer.selector, this.el); this.cardView = new CardView(this.el.paymentContainer.selector + '-details', this.el, this); document.axoDebugSetStatus = (key, value) => { this.setStatus(key, value); } document.axoDebugObject = () => { return this; } if ( this.axoConfig?.insights?.enabled && this.axoConfig?.insights?.client_id && this.axoConfig?.insights?.session_id ) { PayPalInsights.config(this.axoConfig?.insights?.client_id, { debug: true }); PayPalInsights.setSessionId(this.axoConfig?.insights?.session_id); PayPalInsights.trackJsLoad(); if (document.querySelector('.woocommerce-checkout')) { PayPalInsights.trackBeginCheckout({ amount: this.axoConfig?.insights?.amount, page_type: 'checkout', user_data: { country: 'US', is_store_member: false, } }); } } this.triggerGatewayChange(); } registerEventHandlers() { this.$(document).on('change', 'input[name=payment_method]', (ev) => { const map = { 'ppcp-axo-gateway': 'card', 'ppcp-gateway': 'paypal', } PayPalInsights.trackSelectPaymentMethod({ payment_method_selected: map[ev.target.value] || 'other', page_type: 'checkout' }); }); // Listen to Gateway Radio button changes. this.el.gatewayRadioButton.on('change', (ev) => { if (ev.target.checked) { this.activateAxo(); } else { this.deactivateAxo(); } }); this.$(document).on('updated_checkout payment_method_selected', () => { this.triggerGatewayChange(); }); // On checkout form submitted. this.el.submitButton.on('click', () => { this.onClickSubmitButton(); return false; }) // Click change shipping address link. this.el.changeShippingAddressLink.on('click', async () => { if (this.status.hasProfile) { const { selectionChanged, selectedAddress } = await this.fastlane.profile.showShippingAddressSelector(); if (selectionChanged) { this.setShipping(selectedAddress); this.shippingView.refresh(); } } }); // Click change billing address link. this.el.changeBillingAddressLink.on('click', async () => { if (this.status.hasProfile) { this.el.changeCardLink.trigger('click'); } }); // Click change card link. this.el.changeCardLink.on('click', async () => { const response = await this.fastlane.profile.showCardSelector(); if (response.selectionChanged) { this.setCard(response.selectedCard); this.setBilling({ address: response.selectedCard.paymentSource.card.billingAddress }); } }); // Cancel "continuation" mode. this.el.showGatewaySelectionLink.on('click', async () => { this.hideGatewaySelection = false; this.$('.wc_payment_methods label').show(); this.$('.wc_payment_methods input').show(); this.cardView.refresh(); }); // Prevents sending checkout form when pressing Enter key on input field // and triggers customer lookup this.$('form.woocommerce-checkout input').on('keydown', async (ev) => { if (ev.key === 'Enter' && getCurrentPaymentMethod() === 'ppcp-axo-gateway') { ev.preventDefault(); log(`Enter key attempt - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { await this.onChangeEmail(); } } }); // 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}`); this.lastEmailCheckedIdentity = ''; }); // Listening to status update event document.addEventListener('axo_status_updated', (ev) => { const termsField = document.querySelector("[name='terms-field']"); if (termsField) { const status = ev.detail; const shouldHide = status.active && status.validEmail === false && status.hasProfile === false; termsField.parentElement.style.display = shouldHide ? 'none' : 'block'; } }); } rerender() { /** * active | 0 1 1 1 * validEmail | * 0 1 1 * hasProfile | * * 0 1 * -------------------------------- * defaultSubmitButton | 1 0 0 0 * defaultEmailField | 1 0 0 0 * defaultFormFields | 1 0 1 0 * extraFormFields | 0 0 0 1 * axoEmailField | 0 1 0 0 * axoProfileViews | 0 0 0 1 * axoPaymentContainer | 0 0 1 1 * axoSubmitButton | 0 0 1 1 */ const scenario = this.identifyScenario( this.status.active, this.status.validEmail, this.status.hasProfile ); log(`Scenario: ${JSON.stringify(scenario)}`); // Reset some elements to a default status. this.el.watermarkContainer.hide(); if (scenario.defaultSubmitButton) { this.el.defaultSubmitButton.show(); } else { this.el.defaultSubmitButton.hide(); } if (scenario.defaultEmailField) { this.el.fieldBillingEmail.show(); } else { this.el.fieldBillingEmail.hide(); } if (scenario.defaultFormFields) { this.el.customerDetails.show(); this.toggleLoaderAndOverlay(this.el.customerDetails, 'loader', 'ppcp-axo-overlay'); } else { this.el.customerDetails.hide(); } if (scenario.extraFormFields) { this.el.customerDetails.show(); // Hiding of unwanted will be handled by the axoProfileViews handler. } if (scenario.axoEmailField) { this.showAxoEmailField(); this.el.watermarkContainer.show(); // Move watermark to after email. this.$(this.el.fieldBillingEmail.selector).append( this.$(this.el.watermarkContainer.selector) ); // Add the submit button to the email field container. this.renderEmailSubmitNew(); } else { this.el.emailWidgetContainer.hide(); if (!scenario.defaultEmailField) { this.el.fieldBillingEmail.hide(); } } if (scenario.axoProfileViews) { this.shippingView.activate(); this.cardView.activate(); if (this.status.hasCard) { this.billingView.activate(); } // Move watermark to after shipping. this.$(this.el.shippingAddressContainer.selector).after( this.$(this.el.watermarkContainer.selector) ); this.el.watermarkContainer.show(); } else { this.shippingView.deactivate(); this.billingView.deactivate(); this.cardView.deactivate(); } if (scenario.axoPaymentContainer) { this.el.paymentContainer.show(); this.el.gatewayDescription.hide(); } else { this.el.paymentContainer.hide(); } if (scenario.axoSubmitButton) { this.el.submitButtonContainer.show(); } else { this.el.submitButtonContainer.hide(); } this.ensureBillingFieldsConsistency(); this.ensureShippingFieldsConsistency(); } identifyScenario(active, validEmail, hasProfile) { let response = { defaultSubmitButton: false, defaultEmailField: false, defaultFormFields: false, extraFormFields: false, axoEmailField: false, axoProfileViews: false, axoPaymentContainer: false, axoSubmitButton: false, } if (active && validEmail && hasProfile) { response.extraFormFields = true; response.axoProfileViews = true; response.axoPaymentContainer = true; response.axoSubmitButton = true; return response; } if (active && validEmail && !hasProfile) { response.defaultFormFields = true; response.axoEmailField = true; response.axoPaymentContainer = true; response.axoSubmitButton = true; return response; } if (active && !validEmail) { response.axoEmailField = true; return response; } if (!active) { response.defaultSubmitButton = true; response.defaultEmailField = true; response.defaultFormFields = true; return response; } throw new Error('Invalid scenario.'); } ensureBillingFieldsConsistency() { const $billingFields = this.$('.woocommerce-billing-fields .form-row:visible'); const $billingHeaders = this.$('.woocommerce-billing-fields h3'); if (this.billingView.isActive()) { if ($billingFields.length) { $billingHeaders.show(); } else { $billingHeaders.hide(); } } else { $billingHeaders.show(); } } ensureShippingFieldsConsistency() { const $shippingFields = this.$('.woocommerce-shipping-fields .form-row:visible'); const $shippingHeaders = this.$('.woocommerce-shipping-fields h3'); if (this.shippingView.isActive()) { if ($shippingFields.length) { $shippingHeaders.show(); } else { $shippingHeaders.hide(); } } else { $shippingHeaders.show(); } } showAxoEmailField() { if (this.status.useEmailWidget) { this.el.emailWidgetContainer.show(); this.el.fieldBillingEmail.hide(); } else { this.el.emailWidgetContainer.hide(); this.el.fieldBillingEmail.show(); } } setStatus(key, value) { this.status[key] = value; log(`Status updated: ${JSON.stringify(this.status)}`); document.dispatchEvent(new CustomEvent("axo_status_updated", { detail: this.status })); this.rerender(); } activateAxo() { this.initPlacements(); this.initFastlane(); this.setStatus('active', true); log(`Attempt on activation - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { this.onChangeEmail(); } } deactivateAxo() { this.setStatus('active', false); } initPlacements() { const wrapper = this.el.axoCustomerDetails; // Customer details container. if (!document.querySelector(wrapper.selector)) { document.querySelector(wrapper.anchorSelector).insertAdjacentHTML('afterbegin', `
`); } const wrapperElement = document.querySelector(wrapper.selector); // Billing view container. const bc = this.el.billingAddressContainer; if (!document.querySelector(bc.selector)) { wrapperElement.insertAdjacentHTML('beforeend', `
`); } // Shipping view container. const sc = this.el.shippingAddressContainer; if (!document.querySelector(sc.selector)) { wrapperElement.insertAdjacentHTML('beforeend', `
`); } // Watermark container const wc = this.el.watermarkContainer; if (!document.querySelector(wc.selector)) { this.emailInput.insertAdjacentHTML('afterend', `
`); } // Payment container const pc = this.el.paymentContainer; if (!document.querySelector(pc.selector)) { const gatewayPaymentContainer = document.querySelector('.payment_method_ppcp-axo-gateway'); gatewayPaymentContainer.insertAdjacentHTML('beforeend', `
`); } if (this.useEmailWidget()) { // Display email widget. const ec = this.el.emailWidgetContainer; if (!document.querySelector(ec.selector)) { wrapperElement.insertAdjacentHTML('afterbegin', `
--- EMAIL WIDGET PLACEHOLDER ---
`); } } else { // Move email to the AXO container. let emailRow = document.querySelector(this.el.fieldBillingEmail.selector); wrapperElement.prepend(emailRow); } } async initFastlane() { if (this.initialized) { return; } this.initialized = true; await this.connect(); await this.renderWatermark(true, () => { this.renderEmailSubmit(); }); this.watchEmail(); } async connect() { if (this.axoConfig.environment.is_sandbox) { window.localStorage.setItem('axoEnv', 'sandbox'); } await this.fastlane.connect({ locale: this.locale, styles: this.styles }); this.fastlane.setLocale('en_us'); } triggerGatewayChange() { this.el.gatewayRadioButton.trigger('change'); } async renderWatermark(includeAdditionalInfo = true, callback) { (await this.fastlane.FastlaneWatermarkComponent({ includeAdditionalInfo })).render(this.el.watermarkContainer.selector); this.toggleWatermarkLoading(this.el.watermarkContainer, 'ppcp-axo-watermark-loading', 'loader'); // Call the callback if provided if (callback) { callback(); } } async renderEmailSubmitNew() { const billingEmailSubmitButton = this.el.billingEmailSubmitButton; if (!document.querySelector(billingEmailSubmitButton.selector)) { } const submitButton = this.el.billingEmailSubmitButton.selector; // submitButton.innerText = this.axoConfig.billing_email_button_text; const submitButtonSpinner = this.el.billingEmailSubmitButtonSpinner.selector; console.log(submitButton); } async renderEmailSubmit() { // Create the submit button element const submitButton = document.createElement('button'); submitButton.type = 'button'; submitButton.innerText = this.axoConfig.billing_email_button_text; submitButton.className = 'email-submit-button'; // Add a class for styling if needed // Create the spinner element const spinner = document.createElement('span'); spinner.className = 'loader ppcp-axo-overlay'; // Use the native loader class spinner.style.display = 'none'; // Initially hidden // Append the spinner to the button submitButton.appendChild(spinner); // Add an event listener to handle the button click submitButton.addEventListener('click', async () => { const emailInput = document.querySelector(this.el.fieldBillingEmail.selector + ' input'); if (emailInput && emailInput.checkValidity()) { if (this.lastEmailCheckedIdentity !== emailInput.value) { log(`Submit button clicked - emailInput: ${emailInput.value}`); // Show the spinner, add the class to adjust padding and disable the button spinner.style.display = 'inline-block'; submitButton.disabled = true; try { await this.onChangeEmail(); } finally { // Hide the spinner and re-enable the button after the lookup is complete spinner.style.display = 'none'; submitButton.disabled = false; } } } else { emailInput.reportValidity(); // Trigger the HTML5 validation message log('Invalid or empty email input.'); } }); // Append the button inside the wrapper of the billing email input field const emailFieldContainer = document.querySelector(this.el.fieldBillingEmail.selector); if (emailFieldContainer) { const inputWrapper = emailFieldContainer.querySelector('.woocommerce-input-wrapper'); if (inputWrapper) { // Ensure the email input has the required attribute const emailInput = inputWrapper.querySelector('input'); emailInput.setAttribute('required', 'required'); emailInput.style.flex = '1'; // Make the input take the remaining space emailInput.style.marginRight = '10px'; // Ensure the spacing is consistent // Remove any existing loader if present const existingLoader = inputWrapper.querySelector('.loader'); if (existingLoader) { existingLoader.remove(); } // Append the submit button to the input wrapper inputWrapper.appendChild(submitButton); // Force a reflow to apply the transition submitButton.offsetHeight; // Add the class to trigger the animation inputWrapper.classList.add('show-button'); } } } async onChangeEmail() { this.clearData(); if (!this.status.active) { log('Email checking skipped, AXO not active.'); return; } if (!this.emailInput) { log('Email field not initialized.'); return; } log(`Email changed: ${this.emailInput ? this.emailInput.value : ''}`); this.$(this.el.paymentContainer.selector + '-detail').html(''); this.$(this.el.paymentContainer.selector + '-form').html(''); this.setStatus('validEmail', false); this.setStatus('hasProfile', false); this.hideGatewaySelection = false; this.lastEmailCheckedIdentity = this.emailInput.value; if (!this.emailInput.value || !this.emailInput.checkValidity()) { log('The email address is not valid.'); return; } this.data.email = this.emailInput.value; this.billingView.setData(this.data); if (!this.fastlane.identity) { log('Not initialized.'); return; } PayPalInsights.trackSubmitCheckoutEmail({ page_type: 'checkout' }); this.disableGatewaySelection(); const submitButton = document.querySelector('.email-submit-button'); const spinner = submitButton.querySelector('.loader'); if (submitButton && spinner) { // Show the spinner and disable the button spinner.style.display = 'inline-block'; submitButton.classList.add('show-spinner'); submitButton.disabled = true; } setTimeout(async () => { console.log("Delayed for 1 milisecond."); await this.lookupCustomerByEmail(); // Hide the spinner and re-enable the button after the lookup is complete if (submitButton && spinner) { spinner.style.display = 'none'; submitButton.classList.remove('show-spinner'); submitButton.disabled = false; } this.enableGatewaySelection(); }, 1); } watchEmail() { if (this.useEmailWidget()) { // TODO } else { this.emailInput.addEventListener('change', async () => { log(`Change event attempt - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { this.onChangeEmail(); } }); log(`Last, this.emailInput.value attempt - emailInput: ${this.emailInput.value}`); log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput.value) { this.onChangeEmail(); } } } async onChangeEmail() { this.clearData(); if (!this.status.active) { log('Email checking skipped, AXO not active.'); return; } if (!this.emailInput) { log('Email field not initialized.'); return; } log(`Email changed: ${this.emailInput ? this.emailInput.value : ''}`); this.$(this.el.paymentContainer.selector + '-detail').html(''); this.$(this.el.paymentContainer.selector + '-form').html(''); this.setStatus('validEmail', false); this.setStatus('hasProfile', false); this.hideGatewaySelection = false; this.lastEmailCheckedIdentity = this.emailInput.value; if (!this.emailInput.value || !this.emailInput.checkValidity()) { log('The email address is not valid.'); return; } this.data.email = this.emailInput.value; this.billingView.setData(this.data); if (!this.fastlane.identity) { log('Not initialized.'); return; } PayPalInsights.trackSubmitCheckoutEmail({ page_type: 'checkout' }); this.disableGatewaySelection(); const submitButton = document.querySelector('.email-submit-button'); const spinner = submitButton.querySelector('.loader'); if (submitButton && spinner) { // Show the spinner and disable the button spinner.style.display = 'inline-block'; submitButton.disabled = true; } setTimeout(async () => { console.log("Delayed for 1 milisecond."); await this.lookupCustomerByEmail(); // Hide the spinner and re-enable the button after the lookup is complete if (submitButton && spinner) { spinner.style.display = 'none'; submitButton.disabled = false; } this.enableGatewaySelection(); }, 1); } async lookupCustomerByEmail() { const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value); log(`lookupCustomerByEmail: ${JSON.stringify(lookupResponse)}`); if (lookupResponse.customerContextId) { // Email is associated with a Connect profile or a PayPal member. // Authenticate the customer to get access to their profile. log('Email is associated with a Connect profile or a PayPal member'); const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId); log(`AuthResponse - triggerAuthenticationFlow: ${JSON.stringify(authResponse)}`); if (authResponse.authenticationState === 'succeeded') { const shippingData = authResponse.profileData.shippingAddress; if (shippingData) { this.setShipping(shippingData); } if (authResponse.profileData.card) { this.setStatus('hasCard', true); } else { this.cardComponent = (await this.fastlane.FastlaneCardComponent( this.cardComponentData() )).render(this.el.paymentContainer.selector + '-form'); } const cardBillingAddress = authResponse.profileData?.card?.paymentSource?.card?.billingAddress; if (cardBillingAddress) { this.setCard(authResponse.profileData.card); const billingData = { address: cardBillingAddress, }; const phoneNumber = authResponse.profileData?.shippingAddress?.phoneNumber?.nationalNumber ?? ''; if (phoneNumber) { billingData.phoneNumber = phoneNumber } this.setBilling(billingData); } this.setStatus('validEmail', true); this.setStatus('hasProfile', true); this.hideGatewaySelection = true; this.$('.wc_payment_methods label').hide(); this.$('.wc_payment_methods input').hide(); await this.renderWatermark(false); this.rerender(); } else { // authentication failed or canceled by the customer // set status as guest customer log("Authentication Failed") this.setStatus('validEmail', true); this.setStatus('hasProfile', false); await this.renderWatermark(true); this.cardComponent = (await this.fastlane.FastlaneCardComponent( this.cardComponentData() )).render(this.el.paymentContainer.selector + '-form'); } } else { // No profile found with this email address. // This is a guest customer. log('No profile found with this email address.'); this.setStatus('validEmail', true); this.setStatus('hasProfile', false); await this.renderWatermark(true); this.cardComponent = (await this.fastlane.FastlaneCardComponent( this.cardComponentData() )).render(this.el.paymentContainer.selector + '-form'); } } disableGatewaySelection() { this.$('.wc_payment_methods input').prop('disabled', true); } enableGatewaySelection() { this.$('.wc_payment_methods input').prop('disabled', false); } clearData() { this.data = { email: null, billing: null, shipping: null, card: null, }; } setShipping(shipping) { this.data.shipping = shipping; this.shippingView.setData(this.data); } setBilling(billing) { this.data.billing = billing; this.billingView.setData(this.data); } setCard(card) { this.data.card = card; this.cardView.setData(this.data); } onClickSubmitButton() { // TODO: validate data. if (this.data.card) { // Ryan flow log('Starting Ryan flow.'); this.$('#ship-to-different-address-checkbox').prop('checked', 'checked'); let data = {}; this.billingView.toSubmitData(data); this.shippingView.toSubmitData(data); this.cardView.toSubmitData(data); this.ensureBillingPhoneNumber(data); log(`Ryan flow - submitted nonce: ${this.data.card.id}`) this.submit(this.data.card.id, data); } else { // Gary flow log('Starting Gary flow.'); try { this.cardComponent.getPaymentToken( this.tokenizeData() ).then((response) => { log(`Gary flow - submitted nonce: ${response.id}`) this.submit(response.id); }); } catch (e) { alert('Error tokenizing data.'); log(`Error tokenizing data. ${e.message}`, 'error'); } } } cardComponentData() { return { fields: { cardholderName: { enabled: this.axoConfig.name_on_card === '1' } }, styles: this.deleteKeysWithEmptyString(this.axoConfig.style_options) } } tokenizeData() { return { cardholderName: { fullName: this.billingView.fullName() }, billingAddress: { addressLine1: this.billingView.inputValue('street1'), addressLine2: this.billingView.inputValue('street2'), adminArea1: this.billingView.inputValue('stateCode'), adminArea2: this.billingView.inputValue('city'), postalCode: this.billingView.inputValue('postCode'), countryCode: this.billingView.inputValue('countryCode'), } } } submit(nonce, data) { // Send the nonce and previously captured device data to server to complete checkout if (!this.el.axoNonceInput.get()) { this.$('form.woocommerce-checkout').append(``); } this.el.axoNonceInput.get().value = nonce; PayPalInsights.trackEndCheckout({ amount: this.axoConfig?.insights?.amount, page_type: 'checkout', payment_method_selected: 'card', user_data: { country: 'US', is_store_member: false, } }); if (data) { // Ryan flow. const form = document.querySelector('form.woocommerce-checkout'); const formData = new FormData(form); this.showLoading(); // Fill in form data. Object.keys(data).forEach((key) => { formData.set(key, data[key]); }); // Set type of user (Ryan) to be received on WC gateway process payment request. formData.set('fastlane_member', true); fetch(wc_checkout_params.checkout_url, { // TODO: maybe create a new endpoint to process_payment. method: "POST", body: formData }) .then(response => response.json()) .then(responseData => { if (responseData.result === 'failure') { if (responseData.messages) { const $notices = this.$('.woocommerce-notices-wrapper').eq(0); $notices.html(responseData.messages); this.$('html, body').animate({ scrollTop: $notices.offset().top }, 500); } log(`Error sending checkout form. ${responseData}`, 'error'); this.hideLoading(); return; } if (responseData.redirect) { window.location.href = responseData.redirect; } }) .catch(error => { log(`Error sending checkout form. ${error.message}`, 'error'); this.hideLoading(); }); } else { // Gary flow. this.el.defaultSubmitButton.click(); } } showLoading() { const submitContainerSelector = '.woocommerce-checkout-payment'; jQuery('form.woocommerce-checkout').append('
'); disable(submitContainerSelector); } hideLoading() { const submitContainerSelector = '.woocommerce-checkout-payment'; jQuery('form.woocommerce-checkout .blockOverlay').remove(); enable(submitContainerSelector); } useEmailWidget() { return this.axoConfig?.widgets?.email === 'use_widget'; } deleteKeysWithEmptyString = (obj) => { for (let key of Object.keys(obj)) { if (obj[key] === '') { delete obj[key]; } else if (typeof obj[key] === 'object') { obj[key] = this.deleteKeysWithEmptyString(obj[key]); if (Object.keys(obj[key]).length === 0) delete obj[key]; } } return Array.isArray(obj) ? obj.filter(val => val) : obj; } ensureBillingPhoneNumber(data) { if (data.billing_phone === '') { let phone = ''; const cc = this.data?.shipping?.phoneNumber?.countryCode; const number = this.data?.shipping?.phoneNumber?.nationalNumber; if (cc) { phone = `+${cc} `; } phone += number; data.billing_phone = phone; } } toggleLoaderAndOverlay(element, loaderClass, overlayClass) { const loader = document.querySelector(`${element.selector} .${loaderClass}`); const overlay = document.querySelector(`${element.selector} .${overlayClass}`); if (loader) { loader.classList.toggle(loaderClass); } if (overlay) { overlay.classList.toggle(overlayClass); } } toggleWatermarkLoading(container, loadingClass, loaderClass) { const watermarkLoading = document.querySelector(`${container.selector}.${loadingClass}`); const watermarkLoader = document.querySelector(`${container.selector}.${loaderClass}`); if (watermarkLoading) { watermarkLoading.classList.toggle(loadingClass); } if (watermarkLoader) { watermarkLoader.classList.toggle(loaderClass); } } } export default AxoManager;