diff --git a/src/components/widgets/weather/Expanded.jsx b/src/components/widgets/weather/Expanded.jsx index 8db7e33e..3796f82b 100644 --- a/src/components/widgets/weather/Expanded.jsx +++ b/src/components/widgets/weather/Expanded.jsx @@ -1,4 +1,4 @@ -import { memo } from 'react'; +import { memo, useMemo } from 'react'; import { WiHumidity, WiWindy, WiBarometer, WiCloud } from 'react-icons/wi'; import { MdDisabledVisible } from 'react-icons/md'; @@ -8,16 +8,18 @@ import WindDirectionIcon from './WindDirectionIcon'; import Tooltip from 'components/helpers/tooltip/Tooltip'; -function Expanded({ state, weatherType, variables }) { +function Expanded({ state: { weather, icon }, weatherType, variables }) { /** * If the localStorage item is true and the weatherType is greater than or equal to 3, or if the * weatherType is equal to 3, then return true. * @param {string} setting - The localStorage item to check. * @returns a boolean value. */ - const enabled = (setting) => { - return (localStorage.getItem(setting) === 'true' && weatherType >= 3) || weatherType === '3'; - }; + const enabled = useMemo(() => { + return (setting) => { + return (localStorage.getItem(setting) === 'true' && weatherType >= 3) || weatherType === '3'; + }; + }, [weatherType]); return (
@@ -35,7 +37,7 @@ function Expanded({ state, weatherType, variables }) { > - {state.weather.cloudiness}% + {weather.cloudiness}% )} @@ -48,11 +50,11 @@ function Expanded({ state, weatherType, variables }) { > - {state.weather.wind_speed} + {weather.wind_speed} m/s{' '} {enabled('windDirection') && (
- +
)}
@@ -67,7 +69,7 @@ function Expanded({ state, weatherType, variables }) { > - {state.weather.pressure} + {weather.pressure} hPa @@ -80,8 +82,8 @@ function Expanded({ state, weatherType, variables }) { placement="left" > - - {state.weather.description} + + {weather.description} )} @@ -95,7 +97,7 @@ function Expanded({ state, weatherType, variables }) { {variables.getMessage('widgets.weather.meters', { - amount: state.weather.visibility, + amount: weather.visibility, })} @@ -107,7 +109,7 @@ function Expanded({ state, weatherType, variables }) { > - {state.weather.humidity} + {weather.humidity} )} diff --git a/src/components/widgets/weather/Weather.jsx b/src/components/widgets/weather/Weather.jsx index d3c4a035..d65a20cb 100644 --- a/src/components/widgets/weather/Weather.jsx +++ b/src/components/widgets/weather/Weather.jsx @@ -8,6 +8,15 @@ import EventBus from 'modules/helpers/eventbus'; import './weather.scss'; +const convertTemperature = (temp, format) => { + if (format === 'celsius') { + return Math.round(temp - 273.15); + } else if (format === 'fahrenheit') { + return Math.round((temp - 273.15) * 1.8 + 32); + } + return Math.round(temp); +}; + export default class Weather extends PureComponent { constructor() { super(); @@ -18,65 +27,62 @@ export default class Weather extends PureComponent { } async getWeather() { - const zoomWeather = `${Number((localStorage.getItem('zoomWeather') || 100) / 100)}em`; - document.querySelector('.weather').style.fontSize = zoomWeather; - if (this.state.done === true) { return; } - const data = await ( - await fetch( + const zoomWeather = `${Number((localStorage.getItem('zoomWeather') || 100) / 100)}em`; + document.querySelector('.weather').style.fontSize = zoomWeather; + + try { + const response = await fetch( variables.constants.API_URL + `/weather?city=${this.state.location}&language=${variables.languagecode}`, - ) - ).json(); + ); - if (data.status === 404) { - return this.setState({ - location: variables.getMessage('widgets.weather.not_found'), + if (!response.ok) { + throw new Error('Network response was not ok'); + } + + const data = await response.json(); + + if (data.status === 404) { + return this.setState({ + location: variables.getMessage('widgets.weather.not_found'), + }); + } + + const { temp, temp_min, temp_max, feels_like } = data.main; + const tempFormat = localStorage.getItem('tempformat'); + + const tempSymbols = { + celsius: '°C', + kelvin: 'K', + fahrenheit: '°F', + }; + + this.setState({ + icon: data.weather[0].icon, + temp_text: tempSymbols[tempFormat] || 'K', + weather: { + temp: convertTemperature(temp, tempFormat), + description: data.weather[0].description, + temp_min: convertTemperature(temp_min, tempFormat), + temp_max: convertTemperature(temp_max, tempFormat), + feels_like: convertTemperature(feels_like, tempFormat), + humidity: data.main.humidity, + wind_speed: data.wind.speed, + wind_degrees: data.wind.deg, + cloudiness: data.clouds.all, + visibility: data.visibility, + pressure: data.main.pressure, + }, + done: true, }); + } catch (error) { + console.error('Fetch Error: ', error); } - let temp = data.main.temp; - let temp_min = data.main.temp_min; - let temp_max = data.main.temp_max; - let feels_like = data.main.feels_like; - let temp_text = 'K'; - - if (localStorage.getItem('tempformat') === 'celsius') { - temp -= 273.15; - temp_min -= 273.15; - temp_max -= 273.15; - feels_like -= 273.15; - temp_text = '°C'; - } else { - temp = (temp - 273.15) * 1.8 + 32; - temp_min = (temp_min - 273.15) * 1.8 + 32; - temp_max = (temp_max - 273.15) * 1.8 + 32; - feels_like = (feels_like - 273.15) * 1.8 + 32; - temp_text = '°F'; - } - - this.setState({ - icon: data.weather[0].icon, - temp_text, - weather: { - temp: Math.round(temp), - description: data.weather[0].description, - temp_min: Math.round(temp_min), - temp_max: Math.round(temp_max), - feels_like: Math.round(feels_like), - humidity: data.main.humidity, - wind_speed: data.wind.speed, - wind_degrees: data.wind.deg, - cloudiness: data.clouds.all, - visibility: data.visibility, - pressure: data.main.pressure, - }, - done: true, - }); - document.querySelector('.top-weather svg').style.fontSize = zoomWeather; } @@ -115,13 +121,13 @@ export default class Weather extends PureComponent { {weatherType >= 1 && (
- {this.state.weather.temp + this.state.temp_text} + {`${this.state.weather.temp}${this.state.temp_text}`}
)} {weatherType >= 2 && ( - {this.state.weather.temp_min + this.state.temp_text} - {this.state.weather.temp_max + this.state.temp_text} + {`${this.state.weather.temp_min}${this.state.temp_text}`} + {`${this.state.weather.temp_max}${this.state.temp_text}`} )}
@@ -129,7 +135,7 @@ export default class Weather extends PureComponent {
{variables.getMessage('widgets.weather.feels_like', { - amount: this.state.weather.feels_like + this.state.temp_text, + amount: `${this.state.weather.feels_like}${this.state.temp_text}`, })} {this.state.location} diff --git a/src/components/widgets/weather/WeatherIcon.jsx b/src/components/widgets/weather/WeatherIcon.jsx index 51bcf303..125bb1e1 100644 --- a/src/components/widgets/weather/WeatherIcon.jsx +++ b/src/components/widgets/weather/WeatherIcon.jsx @@ -15,42 +15,30 @@ import { WiFog, } from 'react-icons/wi'; +const iconMap = { + '01d': WiDaySunny, + '01n': WiNightClear, + '02d': WiDayCloudy, + '02n': WiNightCloudy, + '03d': WiCloud, + '03n': WiCloud, + '04d': WiCloudy, + '04n': WiCloudy, + '09d': WiDayShowers, + '09n': WiNightShowers, + '10d': WiRain, + '10n': WiRain, + '11d': WiThunderstorm, + '11n': WiThunderstorm, + '13d': WiSnow, + '13n': WiSnow, + '50d': WiFog, + '50n': WiFog, +}; + function WeatherIcon({ name }) { - // name is the openweathermap icon name, see https://openweathermap.org/weather-conditions - switch (name) { - case '01d': - return ; - case '01n': - return ; - case '02d': - return ; - case '02n': - return ; - case '03d': - case '03n': - return ; - case '04d': - case '04n': - return ; - case '09d': - return ; - case '09n': - return ; - case '10d': - case '10n': - return ; - case '11d': - case '11n': - return ; - case '13d': - case '13n': - return ; - case '50d': - case '50n': - return ; - default: - return null; - } + const IconComponent = iconMap[name]; + return IconComponent ? : null; } export default memo(WeatherIcon);