Refactor axo module

This commit is contained in:
Pedro Silva 2024-03-08 14:39:50 +00:00
parent b7d43d3c5b
commit 039cc53f40
No known key found for this signature in database
GPG key ID: E2EE20C0669D24B3
6 changed files with 581 additions and 51 deletions

View file

@ -2,6 +2,7 @@ import Fastlane from "./Entity/Fastlane";
import MockData from "./Helper/MockData";
import {log} from "./Helper/Debug";
import {hide, show} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
import FormFieldGroup from "./Helper/FormFieldGroup";
class AxoManager {
@ -13,6 +14,15 @@ class AxoManager {
this.fastlane = new Fastlane();
this.$ = jQuery;
this.isConnectProfile = false;
this.hideGatewaySelection = false;
this.data = {
billing: null,
shipping: null,
card: null,
}
this.elements = {
gatewayRadioButton: {
selector: '#payment_method_ppcp-axo-gateway',
@ -35,11 +45,24 @@ class AxoManager {
selector: '#ppcp-axo-email-widget',
className: 'ppcp-axo-email-widget'
},
shippingAddressContainer: {
id: 'ppcp-axo-shipping-address-container',
selector: '#ppcp-axo-shipping-address-container',
className: 'ppcp-axo-shipping-address-container',
anchorSelector: '.woocommerce-shipping-fields'
},
billingAddressContainer: {
id: 'ppcp-axo-billing-address-container',
selector: '#ppcp-axo-billing-address-container',
className: 'ppcp-axo-billing-address-container',
anchorSelector: '.woocommerce-billing-fields__field-wrapper'
},
fieldBillingEmail: {
selector: '#billing_email_field'
},
submitButtonContainer: {
selector: '#ppcp-axo-submit-button-container'
selector: '#ppcp-axo-submit-button-container',
buttonSelector: '#ppcp-axo-submit-button-container button'
},
}
@ -51,6 +74,226 @@ class AxoManager {
this.locale = 'en_us';
this.registerEventHandlers();
this.shippingFormFields = new FormFieldGroup({
baseSelector: '.woocommerce-checkout',
contentSelector: this.elements.shippingAddressContainer.selector,
template: (data) => {
const valueOfSelect = (selectSelector, key) => {
const selectElement = document.querySelector(selectSelector);
const option = selectElement.querySelector(`option[value="${key}"]`);
return option ? option.textContent : key;
}
if (data.isEditing()) {
return `
<div style="margin-bottom: 20px;">
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-save-shipping-address style="margin-left: 20px;">Save</a></h3>
</div>
`;
}
if (data.isEmpty()) {
return `
<div style="margin-bottom: 20px;">
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-change-shipping-address style="margin-left: 20px;">Edit</a></h3>
<div>Please fill in your shipping details.</div>
</div>
`;
}
return `
<div style="margin-bottom: 20px;">
<h3>Shipping details <a href="javascript:void(0)" data-ppcp-axo-change-shipping-address style="margin-left: 20px;">Edit</a></h3>
<div>${data.value('company')}</div>
<div>${data.value('firstName')} ${data.value('lastName')}</div>
<div>${data.value('street1')}</div>
<div>${data.value('street2')}</div>
<div>${data.value('postCode')} ${data.value('city')}</div>
<div>${valueOfSelect('#shipping_state', data.value('stateCode'))}</div>
<div>${valueOfSelect('#shipping_country', data.value('countryCode'))}</div>
</div>
`;
},
fields: {
firstName: {
'key': 'firstName',
'selector': '#shipping_first_name_field',
'valuePath': 'shipping.name.firstName',
},
lastName: {
'selector': '#shipping_last_name_field',
'valuePath': 'shipping.name.lastName',
},
street1: {
'selector': '#shipping_address_1_field',
'valuePath': 'shipping.address.addressLine1',
},
street2: {
'selector': '#shipping_address_2_field',
'valuePath': null
},
postCode: {
'selector': '#shipping_postcode_field',
'valuePath': 'shipping.address.postalCode',
},
city: {
'selector': '#shipping_city_field',
'valuePath': 'shipping.address.adminArea2',
},
stateCode: {
'selector': '#shipping_state_field',
'valuePath': 'shipping.address.adminArea1',
},
countryCode: {
'selector': '#shipping_country_field',
'valuePath': 'shipping.address.countryCode',
},
company: {
'selector': '#shipping_company_field',
'valuePath': null,
},
shipDifferentAddress: {
'selector': '#ship-to-different-address',
'valuePath': null,
}
}
});
this.billingFormFields = new FormFieldGroup({
baseSelector: '.woocommerce-checkout',
contentSelector: this.elements.billingAddressContainer.selector,
template: (data) => {
const valueOfSelect = (selectSelector, key) => {
const selectElement = document.querySelector(selectSelector);
const option = selectElement.querySelector(`option[value="${key}"]`);
return option ? option.textContent : key;
}
if (data.isEditing()) {
return `
<div style="margin-bottom: 20px;">
<h4><a href="javascript:void(0)" data-ppcp-axo-save-billing-address>Save</a></h4>
</div>
`;
}
if (data.isEmpty()) {
return `
<div style="margin-bottom: 20px;">
<div>Please fill in your billing details.</div>
<h4><a href="javascript:void(0)" data-ppcp-axo-change-billing-address>Edit</a></h4>
</div>
`;
}
return `
<div style="margin-bottom: 20px;">
<h4>Billing address</h4>
<div>${data.value('company')}</div>
<div>${data.value('firstName')} ${data.value('lastName')}</div>
<div>${data.value('street1')}</div>
<div>${data.value('street2')}</div>
<div>${data.value('postCode')} ${data.value('city')}</div>
<div>${valueOfSelect('#billing_state', data.value('stateCode'))}</div>
<div>${valueOfSelect('#billing_country', data.value('countryCode'))}</div>
<div>${data.value('phone')}</div>
<h4><a href="javascript:void(0)" data-ppcp-axo-change-billing-address>Edit</a></h4>
</div>
`;
},
fields: {
firstName: {
'selector': '#billing_first_name_field',
'valuePath': 'billing.name.firstName',
},
lastName: {
'selector': '#billing_last_name_field',
'valuePath': 'billing.name.lastName',
},
street1: {
'selector': '#billing_address_1_field',
'valuePath': 'billing.address.addressLine1',
},
street2: {
'selector': '#billing_address_2_field',
'valuePath': null
},
postCode: {
'selector': '#billing_postcode_field',
'valuePath': 'billing.address.postalCode',
},
city: {
'selector': '#billing_city_field',
'valuePath': 'billing.address.adminArea2',
},
stateCode: {
'selector': '#billing_state_field',
'valuePath': 'billing.address.adminArea1',
},
countryCode: {
'selector': '#billing_country_field',
'valuePath': 'billing.address.countryCode',
},
company: {
'selector': '#billing_company_field',
'valuePath': null,
},
phone: {
'selector': '#billing_phone_field',
'valuePath': null,
},
}
});
this.cardFormFields = new FormFieldGroup({
baseSelector: '.ppcp-axo-payment-container',
contentSelector: this.elements.paymentContainer.selector,
template: (data) => {
const selectOtherPaymentMethod = () => {
if (!this.hideGatewaySelection) {
return '';
}
return `<p style="margin-top: 40px; text-align: center;"><a href="javascript:void(0)" data-ppcp-axo-show-gateway-selection>Select other payment method</a></p>`;
};
if (data.isEmpty()) {
return `
<div style="margin-bottom: 20px; text-align: center;">
<div>Please fill in your card details.</div>
<h4><a href="javascript:void(0)" data-ppcp-axo-change-card>Edit</a></h4>
${selectOtherPaymentMethod()}
</div>
`;
}
return `
<div style="margin-bottom: 20px;">
<h3>Card Details <a href="javascript:void(0)" data-ppcp-axo-change-card>Edit</a></h3>
<div>${data.value('name')}</div>
<div>${data.value('brand')}</div>
<div>${data.value('lastDigits') ? '************' + data.value('lastDigits'): ''}</div>
<div>${data.value('expiry')}</div>
${selectOtherPaymentMethod()}
</div>
`;
},
fields: {
brand: {
'valuePath': 'card.paymentSource.card.brand',
},
expiry: {
'valuePath': 'card.paymentSource.card.expiry',
},
lastDigits: {
'valuePath': 'card.paymentSource.card.lastDigits',
},
name: {
'valuePath': 'card.paymentSource.card.name',
},
}
});
}
registerEventHandlers() {
// Listen to Gateway Radio button changes.
this.$(document).on('change', this.elements.gatewayRadioButton.selector, (ev) => {
if (ev.target.checked) {
@ -64,16 +307,86 @@ class AxoManager {
this.triggerGatewayChange();
});
this.$(document).on('click', this.elements.submitButtonContainer.selector + ' button', () => {
// On checkout form submitted.
this.$(document).on('click', this.elements.submitButtonContainer.buttonSelector, () => {
this.onClickSubmitButton();
return false;
});
// Click change shipping address link.
this.$(document).on('click', '*[data-ppcp-axo-change-shipping-address]', async () => {
if (this.isConnectProfile) {
console.log('profile', this.fastlane.profile);
//this.shippingFormFields.deactivate();
const { selectionChanged, selectedAddress } = await this.fastlane.profile.showShippingAddressSelector();
console.log('selectedAddress', selectedAddress);
if (selectionChanged) {
this.setShipping(selectedAddress);
this.shippingFormFields.activate();
}
} else {
let checkbox = document.querySelector('#ship-to-different-address-checkbox');
if (checkbox && !checkbox.checked) {
jQuery(checkbox).trigger('click');
}
this.shippingFormFields.deactivate();
}
});
this.$(document).on('click', '*[data-ppcp-axo-save-shipping-address]', async () => {
this.shippingFormFields.activate();
});
// Click change billing address link.
this.$(document).on('click', '*[data-ppcp-axo-change-billing-address]', async () => {
if (this.isConnectProfile) {
this.$('*[data-ppcp-axo-change-card]').trigger('click');
} else {
this.billingFormFields.deactivate();
}
});
this.$(document).on('click', '*[data-ppcp-axo-save-billing-address]', async () => {
this.billingFormFields.activate();
});
// Click change card link.
this.$(document).on('click', '*[data-ppcp-axo-change-card]', async () => {
console.log('profile', this.fastlane.profile);
const response = await this.fastlane.profile.showCardSelector();
console.log('card response', response);
if (response.selectionChanged) {
this.setCard(response.selectedCard);
this.setBilling({
address: response.selectedCard.paymentSource.card.billingAddress
});
}
});
// Cancel "continuation" mode.
this.$(document).on('click', '*[data-ppcp-axo-show-gateway-selection]', async () => {
this.hideGatewaySelection = false;
this.$('.wc_payment_methods label').show();
this.cardFormFields.refresh();
});
}
showAxo() {
this.initEmail();
this.init();
this.initPlacements();
this.initFastlane();
this.shippingFormFields.activate();
this.billingFormFields.activate();
show(this.elements.emailWidgetContainer.selector);
show(this.elements.watermarkContainer.selector);
@ -87,6 +400,9 @@ class AxoManager {
}
hideAxo() {
this.shippingFormFields.deactivate();
this.billingFormFields.deactivate();
hide(this.elements.emailWidgetContainer.selector);
hide(this.elements.watermarkContainer.selector);
hide(this.elements.paymentContainer.selector);
@ -98,15 +414,31 @@ class AxoManager {
}
}
initEmail() {
initPlacements() {
let emailRow = document.querySelector(this.elements.fieldBillingEmail.selector);
const bc = this.elements.billingAddressContainer;
const sc = this.elements.shippingAddressContainer;
const ec = this.elements.emailWidgetContainer;
if (!document.querySelector(bc.selector)) {
document.querySelector(bc.anchorSelector).insertAdjacentHTML('beforeend', `
<div id="${bc.id}" class="${bc.className}"></div>
`);
}
if (!document.querySelector(sc.selector)) {
document.querySelector(sc.anchorSelector).insertAdjacentHTML('afterbegin', `
<div id="${sc.id}" class="${sc.className}"></div>
`);
}
if (this.useEmailWidget()) {
// Display email widget.
if (!document.querySelector(this.elements.emailWidgetContainer.selector)) {
if (!document.querySelector(ec.selector)) {
emailRow.parentNode.insertAdjacentHTML('afterbegin', `
<div id="${this.elements.emailWidgetContainer.id}" class="${this.elements.emailWidgetContainer.className}">
<div id="${ec.id}" class="${ec.className}">
--- EMAIL WIDGET PLACEHOLDER ---
</div>
`);
@ -120,7 +452,7 @@ class AxoManager {
}
}
async init() {
async initFastlane() {
if (this.initialized) {
return;
}
@ -188,30 +520,79 @@ class AxoManager {
async onChangeEmail () {
log('Email changed: ' + this.emailInput.value);
this.isConnectProfile = false;
this.hideGatewaySelection = false;
if (!this.emailInput.checkValidity()) {
log('The email address is not valid.');
return;
}
const { customerContextId } = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
if (customerContextId) {
show(this.elements.paymentContainer.selector);
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');
// TODO : enter hideOtherGateways mode
const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId);
log('AuthResponse', authResponse);
if (authResponse.authenticationState === 'succeeded') {
log(JSON.stringify(authResponse));
// document.querySelector(this.elements.paymentContainer.selector).innerHTML =
// '<a href="javascript:void(0)" data-ppcp-axo-change-card>Change card</a>';
// Add addresses
this.setShipping(authResponse.profileData.shippingAddress);
// TODO : set billing
this.setCard(authResponse.profileData.card);
this.isConnectProfile = true;
this.hideGatewaySelection = true;
this.$('.wc_payment_methods label').hide();
this.shippingFormFields.activate();
this.billingFormFields.activate();
this.cardFormFields.activate();
} else {
// authentication failed or canceled by the customer
log("Authentication Failed")
}
} else {
// No profile found with this email address.
// This is a guest customer.
log('No profile found with this email address.');
document.querySelector(this.elements.paymentContainer.selector)?.classList.remove('hidden');
this.cardComponent = await this.fastlane
.FastlaneCardComponent(MockData.cardComponent())
.render(this.elements.paymentContainer.selector);
}
}
setShipping(shipping) {
this.data.shipping = shipping;
this.shippingFormFields.setData(this.data);
}
setBilling(billing) {
this.data.billing = billing;
this.billingFormFields.setData(this.data);
}
setCard(card) {
this.data.card = card;
this.cardFormFields.setData(this.data);
}
onClickSubmitButton() {
try {
this.cardComponent.tokenize(MockData.cardComponentTokenize()).then((response) => {
@ -227,29 +608,6 @@ class AxoManager {
log('nonce: ' + nonce);
alert('nonce: ' + nonce);
// fetch('submit.php', {
// method: 'POST',
// headers: {
// 'Content-Type': 'application/json',
// },
// body: JSON.stringify({
// nonce: nonce
// }),
// })
// .then(response => {
// if (!response.ok) {
// throw new Error('Network response was not ok');
// }
// return response.json();
// })
// .then(data => {
// log('Submit response', data);
// log(JSON.stringify(data));
// })
// .catch(error => {
// console.error('There has been a problem with your fetch operation:', error);
// });
// Submit form.
document.querySelector(this.elements.defaultSubmitButton.selector).click();
}