mirror of
https://github.com/marcogll/ap_pos.git
synced 2026-01-13 13:15:16 +00:00
fix: Corregir bloqueo del navegador en el dashboard
Se soluciona un error crítico que causaba el bloqueo del navegador al visitar la pestaña del dashboard. El problema era causado por la inicialización de la librería Chart.js en un elemento del DOM que no estaba visible, lo que provocaba un bucle de renderizado infinito. La solución implementada consiste en: - Inicializar el gráfico solo la primera vez que la pestaña del dashboard se hace visible. - En visitas posteriores a la pestaña, solo se actualizan los datos del gráfico ya existente.
This commit is contained in:
@@ -35,33 +35,40 @@ const formCredentials = document.getElementById('formCredentials');
|
|||||||
const formAddUser = document.getElementById('formAddUser');
|
const formAddUser = document.getElementById('formAddUser');
|
||||||
const tblUsersBody = document.getElementById('tblUsers')?.querySelector('tbody');
|
const tblUsersBody = document.getElementById('tblUsers')?.querySelector('tbody');
|
||||||
|
|
||||||
|
let isDashboardLoading = false;
|
||||||
|
|
||||||
// --- LÓGICA DE NEGOCIO ---
|
// --- LÓGICA DE NEGOCIO ---
|
||||||
|
|
||||||
async function loadDashboardData() {
|
async function loadDashboardData() {
|
||||||
// Solo admins pueden cargar esto
|
// Guardia para prevenir ejecuciones múltiples
|
||||||
if (currentUser.role !== 'admin' || !incomeChart) return;
|
if (currentUser.role !== 'admin' || !incomeChart || isDashboardLoading) return;
|
||||||
|
|
||||||
|
isDashboardLoading = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/dashboard');
|
const response = await fetch('/api/dashboard');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
if (response.status === 403) {
|
if (response.status === 403) {
|
||||||
console.warn('Access to dashboard denied.');
|
console.warn('Acceso al dashboard denegado.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error('Failed to fetch dashboard data');
|
throw new Error('Falló la carga de datos del dashboard');
|
||||||
}
|
}
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
// Update stat cards
|
// Actualizar tarjetas de estadísticas
|
||||||
document.getElementById('stat-total-income').textContent = `${Number(data.totalIncome || 0).toFixed(2)}`;
|
document.getElementById('stat-total-income').textContent = `${Number(data.totalIncome || 0).toFixed(2)}`;
|
||||||
document.getElementById('stat-total-movements').textContent = data.totalMovements || 0;
|
document.getElementById('stat-total-movements').textContent = data.totalMovements || 0;
|
||||||
|
|
||||||
// Update chart data instead of recreating it
|
// Actualizar datos del gráfico
|
||||||
incomeChart.data.labels = data.incomeByService.map(item => item.tipo);
|
incomeChart.data.labels = data.incomeByService.map(item => item.tipo);
|
||||||
incomeChart.data.datasets[0].data = data.incomeByService.map(item => item.total);
|
incomeChart.data.datasets[0].data = data.incomeByService.map(item => item.total);
|
||||||
incomeChart.update();
|
incomeChart.update();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading dashboard:', error);
|
console.error('Error al cargar el dashboard:', error);
|
||||||
|
} finally {
|
||||||
|
isDashboardLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,6 +444,27 @@ function activateTab(tabId) {
|
|||||||
|
|
||||||
// Cargar datos dinámicos si es la pestaña del dashboard
|
// Cargar datos dinámicos si es la pestaña del dashboard
|
||||||
if (tabId === 'tab-dashboard' && currentUser.role === 'admin') {
|
if (tabId === 'tab-dashboard' && currentUser.role === 'admin') {
|
||||||
|
// Si es la primera vez que se visita la pestaña, inicializar el gráfico
|
||||||
|
if (!incomeChart) {
|
||||||
|
const ctx = document.getElementById('incomeChart').getContext('2d');
|
||||||
|
incomeChart = new Chart(ctx, {
|
||||||
|
type: 'pie',
|
||||||
|
data: {
|
||||||
|
labels: [],
|
||||||
|
datasets: [{
|
||||||
|
label: 'Ingresos por Servicio',
|
||||||
|
data: [],
|
||||||
|
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'],
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
animation: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Cargar (o recargar) los datos del dashboard
|
||||||
loadDashboardData();
|
loadDashboardData();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -538,25 +566,6 @@ async function initializeApp() {
|
|||||||
if (currentUser.role === 'admin') {
|
if (currentUser.role === 'admin') {
|
||||||
formAddUser?.addEventListener('submit', handleAddUser);
|
formAddUser?.addEventListener('submit', handleAddUser);
|
||||||
tblUsersBody?.addEventListener('click', handleTableClick);
|
tblUsersBody?.addEventListener('click', handleTableClick);
|
||||||
|
|
||||||
// Inicializar el gráfico vacío para el admin
|
|
||||||
const ctx = document.getElementById('incomeChart').getContext('2d');
|
|
||||||
incomeChart = new Chart(ctx, {
|
|
||||||
type: 'pie',
|
|
||||||
data: {
|
|
||||||
labels: [],
|
|
||||||
datasets: [{
|
|
||||||
label: 'Ingresos por Servicio',
|
|
||||||
data: [],
|
|
||||||
backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF', '#FF9F40'],
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
animation: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btnLogout?.addEventListener('click', async () => {
|
btnLogout?.addEventListener('click', async () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user