/** * 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 = `

After payment, we'll send your receipt and request delivery details via WhatsApp

`; } else { formFields = `
`; } // Build gateway options (only show configured ones) let gatewayHTML = ''; if (configuredGateways.length > 0) { configuredGateways.forEach((gateway, index) => { const activeClass = index === 0 ? 'active' : ''; gatewayHTML += `
${gateway.name}
`; }); } else { gatewayHTML = '

No payment gateways configured. Please contact the site administrator.

'; } const modalHTML = `

Express Checkout

Product

${formFields} ${showShipping ? `
` : ''} ${showCoupons ? `
` : ''}
Subtotal: $0.00
${showShipping ? ` ` : ''} ${showCoupons ? ` ` : ''}
Total: $0.00
${gatewayHTML}
`; $('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 += `'; }); $('#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