/**
* Express Buy Frontend Scripts - Complete Rewrite
* Features: Quantity management, Variants, Shipping zones, Coupons, Dynamic pricing
*/
(function($) {
'use strict';
const ExpressBuy = {
modal: null,
currentProduct: null,
currentQuantity: 1,
selectedVariation: null,
selectedShipping: null,
appliedCoupon: null,
basePrice: 0,
shippingCost: 0,
discount: 0,
/**
* Initialize
*/
init: function() {
this.createModal();
this.bindEvents();
},
/**
* Create modal HTML
*/
createModal: function() {
const formType = expressBuyData.form_type || 'minimal';
const showShipping = expressBuyData.show_shipping;
const showCoupons = expressBuyData.show_coupons;
const configuredGateways = expressBuyData.configured_gateways || [];
// Build form fields based on form type
let formFields = '';
if (formType === 'minimal') {
formFields = `
`;
} else {
formFields = `
Full Name *
Email Address *
Phone Number *
Delivery Address *
`;
}
// Build gateway options (only show configured ones)
let gatewayHTML = '';
if (configuredGateways.length > 0) {
configuredGateways.forEach((gateway, index) => {
const activeClass = index === 0 ? 'active' : '';
gatewayHTML += `
`;
});
} else {
gatewayHTML = 'No payment gateways configured. Please contact the site administrator.
';
}
const modalHTML = `
`;
$('body').append(modalHTML);
this.modal = $('#express-buy-modal');
},
/**
* Bind all events
*/
bindEvents: function() {
const self = this;
// Open modal when Express Buy button clicked
$(document).on('click', '.express-buy-button', function(e) {
e.preventDefault();
const $btn = $(this);
// Check if it's from cart or single product
if ($btn.hasClass('express-buy-cart') || $btn.hasClass('express-buy-checkout')) {
self.openModalForCart($btn);
} else {
// Get initial quantity from product page
const initialQty = $('input.qty').val() || 1;
const productData = {
id: $btn.data('product-id'),
name: $btn.data('product-name'),
price: $btn.data('product-price'),
type: $btn.data('product-type'),
variations: $btn.data('variations') || [],
image: $btn.data('product-image') ||
$btn.closest('.product').find('img').first().attr('src') ||
$('.woocommerce-product-gallery__image img').first().attr('src') || ''
};
self.openModal(productData, parseInt(initialQty));
}
});
// Close modal
$(document).on('click', '.express-buy-modal-close, .express-buy-modal', function(e) {
if (e.target === this) {
self.closeModal();
}
});
// Quantity controls
$(document).on('click', '.eb-qty-plus', function() {
self.increaseQuantity();
});
$(document).on('click', '.eb-qty-minus', function() {
self.decreaseQuantity();
});
// Gateway selection
$(document).on('click', '.express-buy-gateway', function() {
$('.express-buy-gateway').removeClass('active');
$(this).addClass('active');
$('#eb-selected-gateway').val($(this).data('gateway'));
$('#eb-gateway-public-key').val($(this).data('public-key'));
});
// Shipping zone selection
$(document).on('click', '.eb-shipping-option', function() {
$('.eb-shipping-option').removeClass('active');
$(this).addClass('active');
const shippingCost = parseFloat($(this).data('cost')) || 0;
const zoneId = $(this).data('zone-id');
self.selectedShipping = { zoneId, cost: shippingCost };
$('#eb-shipping-zone').val(zoneId);
self.updatePricing();
});
// Coupon application
$(document).on('click', '.eb-apply-coupon', function() {
self.applyCoupon();
});
// Variation selection
$(document).on('change', '.eb-variation-select', function() {
self.handleVariationChange();
});
// Form submission
$(document).on('submit', '#express-buy-form', function(e) {
e.preventDefault();
self.processPayment($(this));
});
// Close on ESC key
$(document).on('keydown', function(e) {
if (e.key === 'Escape' && self.modal.hasClass('active')) {
self.closeModal();
}
});
},
/**
* Open modal for cart items
*/
openModalForCart: function() {
// For now, use first cart item (you can expand this later)
const firstProduct = {
id: 0, // Will handle cart differently
name: 'Cart Items',
price: expressBuyData.cart_total || 0,
image: '',
isCart: true
};
this.openModal(firstProduct, 1);
},
/**
* Open modal with product info
*/
openModal: function(product, quantity = 1) {
this.currentProduct = product;
this.currentQuantity = quantity;
this.basePrice = parseFloat(product.price);
this.selectedVariation = null;
this.selectedShipping = null;
this.appliedCoupon = null;
this.shippingCost = 0;
this.discount = 0;
// Populate product info
$('#eb-product-name').text(product.name);
$('#eb-product-id').val(product.id);
$('#eb-quantity').val(quantity);
if (product.image) {
$('#eb-product-image').attr('src', product.image).show();
} else {
$('#eb-product-image').hide();
}
// Handle variations
if (product.variations && product.variations.length > 0) {
this.renderVariations(product.variations);
} else {
$('#eb-variations-container').hide();
}
// Render shipping zones
if (expressBuyData.show_shipping && expressBuyData.shipping_zones) {
this.renderShippingZones(expressBuyData.shipping_zones);
}
// Update pricing
this.updatePricing();
// Clear form and messages
$('#express-buy-form')[0].reset();
$('#eb-quantity').val(quantity);
$('#express-buy-messages').empty();
$('#eb-coupon-message').empty();
// Show modal
this.modal.addClass('active');
$('body').css('overflow', 'hidden');
},
/**
* Close modal
*/
closeModal: function() {
this.modal.removeClass('active');
$('body').css('overflow', '');
this.currentProduct = null;
},
/**
* Render product variations
*/
renderVariations: function(variations) {
if (!variations || variations.length === 0) {
$('#eb-variations-container').hide();
return;
}
// Get unique attributes
const attributes = {};
variations.forEach(v => {
Object.keys(v.attributes).forEach(attr => {
if (!attributes[attr]) {
attributes[attr] = new Set();
}
attributes[attr].add(v.attributes[attr]);
});
});
let html = '';
Object.keys(attributes).forEach(attr => {
const attrName = attr.replace('attribute_', '').replace('pa_', '');
html += `${attrName} Choose ${attrName} `;
attributes[attr].forEach(value => {
html += `${value} `;
});
html += ' ';
});
$('#eb-variations').html(html);
$('#eb-variations-container').show();
},
/**
* Handle variation selection
*/
handleVariationChange: function() {
const selectedAttrs = {};
$('.eb-variation-select').each(function() {
const attr = $(this).data('attribute');
const value = $(this).val();
if (value) {
selectedAttrs[attr] = value;
}
});
// Find matching variation
const variations = this.currentProduct.variations;
const matchedVariation = variations.find(v => {
return Object.keys(selectedAttrs).every(attr => {
return v.attributes[attr] === selectedAttrs[attr];
});
});
if (matchedVariation) {
this.selectedVariation = matchedVariation;
this.basePrice = parseFloat(matchedVariation.price);
$('#eb-variation-id').val(matchedVariation.variation_id);
this.updatePricing();
}
},
/**
* Render shipping zones
*/
renderShippingZones: function(zones) {
if (!zones || zones.length === 0) {
$('#eb-shipping-container').hide();
return;
}
let html = '';
zones.forEach(zone => {
if (zone.methods && zone.methods.length > 0) {
zone.methods.forEach(method => {
const cost = parseFloat(method.cost) || 0;
html += `
${zone.name}
${expressBuyData.currency_symbol}${cost.toFixed(2)}
`;
});
}
});
$('#eb-shipping-zones').html(html);
$('#eb-shipping-container').show();
},
/**
* Increase quantity
*/
increaseQuantity: function() {
this.currentQuantity++;
$('#eb-quantity').val(this.currentQuantity);
this.updatePricing();
},
/**
* Decrease quantity
*/
decreaseQuantity: function() {
if (this.currentQuantity > 1) {
this.currentQuantity--;
$('#eb-quantity').val(this.currentQuantity);
this.updatePricing();
}
},
/**
* Apply coupon code
*/
applyCoupon: function() {
const self = this;
const couponCode = $('#eb-coupon-code').val().trim();
if (!couponCode) {
this.showCouponMessage('Please enter a coupon code', 'error');
return;
}
// AJAX request to validate coupon
$.ajax({
url: expressBuyData.ajax_url,
type: 'POST',
data: {
action: 'express_buy_validate_coupon',
nonce: expressBuyData.nonce,
coupon_code: couponCode,
product_id: this.currentProduct.id,
subtotal: this.basePrice * this.currentQuantity
},
success: function(response) {
if (response.success) {
self.appliedCoupon = response.data;
self.discount = parseFloat(response.data.discount);
$('#eb-applied-coupon').val(couponCode);
self.showCouponMessage(`Coupon applied! You saved ${expressBuyData.currency_symbol}${self.discount.toFixed(2)}`, 'success');
self.updatePricing();
} else {
self.showCouponMessage(response.data.message || 'Invalid coupon code', 'error');
}
},
error: function() {
self.showCouponMessage('Error validating coupon', 'error');
}
});
},
/**
* Show coupon message
*/
showCouponMessage: function(message, type) {
const className = type === 'error' ? 'eb-error-text' : 'eb-success-text';
$('#eb-coupon-message').html(`${message} `);
},
/**
* Update all pricing calculations
*/
updatePricing: function() {
const subtotal = this.basePrice * this.currentQuantity;
const shipping = this.selectedShipping ? this.selectedShipping.cost : 0;
const discount = this.discount;
const total = subtotal + shipping - discount;
// Update display
$('#eb-product-price').text(expressBuyData.currency_symbol + this.basePrice.toFixed(2));
$('#eb-subtotal').text(expressBuyData.currency_symbol + subtotal.toFixed(2));
if (shipping > 0) {
$('#eb-shipping-cost').text(expressBuyData.currency_symbol + shipping.toFixed(2));
$('#eb-shipping-row').show();
} else {
$('#eb-shipping-row').hide();
}
if (discount > 0) {
$('#eb-discount').text('-' + expressBuyData.currency_symbol + discount.toFixed(2));
$('#eb-discount-row').show();
} else {
$('#eb-discount-row').hide();
}
$('#eb-total-price').text(expressBuyData.currency_symbol + total.toFixed(2));
// Store for payment processing
this.shippingCost = shipping;
},
/**
* Show message
*/
showMessage: function(message, type) {
const className = type === 'error' ? 'express-buy-error' : 'express-buy-success';
const html = `${message}
`;
$('#express-buy-messages').html(html);
$('.express-buy-modal-content').animate({ scrollTop: 0 }, 300);
},
/**
* Process payment
*/
processPayment: function($form) {
const self = this;
const $submitBtn = $form.find('.express-buy-submit');
const originalBtnText = $submitBtn.html();
// Disable button
$submitBtn.prop('disabled', true).html('⚡ Processing...');
// Clear messages
$('#express-buy-messages').empty();
// Get form data
const formData = {
action: 'express_buy_process_payment',
nonce: expressBuyData.nonce,
product_id: $('#eb-product-id').val(),
variation_id: $('#eb-variation-id').val(),
quantity: this.currentQuantity,
customer_phone: $('#eb-customer-phone').val(),
gateway: $('#eb-selected-gateway').val(),
shipping_zone: $('#eb-shipping-zone').val(),
shipping_cost: this.shippingCost,
coupon_code: $('#eb-applied-coupon').val(),
discount: this.discount,
form_type: expressBuyData.form_type,
is_cart: $('#eb-is-cart').val(),
cart_items: $('#eb-cart-items').val()
};
// Add full form fields if applicable
if (expressBuyData.form_type === 'full') {
formData.customer_name = $('#eb-customer-name').val();
formData.customer_email = $('#eb-customer-email').val();
formData.customer_address = $('#eb-customer-address').val();
}
// AJAX request
$.ajax({
url: expressBuyData.ajax_url,
type: 'POST',
data: formData,
success: function(response) {
if (response.success) {
self.showMessage('Order created successfully! Initializing payment...', 'success');
// Get gateway and public key
const gateway = $('#eb-selected-gateway').val();
const publicKey = $('#eb-gateway-public-key').val();
const orderData = response.data;
// Initialize payment modal directly
setTimeout(function() {
self.initializePaymentModal(gateway, publicKey, orderData);
}, 1000);
} else {
self.showMessage(response.data.message || 'Payment failed. Please try again.', 'error');
$submitBtn.prop('disabled', false).html(originalBtnText);
}
},
error: function(xhr, status, error) {
console.error('Express Buy Error:', error);
self.showMessage('Connection error. Please check your internet and try again.', 'error');
$submitBtn.prop('disabled', false).html(originalBtnText);
}
});
},
/**
* Initialize payment modal (Paystack/Flutterwave/Stripe)
*/
initializePaymentModal: function(gateway, publicKey, orderData) {
const self = this;
// Animate modal content out
$('.express-buy-modal-content').fadeOut(300, function() {
// Initialize payment based on gateway
if (gateway === 'paystack') {
self.initializePaystack(publicKey, orderData);
} else if (gateway === 'flutterwave') {
self.initializeFlutterwave(publicKey, orderData);
} else if (gateway === 'stripe') {
self.initializeStripe(publicKey, orderData);
} else {
// Fallback - redirect to payment page
window.location.href = orderData.payment_url;
}
});
},
/**
* Initialize Paystack payment
*/
initializePaystack: function(publicKey, orderData) {
const self = this;
// Load Paystack script if not already loaded
if (typeof PaystackPop === 'undefined') {
const script = document.createElement('script');
script.src = 'https://js.paystack.co/v1/inline.js';
script.onload = function() {
self.openPaystackModal(publicKey, orderData);
};
document.body.appendChild(script);
} else {
self.openPaystackModal(publicKey, orderData);
}
},
/**
* Open Paystack modal
*/
openPaystackModal: function(publicKey, orderData) {
const self = this;
const handler = PaystackPop.setup({
key: publicKey,
email: orderData.customer_email || 'customer@expressbuy.com',
amount: Math.round(orderData.total * 100), // Convert to kobo
currency: orderData.currency || 'NGN',
ref: 'EB-' + orderData.order_id + '-' + Date.now(),
metadata: {
order_id: orderData.order_id,
custom_fields: [
{
display_name: "Order ID",
variable_name: "order_id",
value: orderData.order_id
}
]
},
onClose: function() {
// User closed the payment modal
self.closeModal();
alert('Payment cancelled. You can complete payment later from your order page.');
},
callback: function(response) {
// Payment successful
self.handlePaymentSuccess(orderData);
}
});
handler.openIframe();
},
/**
* Initialize Flutterwave payment
*/
initializeFlutterwave: function(publicKey, orderData) {
const self = this;
// Load Flutterwave script if not already loaded
if (typeof FlutterwaveCheckout === 'undefined') {
const script = document.createElement('script');
script.src = 'https://checkout.flutterwave.com/v3.js';
script.onload = function() {
self.openFlutterwaveModal(publicKey, orderData);
};
document.body.appendChild(script);
} else {
self.openFlutterwaveModal(publicKey, orderData);
}
},
/**
* Open Flutterwave modal
*/
openFlutterwaveModal: function(publicKey, orderData) {
const self = this;
FlutterwaveCheckout({
public_key: publicKey,
tx_ref: 'EB-' + orderData.order_id + '-' + Date.now(),
amount: orderData.total,
currency: orderData.currency || 'NGN',
payment_options: 'card,banktransfer,ussd',
customer: {
email: orderData.customer_email || 'customer@expressbuy.com',
phone_number: orderData.customer_phone || '',
name: orderData.customer_name || 'Express Customer'
},
customizations: {
title: 'Express Buy Payment',
description: 'Order #' + orderData.order_id,
logo: ''
},
callback: function(data) {
if (data.status === 'successful') {
self.handlePaymentSuccess(orderData);
} else {
self.closeModal();
alert('Payment failed or was cancelled.');
}
},
onclose: function() {
self.closeModal();
alert('Payment cancelled. You can complete payment later from your order page.');
}
});
},
/**
* Initialize Stripe payment
*/
initializeStripe: function(publicKey, orderData) {
// For Stripe, we'll redirect as it requires more complex setup
// You can implement Stripe Elements here if needed
window.location.href = orderData.payment_url;
},
/**
* Handle successful payment
*/
handlePaymentSuccess: function(orderData) {
this.closeModal();
// Show success message
const successHTML = `
✓
Payment Successful!
Your order #${orderData.order_id} has been confirmed.
View Order Details
`;
$('body').append(successHTML);
// Redirect after 5 seconds
setTimeout(function() {
window.location.href = orderData.order_url;
}, 5000);
}
};
// Initialize when document is ready
$(document).ready(function() {
if (typeof expressBuyData !== 'undefined' && expressBuyData.is_valid) {
ExpressBuy.init();
}
});
})(jQuery);
Warning : Cannot modify header information - headers already sent by (output started at /home/gowithgr/express.gowithgrip.com/wp-content/plugins/express-buy-woocommerce/public/class-frontend.php:1) in /home/gowithgr/express.gowithgrip.com/wp-content/plugins/uncode-privacy/includes/class-uncode-toolkit-privacy-public.php on line 359
Warning : Cannot modify header information - headers already sent by (output started at /home/gowithgr/express.gowithgrip.com/wp-content/plugins/express-buy-woocommerce/public/class-frontend.php:1) in /home/gowithgr/express.gowithgrip.com/wp-includes/pluggable.php on line 1531
Warning : Cannot modify header information - headers already sent by (output started at /home/gowithgr/express.gowithgrip.com/wp-content/plugins/express-buy-woocommerce/public/class-frontend.php:1) in /home/gowithgr/express.gowithgrip.com/wp-includes/pluggable.php on line 1534
Notice : ob_end_flush(): Failed to send buffer of zlib output compression (1) in /home/gowithgr/express.gowithgrip.com/wp-includes/functions.php on line 5481
Notice : ob_end_flush(): Failed to send buffer of zlib output compression (1) in /home/gowithgr/express.gowithgrip.com/wp-includes/functions.php on line 5481