import React, { useState, useEffect } from 'react'; import styled from 'styled-components'; import { motion } from 'framer-motion'; import { useParams } from 'react-router-dom'; import Loader from '../components/Loader'; import Card from '../components/Card'; import LeftArrow from '../assets/left-arrow.svg'; import RightArrow from '../assets/right-arrow.svg'; const Wrapper = styled.div` min-height: 85vh; padding: 2rem 0rem; display: grid; row-gap: 3rem; h2 { text-align: center; } .main, .wind, .humidity { display: grid; justify-content: center; } .slider { display: grid; grid-template-columns: auto 1fr auto; justify-content: center; align-items: center; .slider-background { width: 100%; overflow: hidden; } img { cursor: pointer; width: 4rem; height: 4rem; } } .forecast-grid { display: grid; grid-template-columns: repeat(auto-fit, 10rem); grid-auto-flow: column; column-gap: 2rem; justify-content: center; } .error { display: grid; justify-content: center; align-items: center; h2 { text-align: center; word-break: break-word; } } `; interface WeatherResponse { weather: Array<{ id: number, description: string }>, main: { temp: number, humidity: number }, wind: { speed: number }, name: string, sys: { country: string }, dt: number, coord: { lat: number, lon: number } }; interface ForecastResponse { hourly: Array<{ dt: number, temp: number, weather: Array<{ id: number, description: string }> }>, daily: Array<{ dt: number, temp: { min: number, max: number }, weather: Array<{ id: number, description: string }> }> }; interface Weather { description: string, icon: number, main: { temp: number, humidity: number }, wind: { speed: number }, country: string, timestamp: number, name: string }; interface Forecast { hourly: Array<{ dt: number, temp: number, weather: Array<{ id: number, description: string }> }>, daily: Array<{ dt: number, temp: { min: number, max: number }, weather: Array<{ id: number, description: string }> }> }; const Search: React.FC = () => { const [ weather, setWeather ] = useState(null); const [ forecast, setForecast ] = useState(null); const [ loading, setLoading ] = useState(true); const [ error, setError ] = useState(''); const { query } = useParams<{ query: string }>(); const [ dailyForecastGrid, setDailyForecastGrid ] = useState(0); const [ hourlyForecastGrid, setHourlyForecastGrid ] = useState(0); useEffect(() => { (async () => { try { let weatherRes: Response = await fetch( `https://api.openweathermap.org/data/2.5/weather?q=${query}&appid=${process.env.REACT_APP_WEATHER_API_KEY}&units=metric` ); let weatherResBody: WeatherResponse = await weatherRes.json(); setWeather({ description: weatherResBody.weather[0].description, icon: weatherResBody.weather[0].id, main: weatherResBody.main, wind: weatherResBody.wind, name: weatherResBody.name, country: weatherResBody.sys.country, timestamp: weatherResBody.dt, }); let coords = weatherResBody.coord; let forecastRes: Response = await fetch( `https://api.openweathermap.org/data/2.5/onecall?lat=${coords.lat}&lon=${coords.lon}&appid=${process.env.REACT_APP_WEATHER_API_KEY}&exclude=minutely&units=metric` ); let forecastResBody: ForecastResponse = await forecastRes.json(); setForecast({ hourly: forecastResBody.hourly, daily: forecastResBody.daily }); setLoading(false); } catch (err) { setLoading(false); setError('Could not find any weather data! Try again later'); } })(); return () => { setError(''); setLoading(true); } }, [query]); return !loading ? ( { weather && forecast && !error ? ( <>

{weather.name}, {weather.country}

25 ? 'hot' : weather.main.temp < 20 ? 'cold' : null} icon={weather.icon} description={weather.description} />

Daily Forecast

{ if (dailyForecastGrid <= forecast.daily.length / 2 - 1) setDailyForecastGrid(dailyForecastGrid + 1); }} />
{ forecast.daily.map(day => ( 25 ? 'hot' : day.temp.max < 20 ? 'cold' : null} icon={day.weather[0].id} description={day.weather[0].description} /> )) }
{ if (dailyForecastGrid >= - forecast.daily.length / 2 + 1) setDailyForecastGrid(dailyForecastGrid - 1); }} />

Hourly Forecast

{ if (hourlyForecastGrid <= forecast.hourly.length / 2 - 1) setHourlyForecastGrid(hourlyForecastGrid + 1); }} />
{ forecast.hourly.map(hour => ( 25 ? 'hot' : hour.temp < 20 ? 'cold' : null} icon={hour.weather[0].id} description={hour.weather[0].description} /> )) }
{ if (hourlyForecastGrid >= - forecast.hourly.length / 2 + 1) setHourlyForecastGrid(hourlyForecastGrid - 1); }} />

Wind

Humidity

) : (

{error}

) }
) : ( ); } export default Search;