diff --git a/public/scripts/trends.js b/public/scripts/trends.js index bd5df88..19cc326 100644 --- a/public/scripts/trends.js +++ b/public/scripts/trends.js @@ -1,32 +1,32 @@ +// public/scripts/trends.js -// Timeframes +// Timeframe configurations const tfConfig = [ - { unit: 'hours', count: 24, label: 'Last 24 Hours' }, - { unit: 'days', count: 7, label: 'Last 7 Days' }, - { unit: 'weeks', count: 4, label: 'Last 4 Weeks' }, - { unit: 'months', count: 12, label: 'Last 12 Months' }, - { unit: 'years', count: 1, label: 'All Time' } + { unit: 'hours', count: 24, label: 'Last 24 Hours' }, + { unit: 'days', count: 7, label: 'Last 7 Days' }, + { unit: 'weeks', count: 4, label: 'Last 4 Weeks' }, + { unit: 'months', count: 12, label: 'Last 12 Months' }, + { unit: 'years', count: 1, label: 'All Time' } ]; let readings = []; let chart; -// Helper: subtract time +// Subtract helper function subtract(date, count, unit) { const d = new Date(date); switch (unit) { - case 'hours': d.setHours(d.getHours() - count); break; - case 'days': d.setDate(d.getDate() - count); break; - case 'weeks': d.setDate(d.getDate() - 7 * count); break; - case 'months': d.setMonth(d.getMonth() - count); break; - case 'years': d.setFullYear(d.getFullYear() - count);break; + case 'hours': d.setHours(d.getHours() - count); break; + case 'days': d.setDate(d.getDate() - count); break; + case 'weeks': d.setDate(d.getDate() - 7 * count); break; + case 'months': d.setMonth(d.getMonth() - count); break; + case 'years': d.setFullYear(d.getFullYear() - count); break; } return d; } -// On load document.addEventListener('DOMContentLoaded', () => { - // Grab server-injected data + // 1) Use server‐injected data const data = window.__INITIAL_READINGS__ || []; readings = data.map(r => { @@ -56,7 +56,6 @@ document.addEventListener('DOMContentLoaded', () => { }); function setupUI() { - // Slider const slider = document.getElementById('timeframe-slider'); const label = document.getElementById('timeframe-label'); slider.addEventListener('input', () => { @@ -65,35 +64,32 @@ function setupUI() { }); label.textContent = tfConfig[slider.value].label; - // Metric toggles document.getElementsByName('metric').forEach(cb => { cb.addEventListener('change', updateView); }); - // Sortable headers - document.querySelectorAll('#trends-table thead th.sortable').forEach(th => { - th.addEventListener('click', () => { - // Determine sort order - const asc = !th.classList.contains('asc'); - // Clear other indicators - document.querySelectorAll('#trends-table thead th') - .forEach(h => h.classList.remove('asc','desc')); - th.classList.add(asc ? 'asc' : 'desc'); + document.querySelectorAll('#trends-table thead th.sortable') + .forEach(th => { + th.addEventListener('click', () => { + const asc = !th.classList.contains('asc'); + document.querySelectorAll('#trends-table thead th') + .forEach(h => h.classList.remove('asc','desc')); + th.classList.add(asc ? 'asc' : 'desc'); - const idx = th.cellIndex; - const tbody = document.getElementById('trends-table-body'); - const rows = Array.from(tbody.rows); + const idx = th.cellIndex; + const tbody = document.getElementById('trends-table-body'); + const rows = Array.from(tbody.rows); - rows.sort((a, b) => { - const av = a.cells[idx].textContent; - const bv = b.cells[idx].textContent; - return asc - ? av.localeCompare(bv, undefined, { numeric: true }) - : bv.localeCompare(av, undefined, { numeric: true }); + rows.sort((a, b) => { + const av = a.cells[idx].textContent; + const bv = b.cells[idx].textContent; + return asc + ? av.localeCompare(bv, undefined, { numeric: true }) + : bv.localeCompare(av, undefined, { numeric: true }); + }); + rows.forEach(r => tbody.appendChild(r)); }); - rows.forEach(r => tbody.appendChild(r)); }); - }); } function initChart() { @@ -116,26 +112,22 @@ function initChart() { function updateView() { if (!chart) return; - // Determine 'now' based on latest reading - const maxEpoch = Math.max(...readings.map(r => r.dateObj.getTime())); - const nowDate = new Date(maxEpoch); + // Use latest reading time as “now” + const maxEpoch = readings.reduce((m, r) => Math.max(m, r.dateObj.getTime()), 0); + const now = new Date(maxEpoch); - // Compute cutoff const idx = +document.getElementById('timeframe-slider').value; const { unit, count } = tfConfig[idx]; - const cutoff = idx === 4 + const cutoff = (idx === tfConfig.length - 1) ? new Date(0) - : subtract(nowDate, count, unit); + : subtract(now, count, unit); - // Filter data const filtered = readings.filter(r => r.dateObj >= cutoff); - // Selected metrics const selected = Array.from(document.getElementsByName('metric')) .filter(cb => cb.checked) .map(cb => cb.value); - // Update chart chart.data.labels = filtered.map(r => r.formattedTs); chart.data.datasets = []; if (selected.includes('temperature')) { @@ -161,7 +153,6 @@ function updateView() { } chart.update(); - // Populate table const tbody = document.getElementById('trends-table-body'); tbody.innerHTML = ''; filtered.forEach(r => {