diff --git a/src/Api/weatherApi.js b/src/Api/weatherApi.js
index d676624e..be459115 100644
--- a/src/Api/weatherApi.js
+++ b/src/Api/weatherApi.js
@@ -14,7 +14,13 @@ export const getCurrentWeather = async (longitude, latitude) => {
export const getLocationByCoords = async (longitude, latitude) => {
const result = await instance.get(`/location/${longitude},${latitude}`);
return {
+ id: result.data.id,
city: result.data.name,
country: result.data.country
};
};
+
+export const getHourlyWeather = async (longitude, latitude) => {
+ const result = await instance.get(`/forecast/hourly/${longitude},${latitude}`);
+ return result.data.forecast;
+};
diff --git a/src/Components/CurrentLocation/CurrentLocation.jsx b/src/Components/CurrentLocation/CurrentLocation.jsx
new file mode 100644
index 00000000..8abe6bfb
--- /dev/null
+++ b/src/Components/CurrentLocation/CurrentLocation.jsx
@@ -0,0 +1,9 @@
+function CurrentLocation({ currentLocation }) {
+ return (
+
+ {currentLocation.city}, {currentLocation.country}
+
+ );
+}
+
+export default CurrentLocation;
diff --git a/src/Components/HourlyWeatherItem/HourlyWeatherItem.jsx b/src/Components/HourlyWeatherItem/HourlyWeatherItem.jsx
new file mode 100644
index 00000000..0ce00449
--- /dev/null
+++ b/src/Components/HourlyWeatherItem/HourlyWeatherItem.jsx
@@ -0,0 +1,15 @@
+import { toReadableTime } from '../../helpers/formatHelper';
+import SafeWeatherImage from '../SafeImage/SafeWeatherImage';
+
+function HourlyWeatherItem({ hourly }) {
+ return (
+
+
+ {toReadableTime(hourly.time)} temperature: {hourly.temperature}° precipProb:{' '}
+ {hourly.precipProb} %
+
+
+ );
+}
+
+export default HourlyWeatherItem;
diff --git a/src/Components/Pages/DetailedForesastPage/DetailedForecastPage.jsx b/src/Components/Pages/DetailedForesastPage/DetailedForecastPage.jsx
index f0235d3f..cc700dc6 100644
--- a/src/Components/Pages/DetailedForesastPage/DetailedForecastPage.jsx
+++ b/src/Components/Pages/DetailedForesastPage/DetailedForecastPage.jsx
@@ -1,7 +1,31 @@
+import { useEffect } from 'react';
+import { useSelector, useDispatch } from 'react-redux';
+import { getLocation } from '../../../Store/selectors/geoSelectors';
+import HourlyWeatherItem from '../../HourlyWeatherItem/HourlyWeatherItem';
+import { fetchUserLocationDetailedWeather } from './detailedForecastPageActions';
+import { getHourlyWeather, getLoading } from './detailedForecastPageSelectors';
+import Loader from '../../Loader/Loader';
+import CurrentLocation from '../../CurrentLocation/CurrentLocation';
+
function DetailedForecastPage() {
+ const dispatch = useDispatch();
+ const location = useSelector(getLocation);
+ const hourlyWeather = useSelector(getHourlyWeather);
+ const loading = useSelector(getLoading);
+
+ useEffect(async () => {
+ dispatch(fetchUserLocationDetailedWeather());
+ }, []);
+
return (
Detailed Page
+ {loading && }
+ {location && }
+ {hourlyWeather &&
+ hourlyWeather.map(hourlyItem => (
+
+ ))}
);
}
diff --git a/src/Components/Pages/DetailedForesastPage/detailedForecastPageActions.js b/src/Components/Pages/DetailedForesastPage/detailedForecastPageActions.js
new file mode 100644
index 00000000..438f44dd
--- /dev/null
+++ b/src/Components/Pages/DetailedForesastPage/detailedForecastPageActions.js
@@ -0,0 +1,36 @@
+import { fetchUserGeoData } from '../../../Store/actions/geoActions';
+import { getPosition } from '../../../Store/selectors/geoSelectors';
+import { getHourlyWeather } from '../../../Api/weatherApi';
+
+export const DETAILED_FORECAST_PAGE_ACTIONS = {
+ USER_POSITION_DETAILED_WEATHER_REQUESTED: 'USER_POSITION_DETAILED_WEATHER_REQUESTED',
+ USER_POSITION_DETAILED_WEATHER_RECEIVED: 'USER_POSITION_DETAILED_WEATHER_RECEIVED',
+ USER_POSITION_DETAILED_WEATHER_FAILED: 'USER_POSITION_DETAILED_WEATHER_FAILED'
+};
+
+const userPositionDetailedWeatherRequested = () => ({
+ type: DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_REQUESTED
+});
+
+const userPositionDetailedWeatherReceived = ({ hourlyWeather }) => ({
+ type: DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_RECEIVED,
+ payload: { hourlyWeather }
+});
+
+const userPositionDetailedWeatherFailed = ({ error }) => ({
+ type: DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_FAILED,
+ payload: error
+});
+
+export const fetchUserLocationDetailedWeather = () => async (dispatch, getState) => {
+ dispatch(userPositionDetailedWeatherRequested());
+
+ try {
+ await dispatch(fetchUserGeoData());
+ const { longitude, latitude } = getPosition(getState());
+ const hourlyWeather = await getHourlyWeather(longitude, latitude);
+ dispatch(userPositionDetailedWeatherReceived({ hourlyWeather }));
+ } catch (error) {
+ dispatch(userPositionDetailedWeatherFailed(error));
+ }
+};
diff --git a/src/Components/Pages/DetailedForesastPage/detailedForecastPageInitialState.js b/src/Components/Pages/DetailedForesastPage/detailedForecastPageInitialState.js
new file mode 100644
index 00000000..89a51f6f
--- /dev/null
+++ b/src/Components/Pages/DetailedForesastPage/detailedForecastPageInitialState.js
@@ -0,0 +1,7 @@
+const initialState = {
+ hourlyWeather: null,
+ loading: false,
+ error: null
+};
+
+export default initialState;
diff --git a/src/Components/Pages/DetailedForesastPage/detailedForecastPageReducer.js b/src/Components/Pages/DetailedForesastPage/detailedForecastPageReducer.js
new file mode 100644
index 00000000..aa71bcc8
--- /dev/null
+++ b/src/Components/Pages/DetailedForesastPage/detailedForecastPageReducer.js
@@ -0,0 +1,27 @@
+import initialState from './detailedForecastPageInitialState';
+import { DETAILED_FORECAST_PAGE_ACTIONS } from './detailedForecastPageActions';
+import produce from 'immer';
+
+export const detailedForecastPageReducer = (state = initialState, { type, payload }) => {
+ switch (type) {
+ case DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_REQUESTED:
+ return produce(state, draft => {
+ draft.loading = true;
+ draft.error = null;
+ });
+ case DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_RECEIVED:
+ return produce(state, draft => {
+ draft.loading = false;
+ draft.hourlyWeather = payload.hourlyWeather;
+ });
+ case DETAILED_FORECAST_PAGE_ACTIONS.USER_POSITION_DETAILED_WEATHER_FAILED:
+ return produce(state, draft => {
+ draft.loading = false;
+ draft.error = payload;
+ });
+ default:
+ return state;
+ }
+};
+
+export default detailedForecastPageReducer;
diff --git a/src/Components/Pages/DetailedForesastPage/detailedForecastPageSelectors.js b/src/Components/Pages/DetailedForesastPage/detailedForecastPageSelectors.js
new file mode 100644
index 00000000..57b3b419
--- /dev/null
+++ b/src/Components/Pages/DetailedForesastPage/detailedForecastPageSelectors.js
@@ -0,0 +1,2 @@
+export const getHourlyWeather = state => state.detailedForecastPage.hourlyWeather;
+export const getLoading = state => state.detailedForecastPage.loading;
diff --git a/src/Components/Pages/HomePage/HomePage.jsx b/src/Components/Pages/HomePage/HomePage.jsx
index b9dee2bd..e166578c 100644
--- a/src/Components/Pages/HomePage/HomePage.jsx
+++ b/src/Components/Pages/HomePage/HomePage.jsx
@@ -6,6 +6,7 @@ import Loader from '../../Loader/Loader';
import { capitalize, toReadableDate, toReadableTime } from '../../../helpers/formatHelper';
import { getLocation } from '../../../Store/selectors/geoSelectors';
import { getCurrentWeather, getLoading } from './homePageSelectors';
+import CurrentLocation from '../../CurrentLocation/CurrentLocation';
function HomePage() {
const dispatch = useDispatch();
@@ -20,12 +21,8 @@ function HomePage() {
return (
<>
Home
- {location && (
-
- {location.city}, {location.country}
-
- )}
{loading && }
+ {location && }
{currentWeather && {toReadableDate(currentWeather.current.time)}
}
{currentWeather && {toReadableTime(currentWeather.current.time)}
}
{currentWeather && Probability of precipitation: {currentWeather.current.precipProb}%
}
diff --git a/src/Store/store.js b/src/Store/store.js
index c366ba19..3467e114 100644
--- a/src/Store/store.js
+++ b/src/Store/store.js
@@ -3,9 +3,11 @@ import thunk from 'redux-thunk';
import homePageReducer from '../Components/Pages/HomePage/homePageReducer';
import geoReducer from './reducers/geoReducer';
+import detailedForecastPageReducer from '../Components/Pages/DetailedForesastPage/detailedForecastPageReducer';
const rootReducer = combineReducers({
homePage: homePageReducer,
+ detailedForecastPage: detailedForecastPageReducer,
geoData: geoReducer
});