From 8780fb2ea4d6ac87dfa562517457ef75aea02e6e Mon Sep 17 00:00:00 2001 From: JoshBaneyCS Date: Wed, 30 Apr 2025 02:29:04 +0000 Subject: [PATCH] Update public/scripts/trends.js --- public/scripts/trends.js | 78 +++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 41 deletions(-) diff --git a/public/scripts/trends.js b/public/scripts/trends.js index 0956ab9..4808997 100644 --- a/public/scripts/trends.js +++ b/public/scripts/trends.js @@ -1,52 +1,53 @@ // public/scripts/trends.js -// ─── Timeframe options ─────────────────────────────────────────────────────── +// ─── Timeframes ────────────────────────────────────────────────────────────── 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' } ]; // ─── Helpers ───────────────────────────────────────────────────────────────── function formatESTTimestamp(ts) { + // ts is "YYYY-MM-DD HH:mm:ss" in Eastern time const [date, time] = ts.split(' '); - const [Y, M, D] = date.split('-').map(n=>parseInt(n,10)); + const [Y, M, D] = date.split('-').map(Number); const [h, m] = time.split(':'); return `${M}/${D}/${String(Y).slice(-2)} @${h.padStart(2,'0')}:${m}`; } function parseLocalDate(ts) { const [date, time] = ts.split(' '); - const [Y, M, D] = date.split('-').map(n=>parseInt(n,10)); - const [h, m, s] = time.split(':').map(n=>parseInt(n,10)); + const [Y, M, D] = date.split('-').map(Number); + const [h, m, s] = time.split(':').map(Number); return new Date(Y, M-1, D, h, m, s); } 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 '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; } -// ─── State & Chart Ref ─────────────────────────────────────────────────────── +// ─── State ──────────────────────────────────────────────────────────────────── let readings = []; let chart; -// ─── On Load ───────────────────────────────────────────────────────────────── -document.addEventListener('DOMContentLoaded', async() => { +// ─── Init ───────────────────────────────────────────────────────────────────── +document.addEventListener('DOMContentLoaded', async () => { await loadReadings(); setupUI(); initChart(); updateView(); }); -// ─── Load & parse readings ─────────────────────────────────────────────────── +// ─── Load readings ──────────────────────────────────────────────────────────── async function loadReadings() { const data = await fetch('/api/readings').then(r=>r.json()); readings = data.map(r => ({ @@ -56,9 +57,8 @@ async function loadReadings() { })); } -// ─── UI wiring ─────────────────────────────────────────────────────────────── +// ─── UI Wiring ──────────────────────────────────────────────────────────────── function setupUI() { - // timeframe slider const slider = document.getElementById('timeframe-slider'); const label = document.getElementById('timeframe-label'); slider.addEventListener('input', ()=>{ @@ -67,12 +67,10 @@ function setupUI() { }); label.textContent = tfConfig[slider.value].label; - // metric toggles - document.getElementsByName('metric').forEach(cb => { + document.getElementsByName('metric').forEach(cb=>{ cb.addEventListener('change', updateView); }); - // table sorting document.querySelectorAll('#trends-table thead th.sortable').forEach(th=>{ th.addEventListener('click', ()=>{ const idx = th.cellIndex; @@ -80,43 +78,41 @@ function setupUI() { 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}); + ? a.cells[idx].textContent.localeCompare(b.cells[idx].textContent,undefined,{numeric:true}) + : b.cells[idx].textContent.localeCompare(a.cells[idx].textContent,undefined,{numeric:true}); }); - th.classList.toggle('asc', asc); + th.classList.toggle('asc',asc); rows.forEach(r=>tbody.appendChild(r)); }); }); } -// ─── Chart.js setup ────────────────────────────────────────────────────────── +// ─── Chart Setup ────────────────────────────────────────────────────────────── function initChart() { const ctx = document.getElementById('trend-chart').getContext('2d'); chart = new Chart(ctx, { - type: 'line', - data: { labels: [], datasets: [] }, - options: { - scales: { - x: { title: { display:true, text:'Time (EST)' } }, - y: { title: { display:true, text:'Value' } } + type:'line', + data:{ labels:[], datasets:[] }, + options:{ + scales:{ + x:{ title:{display:true,text:'Time (EST)'} }, + y:{ title:{display:true,text:'Value'} } }, - interaction: { mode:'index', intersect:false }, - plugins: { legend:{ position:'top' } }, + interaction:{mode:'index',intersect:false}, + plugins:{legend:{position:'top'}}, maintainAspectRatio:false } }); } -// ─── Render chart & table ─────────────────────────────────────────────────── +// ─── Render ─────────────────────────────────────────────────────────────────── function updateView() { const idx = +document.getElementById('timeframe-slider').value; const { unit, count } = tfConfig[idx]; const cutoff = subtract(new Date(), count, unit); - const filtered = readings.filter(r => r.dateObj >= cutoff); + const filtered = readings.filter(r=>r.dateObj >= cutoff); const selected = Array.from(document.getElementsByName('metric')) .filter(cb=>cb.checked).map(cb=>cb.value); @@ -133,14 +129,14 @@ function updateView() { datasets.push({ label:'Heat Index (°F)', data:filtered.map(r=>r.heatIndex), tension:0.3 }); } - chart.data.labels = labels; - chart.data.datasets = datasets; + chart.data.labels = labels; + chart.data.datasets = datasets; chart.update(); populateTable(filtered); } -// ─── Populate the table ───────────────────────────────────────────────────── +// ─── Table ─────────────────────────────────────────────────────────────────── function populateTable(data) { const tbody = document.getElementById('trends-table-body'); tbody.innerHTML = '';