108 lines
2.9 KiB
Plaintext
108 lines
2.9 KiB
Plaintext
import { useState, useEffect } from 'react'
|
|
import WeatherDashboard from './components/WeatherDashboard'
|
|
import './App.css'
|
|
|
|
function App() {
|
|
const [weatherData, setWeatherData] = useState([])
|
|
const [loading, setLoading] = useState(true)
|
|
const [error, setError] = useState(null)
|
|
const [lastUpdate, setLastUpdate] = useState(null)
|
|
|
|
const fetchWeatherData = async () => {
|
|
try {
|
|
const apiUrl = import.meta.env.VITE_API_URL || '/api'
|
|
const response = await fetch(`${apiUrl}/weather/history?hours=24`)
|
|
|
|
if (!response.ok) {
|
|
throw new Error('Fehler beim Laden der Daten')
|
|
}
|
|
|
|
const data = await response.json()
|
|
setWeatherData(data)
|
|
setLastUpdate(new Date())
|
|
setError(null)
|
|
} catch (err) {
|
|
setError(err.message)
|
|
console.error('Fehler beim Laden der Wetterdaten:', err)
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
fetchWeatherData()
|
|
|
|
// Berechne Zeit bis zum nächsten 5-Min-Schritt + 1 Minute
|
|
const scheduleNextRefresh = () => {
|
|
const now = new Date()
|
|
const minutes = now.getMinutes()
|
|
const seconds = now.getSeconds()
|
|
const milliseconds = now.getMilliseconds()
|
|
|
|
// Nächster 5-Minuten-Schritt
|
|
const nextFiveMinStep = Math.ceil(minutes / 5) * 5
|
|
// Plus 1 Minute
|
|
const targetMinute = (nextFiveMinStep + 1) % 60
|
|
|
|
let targetTime = new Date(now)
|
|
targetTime.setMinutes(targetMinute, 0, 0)
|
|
|
|
// Wenn die Zielzeit in der Vergangenheit liegt, füge eine Stunde hinzu
|
|
if (targetTime <= now) {
|
|
targetTime.setHours(targetTime.getHours() + 1)
|
|
}
|
|
|
|
const timeUntilRefresh = targetTime - now
|
|
|
|
console.log(`Nächster Refresh: ${targetTime.toLocaleTimeString('de-DE')} (in ${Math.round(timeUntilRefresh / 1000)}s)`)
|
|
|
|
return setTimeout(() => {
|
|
fetchWeatherData()
|
|
scheduleNextRefresh()
|
|
}, timeUntilRefresh)
|
|
}
|
|
|
|
const timeout = scheduleNextRefresh()
|
|
|
|
return () => clearTimeout(timeout)
|
|
}, [])
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="loading-container">
|
|
<div className="loading-spinner"></div>
|
|
<p>Lade Wetterdaten...</p>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<div className="error-container">
|
|
<h2>Fehler beim Laden der Daten</h2>
|
|
<p>{error}</p>
|
|
<button onClick={fetchWeatherData}>Erneut versuchen</button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div className="app">
|
|
<header className="app-header">
|
|
<h1>🌤️ Wetterstation</h1>
|
|
{lastUpdate && (
|
|
<p className="last-update">
|
|
Letzte Aktualisierung: {lastUpdate.toLocaleTimeString('de-DE')}
|
|
</p>
|
|
)}
|
|
</header>
|
|
|
|
<main className="app-main">
|
|
<WeatherDashboard data={weatherData} />
|
|
</main>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default App
|