import { type AmwalCheckoutButtonCustomEvent } from 'amwal-checkout-button' import { type AmwalCheckoutStatus, type AmwalDismissalStatus, type IAddress, type ITransactionDetails } from 'amwal-checkout-button/dist/types/components/amwal-checkout-button/amwal-checkout-button' import $ from 'jquery' declare global { interface HTMLElementEventMap { amwalCheckoutSuccess: AmwalCheckoutButtonCustomEvent updateOrderOnPaymentsuccess: AmwalCheckoutButtonCustomEvent amwalAddressUpdate: AmwalCheckoutButtonCustomEvent amwalAddressCountryUpdate: AmwalCheckoutButtonCustomEvent amwalAddressStateUpdate: AmwalCheckoutButtonCustomEvent amwalDismissed: AmwalCheckoutButtonCustomEvent amwalPrePayTrigger: AmwalCheckoutButtonCustomEvent } const AMWALWC_CONSTANTS: { transactionDetailsURL: string pluginVersion: string extraEvents: string siteURL: string btn_ajax_url: string btn_ajax_nonce: string } } function disableAmwalButtons (): void { const buttons = document.querySelectorAll('amwal-checkout-button') buttons.forEach((button) => { button.disabled = true }) } const enableAmwalButton = (button: HTMLAmwalCheckoutButtonElement): void => { const checkout = new AmwalCheckout(button) checkout.registerEventListeners() if (checkout.position === 'amwal-product-page') { const variationForm = jQuery('form.variations_form') variationForm?.on('show_variation', function () { button.disabled = false }) variationForm?.on('hide_variation', function () { button.disabled = true }) } } function enableAmwalButtons (): void { // woo block based document.querySelectorAll might not be running in the correct scope. // so, using setTimeout for WooCommerce-related block events . setTimeout(() => { const buttons = document.querySelectorAll('amwal-checkout-button') buttons.forEach(enableAmwalButton) }, 1000) } document.addEventListener('DOMContentLoaded', function () { enableAmwalButtons() // https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/client/legacy/js/frontend/cart-fragments.js#L150 }) // for mini-cart button $(document).ready(function () { setInterval(function () { const buttons = document.querySelectorAll('amwal-checkout-button') buttons.forEach(enableAmwalButton) }, 1000) }) $(document).ready(function () { let lastProductId = null const observer = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { $(mutation.addedNodes).each(function () { // Try to get product ID from data-id on the quick view container const quickViewDiv = $('#wqv-quick-view-content') let productId = null if (quickViewDiv.length && quickViewDiv.data('id')) { productId = parseInt(quickViewDiv.data('id'), 10) } else { // Fallback: try to find div with id like "product-XXXX" const productDiv = $('div[id^="product-"]').first() if (productDiv.length) { const idAttr = productDiv.attr('id') // e.g., product-270 const matches = idAttr.match(/^product-(\d+)$/) if (matches?.[1]) { productId = parseInt(matches[1], 10) } } } // Proceed only if productId was found and it’s new if (productId && productId !== lastProductId) { lastProductId = productId console.log('Quick View Product ID:', productId) // Get permalink via AJAX void $.ajax({ url: ajaxurl, method: 'POST', data: { action: 'get_product_permalink', product_id: productId }, timeout: 5000, success: function (response) { if (response.success && response.data.permalink) { const form = document.querySelector('form.cart') if (form && !form.getAttribute('action')) { form.setAttribute('action', response.data.permalink) console.log('Form action set to:', response.data.permalink) } } }, error: function (jqXHR, textStatus, errorThrown) { if (textStatus === 'timeout') { console.warn('AJAX request timed out.') } else { console.error('AJAX error:', textStatus, errorThrown) } } }) } }) }) }) observer.observe(document.body, { childList: true, subtree: true }) }) // This change if to solve the issue of the button not being enabled after the page is loaded, in some scripts DOMContentLoaded is removed before the button is loaded const documentBody = $(document.body) documentBody.on(AMWALWC_CONSTANTS.extraEvents, enableAmwalButtons) documentBody.on('added_to_cart', () => { document.querySelectorAll('.amwal-product-page amwal-checkout-button').forEach(e => { e.remove() }) }) window.onbeforeunload = disableAmwalButtons class AmwalCheckout { handlingPrePayTrigger = false handlingCheckoutPayTrigger = false busyUpdatingOrder = false receivedSuccess = false checkoutButton!: HTMLAmwalCheckoutButtonElement buttonId: string | null position: string | null orderContent: any genOrderId?: string backendURL: string | null pre_existing_order_id?: string buttonVersion: string | null constructor (button: HTMLAmwalCheckoutButtonElement) { this.checkoutButton = button this.buttonId = this.checkoutButton.getAttribute('ref-id') this.position = this.checkoutButton.getAttribute('position') this.orderContent = undefined this.busyUpdatingOrder = false this.receivedSuccess = false this.backendURL = AMWALWC_CONSTANTS.transactionDetailsURL this.pre_existing_order_id = this.checkoutButton?.getAttribute('checkout-order-id') ?? undefined this.buttonVersion = AMWALWC_CONSTANTS.pluginVersion } registerEventListeners (): void { const eventsRegistered = this.checkoutButton.getAttribute('events-registered') if (eventsRegistered) { return } const amwalCheckoutSuccess = (ev: AmwalCheckoutButtonCustomEvent): void => { this.receivedSuccess = true if (this.busyUpdatingOrder) { return } try { if (ev.detail.orderId && this.genOrderId) { window.location.href = AMWALWC_CONSTANTS.siteURL + '?amwal_order_created=' + this.genOrderId } } catch (error: unknown) { throw new Error(error?.toString()) } } const updateOrderOnPaymentsuccess = (ev: AmwalCheckoutButtonCustomEvent): void => { this.busyUpdatingOrder = true if (ev.detail.orderId) { this.completeOrder() .then(() => { this.busyUpdatingOrder = false if (this.receivedSuccess && this.genOrderId) { window.location.href = AMWALWC_CONSTANTS.siteURL + '?amwal_order_created=' + this.genOrderId } }) .catch(err => { throw new Error(err?.toString()) }) } } const amwalAddressUpdate = (ev: AmwalCheckoutButtonCustomEvent): void => { const urlForUpdate = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/checkout/update' postData(urlForUpdate, { amwal_cart_id: this.buttonId, address_details: ev.detail }) .then(data => { this.checkoutButton.setAttribute('discount', data.discount) this.checkoutButton.setAttribute('taxes', data.taxes) this.checkoutButton.setAttribute('amount', data.amount) this.checkoutButton.setAttribute('shipping-methods', JSON.stringify(data.shipping_methods)) this.checkoutButton.shippingMethods = data.shipping_methods this.checkoutButton.dispatchEvent(new Event('amwalAddressAck')) }) .catch(err => { this.checkoutButton.dispatchEvent(new CustomEvent('amwalAddressTriggerError', { detail: { description: 'Error in getting shipping methods', error: err?.toString() } })) }) } const amwalAddressCountryUpdate = (ev: AmwalCheckoutButtonCustomEvent): void => { const urlForUpdate = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/address/update' postData(urlForUpdate, { address_country: ev.detail.addressCountry }) .then(data => { this.checkoutButton.setAttribute('allowed-address-states', JSON.stringify(data)) this.checkoutButton.allowedAddressStates = data this.checkoutButton.dispatchEvent(new Event('amwalAddressCountryAck')) }) .catch(err => { console.log('Error in getting States', err) }) } const amwalAddressStateUpdate = (ev: AmwalCheckoutButtonCustomEvent): void => { const urlForUpdate = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/address/update' postData(urlForUpdate, { address_country: ev.detail.addressCountry, address_state: ev.detail.addressState }) .then(data => { this.checkoutButton.setAttribute('allowed-address-cities', JSON.stringify(data)) this.checkoutButton.allowedAddressCities = data this.checkoutButton.dispatchEvent(new Event('amwalAddressStateAck')) }) .catch(err => { console.log('Error in getting Cities', err) }) } const amwalDismissed = (event: AmwalCheckoutButtonCustomEvent): void => { if (event.detail.orderId) { if (this.genOrderId) { this.completeOrder(event.detail.paymentSuccessful) .catch((err: unknown) => { const errorMessage = err instanceof Error ? err.message : typeof err === 'string' ? err : 'Unknown error occurred' showAmwalErrorModal(errorMessage) }) } this.checkoutButton.disabled = true this.cancelOrder(event.detail.orderId) .finally(() => { this.checkoutButton.disabled = false this.genOrderId = undefined }) } } function showAmwalErrorModal (message: string): void { const fallbackContainer: HTMLDivElement = document.createElement('div') fallbackContainer.className = 'amwal-global-notice' fallbackContainer.innerHTML = ` ` document.body.appendChild(fallbackContainer) setTimeout(() => { fallbackContainer.remove() }, 8000) } const amwalPrePayTrigger = (ev: AmwalCheckoutButtonCustomEvent): void => { if (this.handlingPrePayTrigger) return this.handlingPrePayTrigger = true if (this.position === 'amwal-before-checkout-form' && !this.pre_existing_order_id) { throw new Error('Unexpected error occurred while creating order') } const url = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/order/create' postData(url, { amwal_cart_id: this.buttonId, transaction_details: ev.detail, amwal_order_id: this.pre_existing_order_id }) .then(data => { console.log('amwalPrePayTrigger', data) return data }) .then(data => { this.genOrderId = data.order_id this.checkoutButton.setAttribute('amount', data.amount) this.checkoutButton.dispatchEvent(new CustomEvent('amwalPrePayTriggerAck', { detail: { order_total_amount: data.amount, order_id: data.order_id, card_bin_additional_discount_message: data.card_bin_additional_discount_message ?? '', card_bin_additional_discount: data.card_bin_additional_discount ?? 0, old_amount: data.old_amount ?? 0 } })) }).catch(err => { const errorMessage = err instanceof Error ? err.message : typeof err === 'string' ? err : 'Unknown error occurred' showAmwalErrorModal(errorMessage) this.checkoutButton.dispatchEvent(new CustomEvent('amwalPrePayTriggerError', { detail: { description: errorMessage } })) }).finally(() => { this.handlingPrePayTrigger = false }) } const amwalPreCheckoutTrigger = (ev: Event): void => { if (this.handlingCheckoutPayTrigger) return this.handlingCheckoutPayTrigger = true let productData: Record | undefined if (this.position === 'amwal-product-page') { const cartForm = document.querySelector('form.cart') if (cartForm) { const cartFormData = new FormData(cartForm) productData = Object.fromEntries(cartFormData.entries()) const formSubmitButton = cartForm.querySelector("button[type='submit']") if (formSubmitButton && !productData['add-to-cart']) { productData['add-to-cart'] = formSubmitButton.value } } } const createCheckoutPromise = this.createCheckout(productData) createCheckoutPromise.then(() => { const amount = this.checkoutButton?.getAttribute('amount') if (this.orderContent && this.checkoutButton && amount && parseFloat(amount) > 0) { this.checkoutButton.dispatchEvent(new CustomEvent('amwalPreCheckoutTriggerAck', { detail: { order_position: this.position, order_content: JSON.stringify(this.orderContent), plugin_version: this.buttonVersion ? 'woocommerce ' + this.buttonVersion : undefined } })) } else { throw new Error('Cannot Proceed With Amount Of Zero') } }).catch(err => { const errorMessage = err instanceof Error ? err.message : typeof err === 'string' ? err : 'Unknown error occurred' showAmwalErrorModal(errorMessage) this.checkoutButton.dispatchEvent(new CustomEvent('amwalPreCheckoutTriggerError', { detail: { description: errorMessage } })) }).finally(() => { this.handlingCheckoutPayTrigger = false }) } this.checkoutButton.addEventListener('amwalCheckoutSuccess', amwalCheckoutSuccess, false) this.checkoutButton.addEventListener('updateOrderOnPaymentsuccess', updateOrderOnPaymentsuccess, false) this.checkoutButton.addEventListener('amwalAddressUpdate', amwalAddressUpdate, false) this.checkoutButton.addEventListener('amwalAddressCountryUpdate', amwalAddressCountryUpdate, false) this.checkoutButton.addEventListener('amwalAddressStateUpdate', amwalAddressStateUpdate, false) this.checkoutButton.addEventListener('amwalDismissed', amwalDismissed, false) this.checkoutButton.addEventListener('amwalPrePayTrigger', amwalPrePayTrigger, false) this.checkoutButton.addEventListener('amwalPreCheckoutTrigger', amwalPreCheckoutTrigger, false) this.checkoutButton.setAttribute('events-registered', 'true') } async createCheckout (productData?: Record): Promise { const url = `${AMWALWC_CONSTANTS.siteURL}/wp-json/wc/amwal/v2/checkout/create` const pageType = this.getPageType() if (pageType === 'checkout') { // get current address this.setAddress() this.updateAddressDetails() this.checkoutButton.setAttribute('address-handshake', 'true') this.checkoutButton.setAttribute('debug', 'true') } const shippingComplete = pageType === 'checkout' ? this.isAddressInfoComplete() : false const data = await postData(url, { amwal_cart_id: this.buttonId, pre_existing_order_id: this.pre_existing_order_id, page_type: pageType, product_data: productData }) this.checkoutButton.setAttribute('address-handshake', (data.shipping_selected === 'yes' && shippingComplete) ? 'false' : 'true') this.checkoutButton.setAttribute('taxes', data.taxes) this.checkoutButton.setAttribute('amount', data.amount) this.checkoutButton.setAttribute('discount', data.discount) const virtualcheck = this.checkoutButton.getAttribute('virtual-check') if (virtualcheck === 'true') { this.checkoutButton.setAttribute('address-required', shippingComplete ? 'false' : 'true') } this.orderContent = data.order_content } private getPageType (): 'checkout' | 'cart' | 'product' { const url = window.location.href if (url.includes('/checkout')) return 'checkout' if (url.includes('/cart')) return 'cart' return 'product' } private setAddress (): void { const address = this.getInitialAddress() console.info(address) this.checkoutButton.setAttribute('initial-address', address) this.checkoutButton.initialAddress = JSON.stringify(address) this.checkoutButton.setAttribute('enable-dynamic-shipping-details', 'false') if (jQuery('.wc-block-checkout').length) { this.checkoutButton.setAttribute('initial-first-name', ($('#shipping-first_name').val() ?? $('#billing-first_name').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-last-name', ($('#shipping-last_name').val() ?? $('#billing-last_name').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-phone-number', ($('#shipping-phone').val() ?? $('#billing-phone').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-email', ($('#email').val() ?? $('#email').val() ?? '').toString()) } else { this.checkoutButton.setAttribute('initial-first-name', ($('#shipping_first_name').val() ?? $('#billing_first_name').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-last-name', ($('#shipping_last_name').val() ?? $('#billing_last_name').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-phone-number', ($('#shipping_phone').val() ?? $('#billing_phone').val() ?? '').toString()) this.checkoutButton.setAttribute('initial-email', ($('#shipping_email').val() ?? $('#billing_email').val() ?? '').toString()) } } private getInitialAddress (): string { let address = {} if (jQuery('.wc-block-checkout').length) { address = { street1: ($('#shipping-address_1').val() ?? $('#billing-address_1').val() ?? '').toString(), street2: ($('#shipping-address_2').val() ?? $('#billing-address_2').val() ?? '').toString(), city: ($('#shipping-city').val() ?? $('#billing-city').val() ?? '').toString(), state: ($('#shipping-state').val() ?? $('#billing-state').val() ?? '').toString(), postcode: ($('#shipping-postcode').val() ?? $('#billing-postcode').val() ?? '').toString(), country: ($('#shipping-country').val() ?? $('#billing-country').val() ?? '').toString() } } else { address = { street1: ($('#shipping_address_1').val() ?? $('#billing_address_1').val() ?? '').toString(), street2: ($('#shipping_address_2').val() ?? $('#billing_address_2').val() ?? '').toString(), city: ($('#shipping_city').val() ?? $('#billing_city').val() ?? '').toString(), state: ($('#shipping_state').val() ?? $('#billing_state').val() ?? '').toString(), postcode: ($('#shipping_postcode').val() ?? $('#billing_postcode').val() ?? '').toString(), country: ($('#shipping_country').val() ?? $('#billing_country').val() ?? '').toString() } } return JSON.stringify(address) } private isAddressInfoComplete (): boolean { let requiredFields: string[] = [] let shippingMethodSelected: boolean = false if (jQuery('.wc-block-checkout').length) { // ✅ Assign instead of redeclare requiredFields = jQuery( '.wc-block-components-form input[required], .wc-block-components-form select[required]' ) .map((_, el) => el.id) .get() const { select } = wp.data const selectedShippingRate = select('wc/store/cart') .getShippingRates() ?.flatMap((rate: any) => rate.shipping_rates) ?.find((rate: any) => rate.selected) shippingMethodSelected = !!selectedShippingRate } else { // ✅ Assign instead of redeclare requiredFields = jQuery( '.woocommerce-billing-fields input[aria-required], ' + '.woocommerce-billing-fields select[aria-required], ' + '.woocommerce-shipping-fields input[aria-required], ' + '.woocommerce-shipping-fields select[aria-required]' ) .map((_, el) => el.id) .get() shippingMethodSelected = !!document.querySelector( 'input[id^="shipping_method"]:checked' ) } // ✅ Validate all fields const allFieldsFilled = requiredFields.every((field) => { const input = document.querySelector(`#${field}`) return input && input.value.trim().length > 0 }) return allFieldsFilled && shippingMethodSelected } private updateAddressDetails (): void { let addressData if (jQuery('.wc-block-checkout').length) { addressData = { billing_first_name: $('[id="billing-first_name"]').val(), billing_last_name: $('[id="billing-last_name"]').val(), billing_address_1: $('[id="billing-address_1"]').val(), billing_address_2: $('[id="billing-address_2"]').val(), billing_city: $('[id="billing-city"]').val(), billing_state: $('[id="billing-state"]').val(), billing_postcode: $('[id="billing-postcode"]').val(), billing_country: $('[id="billing-country"]').val(), billing_email: $('[id="email"]').val(), billing_phone: $('[id="billing-phone"]').val(), shipping_first_name: $('[id="shipping-first_name"]').val(), shipping_last_name: $('[id="shipping-last_name"]').val(), shipping_address_1: $('[id="shipping-address_1"]').val(), shipping_address_2: $('[id="shipping-address_2"]').val(), shipping_city: $('[id="shipping-city]').val(), shipping_state: $('[id="shipping-state"]').val(), shipping_postcode: $('[id="shipping-postcode"]').val(), shipping_country: $('[id="shipping-country"]').val(), shipping_email: $('[id="email"]').val(), shipping_phone: $('[id="shipping-phone"]').val() } } else { addressData = { billing_first_name: $('[id="billing_first_name"]').val(), billing_last_name: $('[id="billing_last_name"]').val(), billing_address_1: $('[id="billing_address_1"]').val(), billing_address_2: $('[id="billing_address_2"]').val(), billing_city: $('[id="billing_city"]').val(), billing_state: $('[id="billing_state"]').val(), billing_postcode: $('[id="billing_postcode"]').val(), billing_country: $('[id="billing_country"]').val(), billing_email: $('[id="billing_email"]').val(), billing_phone: $('[id="billing_phone"]').val(), shipping_first_name: $('[id="shipping_first_name"]').val(), shipping_last_name: $('[id="shipping_last_name"]').val(), shipping_address_1: $('[id="shipping_address_1"]').val(), shipping_address_2: $('[id="shipping_address_2"]').val(), shipping_city: $('[id="shipping_city"]').val(), shipping_state: $('[id="shipping_state"]').val(), shipping_postcode: $('[id="shipping_postcode"]').val(), shipping_country: $('[id="shipping_country"]').val(), shipping_email: $('[id="shipping_email"]').val(), shipping_phone: $('[id="shipping_phone"]').val() } } void $.post({ url: ajaxurl, // localized in PHP data: { action: 'amwal_payload_address', data: addressData, ref_id: this.buttonId }, success: function (response) { console.log('address updated:', response) }, error: function (xhr) { console.error('Failed to update address:', xhr.responseText) } }) } async cancelOrder (amwalTransactionID: string): Promise { if (this.position === 'amwal-product-page') { const url = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/orders/cancel' return await postData(url, { amwal_cart_id: this.buttonId, amwal_transaction_id: amwalTransactionID }) } } async completeOrder (assertTransactionStatus: boolean = true): Promise { const orderId = this.checkoutButton?.getAttribute('checkout-order-id') ?? this.genOrderId ?? '' const url = AMWALWC_CONSTANTS.siteURL + '/wp-json/wc/amwal/v2/order/complete' // Let postData throw naturally — don't wrap it unnecessarily return await postData(url, { amwal_cart_id: this.buttonId, order_id: orderId, assert_transaction_status: assertTransactionStatus }) } } const postData = async function (url: string, data: any): Promise { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) let result: any try { result = await response.json() } catch (err) { const errorText = await response.text() throw new Error(errorText || `Error ${response.status}`) } if (!response.ok || result.success === false) { throw new Error(result.message || `Error ${response.status}`) } return result } const AMWAL_METHODS = ['amwalcheckout', 'amwalcheckout_installments'] const PLACE_ORDER_SELECTORS = [ '.wc-block-checkout__form .wc-block-components-button', '.wc-block-components-checkout-place-order-button', '#place_order' ] /** * Inject Amwal button based on page context */ function displayAmwalBtn (page: 'cart' | 'checkout'): void { void jQuery.ajax({ url: AMWALWC_CONSTANTS.btn_ajax_url, type: 'POST', data: { action: 'amwalwc_woo_pages', security: AMWALWC_CONSTANTS.btn_ajax_nonce }, success: function (response: string) { switch (page) { case 'cart': jQuery('.wp-block-woocommerce-cart-order-summary-block').after(response) break case 'checkout': // Uncomment if needed // jQuery('#payment-method').after(response) break } } }) } /** * Inject Amwal button based on mini widget context */ function displayAmwalBtnInMiniCart (): void { void jQuery.ajax({ url: AMWALWC_CONSTANTS.btn_ajax_url, type: 'POST', data: { action: 'amwalwc_woo_minicart', security: AMWALWC_CONSTANTS.btn_ajax_nonce }, success: function (response: string) { if (jQuery('.amwal-container').length === 0) { jQuery('.wc-block-mini-cart__footer-actions').before(response) } } }) } /** * Observe for element appearance and run callback */ function watchForElement (selector: string, callback: () => void): void { const observer = new MutationObserver(() => { if (jQuery(selector).length) { callback() observer.disconnect() } }) observer.observe(document.body, { childList: true, subtree: true }) } /** * Hide Place Order button if Amwal is selected */ function togglePlaceOrderButton (): void { try { const selected = String(jQuery('input[name="payment_method"]:checked').val() || '').toLowerCase().trim() const shouldHide = AMWAL_METHODS.some(method => method.toLowerCase() === selected) PLACE_ORDER_SELECTORS.forEach(selector => { const $btn = jQuery(selector) if ($btn.length) { $btn.prop('disabled', shouldHide).toggle(!shouldHide) } }) } catch (err) { console.error('togglePlaceOrderButton error:', err) } } /** * Disable Amwal buttons if terms not accepted */ function toggleAmwalButtons (): void { const termsCheckbox = document.querySelector('#terms') const buttons = document.querySelectorAll('amwal-checkout-button') const shouldDisable = !termsCheckbox?.checked buttons.forEach((button) => { if (shouldDisable) { button.setAttribute('disabled', 'disabled') } else { button.removeAttribute('disabled') } }) } /** * Watch for terms checkbox and bind events */ (function watchTermsCheckboxAndBind (): void { const attachTermsListener = (): void => { const checkbox = document.querySelector('#terms') if (checkbox && !checkbox.dataset.amwalBound) { checkbox.addEventListener('change', toggleAmwalButtons) checkbox.dataset.amwalBound = 'true' toggleAmwalButtons() } } attachTermsListener() const observer = new MutationObserver(() => { attachTermsListener() }) observer.observe(document.body, { childList: true, subtree: true }) })() /** * Handle payment method radio click (Woo Blocks) */ document.addEventListener('click', function (event: MouseEvent) { const target = event.target as HTMLElement if (target.id.startsWith('radio-control-wc-payment-method-options-')) { const isAmwalSelected = target.id.includes('amwalcheckout') PLACE_ORDER_SELECTORS.forEach(selector => { const $btn = jQuery(selector) if ($btn.length) { $btn.prop('disabled', isAmwalSelected).toggle(!isAmwalSelected) } }) } }) /** * Init logic on DOM ready */ $(document).ready(function () { watchForElement('.wp-block-woocommerce-cart-order-summary-block', () => { displayAmwalBtn('cart') }) watchForElement('#payment-method', () => { displayAmwalBtn('checkout') }) // Mini-cart poller setInterval(() => { if ( jQuery('.wc-block-mini-cart__footer-actions').length && jQuery('.amwal-container').length === 0 ) { displayAmwalBtnInMiniCart() } }, 1000) // Initial and reactive toggle togglePlaceOrderButton() jQuery(document).on('change', 'input[name="payment_method"]', togglePlaceOrderButton) // jQuery('form.checkout').on('change', 'input[id="payment_method"]', togglePlaceOrderButton) jQuery(document.body).on('updated_checkout', togglePlaceOrderButton) jQuery(document.body).on('change', 'form.checkout :input', togglePlaceOrderButton) // Fallback setInterval(togglePlaceOrderButton, 500) }) // TypeScript code to monitor WooCommerce checkout updates declare const jQuery: any (function ($: any) { let previousTotal = '' /** * Trigger `update_checkout` when order total visually changes */ function observeOrderTotalChange (): void { const target = document.body const observer = new MutationObserver(() => { const totalEl = document.querySelector('.order-total .woocommerce-Price-amount') if (!totalEl) return const currentTotal = totalEl.textContent?.trim() if (currentTotal && currentTotal !== previousTotal) { previousTotal = currentTotal $(document.body).trigger('update_checkout') togglePlaceOrderButton() } }) observer.observe(target, { childList: true, subtree: true }) } /** * Init */ function init (): void { observeOrderTotalChange() } $(document).ready(init) })(jQuery)