From 9754ffabaac4c6e73d6641de18b1a23ffb6e2842 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20X=2E=20F=C3=BCrst?= Date: Mon, 1 Jun 2026 18:26:16 +0200 Subject: [PATCH] V 1.6.1 fix: X-Achsen-Beschriftung verbessert (24h/7d/30d/365d) 24h: Mitternacht als DD.MM (blau), sonst HH:MM per tickPositioner. 7d: nur bei 0-Uhr beschriftet, waagerecht. 30d: alle 5 Tage. 365d: nur Monatsnummer (MM), monatliche Ticks. Co-Authored-By: Claude Sonnet 4.6 --- frontend/package.json | 2 +- frontend/src/components/WeatherDashboard.jsx | 100 +++++++++++++++++-- 2 files changed, 92 insertions(+), 10 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 77373c2..810d1e2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "wetterstation-frontend", "private": true, - "version": "1.6.0", + "version": "1.6.1", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/WeatherDashboard.jsx b/frontend/src/components/WeatherDashboard.jsx index 1d94239..4bf070b 100644 --- a/frontend/src/components/WeatherDashboard.jsx +++ b/frontend/src/components/WeatherDashboard.jsx @@ -291,30 +291,93 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = ' } } else { // Vordefinierte Bereiche + const pad = n => String(n).padStart(2, '0') + const fmtDate = d => `${pad(d.getDate())}.${pad(d.getMonth() + 1)}` + const fmtTime = d => `${pad(d.getHours())}:${pad(d.getMinutes())}` + switch (timeRange) { case '24h': - xAxisConfig.tickInterval = 4 * 3600 * 1000 // 4 Stunden - xAxisConfig.labels = { format: '{value:%H:%M}', align: 'center' } + xAxisConfig.tickPositioner = function() { + const positions = [] + const d = new Date(this.min) + d.setMinutes(0, 0, 0) + const h = d.getHours() + const nextH = Math.ceil(h / 4) * 4 + if (nextH >= 24) { d.setDate(d.getDate() + 1); d.setHours(0, 0, 0, 0) } + else d.setHours(nextH, 0, 0, 0) + while (d.getTime() <= this.max) { + positions.push(d.getTime()) + d.setHours(d.getHours() + 4, 0, 0, 0) + } + return positions + } + xAxisConfig.labels = { + rotation: 0, align: 'center', useHTML: true, + formatter: function() { + const d = new Date(this.value) + return d.getHours() === 0 && d.getMinutes() === 0 + ? `${fmtDate(d)}` + : fmtTime(d) + } + } xAxisMin = now - 24 * 3600 * 1000 xAxisMax = now tooltipDateFormat = '%d.%m.%Y %H:%M' break case '7d': - xAxisConfig.labels = { format: '{value:%d.%m}', align: 'center' } + xAxisConfig.tickPositioner = function() { + const positions = [] + const d = new Date(this.min) + d.setHours(0, 0, 0, 0) + while (d.getTime() <= this.max) { + positions.push(d.getTime()) + d.setDate(d.getDate() + 1) + } + return positions + } + xAxisConfig.labels = { + rotation: 0, align: 'center', + formatter: function() { return fmtDate(new Date(this.value)) } + } xAxisMin = now - 7 * 24 * 3600 * 1000 xAxisMax = now tooltipDateFormat = '%d.%m.%Y' break case '30d': - xAxisConfig.labels = { format: '{value:%d.%m}', align: 'center' } + xAxisConfig.tickPositioner = function() { + const positions = [] + const d = new Date(this.min) + d.setHours(0, 0, 0, 0) + while (d.getTime() <= this.max) { + positions.push(d.getTime()) + d.setDate(d.getDate() + 5) + } + return positions + } + xAxisConfig.labels = { + rotation: 0, align: 'center', + formatter: function() { return fmtDate(new Date(this.value)) } + } xAxisMin = now - 30 * 24 * 3600 * 1000 xAxisMax = now tooltipDateFormat = '%d.%m.%Y' break case '365d': - xAxisConfig.labels = { format: '{value:%b %Y}', align: 'center' } - tooltipDateFormat = '%b %Y' - // Bei 365d: Min/Max aus vorhandenen Daten berechnen + xAxisConfig.tickPositioner = function() { + const positions = [] + const d = new Date(this.min) + d.setDate(1); d.setHours(0, 0, 0, 0) + while (d.getTime() <= this.max) { + positions.push(d.getTime()) + d.setMonth(d.getMonth() + 1) + } + return positions + } + xAxisConfig.labels = { + rotation: 0, align: 'center', + formatter: function() { return pad(new Date(this.value).getMonth() + 1) } + } + tooltipDateFormat = '%d.%m.%Y' if (sortedData.length > 0) { xAxisMin = new Date(sortedData[0].datetime).getTime() xAxisMax = new Date(sortedData[sortedData.length - 1].datetime).getTime() @@ -324,8 +387,27 @@ const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = ' } break default: - xAxisConfig.tickInterval = 4 * 3600 * 1000 - xAxisConfig.labels = { format: '{value:%H:%M}', align: 'center' } + xAxisConfig.tickPositioner = function() { + const positions = [] + const d = new Date(this.min) + d.setMinutes(0, 0, 0) + const h = d.getHours() + const nextH = Math.ceil(h / 4) * 4 + if (nextH >= 24) { d.setDate(d.getDate() + 1); d.setHours(0, 0, 0, 0) } + else d.setHours(nextH, 0, 0, 0) + while (d.getTime() <= this.max) { + positions.push(d.getTime()) + d.setHours(d.getHours() + 4, 0, 0, 0) + } + return positions + } + xAxisConfig.labels = { + rotation: 0, align: 'center', + formatter: function() { + const d = new Date(this.value) + return d.getHours() === 0 && d.getMinutes() === 0 ? fmtDate(d) : fmtTime(d) + } + } xAxisMin = now - 24 * 3600 * 1000 xAxisMax = now tooltipDateFormat = '%d.%m.%Y %H:%M'