function showLoading(show, message = 'Cargando...') { const overlay = $('#loading-overlay'); if (show) { overlay.find('.loader').next('span').remove(); overlay.find('.loader').after(`${escapeHtml(message)}`); overlay.addClass('show'); } else { overlay.removeClass('show'); } } function showNotification(message, type = 'info', duration) { if (notificationTimeout) clearTimeout(notificationTimeout); const notification = $('#notification'); notification.text(message).removeClass('success error info warning').addClass(type).addClass('show'); let effectiveDuration = duration; if (effectiveDuration === undefined) { effectiveDuration = type === 'error' ? 8000 : type === 'warning' ? 6000 : 4000; } notificationTimeout = setTimeout(() => { notification.removeClass('show'); notificationTimeout = null; }, effectiveDuration); } function escapeHtml(unsafe) { if (typeof unsafe !== 'string') { return ''; } return unsafe.replace(/[&<>"']/g, m => ({ '&': '&', '<': '<', '>': '>', '"': '"' })[m]); } function debounce(func, wait) { let timeout; return function (...args) { clearTimeout(timeout); timeout = setTimeout(() => func.apply(this, args), wait); }; } async function showConfirmationModal(message, title = "Confirmación", confirmText = "Confirmar", confirmClass = "btn-primary") { return new Promise((resolve) => { const modalId = 'genericConfirmationModal'; let modalElement = document.getElementById(modalId); if (!modalElement) { const wrapper = document.createElement('div'); wrapper.innerHTML = ` `; modalElement = wrapper.firstElementChild; document.body.appendChild(modalElement); } else { $(modalElement).find('.modal-title').text(title); $(modalElement).find('.modal-body p').text(message); $(modalElement).find(`#${modalId}ConfirmBtn`).text(confirmText).attr('class', `btn ${confirmClass}`); } const confirmBtn = document.getElementById(`${modalId}ConfirmBtn`); const modalInstance = bootstrap.Modal.getOrCreateInstance(document.getElementById(modalId)); const confirmHandler = () => { confirmBtn.removeEventListener('click', confirmHandler); modalInstance.hide(); resolve(true); }; $(modalElement).off('hidden.bs.modal.confirm').one('hidden.bs.modal.confirm', () => { confirmBtn.removeEventListener('click', confirmHandler); resolve(false); }); $(confirmBtn).off('click.confirm').one('click.confirm', confirmHandler); modalInstance.show(); }); }