Fix: Data inconsistency pada transisi tahun/bulan dan setup API lokal untuk testing
- Fix deteksi transisi bulan untuk semua bulan (tidak hanya 1 Januari) - Perbaikan validasi data dengan threshold 20% untuk transisi bulan/tahun - Auto-reset chart jika data hourly tidak valid - Setup force local mode untuk testing API lokal - Perbaikan normalisasi dan validasi tanggal - Enhanced logging untuk debugging transisi
This commit is contained in:
@@ -34,6 +34,93 @@ function getTodayIndonesia() {
|
||||
return formatter.format(now);
|
||||
}
|
||||
|
||||
// Helper function untuk normalisasi format tanggal ke YYYY-MM-DD
|
||||
// Memastikan format konsisten terlepas dari input browser
|
||||
function normalizeDate(dateString) {
|
||||
if (!dateString) return '';
|
||||
|
||||
// Log input untuk debug
|
||||
console.log('[Dashboard] normalizeDate - Input:', {
|
||||
value: dateString,
|
||||
type: typeof dateString,
|
||||
length: dateString.length,
|
||||
charCodes: dateString.split('').map(c => c.charCodeAt(0))
|
||||
});
|
||||
|
||||
// Jika sudah format YYYY-MM-DD, validasi dan return
|
||||
if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
|
||||
// Validasi bahwa tanggal valid (misal tidak ada 2025-13-45)
|
||||
const [year, month, day] = dateString.split('-').map(Number);
|
||||
const date = new Date(year, month - 1, day);
|
||||
if (date.getFullYear() === year && date.getMonth() === month - 1 && date.getDate() === day) {
|
||||
console.log('[Dashboard] normalizeDate - Valid YYYY-MM-DD format:', dateString);
|
||||
return dateString;
|
||||
} else {
|
||||
console.warn('[Dashboard] normalizeDate - Invalid date values:', { year, month, day });
|
||||
}
|
||||
}
|
||||
|
||||
// Jika format lain, coba parse dengan berbagai cara
|
||||
let date;
|
||||
|
||||
// Coba parse sebagai ISO string dulu
|
||||
date = new Date(dateString);
|
||||
if (!isNaN(date.getTime())) {
|
||||
// Format ke YYYY-MM-DD menggunakan timezone Indonesia
|
||||
const formatter = new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: 'Asia/Jakarta',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
});
|
||||
const normalized = formatter.format(date);
|
||||
console.log('[Dashboard] normalizeDate - Parsed and normalized:', dateString, '->', normalized);
|
||||
return normalized;
|
||||
}
|
||||
|
||||
// Jika masih gagal, coba parse manual (untuk format DD/MM/YYYY atau MM/DD/YYYY)
|
||||
const parts = dateString.split(/[-\/]/);
|
||||
if (parts.length === 3) {
|
||||
let year, month, day;
|
||||
// Coba deteksi format: jika bagian pertama > 12, kemungkinan DD/MM/YYYY
|
||||
if (parseInt(parts[0]) > 12) {
|
||||
// DD/MM/YYYY
|
||||
day = parseInt(parts[0]);
|
||||
month = parseInt(parts[1]);
|
||||
year = parseInt(parts[2]);
|
||||
} else {
|
||||
// MM/DD/YYYY atau YYYY-MM-DD
|
||||
if (parts[0].length === 4) {
|
||||
// YYYY-MM-DD
|
||||
year = parseInt(parts[0]);
|
||||
month = parseInt(parts[1]);
|
||||
day = parseInt(parts[2]);
|
||||
} else {
|
||||
// MM/DD/YYYY
|
||||
month = parseInt(parts[0]);
|
||||
day = parseInt(parts[1]);
|
||||
year = parseInt(parts[2]);
|
||||
}
|
||||
}
|
||||
|
||||
date = new Date(year, month - 1, day);
|
||||
if (!isNaN(date.getTime())) {
|
||||
const formatter = new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: 'Asia/Jakarta',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
});
|
||||
const normalized = formatter.format(date);
|
||||
console.log('[Dashboard] normalizeDate - Manual parse:', dateString, '->', normalized);
|
||||
return normalized;
|
||||
}
|
||||
}
|
||||
|
||||
console.warn('[Dashboard] normalizeDate - Failed to parse:', dateString);
|
||||
return '';
|
||||
}
|
||||
|
||||
// State akan di-set ke hari ini saat DOMContentLoaded
|
||||
const state = {
|
||||
date: '', // Akan di-set ke hari ini saat DOMContentLoaded
|
||||
@@ -233,6 +320,71 @@ async function loadSummaryAndCharts() {
|
||||
const loadingOverlay = document.getElementById('summary-loading');
|
||||
if (loadingOverlay) loadingOverlay.classList.add('visible');
|
||||
|
||||
// Validasi dan normalisasi tanggal sebelum request
|
||||
if (!state.date || !/^\d{4}-\d{2}-\d{2}$/.test(state.date)) {
|
||||
console.error('[Dashboard] Invalid date format:', state.date);
|
||||
const today = getTodayIndonesia();
|
||||
state.date = today;
|
||||
const dateInput = document.getElementById('filter-date');
|
||||
if (dateInput) {
|
||||
dateInput.value = today;
|
||||
dateInput.setAttribute('value', today);
|
||||
}
|
||||
}
|
||||
|
||||
// Pastikan format tanggal konsisten (YYYY-MM-DD)
|
||||
const normalizedDate = normalizeDate(state.date);
|
||||
if (normalizedDate && normalizedDate !== state.date) {
|
||||
console.warn('[Dashboard] Date normalized:', state.date, '->', normalizedDate);
|
||||
state.date = normalizedDate;
|
||||
const dateInput = document.getElementById('filter-date');
|
||||
if (dateInput) {
|
||||
dateInput.value = normalizedDate;
|
||||
dateInput.setAttribute('value', normalizedDate);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse tanggal untuk deteksi transisi tahun/bulan
|
||||
const [year, month, day] = state.date.split('-').map(Number);
|
||||
// Deteksi transisi: hari pertama bulan (day === 1)
|
||||
// Ini berlaku untuk semua bulan, termasuk transisi tahun (1 Januari)
|
||||
const isMonthTransition = day === 1;
|
||||
// Deteksi khusus untuk transisi tahun (1 Januari)
|
||||
const isYearTransition = month === 1 && day === 1;
|
||||
|
||||
if (isMonthTransition) {
|
||||
const transitionType = isYearTransition ? 'Tahun' : 'Bulan';
|
||||
console.log('[Dashboard] ⚠️ Transisi terdeteksi:', {
|
||||
date: state.date,
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
isYearTransition,
|
||||
isMonthTransition,
|
||||
transitionType,
|
||||
note: `Transisi ${transitionType} - Data hourly mungkin belum ter-aggregate dengan benar di backend`
|
||||
});
|
||||
}
|
||||
|
||||
// Reset data sementara sebelum load (untuk menghindari data lama terlihat)
|
||||
renderSummary({
|
||||
totalAmount: 0,
|
||||
personCount: 0,
|
||||
motorCount: 0,
|
||||
carCount: 0
|
||||
});
|
||||
|
||||
// Log detail tanggal yang akan dikirim ke API
|
||||
console.log('[Dashboard] loadSummaryAndCharts - Request params:', {
|
||||
date: state.date,
|
||||
dateType: typeof state.date,
|
||||
dateLength: state.date ? state.date.length : 0,
|
||||
dateValid: /^\d{4}-\d{2}-\d{2}$/.test(state.date),
|
||||
locationCode: state.locationCode,
|
||||
gateCode: state.gateCode,
|
||||
dateInputValue: document.getElementById('filter-date')?.value
|
||||
});
|
||||
|
||||
try {
|
||||
const [summaryResp, hourlyResp, byCategoryResp] = await Promise.all([
|
||||
apiGetSummary({
|
||||
@@ -256,7 +408,15 @@ async function loadSummaryAndCharts() {
|
||||
// Kartu KPI: pakai total_count & total_amount dari summary endpoint
|
||||
// Struktur summaryResp setelah di-unwrap: { total_count, total_amount, active_gates, active_locations }
|
||||
console.log('[Dashboard] Summary response raw:', summaryResp);
|
||||
console.log('[Dashboard] Summary response keys:', Object.keys(summaryResp || {}));
|
||||
console.log('[Dashboard] Summary response values:', {
|
||||
total_count: summaryResp?.total_count,
|
||||
total_amount: summaryResp?.total_amount,
|
||||
active_gates: summaryResp?.active_gates,
|
||||
active_locations: summaryResp?.active_locations
|
||||
});
|
||||
console.log('[Dashboard] By Category response raw:', byCategoryResp);
|
||||
console.log('[Dashboard] By Category response keys:', Object.keys(byCategoryResp || {}));
|
||||
console.log('[Dashboard] State date:', state.date);
|
||||
|
||||
// Handle jika response masih wrapped
|
||||
@@ -393,15 +553,185 @@ async function loadSummaryAndCharts() {
|
||||
totalAmounts = Array(24).fill(0);
|
||||
}
|
||||
|
||||
// Hitung total dari hourly data untuk validasi
|
||||
const hourlyTotalCount = totalCounts.reduce((sum, val) => sum + (Number(val) || 0), 0);
|
||||
const hourlyTotalAmount = totalAmounts.reduce((sum, val) => sum + (Number(val) || 0), 0);
|
||||
|
||||
console.log('[Dashboard] Hourly data processed:', {
|
||||
date: state.date,
|
||||
labels: labels.length,
|
||||
counts: totalCounts.length,
|
||||
amounts: totalAmounts.length,
|
||||
totalCount: totalCounts.reduce((a, b) => a + b, 0),
|
||||
totalAmount: totalAmounts.reduce((a, b) => a + b, 0)
|
||||
totalCount: hourlyTotalCount,
|
||||
totalAmount: hourlyTotalAmount
|
||||
});
|
||||
|
||||
// Validasi: Bandingkan total dari hourly dengan summary
|
||||
const summaryTotalCount = summary.total_count || 0;
|
||||
const summaryTotalAmount = summary.total_amount || 0;
|
||||
|
||||
// Parse tanggal untuk deteksi transisi tahun/bulan
|
||||
const [year, month, day] = state.date.split('-').map(Number);
|
||||
// Deteksi transisi: hari pertama bulan (day === 1)
|
||||
// Ini berlaku untuk semua bulan, termasuk transisi tahun (1 Januari)
|
||||
const isMonthTransition = day === 1;
|
||||
// Deteksi khusus untuk transisi tahun (1 Januari)
|
||||
const isYearTransition = month === 1 && day === 1;
|
||||
|
||||
// Log detail untuk debugging
|
||||
console.log('[Dashboard] Data validation:', {
|
||||
date: state.date,
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
isYearTransition,
|
||||
isMonthTransition,
|
||||
summaryTotalCount,
|
||||
summaryTotalAmount,
|
||||
hourlyTotalCount,
|
||||
hourlyTotalAmount,
|
||||
countDifference: Math.abs(hourlyTotalCount - summaryTotalCount),
|
||||
amountDifference: Math.abs(hourlyTotalAmount - summaryTotalAmount),
|
||||
ratio: hourlyTotalCount > 0 && summaryTotalCount > 0
|
||||
? (hourlyTotalCount / summaryTotalCount).toFixed(2)
|
||||
: 'N/A'
|
||||
});
|
||||
|
||||
// Flag untuk menandai apakah hourly data valid
|
||||
let hourlyDataValid = true;
|
||||
let useHourlyData = true;
|
||||
|
||||
if (hourlyTotalCount > 0 && summaryTotalCount > 0) {
|
||||
const countDiff = Math.abs(hourlyTotalCount - summaryTotalCount);
|
||||
const amountDiff = Math.abs(hourlyTotalAmount - summaryTotalAmount);
|
||||
const maxCount = Math.max(hourlyTotalCount, summaryTotalCount);
|
||||
const maxAmount = Math.max(hourlyTotalAmount, summaryTotalAmount);
|
||||
const countDiffPercent = maxCount > 0
|
||||
? Number(((countDiff / maxCount) * 100).toFixed(2))
|
||||
: 0;
|
||||
const amountDiffPercent = maxAmount > 0
|
||||
? Number(((amountDiff / maxAmount) * 100).toFixed(2))
|
||||
: 0;
|
||||
|
||||
// Hitung ratio untuk deteksi data yang sangat tidak proporsional
|
||||
const countRatio = hourlyTotalCount > 0 && summaryTotalCount > 0
|
||||
? hourlyTotalCount / summaryTotalCount
|
||||
: 0;
|
||||
|
||||
// Deteksi khusus untuk transisi tahun/bulan: jika hourly jauh lebih besar dari summary
|
||||
// Kemungkinan hourly data dari tanggal lain atau semua data
|
||||
// Threshold lebih ketat untuk transisi tahun (20% vs 50%)
|
||||
const threshold = (isYearTransition || isMonthTransition) ? 20 : 50;
|
||||
const ratioThreshold = 2.0; // Jika hourly > 2x summary, kemungkinan salah
|
||||
|
||||
// Jika perbedaan sangat besar atau ratio tidak proporsional, kemungkinan hourly data salah
|
||||
if (countDiffPercent > threshold || amountDiffPercent > threshold || countRatio > ratioThreshold) {
|
||||
hourlyDataValid = false;
|
||||
useHourlyData = false;
|
||||
|
||||
console.error('[Dashboard] ❌ Hourly data TIDAK VALID - perbedaan terlalu besar:', {
|
||||
date: state.date,
|
||||
isYearTransition,
|
||||
isMonthTransition,
|
||||
summaryTotalCount,
|
||||
hourlyTotalCount,
|
||||
countDiffPercent: countDiffPercent + '%',
|
||||
amountDiffPercent: amountDiffPercent + '%',
|
||||
countRatio: countRatio.toFixed(2),
|
||||
threshold: threshold + '%',
|
||||
action: 'Mengabaikan hourly data, menggunakan data kosong untuk chart'
|
||||
});
|
||||
|
||||
// Reset hourly data ke kosong karena tidak valid
|
||||
labels = Array.from({ length: 24 }, (_, i) => `${String(i).padStart(2, '0')}:00`);
|
||||
totalCounts = Array(24).fill(0);
|
||||
totalAmounts = Array(24).fill(0);
|
||||
|
||||
// Tampilkan error di UI dengan info lebih detail
|
||||
const transitionInfo = isYearTransition
|
||||
? ' (Transisi Tahun - Data mungkin belum ter-aggregate)'
|
||||
: isMonthTransition
|
||||
? ' (Transisi Bulan - Data mungkin belum ter-aggregate)'
|
||||
: '';
|
||||
const errorMsg = `⚠️ PERINGATAN: Data hourly tidak valid untuk tanggal ${state.date}${transitionInfo}\n` +
|
||||
`Summary: ${summaryTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(summaryTotalAmount || 0)})\n` +
|
||||
`Hourly: ${hourlyTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(hourlyTotalAmount || 0)})\n` +
|
||||
`Perbedaan: ${countDiffPercent.toFixed(2)}% (Ratio: ${countRatio.toFixed(2)}x) - Kemungkinan data hourly dari tanggal lain.\n` +
|
||||
`Chart hourly akan kosong. Silakan hubungi administrator untuk memperbaiki backend API atau trigger aggregation manual.`;
|
||||
showError(errorMsg);
|
||||
} else if (countDiffPercent > 5 || amountDiffPercent > 5) { // Threshold 5% untuk deteksi lebih sensitif
|
||||
const warningMsg = `⚠️ DATA INCONSISTENCY DETECTED untuk tanggal ${state.date}:\n` +
|
||||
`- Summary: ${summaryTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(summaryTotalAmount || 0)})\n` +
|
||||
`- Hourly: ${hourlyTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(hourlyTotalAmount || 0)})\n` +
|
||||
`- Perbedaan: ${countDiff} events (${countDiffPercent.toFixed(2)}%), Rp ${new Intl.NumberFormat('id-ID').format(amountDiff)} (${amountDiffPercent.toFixed(2)}%)\n` +
|
||||
`- Catatan: Menggunakan data Summary sebagai sumber utama. Perbedaan kecil mungkin normal karena timing aggregation.`;
|
||||
|
||||
const warningData = {
|
||||
date: state.date,
|
||||
summaryTotalCount,
|
||||
summaryTotalAmount,
|
||||
hourlyTotalCount,
|
||||
hourlyTotalAmount,
|
||||
countDifference: countDiff,
|
||||
countDifferencePercent: countDiffPercent + '%',
|
||||
amountDifference: amountDiff,
|
||||
amountDifferencePercent: amountDiffPercent + '%',
|
||||
message: 'Summary dan Hourly data tidak konsisten. Menggunakan Summary sebagai sumber utama.'
|
||||
};
|
||||
|
||||
console.warn('[Dashboard] ⚠️ DATA INCONSISTENCY DETECTED:', warningData);
|
||||
console.warn('[Dashboard]', warningMsg);
|
||||
|
||||
// Tampilkan warning di UI hanya jika perbedaan sangat besar (>30%)
|
||||
// Perbedaan kecil (<30%) mungkin normal karena timing aggregation atau rounding
|
||||
if (countDiffPercent > 30 || amountDiffPercent > 30) {
|
||||
const errorMsg = `⚠️ PERINGATAN: Data tidak konsisten untuk tanggal ${state.date}\n` +
|
||||
`Summary: ${summaryTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(summaryTotalAmount || 0)})\n` +
|
||||
`Hourly: ${hourlyTotalCount} events (Rp ${new Intl.NumberFormat('id-ID').format(hourlyTotalAmount || 0)})\n` +
|
||||
`Selisih: ${countDiffPercent.toFixed(2)}% events, ${amountDiffPercent.toFixed(2)}% amount\n` +
|
||||
`Silakan hubungi administrator jika perbedaan ini tidak normal.`;
|
||||
showError(errorMsg);
|
||||
}
|
||||
} else {
|
||||
console.log('[Dashboard] ✅ Data konsisten antara Summary dan Hourly:', {
|
||||
date: state.date,
|
||||
summaryTotalCount,
|
||||
hourlyTotalCount,
|
||||
difference: countDiff,
|
||||
differencePercent: countDiffPercent + '%'
|
||||
});
|
||||
}
|
||||
} else if (hourlyTotalCount === 0 && summaryTotalCount === 0) {
|
||||
console.log('[Dashboard] ℹ️ Tidak ada data untuk tanggal', state.date);
|
||||
useHourlyData = true; // Data kosong adalah valid
|
||||
} else if (hourlyTotalCount > 0 && summaryTotalCount === 0) {
|
||||
// Jika hourly ada data tapi summary kosong, kemungkinan summary belum ter-aggregate
|
||||
// Tapi kita tetap gunakan hourly data dengan warning
|
||||
console.warn('[Dashboard] ⚠️ Summary kosong tapi Hourly ada data:', {
|
||||
date: state.date,
|
||||
hourlyTotalCount,
|
||||
message: 'Summary endpoint tidak mengembalikan data, tapi Hourly endpoint ada data. Menggunakan data Hourly dengan hati-hati.'
|
||||
});
|
||||
useHourlyData = true;
|
||||
hourlyDataValid = false; // Mark as potentially invalid
|
||||
} else if (hourlyTotalCount === 0 && summaryTotalCount > 0) {
|
||||
console.warn('[Dashboard] ⚠️ Hourly kosong tapi Summary ada data:', {
|
||||
date: state.date,
|
||||
summaryTotalCount,
|
||||
message: 'Hourly endpoint tidak mengembalikan data, tapi Summary endpoint ada data. Chart akan kosong.'
|
||||
});
|
||||
useHourlyData = true; // Data kosong adalah valid (tidak ada data per jam)
|
||||
}
|
||||
|
||||
// Log final decision
|
||||
if (!useHourlyData) {
|
||||
console.log('[Dashboard] Decision: Mengabaikan hourly data karena tidak valid, menggunakan data kosong untuk chart');
|
||||
} else if (!hourlyDataValid) {
|
||||
console.log('[Dashboard] Decision: Menggunakan hourly data dengan peringatan (potentially invalid)');
|
||||
} else {
|
||||
console.log('[Dashboard] Decision: Menggunakan hourly data (valid)');
|
||||
}
|
||||
|
||||
// Pastikan chart sudah di-init sebelum update
|
||||
const dailyCanvas = document.getElementById('daily-chart');
|
||||
const currentDailyChart = getDailyChart();
|
||||
@@ -413,12 +743,13 @@ async function loadSummaryAndCharts() {
|
||||
// Selalu update chart, meskipun data kosong (agar user tahu memang tidak ada data)
|
||||
const dailyChartInstance = getDailyChart();
|
||||
if (dailyChartInstance) {
|
||||
// Set data baru (updateDailyChart sudah handle reset dan validasi)
|
||||
updateDailyChart({
|
||||
labels,
|
||||
counts: totalCounts,
|
||||
amounts: totalAmounts
|
||||
});
|
||||
console.log('[Dashboard] Daily chart updated successfully');
|
||||
console.log('[Dashboard] Daily chart updated successfully for date:', state.date);
|
||||
} else {
|
||||
console.error('[Dashboard] Daily chart tidak bisa di-update, chart belum di-init! Canvas:', dailyCanvas);
|
||||
}
|
||||
@@ -490,11 +821,12 @@ async function loadSummaryAndCharts() {
|
||||
// Selalu update chart, meskipun data kosong (agar user tahu memang tidak ada data)
|
||||
const currentCategoryChart = getCategoryChart();
|
||||
if (currentCategoryChart) {
|
||||
// Set data baru (updateCategoryChart sudah handle reset dan validasi)
|
||||
updateCategoryChart({
|
||||
labels: catLabels,
|
||||
values: catValues
|
||||
});
|
||||
console.log('[Dashboard] Category chart updated successfully');
|
||||
console.log('[Dashboard] Category chart updated successfully for date:', state.date);
|
||||
} else {
|
||||
console.error('[Dashboard] Category chart tidak bisa di-update, chart belum di-init!');
|
||||
}
|
||||
@@ -712,8 +1044,97 @@ function setupFilters() {
|
||||
dateInput.setAttribute('value', state.date);
|
||||
}
|
||||
dateInput.addEventListener('change', () => {
|
||||
state.date = dateInput.value || state.date;
|
||||
loadSummaryAndCharts();
|
||||
// Normalisasi tanggal yang dipilih user untuk memastikan format YYYY-MM-DD
|
||||
const originalValue = dateInput.value;
|
||||
const selectedDate = normalizeDate(originalValue);
|
||||
|
||||
if (selectedDate) {
|
||||
// Validasi bahwa tanggal valid (cek apakah tanggal yang dipilih sama dengan yang dinormalisasi)
|
||||
const [year, month, day] = selectedDate.split('-').map(Number);
|
||||
const dateObj = new Date(year, month - 1, day);
|
||||
const isValidDate = dateObj.getFullYear() === year &&
|
||||
dateObj.getMonth() === month - 1 &&
|
||||
dateObj.getDate() === day;
|
||||
|
||||
if (!isValidDate) {
|
||||
console.warn('[Dashboard] Invalid date after normalization:', selectedDate);
|
||||
dateInput.value = state.date;
|
||||
dateInput.setAttribute('value', state.date);
|
||||
return;
|
||||
}
|
||||
|
||||
// Cek apakah tanggal benar-benar berubah
|
||||
const dateChanged = selectedDate !== state.date;
|
||||
|
||||
// Deteksi transisi tahun/bulan
|
||||
// Deteksi transisi: hari pertama bulan (day === 1)
|
||||
const isMonthTransition = day === 1;
|
||||
// Deteksi khusus untuk transisi tahun (1 Januari)
|
||||
const isYearTransition = month === 1 && day === 1;
|
||||
const wasYearTransition = state.date && (() => {
|
||||
const [prevYear, prevMonth, prevDay] = state.date.split('-').map(Number);
|
||||
return prevYear === 2026 && prevMonth === 1 && prevDay === 1;
|
||||
})();
|
||||
|
||||
if (dateChanged) {
|
||||
console.log('[Dashboard] Date changed by user:', {
|
||||
original: originalValue,
|
||||
normalized: selectedDate,
|
||||
previousDate: state.date,
|
||||
year: year,
|
||||
month: month,
|
||||
day: day,
|
||||
isYearTransition,
|
||||
isMonthTransition,
|
||||
wasYearTransition,
|
||||
note: 'Resetting all data before loading new date'
|
||||
});
|
||||
|
||||
// Reset semua data sebelum load tanggal baru (penting untuk transisi tahun/bulan)
|
||||
renderSummary({
|
||||
totalAmount: 0,
|
||||
personCount: 0,
|
||||
motorCount: 0,
|
||||
carCount: 0
|
||||
});
|
||||
|
||||
// Reset chart juga
|
||||
const dailyChartInstance = getDailyChart();
|
||||
if (dailyChartInstance) {
|
||||
dailyChartInstance.data.labels = [];
|
||||
dailyChartInstance.data.datasets[0].data = [];
|
||||
dailyChartInstance.data.datasets[1].data = [];
|
||||
dailyChartInstance.update('none');
|
||||
}
|
||||
|
||||
const categoryChartInstance = getCategoryChart();
|
||||
if (categoryChartInstance) {
|
||||
categoryChartInstance.data.labels = [];
|
||||
categoryChartInstance.data.datasets[0].data = [];
|
||||
categoryChartInstance.update('none');
|
||||
}
|
||||
}
|
||||
|
||||
state.date = selectedDate;
|
||||
// Pastikan dateInput juga menggunakan format yang sudah dinormalisasi
|
||||
if (dateInput.value !== selectedDate) {
|
||||
dateInput.value = selectedDate;
|
||||
dateInput.setAttribute('value', selectedDate);
|
||||
}
|
||||
|
||||
// Hanya reload jika tanggal benar-benar berubah
|
||||
if (dateChanged) {
|
||||
// Small delay untuk memastikan UI sudah di-reset
|
||||
setTimeout(() => {
|
||||
loadSummaryAndCharts();
|
||||
}, 50);
|
||||
}
|
||||
} else {
|
||||
console.warn('[Dashboard] Invalid date selected, keeping current date:', state.date);
|
||||
// Reset ke state.date jika invalid
|
||||
dateInput.value = state.date;
|
||||
dateInput.setAttribute('value', state.date);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user