/** * Easy Invoice Global Toast Notification System * * A consistent toast notification system for the entire Easy Invoice plugin. * Replaces all alert() calls and inconsistent notification styles. */ (function($) { 'use strict'; // Toast configuration const TOAST_CONFIG = { duration: 5000, // 5 seconds position: 'top-right', animation: 'slide-in', maxToasts: 5 }; // Toast types and their styling const TOAST_TYPES = { success: { icon: '', bgColor: 'bg-green-50', textColor: 'text-green-800', borderColor: 'border-green-200', iconColor: 'text-green-400' }, error: { icon: '', bgColor: 'bg-red-50', textColor: 'text-red-800', borderColor: 'border-red-200', iconColor: 'text-red-400' }, warning: { icon: '', bgColor: 'bg-yellow-50', textColor: 'text-yellow-800', borderColor: 'border-yellow-200', iconColor: 'text-yellow-400' }, info: { icon: '', bgColor: 'bg-blue-50', textColor: 'text-blue-800', borderColor: 'border-blue-200', iconColor: 'text-blue-400' } }; // Global toast container let toastContainer = null; let activeToasts = []; /** * Initialize the toast system */ function init() { createToastContainer(); $(document).ready(function() { // Auto-hide toasts after duration setInterval(function() { activeToasts.forEach(function(toast, index) { if (toast.autoHide && Date.now() - toast.created > TOAST_CONFIG.duration) { hideToast(toast.id); } }); }, 1000); }); } /** * Create the toast container */ function createToastContainer() { if (toastContainer) return; toastContainer = $('
', { id: 'easy-invoice-toast-container', class: 'fixed top-4 right-4 z-50 space-y-2 max-w-sm w-full' }); $('body').append(toastContainer); } /** * Show a toast notification * * @param {string} type - success, error, warning, info * @param {string} message - The message to display * @param {object} options - Additional options */ function show(type, message, options = {}) { const config = { duration: options.duration || TOAST_CONFIG.duration, autoHide: options.autoHide !== false, dismissible: options.dismissible !== false, ...options }; // Validate type if (!TOAST_TYPES[type]) { type = 'info'; } const toastId = 'toast-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9); const toastType = TOAST_TYPES[type]; // Create toast element const toast = $('
', { id: toastId, class: `easy-invoice-toast ${toastType.bgColor} ${toastType.borderColor} border rounded-lg p-4 shadow-lg transform transition-all duration-300 ease-in-out translate-x-full opacity-0`, html: `
${toastType.icon}

${message}

${config.dismissible ? `
` : ''}
` }); // Add to container toastContainer.append(toast); // Store toast info const toastInfo = { id: toastId, element: toast, type: type, message: message, created: Date.now(), autoHide: config.autoHide, duration: config.duration }; activeToasts.push(toastInfo); // Limit number of toasts if (activeToasts.length > TOAST_CONFIG.maxToasts) { const oldestToast = activeToasts.shift(); hideToast(oldestToast.id); } // Animate in setTimeout(function() { toast.removeClass('translate-x-full opacity-0').addClass('translate-x-0 opacity-100'); }, 10); // Handle close button if (config.dismissible) { toast.find('.toast-close').on('click', function() { hideToast(toastId); }); } // Auto-hide if enabled if (config.autoHide && config.duration > 0) { setTimeout(function() { hideToast(toastId); }, config.duration); } return toastId; } /** * Hide a specific toast * * @param {string} toastId - The ID of the toast to hide */ function hideToast(toastId) { const toastIndex = activeToasts.findIndex(t => t.id === toastId); if (toastIndex === -1) return; const toast = activeToasts[toastIndex]; // Animate out toast.element.addClass('translate-x-full opacity-0'); setTimeout(function() { toast.element.remove(); activeToasts.splice(toastIndex, 1); }, 300); } /** * Hide all toasts */ function hideAll() { activeToasts.forEach(function(toast) { hideToast(toast.id); }); } /** * Show success toast */ function success(message, options = {}) { return show('success', message, options); } /** * Show error toast */ function error(message, options = {}) { return show('error', message, options); } /** * Show warning toast */ function warning(message, options = {}) { return show('warning', message, options); } /** * Show info toast */ function info(message, options = {}) { return show('info', message, options); } // Initialize when DOM is ready $(document).ready(function() { init(); }); // Expose the toast API globally window.EasyInvoiceToast = { show: show, success: success, error: error, warning: warning, info: info, hide: hideToast, hideAll: hideAll }; // Temporarily disable alert override to prevent errors // window.originalAlert = window.alert; // window.alert = function(message) { // EasyInvoiceToast.info(message, { duration: 4000 }); // }; // Global AJAX response handler for toast notifications $(document).ajaxSuccess(function(event, xhr, settings) { try { const response = JSON.parse(xhr.responseText); // Check if response contains toast data if (response.data && response.data.toast) { const toast = response.data.toast; const options = toast.options || {}; switch (toast.type) { case 'success': EasyInvoiceToast.success(toast.message, options); break; case 'error': EasyInvoiceToast.error(toast.message, options); break; case 'warning': EasyInvoiceToast.warning(toast.message, options); break; case 'info': EasyInvoiceToast.info(toast.message, options); break; } } } catch (e) { // Response is not JSON or doesn't contain toast data } }); $(document).ajaxError(function(event, xhr, settings, error) { // Show error toast for failed AJAX requests if (xhr.status !== 0) { // Don't show for aborted requests EasyInvoiceToast.error('Request failed. Please try again.', { duration: 5000 }); } }); })(jQuery);