jQuery(document).ready(function($) { // Determine if this is a quote form const isQuoteForm = window.isQuoteForm || false; const formType = isQuoteForm ? 'quote' : 'invoice'; const templateFieldName = isQuoteForm ? 'quote_template' : 'invoice_template'; const previewClass = isQuoteForm ? 'quote-preview' : 'invoice-preview'; // Function to get URL parameter function getUrlParameter(name) { name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); var results = regex.exec(location.search); return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); } // Function to switch to a specific tab function switchToTab(tabId) { if (tabId && $('#' + tabId).length) { // Remove active state from all tabs $('.tab-button').removeClass('border-indigo-500 text-indigo-600').addClass('border-transparent text-gray-500'); $('.tab-content').addClass('hidden'); // Activate the specified tab $('.tab-button[data-tab="' + tabId + '"]').addClass('border-indigo-500 text-indigo-600'); $('#' + tabId).removeClass('hidden'); // Update URL without page reload var url = new URL(window.location); url.searchParams.set('tab', tabId); window.history.replaceState({}, '', url); } } // Make switchToTab globally available window.switchToTab = switchToTab; // Check for tab parameter on page load var initialTab = getUrlParameter('tab'); if (initialTab) { switchToTab(initialTab); } // Tab switching $('.tab-button').on('click', function() { var tabId = $(this).data('tab'); switchToTab(tabId); }); // Remove the updateTemplatePreview function and all quote-specific template preview logic // (No need to handle quote template preview here anymore) // Handle template selection after page reload const selectedTemplate = sessionStorage.getItem('selectedTemplate'); if (selectedTemplate) { // Update the hidden input field $('input[name="' + templateFieldName + '"][type="hidden"]').val(selectedTemplate); // Update the radio button if it exists let radioInput = $('input[name="' + templateFieldName + '"][type="radio"][value="' + selectedTemplate + '"]'); if (radioInput.length > 0) { $('input[name="' + templateFieldName + '"][type="radio"]').prop('checked', false); radioInput.prop('checked', true); } // Update the visual state and trigger click event $('.template-card').removeClass('selected'); const selectedCard = $('.template-card[data-template-id="' + selectedTemplate + '"]'); if (selectedCard.length > 0) { selectedCard.addClass('selected'); // Trigger click event to ensure all handlers are executed selectedCard.trigger('click'); } // Clear the sessionStorage sessionStorage.removeItem('selectedTemplate'); } else { // Handle initial template state for existing invoices/quotes const currentTemplate = $('input[name="' + templateFieldName + '"][type="hidden"]').val(); if (currentTemplate) { // Update the radio button if it exists let radioInput = $('input[name="' + templateFieldName + '"][type="radio"][value="' + currentTemplate + '"]'); if (radioInput.length > 0) { $('input[name="' + templateFieldName + '"][type="radio"]').prop('checked', false); radioInput.prop('checked', true); } // Update the visual state $('.template-card').removeClass('selected'); const selectedCard = $('.template-card[data-template-id="' + currentTemplate + '"]'); if (selectedCard.length > 0) { selectedCard.addClass('selected'); } // Update the preview //updateTemplatePreview(currentTemplate); } } // Initialize item counter let itemCounter = $('.invoice-item, .quote-item').length; // Auto-calculate totals when quantity or price changes $(document).on('input', 'input[name="item-quantity[]"], input[name="item-price[]"]', function() { // This will be handled by invoice-builder.js if (window.EasyInvoiceBuilder && typeof window.EasyInvoiceBuilder.calculateItemTotal === 'function') { window.EasyInvoiceBuilder.calculateItemTotal($(this).closest('.invoice-item, .quote-item')); } }); // Both buttons should open the template gallery - using event delegation for better reliability $(document).on('click', '#browse-all-templates, #browse-templates-btn', function(e) { e.preventDefault(); e.stopPropagation(); // Check if this is the free version const isFreeVersion = !window.easyInvoice || !window.easyInvoice.isPro; if (isFreeVersion) { // Show premium upgrade modal for free users if (typeof EasyInvoiceConfirmation !== 'undefined' && EasyInvoiceConfirmation.showFeatureUpgrade) { const title = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumTemplates : 'Premium Templates'; const description = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumTemplatesDescription : 'Access all premium templates including Modern, Professional, Classic, and more to give your invoices a unique and professional look.'; EasyInvoiceConfirmation.showFeatureUpgrade(title, description); } else { const message = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumFeatureMessage : 'This is a premium feature. Please upgrade to Pro to access all templates.'; if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.show('info', message); } } } else { // Pro users can browse all templates $('#template-gallery-modal').fadeIn(); // Highlight the currently selected template in the gallery const currentTemplate = $('input[name="' + templateFieldName + '"]:checked').val(); if (currentTemplate) { $('.gallery-template-card').removeClass('selected'); $('.gallery-template-card[data-template-id="' + currentTemplate + '"]').addClass('selected'); } } }); // Template card click handler in main grid $('.template-card').on('click', function(e) { // If clicking on premium upgrade button, handle separately if ($(e.target).hasClass('premium-upgrade-btn') || $(e.target).closest('.premium-upgrade-btn').length) { return; } const templateId = $(this).data('template-id'); const radioInput = $(this).find('input[type="radio"]'); // Check if this is a premium template in free version const isPremium = $(this).attr('data-is-premium') === 'true'; const isFreeVersion = !window.easyInvoice || !window.easyInvoice.isPro; if (isPremium && isFreeVersion) { // Show premium upgrade modal instead of selecting the template if (typeof EasyInvoiceConfirmation !== 'undefined' && EasyInvoiceConfirmation.showFeatureUpgrade) { const title = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumTemplates : 'Premium Templates'; const description = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumTemplatesDescription : 'Access all premium templates including Modern, Professional, Classic, and more to give your invoices a unique and professional look.'; EasyInvoiceConfirmation.showFeatureUpgrade(title, description); } else { const message = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.premiumFeatureMessage : 'This is a premium feature. Please upgrade to Pro to access all templates.'; if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.show('info', message); } } return; } // Check the radio input within this card radioInput.prop('checked', true); // Update the hidden input field value $('input[name="' + templateFieldName + '"][type="hidden"]').val(templateId); // Update the visual state $('.template-card').removeClass('selected'); $(this).addClass('selected'); // No need to call updateTemplatePreview for quotes }); // Apply button click handler $('#apply-selected-template').on('click', function() { // Get the selected template from the gallery const selectedGalleryCard = $('.gallery-template-card.selected'); if (selectedGalleryCard.length === 0) { // If no template is selected, show an error message and return const message = window.easyInvoice && window.easyInvoice.translations ? window.easyInvoice.translations.selectTemplateFirst : 'Please select a template first'; if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.show('error', message); } return; } const templateId = selectedGalleryCard.data('template-id'); const templateName = selectedGalleryCard.find('.font-medium').text(); const templateDescription = selectedGalleryCard.find('.text-sm.text-gray-600').text(); const templateIcon = selectedGalleryCard.find('i').attr('class'); const isPremium = selectedGalleryCard.data('is-premium') === 'true'; // Store the selected template in sessionStorage for after page reload sessionStorage.setItem('selectedTemplate', templateId); // Update the hidden input field value $('input[name="' + templateFieldName + '"][type="hidden"]').val(templateId); // Update the main template grid updateMainTemplateGrid(templateId, templateName, templateDescription, templateIcon, isPremium); // Close the modal $('#template-gallery-modal').fadeOut(); }); // Close gallery modal $('.close-gallery-modal, .gallery-close-btn').on('click', function() { $('#template-gallery-modal').fadeOut(); }); // Close gallery when clicking outside of it $(window).on('click', function(e) { if ($(e.target).is('#template-gallery-modal')) { $('#template-gallery-modal').fadeOut(); } }); // Gallery template card click handler - just selects the template visually $('.gallery-template-card').on('click', function(e) { // If clicking on the favorite icon, handle separately if ($(e.target).hasClass('template-favorite') || $(e.target).closest('.template-favorite').length) { return; } // Update the visual state in the gallery $('.gallery-template-card').removeClass('selected'); $(this).addClass('selected'); }); // Client selection functionality - only for invoice forms, not quote forms if (!isQuoteForm) { $('#select-client').on('change', function() { const selectedClientId = $(this).val(); const $clientInfoDisplay = $('#client-info-display'); const $noClientMessage = $('#no-client-message'); const $clientIdField = $('#client-id'); if (selectedClientId) { // Set the hidden client ID field $clientIdField.val(selectedClientId); // Get client information via AJAX loadClientInformation(selectedClientId); // Show client info display, hide no client message $clientInfoDisplay.removeClass('hidden'); $noClientMessage.addClass('hidden'); } else { // Clear the hidden client ID field $clientIdField.val(''); // Hide client info display, show no client message $clientInfoDisplay.addClass('hidden'); $noClientMessage.removeClass('hidden'); // Clear all display fields clearClientDisplay(); } }); } // Function to load client information function loadClientInformation(clientId) { // First check if we have client data already loaded from PHP if (typeof easyInvoice !== 'undefined' && easyInvoice.clientData && easyInvoice.clientData.id == clientId) { const clientData = easyInvoice.clientData; populateClientDisplay(clientData); return; } // If we don't have the client data pre-loaded, we should load it via PHP // This should not happen in normal circumstances since client data is loaded on page load // Client data not found in pre-loaded data clearClientDisplay(); } // Function to populate client display function populateClientDisplay(clientData) { $('#display-client-name').text(clientData.name || '-'); $('#display-client-email').text(clientData.email || '-'); $('#display-client-phone').text(clientData.phone || '-'); $('#display-client-company').text(clientData.company || '-'); $('#display-client-address').text(clientData.address || '-'); $('#display-client-website').text(clientData.website || '-'); } // Function to clear client display function clearClientDisplay() { $('#display-client-name').text('-'); $('#display-client-email').text('-'); $('#display-client-phone').text('-'); $('#display-client-company').text('-'); $('#display-client-address').text('-'); $('#display-client-website').text('-'); } // Function to update main template grid when template is selected from popup function updateMainTemplateGrid(templateId, templateName, templateDescription, templateIcon, isPremium) { const $mainGrid = $('#main-templates-grid'); const $existingCards = $mainGrid.find('.template-card'); // Check if the selected template already exists in the main grid const $existingCard = $mainGrid.find('.template-card[data-template-id="' + templateId + '"]'); if ($existingCard.length > 0) { // Template already exists, just select it and don't add duplicates $existingCard.addClass('selected'); $existingCard.find('input[type="radio"]').prop('checked', true); $mainGrid.find('.template-card').not($existingCard).removeClass('selected'); return; } // If we have 3 templates and the new one doesn't exist, replace the currently selected one if ($existingCards.length >= 3) { const $selectedCard = $mainGrid.find('.template-card.selected'); if ($selectedCard.length > 0) { $selectedCard.remove(); } else { // If no template is selected, remove the first one $existingCards.first().remove(); } } // Create new template card HTML const isFreeVersion = !window.easyInvoice || !window.easyInvoice.isPro; const premiumClasses = (isPremium && isFreeVersion) ? 'premium-template-blurred' : ''; const disabledAttr = (isPremium && isFreeVersion) ? 'disabled' : ''; const newCardHtml = `
${templateName}

${templateDescription}

`; // Add the new template card to the main grid $mainGrid.append(newCardHtml); // Update the visual state - ensure only the new template is selected $mainGrid.find('.template-card').removeClass('selected'); $mainGrid.find('.template-card[data-template-id="' + templateId + '"]').addClass('selected'); } // Save to Item Library functionality $(document).on('click', '.save-to-library-btn', function(e) { e.preventDefault(); var $btn = $(this); var itemIndex = $btn.data('item-index'); // Find the closest item container (either invoice-item or quote-item) var $itemContainer = $btn.closest('.invoice-item, .quote-item'); console.log('Save to Library - Item container found:', $itemContainer.length); console.log('Save to Library - Item index:', itemIndex); if (!$itemContainer.length) { console.error('Save to Library - Could not find item container'); return; } // Get item data from the form var itemData = { title: '', description: '', price: 0, quantity: 0, taxable: 0 }; // Extract data from the item fields $itemContainer.find('input, textarea, select').each(function() { var $field = $(this); var name = $field.attr('name'); var value = $field.val(); var type = $field.attr('type'); if (name) { // Handle array names like items[0][title] or quote_items[0][title] var matches = name.match(/(items|quote_items)\[\d+\]\[(.+)\]/); if (matches && matches[2]) { if (type === 'checkbox' || type === 'radio') { itemData[matches[2]] = $field.is(':checked') ? 1 : 0; } else { itemData[matches[2]] = value; } } } }); console.log('Save to Library - Extracted raw data:', itemData); // Convert numeric fields itemData.price = parseFloat(itemData.price) || 0; itemData.quantity = parseInt(itemData.quantity) || 0; itemData.taxable = parseInt(itemData.taxable) || 0; console.log('Save to Library - Processed data:', itemData); // Validate required fields if (!itemData.title || !itemData.title.trim()) { if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.error('Please fill in item title before saving to library'); } else { alert('Please fill in item title before saving to library'); } return; } if (!itemData.price || itemData.price <= 0) { if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.error('Please fill in item price before saving to library'); } else { alert('Please fill in item price before saving to library'); } return; } // Show loading state var originalHtml = $btn.html(); $btn.html('').prop('disabled', true); // AJAX call to save to item library $.ajax({ url: ajaxurl, type: 'POST', data: { action: 'easy_invoice_pro_add_item', nonce: $btn.data('nonce'), item_data: JSON.stringify(itemData) }, success: function(response) { if (response.success) { if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.success('Item saved to library successfully!'); } else { alert('Item saved to library successfully!'); } } else { if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.error(response.data.message || 'Failed to save item'); } else { alert('Failed to save item: ' + (response.data.message || 'Unknown error')); } } }, error: function() { if (typeof EasyInvoiceToast !== 'undefined') { EasyInvoiceToast.error('Error saving item to library'); } else { alert('Error saving item to library'); } }, complete: function() { // Restore button $btn.html(originalHtml).prop('disabled', false); } }); }); });