import { useState, useEffect } from "react"; import { Cloud, Sun, CloudRain, CloudSnow, CloudLightning, CloudDrizzle, Wind, Droplets, Thermometer, MapPin } from "lucide-react"; interface WeatherData { temperature: number; weatherCode: number; windSpeed: number; humidity: number; city: string; } function getWeatherIcon(code: number) { if (code === 0 || code === 1) return ; if (code === 2 || code === 3) return ; if (code >= 51 && code <= 57) return ; if (code >= 61 && code <= 67) return ; if (code >= 71 && code <= 77) return ; if (code >= 80 && code <= 82) return ; if (code >= 95) return ; return ; } function getWeatherText(code: number): string { if (code === 0) return "Klar"; if (code === 1) return "Überwiegend klar"; if (code === 2) return "Teilweise bewölkt"; if (code === 3) return "Bewölkt"; if (code >= 51 && code <= 57) return "Nieselregen"; if (code >= 61 && code <= 65) return "Regen"; if (code === 66 || code === 67) return "Gefrierender Regen"; if (code >= 71 && code <= 75) return "Schneefall"; if (code === 77) return "Schneegriesel"; if (code >= 80 && code <= 82) return "Regenschauer"; if (code === 85 || code === 86) return "Schneeschauer"; if (code >= 95) return "Gewitter"; return "Unbekannt"; } async function reverseGeocode(lat: number, lon: number): Promise { try { const res = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lon}&format=json&zoom=10&accept-language=de`); const data = await res.json(); return data.address?.city || data.address?.town || data.address?.village || data.address?.municipality || "Unbekannt"; } catch { return "Unbekannt"; } } export function WeatherWidget() { const [weather, setWeather] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(false); useEffect(() => { const defaultLat = 46.55; const defaultLon = 14.55; const defaultCity = "Klagenfurt"; async function fetchWeather(lat: number, lon: number, city: string) { try { const res = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,weather_code,wind_speed_10m,relative_humidity_2m&timezone=auto` ); const data = await res.json(); setWeather({ temperature: Math.round(data.current.temperature_2m), weatherCode: data.current.weather_code, windSpeed: Math.round(data.current.wind_speed_10m), humidity: data.current.relative_humidity_2m, city, }); } catch { setError(true); } finally { setLoading(false); } } async function getLocationByIP() { try { const res = await fetch("https://ipapi.co/json/"); const data = await res.json(); if (data.latitude && data.longitude) { const city = data.city || await reverseGeocode(data.latitude, data.longitude); fetchWeather(data.latitude, data.longitude, city); } else { fetchWeather(defaultLat, defaultLon, defaultCity); } } catch { fetchWeather(defaultLat, defaultLon, defaultCity); } } getLocationByIP(); }, []); if (loading) { return (

Wetter

); } if (error || !weather) return null; return (
{getWeatherIcon(weather.weatherCode)}
{weather.temperature}°C {getWeatherText(weather.weatherCode)}
{weather.city} {weather.windSpeed} km/h {weather.humidity}%
); } export function SidebarWeatherWidget() { const [weather, setWeather] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { const defaultLat = 46.55; const defaultLon = 14.55; const defaultCity = "Klagenfurt"; async function fetchWeather(lat: number, lon: number, city: string) { try { const res = await fetch( `https://api.open-meteo.com/v1/forecast?latitude=${lat}&longitude=${lon}¤t=temperature_2m,weather_code,wind_speed_10m,relative_humidity_2m&daily=temperature_2m_max,temperature_2m_min,weather_code&timezone=auto&forecast_days=3` ); const data = await res.json(); setWeather({ temperature: Math.round(data.current.temperature_2m), weatherCode: data.current.weather_code, windSpeed: Math.round(data.current.wind_speed_10m), humidity: data.current.relative_humidity_2m, city, }); setForecast(data.daily ? data.daily.time.slice(1, 3).map((d: string, i: number) => ({ day: new Date(d).toLocaleDateString("de-DE", { weekday: "short" }), high: Math.round(data.daily.temperature_2m_max[i + 1]), low: Math.round(data.daily.temperature_2m_min[i + 1]), code: data.daily.weather_code[i + 1], })) : []); } catch { } finally { setLoading(false); } } async function getLocationByIP() { try { const res = await fetch("https://ipapi.co/json/"); const ipData = await res.json(); if (ipData.latitude && ipData.longitude) { fetchWeather(ipData.latitude, ipData.longitude, ipData.city || "Unbekannt"); } else { fetchWeather(defaultLat, defaultLon, defaultCity); } } catch { fetchWeather(defaultLat, defaultLon, defaultCity); } } if (navigator.geolocation) { navigator.geolocation.getCurrentPosition( async (pos) => { try { const res = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${pos.coords.latitude}&lon=${pos.coords.longitude}&format=json&accept-language=de`); const geo = await res.json(); const city = geo.address?.city || geo.address?.town || geo.address?.village || "Unbekannt"; fetchWeather(pos.coords.latitude, pos.coords.longitude, city); } catch { fetchWeather(pos.coords.latitude, pos.coords.longitude, "Unbekannt"); } }, () => { getLocationByIP(); }, { timeout: 5000 } ); } else { getLocationByIP(); } }, []); const [forecast, setForecast] = useState<{ day: string; high: number; low: number; code: number }[]>([]); if (loading) { return (
); } if (!weather) return null; return (
{weather.city}
{new Date().toLocaleDateString("de-DE", { weekday: "short", day: "numeric", month: "short" })}
{getWeatherIcon(weather.weatherCode)}
{weather.temperature}°
{getWeatherText(weather.weatherCode)}
{weather.windSpeed} km/h {weather.humidity}%
{forecast.length > 0 && (
{forecast.map((f) => (
{f.day}
{getWeatherIcon(f.code)}
{f.high}°
{f.low}°
))}
)}
); }