/**
* Formipay Checkout Shipping Integration
* Handles country selection, shipping method display, and cost calculation
*/
(function($) {
'use strict';
const FormipayCheckoutShipping = {
selectedCountry: '',
selectedMethod: '',
availableMethods: [],
formId: null,
init() {
this.formId = $('form[data-form-id]').data('form-id');
if (!this.formId) {
return;
}
this.bindEvents();
this.initializeCountrySelector();
},
bindEvents() {
// Country selection change
$(document).on('change', '.formipay-shipping-country', (e) => {
this.onCountryChange($(e.currentTarget).val());
});
// Shipping method selection change
$(document).on('change', '.formipay-shipping-method', (e) => {
this.onShippingMethodChange($(e.currentTarget).val());
});
},
initializeCountrySelector() {
// Check if this form has shipping enabled
if (this.isShippingEnabled()) {
// Add country selector before payment options
this.insertCountrySelector();
}
},
isShippingEnabled() {
// Check if shipping is enabled for this form
// With form-level shipping, we check shipping_enabled setting
return window.formipayFormData?.shipping_enabled &&
window.formipayFormData.shipping_enabled !== 'no_shipping';
},
insertCountrySelector() {
const orderReviewTable = $('#formipay-review-order');
if (orderReviewTable.length === 0) {
return;
}
// Create country selector row before subtotal
const countryRow = `
|
|
⏳
|
`;
orderReviewTable.find('tbody').append(countryRow);
// Populate countries from settings
this.loadCountries();
},
loadCountries() {
// Get supported countries from shipping settings
$.ajax({
url: formipay_admin.ajaxUrl,
type: 'POST',
data: {
action: 'formipay_get_supported_countries',
nonce: formipay_admin.nonce,
form_id: this.formId
},
success: (response) => {
if (response.success && response.data.countries) {
this.populateCountries(response.data.countries);
}
},
error: () => {
// Fallback: show all countries
this.populateCountries(this.getAllCountries());
}
});
},
populateCountries(countries) {
const select = $(`#shipping-country-${this.formId}`);
select.find('option:not([value=""])').remove();
$.each(countries, (code, name) => {
select.append(``);
});
},
getAllCountries() {
// Fallback country list
return {
'ID': 'Indonesia',
'MY': 'Malaysia',
'SG': 'Singapore',
'TH': 'Thailand',
'VN': 'Vietnam',
'PH': 'Philippines',
'TW': 'Taiwan',
'HK': 'Hong Kong',
'IN': 'India',
'CN': 'China',
'JP': 'Japan',
'KR': 'South Korea',
'AU': 'Australia',
'NZ': 'New Zealand',
'GB': 'United Kingdom',
'US': 'United States',
'CA': 'Canada',
'FR': 'France',
'DE': 'Germany',
'IT': 'Italy',
'ES': 'Spain',
'NL': 'Netherlands',
'BE': 'Belgium',
'CH': 'Switzerland',
'AT': 'Austria',
'IE': 'Ireland',
'DK': 'Denmark',
'SE': 'Sweden',
'NO': 'Norway',
'FI': 'Finland',
};
},
onCountryChange(countryCode) {
this.selectedCountry = countryCode;
if (!countryCode) {
this.hideShippingMethods();
return;
}
// Get available shipping methods for this country
this.fetchShippingMethods(countryCode);
},
fetchShippingMethods(countryCode) {
const spinner = $('.formipay-loading-spinner');
spinner.show();
$.ajax({
url: formipay_admin.ajaxUrl,
type: 'POST',
data: {
action: 'formipay_get_shipping_methods',
nonce: formipay_public.nonce,
form_id: this.formId,
country: countryCode,
currency: formipay.currency_code || 'IDR'
},
success: (response) => {
spinner.hide();
if (response.success) {
this.availableMethods = response.data.methods || [];
this.displayShippingMethods(this.availableMethods, response.data.default_method);
} else {
this.showError(response.data.message || 'Unable to load shipping methods');
}
},
error: () => {
spinner.hide();
this.showError('Unable to connect to shipping service');
}
});
},
displayShippingMethods(methods, defaultMethod) {
// Remove existing shipping method selector if any
$('.formipay-shipping-method-row').remove();
if (methods.length === 0) {
this.showError('Shipping is not available for this form');
return;
}
// Get order total for percentage calculations
const orderTotal = this.getOrderTotal();
let methodsHtml = '';
// Insert after country selector
const countryRow = $('.formipay-shipping-row');
const shippingRow = `
|
${methodsHtml}
|
`;
countryRow.after(shippingRow);
// Bind shipping method change events
$('.formipay-shipping-method').on('change', (e) => {
const target = $(e.currentTarget);
const cost = parseFloat(target.data('cost'));
const type = target.data('type');
const baseCost = parseFloat(target.data('base-cost'));
const method = target.val();
// For percentage, recalculate in case order total changed
let finalCost = cost;
if (type === 'percentage') {
finalCost = (this.getOrderTotal() * baseCost) / 100;
}
// Update hidden input
$('.formipay-shipping-method-input').val(method);
// Update order total
this.updateOrderTotal(finalCost);
});
// Trigger change on default method to set initial cost
$(`input[name="shipping_method_display"][value="${defaultMethod}"]`).trigger('change');
},
hideShippingMethods() {
$('.formipay-shipping-method-row').remove();
},
getOrderTotal() {
// Get current order total (excluding shipping)
const subtotalRow = $('.formipay-total-row td').text();
const subtotal = this.parseCurrency(subtotalRow);
return subtotal;
},
updateOrderTotal(shippingCost) {
const currentTotal = this.getOrderTotal();
const newTotal = currentTotal + shippingCost;
// Update the total display
const totalRow = $('.formipay-grand-total-row td');
totalRow.text(this.formatCost(newTotal));
// Update submit button
const submitBtn = $('.formipay-submit-button');
const currentText = submitBtn.attr('data-button-text');
submitBtn.html(`${currentText} - ${this.formatCost(newTotal)}`);
},
formatCost(cost, currency) {
// Format cost using same format as product prices
const formatted = cost.toFixed(formipay.decimal_digits || 2);
return (currency || formipay.currency || '') + ' ' + formatted;
},
parseCurrency(text) {
// Parse currency string to get numeric value
// Removes currency symbols and formats
const numeric = text.replace(/[^\d.-]/g, '');
return parseFloat(numeric) || 0;
},
showError(message) {
const errorHtml = `
`;
$('.formipay-shipping-method-row').html(`${errorHtml} | `);
}
};
// Initialize when document is ready
$(document).ready(() => {
if (typeof formipay_shipping !== 'undefined' && typeof formipay_shipping.labels !== 'undefined') {
FormipayCheckoutShipping.init();
}
});
// Expose for global access
window.FormipayCheckoutShipping = FormipayCheckoutShipping;
})(jQuery);