From 8b0e12c06d4be992b0ac4e99b3b29872637d382f Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Mon, 30 Sep 2024 18:29:02 +0200 Subject: [PATCH 1/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Minor=20code=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Define class properties - Change visibility of properties - Add some comments --- .../resources/js/Components/FormFieldGroup.js | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index b4318a43d..77ca2317b 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -1,30 +1,36 @@ class FormFieldGroup { - constructor( config ) { - this.data = {}; + #stored; + #data = {}; + #active = false; + #baseSelector; + #contentSelector; + #fields = {}; + #template; - this.baseSelector = config.baseSelector; - this.contentSelector = config.contentSelector; - this.fields = config.fields || {}; - this.template = config.template; + constructor( config ) { + this.#baseSelector = config.baseSelector; + this.#contentSelector = config.contentSelector; + this.#fields = config.fields || {}; + this.#template = config.template; + this.#stored = new Map(); - this.active = false; } setData( data ) { - this.data = data; + this.#data = data; this.refresh(); } dataValue( fieldKey ) { - if ( ! fieldKey || ! this.fields[ fieldKey ] ) { + if ( ! fieldKey || ! this.#fields[ fieldKey ] ) { return ''; } - if ( typeof this.fields[ fieldKey ].valueCallback === 'function' ) { - return this.fields[ fieldKey ].valueCallback( this.data ); + if ( typeof this.#fields[ fieldKey ].valueCallback === 'function' ) { + return this.#fields[ fieldKey ].valueCallback( this.#data ); } - const path = this.fields[ fieldKey ].valuePath; + const path = this.#fields[ fieldKey ].valuePath; if ( ! path ) { return ''; @@ -35,27 +41,42 @@ class FormFieldGroup { .reduce( ( acc, key ) => acc && acc[ key ] !== undefined ? acc[ key ] : undefined, - this.data + this.#data ); return value ? value : ''; } + /** + * Activate form group: Render a custom Fastlane UI to replace the WooCommerce form. + * + * Indicates: Ryan flow. + */ activate() { - this.active = true; + this.#active = true; this.refresh(); } + /** + * Deactivate form group: Remove the custom Fastlane UI - either display the default + * WooCommerce checkout form or no form at all (when no email was provided yet). + * + * Indicates: Gary flow / no email provided / not using Fastlane. + */ deactivate() { - this.active = false; + this.#active = false; this.refresh(); } toggle() { - this.active ? this.deactivate() : this.activate(); + if ( this.#active ) { + this.deactivate(); + } else { + this.activate(); + } } refresh() { - const content = document.querySelector( this.contentSelector ); + const content = document.querySelector( this.#contentSelector ); if ( ! content ) { return; @@ -63,10 +84,10 @@ class FormFieldGroup { content.innerHTML = ''; - if ( ! this.active ) { - this.hideField( this.contentSelector ); + if ( ! this.#active ) { + this.hideField( this.#contentSelector ); } else { - this.showField( this.contentSelector ); + this.showField( this.#contentSelector ); } Object.keys( this.fields ).forEach( ( key ) => { @@ -79,8 +100,8 @@ class FormFieldGroup { } } ); - if ( typeof this.template === 'function' ) { - content.innerHTML = this.template( { + if ( typeof this.#template === 'function' ) { + content.innerHTML = this.#template( { value: ( fieldKey ) => { return this.dataValue( fieldKey ); }, @@ -100,7 +121,7 @@ class FormFieldGroup { showField( selector ) { const field = document.querySelector( - this.baseSelector + ' ' + selector + this.#baseSelector + ' ' + selector ); if ( field ) { field.classList.remove( 'ppcp-axo-field-hidden' ); @@ -109,7 +130,7 @@ class FormFieldGroup { hideField( selector ) { const field = document.querySelector( - this.baseSelector + ' ' + selector + this.#baseSelector + ' ' + selector ); if ( field ) { field.classList.add( 'ppcp-axo-field-hidden' ); @@ -117,7 +138,7 @@ class FormFieldGroup { } inputElement( name ) { - const baseSelector = this.fields[ name ].selector; + const baseSelector = this.#fields[ name ].selector; const select = document.querySelector( baseSelector + ' select' ); if ( select ) { From 89fa0f1fa7768a343b435563eef3e55570df783c Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Mon, 30 Sep 2024 18:57:00 +0200 Subject: [PATCH 2/9] =?UTF-8?q?=E2=9C=A8=20New=20utility=20function=20to?= =?UTF-8?q?=20loop=20all=20group-fields?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Components/FormFieldGroup.js | 37 ++++++++++++++----- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index 77ca2317b..e7394e731 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -90,13 +90,11 @@ class FormFieldGroup { this.showField( this.#contentSelector ); } - Object.keys( this.fields ).forEach( ( key ) => { - const field = this.fields[ key ]; - - if ( this.active && ! field.showInput ) { - this.hideField( field.selector ); + this.loopFields( ( { selector } ) => { + if ( this.#active /* && ! field.showInput */ ) { + this.hideField( selector ); } else { - this.showField( field.selector ); + this.showField( selector ); } } ); @@ -107,18 +105,39 @@ class FormFieldGroup { }, isEmpty: () => { let isEmpty = true; - Object.keys( this.fields ).forEach( ( fieldKey ) => { + + this.loopFields( ( field, fieldKey ) => { if ( this.dataValue( fieldKey ) ) { isEmpty = false; return false; } } ); + return isEmpty; }, } ); } } + /** + * Invoke a callback on every field in the current group. + * + * @param {(field: object, key: string) => void} callback + */ + loopFields( callback ) { + Object.keys( this.#fields ).forEach( ( key ) => { + const field = this.#fields[ key ]; + const fieldSelector = `${ this.#baseSelector } ${ field.selector }`; + + callback( + { + ...field, + }, + key + ); + } ); + } + showField( selector ) { const field = document.querySelector( this.#baseSelector + ' ' + selector @@ -159,9 +178,7 @@ class FormFieldGroup { } toSubmitData( data ) { - Object.keys( this.fields ).forEach( ( fieldKey ) => { - const field = this.fields[ fieldKey ]; - + this.loopFields( ( field, fieldKey ) => { if ( ! field.valuePath || ! field.selector ) { return true; } From 0abb2e0f8dc16df6f175b185a5d3f997cfaa4504 Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Mon, 30 Sep 2024 18:59:13 +0200 Subject: [PATCH 3/9] =?UTF-8?q?=E2=9C=A8=20Store=20&=20restore=20the=20Woo?= =?UTF-8?q?=20form=20as=20needed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When Ryan flow starts, the values of the Woo-form are saved in an internal Map, and restored once the Ryan flow is disabled again (change email or select other payment gateway) --- .../resources/js/Components/FormFieldGroup.js | 55 +++++++++++++++++++ .../resources/js/Views/BillingView.js | 10 ++++ .../resources/js/Views/ShippingView.js | 10 ++++ 3 files changed, 75 insertions(+) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index e7394e731..ec7f69736 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -53,6 +53,7 @@ class FormFieldGroup { */ activate() { this.#active = true; + this.storeFormData(); this.refresh(); } @@ -64,6 +65,7 @@ class FormFieldGroup { */ deactivate() { this.#active = false; + this.restoreFormData(); this.refresh(); } @@ -131,6 +133,9 @@ class FormFieldGroup { callback( { + inputSelector: field.inputName + ? `${ fieldSelector } [name="${ field.inputName }"]` + : '', ...field, }, key @@ -138,6 +143,56 @@ class FormFieldGroup { } ); } + /** + * Stores the current form data in an internal storage. + * This allows the original form to be restored later. + */ + storeFormData() { + const storeValue = ( field, name ) => { + if ( 'checkbox' === field.type || 'radio' === field.type ) { + this.#stored.set( name, field.checked ); + } else { + this.#stored.set( name, field.value ); + } + }; + + this.loopFields( ( { inputSelector }, fieldKey ) => { + if ( inputSelector && ! this.#stored.has( fieldKey ) ) { + const elInput = document.querySelector( inputSelector ); + + if ( elInput ) { + storeValue( elInput, fieldKey ); + } + } + } ); + } + + /** + * Restores the form data to its initial state before the form group was activated. + * This function iterates through the stored form fields and resets their values or states. + */ + restoreFormData() { + const restoreValue = ( field, name ) => { + if ( 'checkbox' === field.type || 'radio' === field.type ) { + field.checked = this.#stored.get( name ); + } else { + field.value = this.#stored.get( name ); + } + }; + + this.loopFields( ( { inputSelector }, fieldKey ) => { + if ( inputSelector && this.#stored.has( fieldKey ) ) { + const elInput = document.querySelector( inputSelector ); + + if ( elInput ) { + restoreValue( elInput, fieldKey ); + } + + this.#stored.delete( fieldKey ); + } + } ); + } + showField( selector ) { const field = document.querySelector( this.#baseSelector + ' ' + selector diff --git a/modules/ppcp-axo/resources/js/Views/BillingView.js b/modules/ppcp-axo/resources/js/Views/BillingView.js index c9047f417..7f62f7d64 100644 --- a/modules/ppcp-axo/resources/js/Views/BillingView.js +++ b/modules/ppcp-axo/resources/js/Views/BillingView.js @@ -45,42 +45,52 @@ class BillingView { firstName: { selector: '#billing_first_name_field', valuePath: null, + inputName: 'billing_first_name', }, lastName: { selector: '#billing_last_name_field', valuePath: null, + inputName: 'billing_last_name', }, street1: { selector: '#billing_address_1_field', valuePath: 'billing.address.addressLine1', + inputName: 'billing_address_1', }, street2: { selector: '#billing_address_2_field', valuePath: null, + inputName: 'billing_address_2', }, postCode: { selector: '#billing_postcode_field', valuePath: 'billing.address.postalCode', + inputName: 'billing_postcode', }, city: { selector: '#billing_city_field', valuePath: 'billing.address.adminArea2', + inputName: 'billing_city', }, stateCode: { selector: '#billing_state_field', valuePath: 'billing.address.adminArea1', + inputName: 'billing_state', }, countryCode: { selector: '#billing_country_field', valuePath: 'billing.address.countryCode', + inputName: 'billing_country', }, company: { selector: '#billing_company_field', valuePath: null, + inputName: 'billing_company', }, phone: { selector: '#billing_phone_field', valuePath: 'billing.phoneNumber', + inputName: 'billing_phone', }, }, } ); diff --git a/modules/ppcp-axo/resources/js/Views/ShippingView.js b/modules/ppcp-axo/resources/js/Views/ShippingView.js index ba7ffb408..c656a010e 100644 --- a/modules/ppcp-axo/resources/js/Views/ShippingView.js +++ b/modules/ppcp-axo/resources/js/Views/ShippingView.js @@ -90,42 +90,52 @@ class ShippingView { key: 'firstName', selector: '#shipping_first_name_field', valuePath: 'shipping.name.firstName', + inputName: 'shipping_first_name', }, lastName: { selector: '#shipping_last_name_field', valuePath: 'shipping.name.lastName', + inputName: 'shipping_last_name', }, street1: { selector: '#shipping_address_1_field', valuePath: 'shipping.address.addressLine1', + inputName: 'shipping_address_1', }, street2: { selector: '#shipping_address_2_field', valuePath: null, + inputName: 'shipping_address_2', }, postCode: { selector: '#shipping_postcode_field', valuePath: 'shipping.address.postalCode', + inputName: 'shipping_postcode', }, city: { selector: '#shipping_city_field', valuePath: 'shipping.address.adminArea2', + inputName: 'shipping_city', }, stateCode: { selector: '#shipping_state_field', valuePath: 'shipping.address.adminArea1', + inputName: 'shipping_state', }, countryCode: { selector: '#shipping_country_field', valuePath: 'shipping.address.countryCode', + inputName: 'shipping_country', }, company: { selector: '#shipping_company_field', valuePath: null, + inputName: 'shipping_company', }, shipDifferentAddress: { selector: '#ship-to-different-address', valuePath: null, + inputName: 'ship_to_different_address', }, phone: { //'selector': '#billing_phone_field', // There is no shipping phone field. From 9e03c503acfcea5c1ccabc2a99287c18432450fa Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 16:16:53 +0200 Subject: [PATCH 4/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Extract=20common=20log?= =?UTF-8?q?ic=20into=20a=20class-method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Components/FormFieldGroup.js | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index ec7f69736..b963f2637 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -13,7 +13,6 @@ class FormFieldGroup { this.#fields = config.fields || {}; this.#template = config.template; this.#stored = new Map(); - } setData( data ) { @@ -46,6 +45,25 @@ class FormFieldGroup { return value ? value : ''; } + /** + * Changes the value of the input field. + * + * @param {Element|null} field + * @param {string|boolean} value + */ + #setFieldValue( field, value ) { + if ( ! field ) { + return false; + } + + if ( 'checkbox' === field.type || 'radio' === field.type ) { + value = !! value; + field.checked = value; + } else { + field.value = value; + } + } + /** * Activate form group: Render a custom Fastlane UI to replace the WooCommerce form. * @@ -151,8 +169,10 @@ class FormFieldGroup { const storeValue = ( field, name ) => { if ( 'checkbox' === field.type || 'radio' === field.type ) { this.#stored.set( name, field.checked ); + this.#setFieldValue( field, this.dataValue( name ) ); } else { this.#stored.set( name, field.value ); + this.#setFieldValue( field, '' ); } }; @@ -172,22 +192,11 @@ class FormFieldGroup { * This function iterates through the stored form fields and resets their values or states. */ restoreFormData() { - const restoreValue = ( field, name ) => { - if ( 'checkbox' === field.type || 'radio' === field.type ) { - field.checked = this.#stored.get( name ); - } else { - field.value = this.#stored.get( name ); - } - }; - this.loopFields( ( { inputSelector }, fieldKey ) => { if ( inputSelector && this.#stored.has( fieldKey ) ) { const elInput = document.querySelector( inputSelector ); - if ( elInput ) { - restoreValue( elInput, fieldKey ); - } - + this.#setFieldValue( elInput, this.#stored.get( fieldKey ) ); this.#stored.delete( fieldKey ); } } ); From 1e645a64e20441a908004b73847548664b336776 Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 16:20:37 +0200 Subject: [PATCH 5/9] =?UTF-8?q?=E2=9C=A8=20Sync=20Fastlane=20data=20with?= =?UTF-8?q?=20Woo=20cart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Main change of this branch. Tell WooCommerce about the shipping address used by Fastlane, so taxes and shipping options are correct --- .../resources/js/Components/FormFieldGroup.js | 33 +++++++++++++++++++ .../resources/js/Views/ShippingView.js | 4 +++ 2 files changed, 37 insertions(+) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index b963f2637..b94932dd2 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -50,18 +50,24 @@ class FormFieldGroup { * * @param {Element|null} field * @param {string|boolean} value + * @return {boolean} True indicates that the previous value was different from the new value. */ #setFieldValue( field, value ) { if ( ! field ) { return false; } + let oldVal; if ( 'checkbox' === field.type || 'radio' === field.type ) { value = !! value; + oldVal = field.checked; field.checked = value; } else { + oldVal = field.value; field.value = value; } + + return oldVal !== value; } /** @@ -202,6 +208,33 @@ class FormFieldGroup { } ); } + /** + * Syncs the internal field-data with the hidden checkout form fields. + */ + syncDataToForm() { + if ( ! this.#active ) { + return; + } + + let formHasChanged = false; + + // Push data to the (hidden) checkout form. + this.loopFields( ( { inputSelector }, fieldKey ) => { + const elInput = inputSelector + ? document.querySelector( inputSelector ) + : null; + + if ( this.#setFieldValue( elInput, this.dataValue( fieldKey ) ) ) { + formHasChanged = true; + } + } ); + + // Tell WooCommerce about the changes. + if ( formHasChanged ) { + document.body.dispatchEvent( new Event( 'update_checkout' ) ); + } + } + showField( selector ) { const field = document.querySelector( this.#baseSelector + ' ' + selector diff --git a/modules/ppcp-axo/resources/js/Views/ShippingView.js b/modules/ppcp-axo/resources/js/Views/ShippingView.js index c656a010e..4853659b7 100644 --- a/modules/ppcp-axo/resources/js/Views/ShippingView.js +++ b/modules/ppcp-axo/resources/js/Views/ShippingView.js @@ -136,6 +136,8 @@ class ShippingView { selector: '#ship-to-different-address', valuePath: null, inputName: 'ship_to_different_address', + // Used by Woo to ensure correct location for taxes & shipping cost. + valueCallback: () => true, }, phone: { //'selector': '#billing_phone_field', // There is no shipping phone field. @@ -173,6 +175,7 @@ class ShippingView { activate() { this.group.activate(); + this.group.syncDataToForm(); } deactivate() { @@ -185,6 +188,7 @@ class ShippingView { setData( data ) { this.group.setData( data ); + this.group.syncDataToForm(); } toSubmitData( data ) { From 09e7c3670a7211ab00f5989a2538f8bc44c4bcf4 Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 16:27:21 +0200 Subject: [PATCH 6/9] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Small=20cleanup?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Components/FormFieldGroup.js | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index b94932dd2..027a0c0d7 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -151,20 +151,17 @@ class FormFieldGroup { * @param {(field: object, key: string) => void} callback */ loopFields( callback ) { - Object.keys( this.#fields ).forEach( ( key ) => { - const field = this.#fields[ key ]; - const fieldSelector = `${ this.#baseSelector } ${ field.selector }`; - - callback( - { - inputSelector: field.inputName - ? `${ fieldSelector } [name="${ field.inputName }"]` - : '', - ...field, - }, - key - ); - } ); + for ( const [ key, field ] of Object.entries( this.#fields ) ) { + const { selector, inputName } = field; + const inputSelector = `${ selector } [name="${ inputName }"]`; + + const fieldInfo = { + inputSelector: inputName ? inputSelector : '', + ...field, + }; + + callback( fieldInfo, key ); + } } /** From a897557f4f12195eadd288d846f241d928ef05c0 Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 16:28:04 +0200 Subject: [PATCH 7/9] =?UTF-8?q?=F0=9F=90=9B=20Fix=20duplicate=20AXO=20chec?= =?UTF-8?q?k=20on=20initial=20load?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- modules/ppcp-axo/resources/js/AxoManager.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index d315ce374..551566042 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -801,8 +801,6 @@ class AxoManager { } async onChangeEmail() { - this.clearData(); - if ( ! this.status.active ) { log( 'Email checking skipped, AXO not active.' ); return; @@ -813,11 +811,17 @@ class AxoManager { return; } + if ( this.data.email === this.emailInput.value ) { + log( 'Email has not changed since last validation.' ); + return; + } + log( `Email changed: ${ this.emailInput ? this.emailInput.value : '<empty>' }` ); + this.clearData(); this.emailInput.value = this.stripSpaces( this.emailInput.value ); From d8d87ce1b817d63bf2133e1e40fcfb22052adb0e Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 17:29:28 +0200 Subject: [PATCH 8/9] =?UTF-8?q?=F0=9F=90=9B=20Prevent=20infinite=20loop=20?= =?UTF-8?q?for=20invalid=20state=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/js/Components/FormFieldGroup.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index 027a0c0d7..67fdd58ec 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -53,10 +53,25 @@ class FormFieldGroup { * @return {boolean} True indicates that the previous value was different from the new value. */ #setFieldValue( field, value ) { + let oldVal; + + const isValidOption = () => { + for ( let i = 0; i < field.options.length; i++ ) { + if ( field.options[ i ].value === value ) { + return true; + } + } + return false; + }; + if ( ! field ) { return false; } - let oldVal; + + // If an invalid option is provided, do nothing. + if ( 'SELECT' === field.tagName && ! isValidOption() ) { + return false; + } if ( 'checkbox' === field.type || 'radio' === field.type ) { value = !! value; From 41e69fe556bbf6921bb702fcdf870453fea9af37 Mon Sep 17 00:00:00 2001 From: Philipp Stracker <p.stracker@syde.com> Date: Tue, 1 Oct 2024 18:16:15 +0200 Subject: [PATCH 9/9] =?UTF-8?q?=F0=9F=90=9B=20Refresh=20cart=20when=20exit?= =?UTF-8?q?ing=20Ryan=20flow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After restoring the original WooCommerce form, also trigger a cart refresh Ajax call --- .../resources/js/Components/FormFieldGroup.js | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js index 67fdd58ec..2ea88feee 100644 --- a/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js +++ b/modules/ppcp-axo/resources/js/Components/FormFieldGroup.js @@ -210,14 +210,28 @@ class FormFieldGroup { * This function iterates through the stored form fields and resets their values or states. */ restoreFormData() { + let formHasChanged = false; + + // Reset form fields to their initial state. this.loopFields( ( { inputSelector }, fieldKey ) => { - if ( inputSelector && this.#stored.has( fieldKey ) ) { - const elInput = document.querySelector( inputSelector ); + if ( ! this.#stored.has( fieldKey ) ) { + return; + } - this.#setFieldValue( elInput, this.#stored.get( fieldKey ) ); - this.#stored.delete( fieldKey ); + const elInput = inputSelector + ? document.querySelector( inputSelector ) + : null; + const oldValue = this.#stored.get( fieldKey ); + this.#stored.delete( fieldKey ); + + if ( this.#setFieldValue( elInput, oldValue ) ) { + formHasChanged = true; } } ); + + if ( formHasChanged ) { + document.body.dispatchEvent( new Event( 'update_checkout' ) ); + } } /**