|
@@ -1,110 +1,94 @@
|
|
import { useState, ChangeEvent, useEffect, FormEvent } from 'react';
|
|
import { useState, ChangeEvent, useEffect, FormEvent } from 'react';
|
|
-import { connect } from 'react-redux';
|
|
|
|
import axios from 'axios';
|
|
import axios from 'axios';
|
|
-import { ApiResponse, Config, NewNotification, Weather } from '../../../interfaces';
|
|
|
|
|
|
|
|
|
|
+// Redux
|
|
|
|
+import { connect } from 'react-redux';
|
|
|
|
+import { createNotification, updateConfig } from '../../../store/actions';
|
|
|
|
+
|
|
|
|
+// Typescript
|
|
|
|
+import { ApiResponse, GlobalState, NewNotification, Weather, WeatherForm } from '../../../interfaces';
|
|
|
|
+
|
|
|
|
+// UI
|
|
import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
|
|
import InputGroup from '../../UI/Forms/InputGroup/InputGroup';
|
|
import Button from '../../UI/Buttons/Button/Button';
|
|
import Button from '../../UI/Buttons/Button/Button';
|
|
-import { createNotification } from '../../../store/actions';
|
|
|
|
|
|
|
|
-interface FormState {
|
|
|
|
- WEATHER_API_KEY: string;
|
|
|
|
- lat: number;
|
|
|
|
- long: number;
|
|
|
|
- isCelsius: number;
|
|
|
|
-}
|
|
|
|
|
|
+// Utils
|
|
|
|
+import { searchConfig } from '../../../utility';
|
|
|
|
|
|
interface ComponentProps {
|
|
interface ComponentProps {
|
|
createNotification: (notification: NewNotification) => void;
|
|
createNotification: (notification: NewNotification) => void;
|
|
|
|
+ updateConfig: (formData: WeatherForm) => void;
|
|
|
|
+ loading: boolean;
|
|
}
|
|
}
|
|
|
|
|
|
const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
- const [formData, setFormData] = useState<FormState>({
|
|
|
|
|
|
+ // Initial state
|
|
|
|
+ const [formData, setFormData] = useState<WeatherForm>({
|
|
WEATHER_API_KEY: '',
|
|
WEATHER_API_KEY: '',
|
|
lat: 0,
|
|
lat: 0,
|
|
long: 0,
|
|
long: 0,
|
|
isCelsius: 1
|
|
isCelsius: 1
|
|
})
|
|
})
|
|
|
|
|
|
- const inputChangeHandler = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>, isNumber?: boolean) => {
|
|
|
|
- let value: string | number = e.target.value;
|
|
|
|
-
|
|
|
|
- if (isNumber) {
|
|
|
|
- value = parseFloat(value);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
|
|
+ // Get config
|
|
|
|
+ useEffect(() => {
|
|
setFormData({
|
|
setFormData({
|
|
- ...formData,
|
|
|
|
- [e.target.name]: value
|
|
|
|
|
|
+ WEATHER_API_KEY: searchConfig('WEATHER_API_KEY', ''),
|
|
|
|
+ lat: searchConfig('lat', 0),
|
|
|
|
+ long: searchConfig('long', 0),
|
|
|
|
+ isCelsius: searchConfig('isCelsius', 1)
|
|
})
|
|
})
|
|
- }
|
|
|
|
-
|
|
|
|
- useEffect(() => {
|
|
|
|
- axios.get<ApiResponse<Config[]>>('/api/config?keys=WEATHER_API_KEY,lat,long,isCelsius')
|
|
|
|
- .then(data => {
|
|
|
|
- let tmpFormData = { ...formData };
|
|
|
|
-
|
|
|
|
- data.data.data.forEach((config: Config) => {
|
|
|
|
- let value: string | number = config.value;
|
|
|
|
- if (config.valueType === 'number') {
|
|
|
|
- value = parseFloat(value);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- tmpFormData = {
|
|
|
|
- ...tmpFormData,
|
|
|
|
- [config.key]: value
|
|
|
|
- }
|
|
|
|
- })
|
|
|
|
-
|
|
|
|
- setFormData(tmpFormData);
|
|
|
|
- })
|
|
|
|
- .catch(err => console.log(err));
|
|
|
|
- }, []);
|
|
|
|
|
|
+ }, [props.loading]);
|
|
|
|
|
|
- const formSubmitHandler = (e: FormEvent) => {
|
|
|
|
|
|
+ // Form handler
|
|
|
|
+ const formSubmitHandler = async (e: FormEvent) => {
|
|
e.preventDefault();
|
|
e.preventDefault();
|
|
|
|
|
|
// Check for api key input
|
|
// Check for api key input
|
|
if ((formData.lat || formData.long) && !formData.WEATHER_API_KEY) {
|
|
if ((formData.lat || formData.long) && !formData.WEATHER_API_KEY) {
|
|
props.createNotification({
|
|
props.createNotification({
|
|
title: 'Warning',
|
|
title: 'Warning',
|
|
- message: 'API Key is missing. Weather Module will NOT work'
|
|
|
|
|
|
+ message: 'API key is missing. Weather Module will NOT work'
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
|
|
// Save settings
|
|
// Save settings
|
|
- axios.put<ApiResponse<{}>>('/api/config', formData)
|
|
|
|
|
|
+ await props.updateConfig(formData);
|
|
|
|
+
|
|
|
|
+ // Update weather
|
|
|
|
+ axios.get<ApiResponse<Weather>>('/api/weather/update')
|
|
.then(() => {
|
|
.then(() => {
|
|
props.createNotification({
|
|
props.createNotification({
|
|
title: 'Success',
|
|
title: 'Success',
|
|
- message: 'Settings updated'
|
|
|
|
|
|
+ message: 'Weather 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(parseInt(`${formData.isCelsius}`) === 1))
|
|
|
|
|
|
+ .catch((err) => {
|
|
|
|
+ props.createNotification({
|
|
|
|
+ title: 'Error',
|
|
|
|
+ message: err.response.data.error
|
|
|
|
+ })
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Input handler
|
|
|
|
+ const inputChangeHandler = (e: ChangeEvent<HTMLInputElement | HTMLSelectElement>, isNumber?: boolean) => {
|
|
|
|
+ let value: string | number = e.target.value;
|
|
|
|
+
|
|
|
|
+ if (isNumber) {
|
|
|
|
+ value = parseFloat(value);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ setFormData({
|
|
|
|
+ ...formData,
|
|
|
|
+ [e.target.name]: value
|
|
|
|
+ })
|
|
}
|
|
}
|
|
|
|
|
|
return (
|
|
return (
|
|
<form onSubmit={(e) => formSubmitHandler(e)}>
|
|
<form onSubmit={(e) => formSubmitHandler(e)}>
|
|
<InputGroup>
|
|
<InputGroup>
|
|
- <label htmlFor='WEATHER_API_KEY'>API Key</label>
|
|
|
|
|
|
+ <label htmlFor='WEATHER_API_KEY'>API key</label>
|
|
<input
|
|
<input
|
|
type='text'
|
|
type='text'
|
|
id='WEATHER_API_KEY'
|
|
id='WEATHER_API_KEY'
|
|
@@ -124,7 +108,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
</span>
|
|
</span>
|
|
</InputGroup>
|
|
</InputGroup>
|
|
<InputGroup>
|
|
<InputGroup>
|
|
- <label htmlFor='lat'>Location Latitude</label>
|
|
|
|
|
|
+ <label htmlFor='lat'>Location latitude</label>
|
|
<input
|
|
<input
|
|
type='number'
|
|
type='number'
|
|
id='lat'
|
|
id='lat'
|
|
@@ -143,7 +127,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
</span>
|
|
</span>
|
|
</InputGroup>
|
|
</InputGroup>
|
|
<InputGroup>
|
|
<InputGroup>
|
|
- <label htmlFor='long'>Location Longitude</label>
|
|
|
|
|
|
+ <label htmlFor='long'>Location longitude</label>
|
|
<input
|
|
<input
|
|
type='number'
|
|
type='number'
|
|
id='long'
|
|
id='long'
|
|
@@ -154,7 +138,7 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
/>
|
|
/>
|
|
</InputGroup>
|
|
</InputGroup>
|
|
<InputGroup>
|
|
<InputGroup>
|
|
- <label htmlFor='isCelsius'>Temperature Unit</label>
|
|
|
|
|
|
+ <label htmlFor='isCelsius'>Temperature unit</label>
|
|
<select
|
|
<select
|
|
id='isCelsius'
|
|
id='isCelsius'
|
|
name='isCelsius'
|
|
name='isCelsius'
|
|
@@ -170,4 +154,10 @@ const WeatherSettings = (props: ComponentProps): JSX.Element => {
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
-export default connect(null, { createNotification })(WeatherSettings);
|
|
|
|
|
|
+const mapStateToProps = (state: GlobalState) => {
|
|
|
|
+ return {
|
|
|
|
+ loading: state.config.loading
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+export default connect(mapStateToProps, { createNotification, updateConfig })(WeatherSettings);
|