JezK
Edit File: apo-scripts.js
jQuery(document).ready(function($) { console.log("Advanced Product Options script loaded"); $(".apo-datepicker").flatpickr({ dateFormat: "Y-m-d", minDate: new Date().fp_incr(1), // Start from tomorrow disableMobile: "true", theme: "airbnb", locale: { firstDayOfWeek: 1 // Start week on Monday }, disable: [ function(date) { // Get day of week (0 = Sunday, 6 = Saturday) const day = date.getDay(); // Return true to disable Saturdays (6) and Sundays (0) return (day === 0 || day === 6); } ], onChange: function(selectedDates, dateStr, instance) { // Additional check to prevent weekend selection if (selectedDates.length > 0) { const selectedDay = selectedDates[0].getDay(); if (selectedDay === 0 || selectedDay === 6) { instance.clear(); // Clear the selection if it's a weekend } } }, onDayCreate: function(dObj, dStr, fp, dayElem) { const day = dayElem.dateObj.getDay(); if (day === 0 || day === 6) { dayElem.className += ' weekend disabled'; } }, prevArrow: "<svg xmlns='http://www.w3.org/2000/svg' width='18px' height='18px' viewBox='0 0 256 256'><path d='M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z'></path></svg>", nextArrow: "<svg xmlns='http://www.w3.org/2000/svg' width='18px' height='18px' viewBox='0 0 256 256'><path d='M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z'></path></svg>", }); const modal = { container: $('#meal-addons-modal'), trigger: $('#meal-addons-trigger'), closeBtn: $('.modal-close'), applyBtn: $('.apply-addons-button'), addonsList: $('#meal-addons-list'), init: function() { this.bindEvents(); this.loadAddons(); }, bindEvents: function() { this.trigger.on('click', (e) => { e.preventDefault(); this.open(); }); this.closeBtn.on('click', (e) => { e.preventDefault(); this.close(); }); this.applyBtn.on('click', (e) => { e.preventDefault(); this.applyAddons(); }); $(window).on('click', (e) => { if ($(e.target).is(this.container)) { this.close(); } }); }, open: function() { this.container.fadeIn(200); $('body').css('overflow', 'hidden'); }, close: function() { this.container.fadeOut(200); $('body').css('overflow', ''); }, loadAddons: function() { $.get('/wp-json/apo/v1/meal-addons') .done((addons) => { console.log('Loaded addons:', addons); this.renderAddons(addons); }) .fail((err) => console.error('Failed to load addons:', err)); }, renderAddons: function(addons) { if (!Array.isArray(addons)) { console.error('Invalid addons data:', addons); return; } const html = addons.map(addon => { const price = parseFloat(addon.price) || 0; return ` <div class="meal-addon-item" data-addon-id="${addon.id}"> <div class="addon-details"> <div class="addon-name">${addon.name}</div> <div class="addon-price">${this.formatPrice(price)} per unit</div> </div> <div class="quantity-controls"> <button type="button" class="quantity-btn minus">-</button> <input type="number" class="quantity-input" value="0" min="0" max="${addon.max_quantity}" data-price="${price}"> <button type="button" class="quantity-btn plus">+</button> </div> </div> `; }).join(''); this.addonsList.html(html); this.bindQuantityControls(); }, bindQuantityControls: function() { $('.quantity-btn.minus').on('click', function(e) { e.preventDefault(); const input = $(this).siblings('.quantity-input'); const currentVal = parseInt(input.val()) || 0; if (currentVal > 0) { input.val(currentVal - 1).trigger('change'); } }); $('.quantity-btn.plus').on('click', function(e) { e.preventDefault(); const input = $(this).siblings('.quantity-input'); const currentVal = parseInt(input.val()) || 0; const max = parseInt(input.attr('max')) || 99; if (currentVal < max) { input.val(currentVal + 1).trigger('change'); } }); $('.quantity-input').on('change', () => this.updateTotal()); }, formatPrice: function(price) { const numPrice = parseFloat(price); if (isNaN(numPrice)) { console.error('Invalid price value:', price); return apoData.currencySymbol + '0.00'; } try { let formattedPrice = numPrice.toFixed(apoData.numDecimals); if (apoData.decimalSeparator !== '.') { formattedPrice = formattedPrice.replace('.', apoData.decimalSeparator); } formattedPrice = formattedPrice.replace(/\B(?=(\d{3})+(?!\d))/g, apoData.thousandSeparator); switch (apoData.currencyPosition) { case 'left': return apoData.currencySymbol + formattedPrice; case 'right': return formattedPrice + apoData.currencySymbol; case 'left_space': return apoData.currencySymbol + ' ' + formattedPrice; case 'right_space': return formattedPrice + ' ' + apoData.currencySymbol; default: return apoData.currencySymbol + formattedPrice; } } catch (error) { console.error('Price formatting error:', error); return apoData.currencySymbol + '0.00'; } }, updateTotal: function() { /** * Pull the number of tiffins directly from the * select field name (e.g., apo_67a25a6de2811). */ const tiffinNameAttr = 'apo_67b726e953eac'; const numTiffins = parseInt($(`[name="${tiffinNameAttr}"]`).val()) || 1; let total = 0; $('.quantity-input').each(function() { const quantity = parseInt($(this).val()) || 0; const pricePerUnit = parseFloat($(this).data('price')) || 0; total += quantity * pricePerUnit * numTiffins; }); $('.addon-total .addon-price').html(this.formatPrice(total)); }, applyAddons: function() { const selectedAddons = []; $('.meal-addon-item').each(function() { const quantity = parseInt($(this).find('.quantity-input').val()); if (quantity > 0) { selectedAddons.push({ id: $(this).data('addon-id'), quantity: quantity }); } }); // Remove any existing addon inputs $('input[name="selected_meal_addons"]').remove(); $('input[name="number_of_tiffins"]').remove(); // Add selected addons to the form const form = $('form.cart'); if (selectedAddons.length > 0) { $('<input>').attr({ type: 'hidden', name: 'selected_meal_addons', value: JSON.stringify(selectedAddons) }).appendTo(form); } /** * Also append the current tiffin count to ensure * it is submitted with the form. */ const tiffinNameAttr = 'apo_67b726e953eac'; const tiffinVal = $(`[name="${tiffinNameAttr}"]`).val() || ''; if (tiffinVal) { $('<input>').attr({ type: 'hidden', name: 'number_of_tiffins', value: tiffinVal }).appendTo(form); } this.close(); this.updateProductPrice(); }, updateProductPrice: function() { const basePrice = parseFloat($('[name="base_price"]').val()) || 0; /** * Pull the number of tiffins from the form select again * (or from the newly appended 'number_of_tiffins' if you prefer). */ const tiffinNameAttr = 'apo_67b726e953eac'; const numTiffins = parseInt($(`[name="${tiffinNameAttr}"]`).val()) || 1; let addonsTotal = 0; $('.quantity-input').each(function() { const quantity = parseInt($(this).val()) || 0; const pricePerUnit = parseFloat($(this).data('price')) || 0; addonsTotal += quantity * pricePerUnit * numTiffins; }); const totalPrice = basePrice + addonsTotal; $('.product-price .amount').html(this.formatPrice(totalPrice)); } }; // Initialize modal if meal addons are enabled if ($('#meal-addons-modal').length) { modal.init(); } // Conditionally show/hide the "Add Meal Add-ons" button function checkRequiredOptions() { const allRequired = $('.apo-option[required]').length; const filledRequired = $('.apo-option[required]').filter(function() { return $(this).val() !== ''; }).length; if (allRequired === filledRequired) { $('#meal-addons-trigger').show(); } else { $('#meal-addons-trigger').hide(); } } $('.apo-option').on('change', checkRequiredOptions); });