diff --git a/frontend/package.json b/frontend/package.json index 85f5b49..35e66da 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "wetterstation-frontend", "private": true, - "version": "1.1.0", + "version": "1.2.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 4d04010..a4dd92a 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -4,6 +4,7 @@ import './App.css' function App() { const [weatherData, setWeatherData] = useState([]) + const [currentWeatherData, setCurrentWeatherData] = useState([]) // Immer die aktuellen 24h-Werte const [rainData, setRainData] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) @@ -18,6 +19,7 @@ function App() { // Prüfe ob eingebettete Daten vorhanden sind (statischer Build) if (window.__WEATHER_DATA__ && timeRange === '24h') { setWeatherData(window.__WEATHER_DATA__) + setCurrentWeatherData(window.__WEATHER_DATA__) setRainData([]) setLastUpdate(new Date()) setLoading(false) @@ -58,6 +60,18 @@ function App() { const weatherDataResult = await weatherResponse.json() setWeatherData(weatherDataResult) + // Immer die aktuellen 24h-Daten für "Aktuell"-Anzeige laden + if (timeRange !== '24h') { + const currentUrl = `${baseUrl}/weather/history?hours=24` + const currentResponse = await fetch(currentUrl) + if (currentResponse.ok) { + const currentDataResult = await currentResponse.json() + setCurrentWeatherData(currentDataResult) + } + } else { + setCurrentWeatherData(weatherDataResult) + } + // Regendaten laden (falls separater Endpunkt) if (rainUrl) { const rainResponse = await fetch(rainUrl) @@ -138,6 +152,7 @@ function App() {
{ +const WeatherDashboard = ({ data, currentData = [], rainData = [], timeRange = '24h', onTimeRangeChange }) => { // Daten vorbereiten und nach Zeit sortieren (älteste zuerst) const sortedData = useMemo(() => { return [...data].sort((a, b) => new Date(a.datetime) - new Date(b.datetime)) }, [data]) + // Aktuelle Werte aus separaten currentData (immer 24h) + const sortedCurrentData = useMemo(() => { + return [...currentData].sort((a, b) => new Date(a.datetime) - new Date(b.datetime)) + }, [currentData]) + // Zeitraum-Label const timeRangeLabel = useMemo(() => { switch (timeRange) { @@ -118,7 +123,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC tooltip: { shared: true, crosshairs: true, - xDateFormat: timeRange === '24h' ? '%d.%m.%Y %H:%M' : '%d.%m.%Y' + xDateFormat: timeRange === '24h' ? '%d.%m.%Y %H:%M' : (timeRange === '7d' || timeRange === '30d' ? '%d.%m.%Y - %Hh' : '%d.%m.%Y') }, plotOptions: { series: { @@ -160,7 +165,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC ...getCommonOptions(), yAxis: { ...getCommonOptions().yAxis, - title: { text: 'Temperatur (°C)' }, + title: { text: null }, min: yMin, max: yMax }, @@ -181,6 +186,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 1, valueSuffix: ' °C' } }] @@ -192,7 +198,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC ...getCommonOptions(), yAxis: { ...getCommonOptions().yAxis, - title: { text: 'Feuchte (%)' }, + title: { text: null }, min: 40, max: 100 }, @@ -212,6 +218,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 0, valueSuffix: ' %' } }] @@ -237,7 +244,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC ...getCommonOptions(), yAxis: { ...getCommonOptions().yAxis, - title: { text: 'Luftdruck (hPa)' }, + title: { text: null }, min: yMin, max: yMax }, @@ -257,6 +264,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 0, valueSuffix: ' hPa' } }] @@ -320,7 +328,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC ...getCommonOptions(), yAxis: { ...getCommonOptions().yAxis, - title: { text: yAxisTitle } + title: { text: null } }, series } @@ -342,6 +350,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 1, valueSuffix: ' km/h' } }] @@ -357,6 +366,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 1, valueSuffix: ' km/h' } }, { @@ -371,6 +381,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC gapSize: 2 * 24 * 3600 * 1000, gapUnit: 'value', tooltip: { + valueDecimals: 1, valueSuffix: ' km/h' } }] @@ -390,12 +401,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC }, yAxis: { ...getCommonOptions().yAxis, - title: { - text: 'Windspeed (km/h)', - style: { - whiteSpace: 'nowrap' - } - } + title: { text: null } }, series } @@ -404,6 +410,13 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC // Windrichtung Chart const windDirOptions = useMemo(() => ({ ...getCommonOptions(), + tooltip: { + formatter: function() { + const dateFormat = timeRange === '24h' ? '%d.%m.%Y %H:%M' : (timeRange === '7d' || timeRange === '30d' ? '%d.%m.%Y - %Hh' : '%d.%m.%Y') + const dateStr = Highcharts.dateFormat(dateFormat, this.x) + return `${dateStr}
\u25CF ${this.series.name}: ${this.y.toFixed(0)}°` + } + }, plotOptions: { scatter: { marker: { @@ -420,7 +433,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC }, yAxis: { ...getCommonOptions().yAxis, - title: { text: 'Windrichtung' }, + title: { text: null }, min: 0, max: 360, tickInterval: 45, @@ -438,15 +451,12 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC name: 'Windrichtung', data: sortedData.filter(item => item.wind_dir != null).map(item => [new Date(item.datetime).getTime(), item.wind_dir]), color: 'rgb(54, 162, 235)', - type: 'scatter', - tooltip: { - valueSuffix: ' °' - } + type: 'scatter' }] - }), [sortedData]) + }), [sortedData, timeRange]) - // Aktuellste Werte für Übersicht - const current = sortedData[sortedData.length - 1] || {} + // Aktuellste Werte für Übersicht (immer aus den 24h-Daten, Fallback auf sortedData) + const current = (sortedCurrentData.length > 0 ? sortedCurrentData[sortedCurrentData.length - 1] : sortedData[sortedData.length - 1]) || {} // Berechne Min/Max für den gewählten Zeitraum const periodStats = useMemo(() => { @@ -512,25 +522,29 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC className={timeRange === '24h' ? 'active' : ''} onClick={() => onTimeRangeChange('24h')} > - 24 Stunden + 24 Stunden + 24h @@ -541,57 +555,77 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC {/* Charts Grid */}
-
-

🌡️ Temperatur{aggregationSuffix} - Aktuell: {current.temperature?.toFixed(1) || '-'}°C

-
- -
-
- Min: {periodStats.minTemp?.toFixed(1) || '-'}°C ({periodStats.minTempTime || '-'}) | Max: {periodStats.maxTemp?.toFixed(1) || '-'}°C ({periodStats.maxTempTime || '-'}) +
+
Aktuell: {current.temperature?.toFixed(1) || '-'}°C
+
+

🌡️ Temperatur{aggregationSuffix}[°C]

+
+ +
+
+ Min: {periodStats.minTemp?.toFixed(1) || '-'}°C ({periodStats.minTempTime || '-'}) | Max: {periodStats.maxTemp?.toFixed(1) || '-'}°C ({periodStats.maxTempTime || '-'}) +
-
-

🌐 Luftdruck{aggregationSuffix} - Aktuell: {current.pressure?.toFixed(1) || '-'} hPa

-
- -
-
- Min: {periodStats.minPressure?.toFixed(1) || '-'} hPa ({periodStats.minPressureTime || '-'}) | Max: {periodStats.maxPressure?.toFixed(1) || '-'} hPa ({periodStats.maxPressureTime || '-'}) +
+
Aktuell: {current.pressure?.toFixed(0) || '-'} hPa
+
+

🌐 Luftdruck{aggregationSuffix}[hPa]

+
+ +
+
+ Min: {periodStats.minPressure?.toFixed(0) || '-'} hPa ({periodStats.minPressureTime || '-'}) | Max: {periodStats.maxPressure?.toFixed(0) || '-'} hPa ({periodStats.maxPressureTime || '-'}) +
-
-

💧 Luftfeuchtigkeit{aggregationSuffix} - Aktuell: {current.humidity || '-'}%

-
- -
-
- Min: {periodStats.minHumidity || '-'}% ({periodStats.minHumidityTime || '-'}) | Max: {periodStats.maxHumidity || '-'}% ({periodStats.maxHumidityTime || '-'}) +
+
Aktuell: {current.humidity || '-'}%
+
+

💧 Luftfeuchtigkeit{aggregationSuffix}[%]

+
+ +
+
+ Min: {periodStats.minHumidity || '-'}% ({periodStats.minHumidityTime || '-'}) | Max: {periodStats.maxHumidity || '-'}% ({periodStats.maxHumidityTime || '-'}) +
-
-

🌧️ Regen{aggregationSuffix} - Aktuell: {current.rain?.toFixed(1) || '-'} mm

-
- +
+
Aktuell: {current.rain?.toFixed(1) || '-'} mm
+
+

🌧️ Regen{aggregationSuffix}[mm]

+
+ +
+
 
-
-

🧭 Windrichtung{aggregationSuffix} - Aktuell: {current.wind_dir ?? '-'}°

-
- +
+
Aktuell: {current.wind_dir ?? '-'}°
+
+

🧭 Windrichtung{aggregationSuffix}[°]

+
+ +
+
 
-
-

💨 Windspeed{aggregationSuffix} - Aktuell: {current.wind_speed?.toFixed(1) || '-'} km/h

-
- -
-
- Max: {periodStats.maxWindGust?.toFixed(1) || '-'} km/h ({periodStats.maxWindGustTime || '-'}) +
+
Aktuell: {current.wind_speed?.toFixed(1) || '-'} km/h
+
+

💨 Windspeed{aggregationSuffix}[km/h]

+
+ +
+
+ Max: {periodStats.maxWindGust?.toFixed(1) || '-'} km/h ({periodStats.maxWindGustTime || '-'}) +
@@ -610,7 +644,7 @@ const WeatherDashboard = ({ data, rainData = [], timeRange = '24h', onTimeRangeC {' '}{version} – {buildDate}
-
+
Daten-Erfassung mit einer Davis VantagePro.
Grafiken erzeugt mit HighCharts