Преглед на файлове

Add stats module with bar chart rendering

k4be преди 7 часа
родител
ревизия
b857d128b6
променени са 1 файла, в които са добавени 98 реда и са изтрити 0 реда
  1. 98 0
      gpx-vis-frontend/js/stats.js

+ 98 - 0
gpx-vis-frontend/js/stats.js

@@ -0,0 +1,98 @@
+const Stats = (() => {
+  async function init() {
+    await loadStats();
+  }
+
+  async function loadStats() {
+    const content = document.getElementById('stats-content');
+    content.innerHTML = '<div class="loading">Loading stats...</div>';
+
+    try {
+      const stats = await API.getStats();
+      renderStats(stats);
+    } catch (e) {
+      content.innerHTML = '<div class="error-msg">Error loading stats: ' + escHtml(e.message) + '</div>';
+    }
+  }
+
+  function renderStats(stats) {
+    const content = document.getElementById('stats-content');
+    let html = '';
+
+    // Summary totals
+    if (stats.total !== undefined || stats.totalDistance !== undefined) {
+      const totalDist = stats.total?.distance || stats.totalDistance || 0;
+      const totalTracks = stats.total?.count || stats.trackCount || 0;
+      html += `<div class="stats-section">
+        <h3>Total</h3>
+        <div class="stat-row">
+          <span class="stat-label">Tracks</span>
+          <div class="stat-bar-wrap"><div class="stat-bar" style="width:100%"></div></div>
+          <span class="stat-value">${totalTracks}</span>
+        </div>
+        <div class="stat-row">
+          <span class="stat-label">Distance</span>
+          <div class="stat-bar-wrap"><div class="stat-bar" style="width:100%"></div></div>
+          <span class="stat-value">${formatDistance(totalDist)}</span>
+        </div>
+      </div>`;
+    }
+
+    // By year
+    if (stats.byYear && stats.byYear.length > 0) {
+      const maxDist = Math.max(...stats.byYear.map(s => s.distance || 0));
+      html += '<div class="stats-section"><h3>By Year</h3>';
+      for (const s of stats.byYear) {
+        const pct = maxDist > 0 ? ((s.distance || 0) / maxDist * 100) : 0;
+        html += `<div class="stat-row">
+          <span class="stat-label">${s.year}</span>
+          <div class="stat-bar-wrap"><div class="stat-bar" style="width:${pct.toFixed(1)}%"></div></div>
+          <span class="stat-value">${formatDistance(s.distance)}</span>
+        </div>`;
+      }
+      html += '</div>';
+    }
+
+    // By month (last 24 months)
+    if (stats.byMonth && stats.byMonth.length > 0) {
+      const recent = stats.byMonth.slice(-24);
+      const maxDist = Math.max(...recent.map(s => s.distance || 0));
+      html += '<div class="stats-section"><h3>By Month (last 24)</h3>';
+      for (const s of recent) {
+        const pct = maxDist > 0 ? ((s.distance || 0) / maxDist * 100) : 0;
+        const label = `${s.year}-${String(s.month).padStart(2, '0')}`;
+        html += `<div class="stat-row">
+          <span class="stat-label">${label}</span>
+          <div class="stat-bar-wrap"><div class="stat-bar" style="width:${pct.toFixed(1)}%"></div></div>
+          <span class="stat-value">${formatDistance(s.distance)}</span>
+        </div>`;
+      }
+      html += '</div>';
+    }
+
+    // By week (last 52 weeks)
+    if (stats.byWeek && stats.byWeek.length > 0) {
+      const recent = stats.byWeek.slice(-52);
+      const maxDist = Math.max(...recent.map(s => s.distance || 0));
+      html += '<div class="stats-section"><h3>By Week (last 52)</h3>';
+      for (const s of recent) {
+        const pct = maxDist > 0 ? ((s.distance || 0) / maxDist * 100) : 0;
+        const label = `${s.year}-W${String(s.week).padStart(2, '0')}`;
+        html += `<div class="stat-row">
+          <span class="stat-label">${label}</span>
+          <div class="stat-bar-wrap"><div class="stat-bar" style="width:${pct.toFixed(1)}%"></div></div>
+          <span class="stat-value">${formatDistance(s.distance)}</span>
+        </div>`;
+      }
+      html += '</div>';
+    }
+
+    if (!html) {
+      html = '<div class="empty-list">No tracks yet. Upload some GPX files to see stats.</div>';
+    }
+
+    content.innerHTML = html;
+  }
+
+  return { init, loadStats };
+})();