WeatherWidget temp unit. WeatherSettings update on change

This commit is contained in:
unknown 2021-06-07 12:17:10 +02:00
parent 08c769b630
commit d2e6ebae4f
8 changed files with 68 additions and 24 deletions

View file

@ -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<ApiResponse<{}>>('/api/config', formData)
.then(data => {
.then(() => {
props.createNotification({
title: 'Success',
message: 'Settings updated'
})
// Update weather with new settings
axios.get<ApiResponse<Weather>>('/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 (

View file

@ -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<ApiResponse<Weather[]>>('/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<ApiResponse<Config>>('/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 => {
/>
</div>
<div className={classes.WeatherDetails}>
<span>{weather.tempC}°C</span>
<span>{weather.conditionCode}</span>
{isCelsius
? <span>{weather.tempC}°C</span>
: <span>{weather.tempF}°F</span>
}
<span>{weather.cloud}%</span>
</div>
</Fragment>)
)

View file

@ -5,6 +5,7 @@ export interface Weather extends Model {
tempC: number;
tempF: number;
isDay: number;
cloud: number;
conditionText: string;
conditionCode: number;
}

View file

@ -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({
@ -16,3 +17,15 @@ exports.getWeather = asyncWrapper(async (req, res, next) => {
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
})
})

View file

@ -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
}, {

View file

@ -11,7 +11,7 @@ const {
} = require('../controllers/config');
router
.route('')
.route('/')
.post(createPair)
.get(getAllPairs)
.put(updateValues);

View file

@ -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;

View file

@ -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
});