import React, { useState, useEffect } from 'react'; import { UmbrellaIcon, SnowflakeIcon, SunIcon, WindIcon, AlertTriangleIcon } from '../components/icons'; import { useLocalStorage } from '../hooks/useLocalStorage'; import type { BonsaiTree } from '../types'; import Spinner from '../components/Spinner'; interface WeatherData { daily: { time: string[]; weathercode: number[]; temperature_2m_max: number[]; temperature_2m_min: number[]; windspeed_10m_max: number[]; }; } const WeatherShieldView: React.FC = () => { const [trees] = useLocalStorage('bonsai-diary-trees', []); const [weather, setWeather] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(''); useEffect(() => { const fetchWeather = async () => { if (trees.length === 0) { setIsLoading(false); return; } // For simplicity, use the location of the first tree as the primary location const primaryLocation = trees[0].location; if (!primaryLocation) { setError("No location set for your trees. Please add a location in 'My Garden'."); setIsLoading(false); return; } try { // Simple geocoding using a public API const geoResponse = await fetch(`https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(primaryLocation)}&count=1`); const geoData = await geoResponse.json(); if (!geoData.results || geoData.results.length === 0) { throw new Error(`Could not find location: ${primaryLocation}`); } const { latitude, longitude } = geoData.results[0]; // Fetch weather forecast const weatherResponse = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min,windspeed_10m_max&timezone=auto`); const weatherData = await weatherResponse.json(); setWeather(weatherData); } catch (err) { if (err instanceof Error) { setError(`Failed to fetch weather data: ${err.message}`); } else { setError("An unknown error occurred while fetching weather data."); } } finally { setIsLoading(false); } }; fetchWeather(); }, [trees]); const getWeatherIcon = (code: number) => { if (code >= 200 && code < 600) return ; // Rain if (code >= 600 && code < 700) return ; // Snow if (code === 800) return ; // Clear return ; // Default/Clouds }; const generateAlertsForTree = (tree: BonsaiTree) => { if (!weather || !tree.protectionProfile || !tree.protectionProfile.alertsEnabled) return []; const alerts: string[] = []; weather.daily.time.slice(0, 5).forEach((_, i) => { const dayMinTemp = weather.daily.temperature_2m_min[i]; const dayMaxTemp = weather.daily.temperature_2m_max[i]; const dayMaxWind = weather.daily.windspeed_10m_max[i]; if (dayMinTemp < tree.protectionProfile!.minTempC) { alerts.push(`Frost Alert for ${new Date(weather.daily.time[i]).toLocaleDateString([], {weekday: 'short'})}: Low of ${dayMinTemp.toFixed(0)}°C`); } if (dayMaxTemp > tree.protectionProfile!.maxTempC) { alerts.push(`Heat Alert for ${new Date(weather.daily.time[i]).toLocaleDateString([], {weekday: 'short'})}: High of ${dayMaxTemp.toFixed(0)}°C`); } if (dayMaxWind > tree.protectionProfile!.maxWindKph) { alerts.push(`Wind Alert for ${new Date(weather.daily.time[i]).toLocaleDateString([], {weekday: 'short'})}: Gusts up to ${dayMaxWind.toFixed(0)} km/h`); } }); return alerts; } return (

Weather Shield

Proactive weather alerts for your bonsai collection, based on their individual needs.

{isLoading ? : error ?

{error}

: !weather ?

Add trees to your garden to see weather alerts.

: ( <>

5-Day Forecast for {trees[0]?.location || 'Your Area'}

{weather.daily.time.slice(0, 5).map((time, i) => (

{new Date(time).toLocaleDateString([], { weekday: 'short', day: 'numeric'})}

{getWeatherIcon(weather.daily.weathercode[i])}

{weather.daily.temperature_2m_min[i].toFixed(0)}°C

{weather.daily.temperature_2m_max[i].toFixed(0)}°C

{weather.daily.windspeed_10m_max[i].toFixed(0)} km/h

))}

Tree Protection Status

{trees.map(tree => { const alerts = generateAlertsForTree(tree); const hasAlerts = alerts.length > 0; return (

{tree.name} ({tree.species})

{hasAlerts ? (
{alerts.map((alert, i) => (

{alert}

))}
) : (

No weather threats detected in the next 5 days.

)}
); })}
) }
); }; export default WeatherShieldView;