Raw Text Content QR Remove
mole-gecko-pig



File: assets/js/Charts.js

(async function () {
    console.log('Charts.js loaded');

    const DATA_URL = '/health-data/walking_data.json';
    const WEEK_CONTAINER_ID = 'weekly-chart';
    const YEAR_CONTAINER_ID = 'yearly-chart';

    try {
      const response = await fetch(DATA_URL);
      if (!response.ok) throw new Error(\`Fetch failed: \${response.status}\`);
      const rawData = await response.json();

      if (typeof rawData !== 'object' || Array.isArray(rawData)) throw new Error('Unexpected JSON structure');

      const entries = Object.entries(rawData)
        .filter(([date, km]) => typeof km === 'number' && km >= 0)
        .sort(([a], [b]) => a.localeCompare(b));

      if (entries.length === 0) throw new Error('No data points found');

      // ========================
      // Hilfsfunktionen
      // ========================
      function getWeekStart(date) {
        const d = new Date(date);
        const day = d.getDay();
        d.setDate(d.getDate() - (day === 0 ? 6 : day - 1)); // Montag
        return d;
      }

      function getWeekDates(startDate) {
        const dates = [];
        for (let i = 0; i < 7; i++) {
          const d = new Date(startDate);
          d.setDate(d.getDate() + i);
          dates.push(d.toISOString().slice(0, 10));
        }
        return dates;
      }

      function getWeekData(startDate) {
        return getWeekDates(startDate).map(d => rawData[d] || 0);
      }

      // ========================
      // Wochen-Chart
      // ========================
      let latestDate = entries[entries.length - 1][0];
      let currentWeekStart = getWeekStart(latestDate);

      const weeklyContainer = document.getElementById(WEEK_CONTAINER_ID);
      if (!weeklyContainer) throw new Error(\`#\${WEEK_CONTAINER_ID} not found\`);
      weeklyContainer.innerHTML = ''; // clean container

      // Navigation Pfeile
      const navContainer = document.createElement('div');
      navContainer.style.display = 'flex';
      navContainer.style.justifyContent = 'space-between';
      navContainer.style.alignItems = 'center';
      navContainer.style.marginBottom = '2px';

      const leftArrow = document.createElement('span');
      leftArrow.textContent = '◀';
      leftArrow.style.cursor = 'pointer';
      leftArrow.style.fontSize = '14px';
      leftArrow.title = 'Vorherige Woche';

      const rightArrow = document.createElement('span');
      rightArrow.textContent = '▶';
      rightArrow.style.cursor = 'pointer';
      rightArrow.style.fontSize = '14px';
      rightArrow.title = 'Nächste Woche';

      navContainer.appendChild(leftArrow);
      navContainer.appendChild(rightArrow);
      weeklyContainer.appendChild(navContainer);

      const yearTitle = document.createElement('h4');
      yearTitle.style.textAlign = 'center';
      yearTitle.style.margin = '0 0 5px 0';
      yearTitle.style.fontWeight = '400';
      yearTitle.style.fontSize = '14px';
      weeklyContainer.appendChild(yearTitle);

      const canvasWeek = document.createElement('canvas');
      canvasWeek.style.maxHeight = '180px';
      canvasWeek.style.width = '100%';
      weeklyContainer.appendChild(canvasWeek);

      let weekChart;

      function renderWeekChart(startDate) {
        const weekDates = getWeekDates(startDate);
        const weekData = getWeekData(startDate);
        const weekLabels = weekDates.map(d => {
          const dt = new Date(d);
          const weekday = dt.toLocaleDateString(undefined, { weekday: 'short' });
          const dayMonth = dt.toLocaleDateString(undefined, { day: '2-digit', month: '2-digit' });
          return \`\${weekday} \${dayMonth}\`;
        });

        yearTitle.textContent = new Date(weekDates[0]).getFullYear();

        if (weekChart) {
          weekChart.data.labels = weekLabels;
          weekChart.data.datasets[0].data = weekData;
          weekChart.update();
        } else {
          weekChart = new Chart(canvasWeek, {
            type: 'bar',
            data: {
              labels: weekLabels,
              datasets: [{
                label: 'Km pro Tag',
                data: weekData,
                backgroundColor: 'rgba(0,123,255,0.7)',
                borderRadius: 4
              }]
            },
            options: {
              responsive: true,
              maintainAspectRatio: false,
              plugins: {
                legend: { display: false },
                tooltip: { callbacks: { label: ctx => \`\${ctx.raw} km\` } }
              },
              scales: {
                y: { beginAtZero: true, ticks: { font: { size: 10 }, callback: v => v + ' km' }, grid: { drawTicks: false, color: '#eee' } },
                x: { ticks: { font: { size: 10 } }, grid: { drawTicks: false, color: '#eee' } }
              }
            }
          });
        }
      }

      renderWeekChart(currentWeekStart);

      // Pfeil-Events
      leftArrow.addEventListener('click', () => {
        currentWeekStart.setDate(currentWeekStart.getDate() - 7);
        renderWeekChart(currentWeekStart);
      });
      rightArrow.addEventListener('click', () => {
        const nextWeek = new Date(currentWeekStart);
        nextWeek.setDate(nextWeek.getDate() + 7);
        if (nextWeek <= getWeekStart(latestDate)) {
          currentWeekStart = nextWeek;
          renderWeekChart(currentWeekStart);
        }
      });

      // ========================
      // Jahres-Chart
      // ========================
      const yearContainer = document.getElementById(YEAR_CONTAINER_ID);
      if (!yearContainer) throw new Error(\`#\${YEAR_CONTAINER_ID} not found\`);
      yearContainer.innerHTML = '';

      const canvasYear = document.createElement('canvas');
      canvasYear.style.maxHeight = '120px';
      canvasYear.style.width = '100%';
      yearContainer.appendChild(canvasYear);

      const yearlySums = {};
      for (const [date, km] of entries) {
        const year = date.slice(0, 4);
        yearlySums[year] = (yearlySums[year] || 0) + km;
      }

      const years = Object.keys(yearlySums).sort();
      const yearValues = years.map(y => Math.round(yearlySums[y] * 100) / 100);

      new Chart(canvasYear, {
        type: 'bar',
        data: { labels: years, datasets: [{ label: 'Km pro Jahr', data: yearValues, backgroundColor: 'rgba(40,167,69,0.7)', borderRadius: 4 }] },
        options: {
          responsive: true,
          maintainAspectRatio: false,
          plugins: { legend: { display: false } },
          scales: {
            y: { beginAtZero: true, ticks: { font: { size: 10 }, callback: v => v + ' km' }, grid: { drawTicks: false, color: '#eee' } },
            x: { ticks: { font: { size: 10 } }, grid: { drawTicks: false, color: '#eee' } }
          }
        }
      });

    } catch (err) {
      console.error('Health chart error:', err);
    }
  })();

Read 14 times, last 108 minutes ago


WE LOVE YOU