Files
nomina_ventas/public/js/app.js

242 lines
6.5 KiB
JavaScript
Executable File

/**
* Nómina Pegaso - Global JavaScript Functions
*/
document.addEventListener('DOMContentLoaded', function() {
// Initialize all components
initTooltips();
initAnimations();
initFormValidation();
initDeleteConfirmations();
// Auto-dismiss alerts after 5 seconds
setTimeout(function() {
const alerts = document.querySelectorAll('.alert:not(.alert-permanent)');
alerts.forEach(function(alert) {
const bsAlert = new bootstrap.Alert(alert);
bsAlert.close();
});
}, 5000);
});
/**
* Initialize Bootstrap tooltips
*/
function initTooltips() {
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function(tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
}
/**
* Add subtle animations on page load
*/
function initAnimations() {
// Fade in cards
const cards = document.querySelectorAll('.card');
cards.forEach(function(card, index) {
card.style.opacity = '0';
card.style.transform = 'translateY(20px)';
card.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
setTimeout(function() {
card.style.opacity = '1';
card.style.transform = 'translateY(0)';
}, index * 100);
});
// Animate stat numbers
const statNumbers = document.querySelectorAll('.stat-number');
statNumbers.forEach(function(el) {
const target = parseFloat(el.getAttribute('data-target'));
if (target) {
animateValue(el, 0, target, 1000);
}
});
}
/**
* Animate number counting
*/
function animateValue(el, start, end, duration) {
let startTimestamp = null;
const step = function(timestamp) {
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
const value = progress * (end - start) + start;
el.textContent = formatCurrency(value);
if (progress < 1) {
window.requestAnimationFrame(step);
}
};
window.requestAnimationFrame(step);
}
/**
* Format currency
*/
function formatCurrency(amount) {
return '$' + parseFloat(amount).toLocaleString('es-ES', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}
/**
* Initialize form validation feedback
*/
function initFormValidation() {
const forms = document.querySelectorAll('.needs-validation');
forms.forEach(function(form) {
form.addEventListener('submit', function(event) {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}
/**
* Add confirmation to delete buttons
*/
function initDeleteConfirmations() {
const deleteButtons = document.querySelectorAll('.btn-delete');
deleteButtons.forEach(function(btn) {
btn.addEventListener('click', function(e) {
if (!confirm('¿Estás seguro de que deseas eliminar este elemento?')) {
e.preventDefault();
return false;
}
});
});
}
/**
* Format date for display
*/
window.formatDate = function(dateStr, format = 'short') {
if (!dateStr) return '';
const date = new Date(dateStr);
if (format === 'short') {
return date.toLocaleDateString('es-ES');
}
return date.toLocaleDateString('es-ES', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
});
};
/**
* Show toast notification
*/
window.showToast = function(message, type = 'info') {
const toastContainer = document.querySelector('.toast-container');
if (!toastContainer) return;
const toast = document.createElement('div');
toast.className = `toast show align-items-center text-white bg-${type} border-0`;
toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', 'assertive');
toast.setAttribute('aria-atomic', 'true');
const icons = {
success: 'bi-check-circle',
error: 'bi-exclamation-circle',
warning: 'bi-exclamation-triangle',
info: 'bi-info-circle'
};
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">
<i class="${icons[type] || 'bi-info-circle'} me-2"></i>
${message}
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
`;
toastContainer.appendChild(toast);
setTimeout(function() {
toast.remove();
}, 5000);
};
/**
* Mobile sidebar functionality
*/
document.addEventListener('DOMContentLoaded', function() {
const mobileNavBtn = document.getElementById('mobileNavBtn');
const mobileNavBtn2 = document.getElementById('mobileNavBtn2');
const sidebar = document.getElementById('sidebar');
const sidebarOverlay = document.getElementById('sidebarOverlay');
function toggleSidebar() {
if (sidebar && sidebarOverlay) {
sidebar.classList.toggle('show');
sidebarOverlay.classList.toggle('show');
}
}
if (mobileNavBtn) {
mobileNavBtn.addEventListener('click', toggleSidebar);
}
if (mobileNavBtn2) {
mobileNavBtn2.addEventListener('click', toggleSidebar);
}
if (sidebarOverlay) {
sidebarOverlay.addEventListener('click', toggleSidebar);
}
// Close sidebar on escape key
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && sidebar && sidebar.classList.contains('show')) {
toggleSidebar();
}
});
});
/**
* Helper to parse numeric input
*/
window.parseNumber = function(value, decimals = 2) {
const parsed = parseFloat(value);
return isNaN(parsed) ? 0 : parseFloat(parsed.toFixed(decimals));
};
/**
* Calculate percentage
*/
window.calculatePercentage = function(value, total) {
if (total === 0) return 0;
return ((value / total) * 100).toFixed(2);
};
/**
* Debounce function for search inputs
*/
window.debounce = function(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};