From d2e6ebae4ffbf2ca6b33a16838d9a65aa72ed810 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Jun 2021 12:17:10 +0200 Subject: [PATCH] WeatherWidget temp unit. WeatherSettings update on change --- .../WeatherSettings/WeatherSettings.tsx | 22 +++++++++++-- .../Widgets/WeatherWidget/WeatherWidget.tsx | 32 ++++++++++++------- client/src/interfaces/Weather.ts | 1 + controllers/weather.js | 15 ++++++++- models/Weather.js | 1 + routes/config.js | 2 +- routes/weather.js | 9 ++++-- utils/getExternalWeather.js | 10 ++---- 8 files changed, 68 insertions(+), 24 deletions(-) diff --git a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx index 5e1f7af..3ab9618 100644 --- a/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx +++ b/client/src/components/Settings/WeatherSettings/WeatherSettings.tsx @@ -1,7 +1,7 @@ import { useState, ChangeEvent, useEffect, FormEvent } from 'react'; import { connect } from 'react-redux'; import axios from 'axios'; -import { ApiResponse, Config, NewNotification } from '../../../interfaces'; +import { ApiResponse, Config, NewNotification, Weather } from '../../../interfaces'; import InputGroup from '../../UI/Forms/InputGroup/InputGroup'; import Button from '../../UI/Buttons/Button/Button'; @@ -65,13 +65,31 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => { e.preventDefault(); axios.put>('/api/config', formData) - .then(data => { + .then(() => { props.createNotification({ title: 'Success', message: 'Settings updated' }) + + // Update weather with new settings + axios.get>('/api/weather/update') + .then(() => { + props.createNotification({ + title: 'Success', + message: 'Weather updated' + }) + }) + .catch((err) => { + props.createNotification({ + title: 'Error', + message: err.response.data.error + }) + }); }) .catch(err => console.log(err)); + + // set localStorage + localStorage.setItem('isCelsius', JSON.stringify(formData.isCelsius === 1)) } return ( diff --git a/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx b/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx index 1872089..7d7cbd9 100644 --- a/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx +++ b/client/src/components/Widgets/WeatherWidget/WeatherWidget.tsx @@ -1,5 +1,5 @@ import { useState, useEffect, Fragment } from 'react'; -import { Weather, ApiResponse } from '../../../interfaces'; +import { Weather, ApiResponse, Config } from '../../../interfaces'; import axios from 'axios'; import WeatherIcon from '../../UI/Icons/WeatherIcon/WeatherIcon'; @@ -12,6 +12,7 @@ const WeatherWidget = (): JSX.Element => { tempC: 0, tempF: 0, isDay: 1, + cloud: 0, conditionText: '', conditionCode: 1000, id: -1, @@ -19,9 +20,11 @@ const WeatherWidget = (): JSX.Element => { updatedAt: new Date() }); const [isLoading, setIsLoading] = useState(true); + const [isCelsius, setIsCelsius] = useState(true); // Initial request to get data useEffect(() => { + // get weather axios.get>('/api/weather') .then(data => { const weatherData = data.data.data[0]; @@ -31,20 +34,24 @@ const WeatherWidget = (): JSX.Element => { setIsLoading(false); }) .catch(err => console.log(err)); + + // get config + if (!localStorage.isCelsius) { + axios.get>('/api/config/isCelsius') + .then((data) => { + setIsCelsius(parseInt(data.data.data.value) === 1); + localStorage.setItem('isCelsius', JSON.stringify(isCelsius)); + }) + .catch((err) => console.log(err)); + } else { + setIsCelsius(JSON.parse(localStorage.isCelsius)); + } }, []); // Open socket for data updates useEffect(() => { const webSocketClient = new WebSocket('ws://localhost:5005'); - webSocketClient.onopen = () => { - console.log('WebSocket opened'); - } - - webSocketClient.onclose = () => { - console.log('WebSocket closed') - } - webSocketClient.onmessage = (e) => { const data = JSON.parse(e.data); setWeather({ @@ -69,8 +76,11 @@ const WeatherWidget = (): JSX.Element => { />
- {weather.tempC}°C - {weather.conditionCode} + {isCelsius + ? {weather.tempC}°C + : {weather.tempF}°F + } + {weather.cloud}%
) ) diff --git a/client/src/interfaces/Weather.ts b/client/src/interfaces/Weather.ts index a99e2c7..c71ac48 100644 --- a/client/src/interfaces/Weather.ts +++ b/client/src/interfaces/Weather.ts @@ -5,6 +5,7 @@ export interface Weather extends Model { tempC: number; tempF: number; isDay: number; + cloud: number; conditionText: string; conditionCode: number; } \ No newline at end of file diff --git a/controllers/weather.js b/controllers/weather.js index 66c63de..4a5392f 100644 --- a/controllers/weather.js +++ b/controllers/weather.js @@ -1,9 +1,10 @@ const asyncWrapper = require('../middleware/asyncWrapper'); const ErrorResponse = require('../utils/ErrorResponse'); const Weather = require('../models/Weather'); +const getExternalWeather = require('../utils/getExternalWeather'); // @desc Get latest weather status -// @route POST /api/weather +// @route GET /api/weather // @access Public exports.getWeather = asyncWrapper(async (req, res, next) => { const weather = await Weather.findAll({ @@ -11,6 +12,18 @@ exports.getWeather = asyncWrapper(async (req, res, next) => { limit: 1 }); + res.status(200).json({ + success: true, + data: weather + }) +}) + +// @desc Update weather +// @route GET /api/weather/update +// @access Public +exports.updateWeather = asyncWrapper(async (req, res, next) => { + const weather = await getExternalWeather(); + res.status(200).json({ success: true, data: weather diff --git a/models/Weather.js b/models/Weather.js index d79add5..c85c29f 100644 --- a/models/Weather.js +++ b/models/Weather.js @@ -6,6 +6,7 @@ const Weather = sequelize.define('Weather', { tempC: DataTypes.FLOAT, tempF: DataTypes.FLOAT, isDay: DataTypes.INTEGER, + cloud: DataTypes.INTEGER, conditionText: DataTypes.TEXT, conditionCode: DataTypes.INTEGER }, { diff --git a/routes/config.js b/routes/config.js index 3b7c3f2..caadbe5 100644 --- a/routes/config.js +++ b/routes/config.js @@ -11,7 +11,7 @@ const { } = require('../controllers/config'); router - .route('') + .route('/') .post(createPair) .get(getAllPairs) .put(updateValues); diff --git a/routes/weather.js b/routes/weather.js index 1bc264a..4d4a110 100644 --- a/routes/weather.js +++ b/routes/weather.js @@ -2,11 +2,16 @@ const express = require('express'); const router = express.Router(); const { - getWeather + getWeather, updateWeather } = require('../controllers/weather'); router - .route('') + .route('/') .get(getWeather); +router + .route('/update') + .get(updateWeather); + + module.exports = router; \ No newline at end of file diff --git a/utils/getExternalWeather.js b/utils/getExternalWeather.js index bda234f..1135ef7 100644 --- a/utils/getExternalWeather.js +++ b/utils/getExternalWeather.js @@ -12,22 +12,17 @@ const getExternalWeather = async () => { const long = config.find(pair => pair.key === 'long'); if (!secret) { - console.log('API key was not found. Weather updated failed'); - return; + throw new Error('API key was not found. Weather updated failed'); } if (!lat || !long) { - console.log('Location was not found. Weather updated failed'); - return; + throw new Error('Location was not found. Weather updated failed'); } // Fetch data from external API try { const res = await axios.get(`http://api.weatherapi.com/v1/current.json?key=${secret.value}&q=${lat.value},${long.value}`); - // For dev - // console.log(res.data); - // Save weather data const cursor = res.data.current; const weatherData = await Weather.create({ @@ -35,6 +30,7 @@ const getExternalWeather = async () => { tempC: cursor.temp_c, tempF: cursor.temp_f, isDay: cursor.is_day, + cloud: cursor.cloud, conditionText: cursor.condition.text, conditionCode: cursor.condition.code });