import { useState, useEffect } from 'react' import { Sun, Cloud, CloudRain, CloudSnow, CloudDrizzle, CloudLightning, Wind } from 'lucide-react' import { fetchWeather } from '../../services/weatherQueue' import { useSettingsStore } from '../../store/settingsStore' const WEATHER_ICON_MAP = { Clear: Sun, Clouds: Cloud, Rain: CloudRain, Drizzle: CloudDrizzle, Thunderstorm: CloudLightning, Snow: CloudSnow, Mist: Wind, Fog: Wind, Haze: Wind, } interface WeatherIconProps { main: string size?: number } function WeatherIcon({ main, size = 13 }: WeatherIconProps) { const Icon = WEATHER_ICON_MAP[main] || Cloud return } function getWeatherCache(key) { try { const raw = sessionStorage.getItem(key) if (raw === null) return undefined return JSON.parse(raw) } catch { return undefined } } function setWeatherCache(key, value) { try { sessionStorage.setItem(key, JSON.stringify(value)) } catch {} } interface WeatherWidgetProps { lat: number | null lng: number | null date: string compact?: boolean /** Vertical icon-over-temp layout that inherits its color (for the day badge). */ stacked?: boolean } export default function WeatherWidget({ lat, lng, date, compact = false, stacked = false }: WeatherWidgetProps) { const [weather, setWeather] = useState(null) const [loading, setLoading] = useState(false) const [failed, setFailed] = useState(false) const isFahrenheit = useSettingsStore(s => s.settings.temperature_unit) === 'fahrenheit' useEffect(() => { if (!lat || !lng || !date) return const rLat = Math.round(lat * 100) / 100 const rLng = Math.round(lng * 100) / 100 const cacheKey = `weather_${rLat}_${rLng}_${date}` const cached = getWeatherCache(cacheKey) if (cached !== undefined) { if (cached === null) setFailed(true) // Climate data: use from cache but re-fetch in background to upgrade to forecast else if (cached.type === 'climate') { setWeather(cached) fetchWeather(lat, lng, date) .then(data => { if (!data.error && data.temp !== undefined && data.type === 'forecast') { setWeatherCache(cacheKey, data) setWeather(data) } }) .catch(() => {}) return } else { setWeather(cached) return } return } setLoading(true) fetchWeather(lat, lng, date) .then(data => { if (data.error || data.temp === undefined) { setFailed(true) } else { setWeatherCache(cacheKey, data) setWeather(data) } }) .catch(() => { setFailed(true) }) .finally(() => setLoading(false)) }, [lat, lng, date]) if (!lat || !lng) return null const fontStyle = { fontFamily: "var(--font-system)" } if (loading) { return ( ) } if (failed || !weather) { return ( ) } const rawTemp = weather.temp const temp = rawTemp !== undefined ? Math.round(isFahrenheit ? rawTemp * 9/5 + 32 : rawTemp) : null const unit = isFahrenheit ? '°F' : '°C' const isClimate = weather.type === 'climate' if (stacked) { return (
{temp !== null && {isClimate ? 'Ø' : ''}{temp}°}
) } if (compact) { return ( {temp !== null && {isClimate ? 'Ø ' : ''}{temp}{unit}} ) } return (
{temp !== null && {isClimate ? 'Ø ' : ''}{temp}{unit}} {weather.description && {weather.description}}
) }