diff --git a/src/pages/offer-screen/offer-screen.tsx b/src/pages/offer-screen/offer-screen.tsx
index 562c593..b9c3d74 100644
--- a/src/pages/offer-screen/offer-screen.tsx
+++ b/src/pages/offer-screen/offer-screen.tsx
@@ -1,68 +1,39 @@
-import { Link } from 'react-router-dom';
import ReviewsList from '../../components/reviews-list/reviews-list';
import Map from '../../components/map/map';
import OfferList from '../../components/offer-list/offer-list';
import { ratingPercentage, typeOfCardList } from '../../utils';
import { useAppSelector } from '../../hooks';
import { REVIEWS } from '../../mocks/reviews';
+import Header from '../../components/header/header';
function OfferScreen(): JSX.Element {
- const [offer, offers] = useAppSelector((state) => [state.chosenOffer, state.offers]);
+ const offer = useAppSelector((state) => state.chosenOffer);
+ const offers = useAppSelector((state) => state.offers);
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -145,7 +116,7 @@ function OfferScreen(): JSX.Element {
Meet the host
-
+
Angelina
@@ -164,13 +135,13 @@ function OfferScreen(): JSX.Element {
-
Other places in the neighbourhood
-
+
diff --git a/src/store/action.ts b/src/store/action.ts
index 366ca6f..e49c3af 100644
--- a/src/store/action.ts
+++ b/src/store/action.ts
@@ -2,6 +2,8 @@ import { createAction } from '@reduxjs/toolkit';
import { City } from '../types/location';
import { Point } from '../types/location';
import { Offer } from '../types/offer';
+import { AppRoute, AuthorizationStatus } from '../const';
+import { UserData } from '../types/user-data';
export const changeCity = createAction('CITY_CHANGE', (value: City) => ({
payload: value
@@ -23,10 +25,22 @@ export const changeChosenOffer = createAction('CHANGE_CHOSEN_OFFER', (value:Offe
payload: value
}));
-export const setQuestionsDataLoadingStatus = createAction('SET_QUESTIONS_DATA_LOADING_STATUS', (value: boolean) => ({
+export const setOffersDataLoadingStatus = createAction('SET_OFFERS_DATA_LOADING_STATUS', (value: boolean) => ({
payload: value
}));
export const setError = createAction('SET_ERROR', (value: string | null) => ({
payload: value
}));
+
+export const requireAuthorization = createAction('REQUIRE_AUTHORIZATION', (value: AuthorizationStatus) => ({
+ payload: value
+}));
+
+export const loadUserData = createAction('LOAD_USER_DATA', (value: UserData) => ({
+ payload: value
+}));
+
+export const redirectToRoute = createAction('REDIRECT_TO_ROUTE', (value: AppRoute) => ({
+ payload: value
+}));
diff --git a/src/store/api-actions.ts b/src/store/api-actions.ts
index 4cffb9f..c407edc 100644
--- a/src/store/api-actions.ts
+++ b/src/store/api-actions.ts
@@ -1,11 +1,13 @@
import { createAsyncThunk } from '@reduxjs/toolkit';
import { AppDispatch, State } from '../types/state';
import { AxiosInstance } from 'axios';
-import { loadOffers, setError, setQuestionsDataLoadingStatus } from './action';
+import { loadOffers, loadUserData, redirectToRoute, requireAuthorization, setError, setOffersDataLoadingStatus } from './action';
import { Offer } from '../types/offer';
-import { APIRoute, TIMEOUT_SHOW_ERROR } from '../const';
-
-import {store} from './';
+import { APIRoute, AppRoute, AuthorizationStatus, TIMEOUT_SHOW_ERROR } from '../const';
+import { store } from './';
+import { AuthData } from '../types/auth-data';
+import { UserData } from '../types/user-data';
+import { dropToken, saveToken } from '../services/token';
export const clearErrorAction = createAsyncThunk(
'CLEAR_ERROR_ACTION',
@@ -18,15 +20,59 @@ export const clearErrorAction = createAsyncThunk(
);
export const fetchOffersAction = createAsyncThunk
(
- 'FETCH_OFFERS_ACTION',
- async (_arg, {dispatch, extra: api}) => {
- dispatch(setQuestionsDataLoadingStatus(true));
- const {data} = await api.get(APIRoute.Offers);
- dispatch(setQuestionsDataLoadingStatus(false));
- dispatch(loadOffers(data));
- },
- );
+ dispatch: AppDispatch;
+ state: State;
+ extra: AxiosInstance;
+}>(
+ 'FETCH_OFFERS_ACTION',
+ async (_arg, { dispatch, extra: api }) => {
+ dispatch(setOffersDataLoadingStatus(true));
+ const { data } = await api.get(APIRoute.Offers);
+ dispatch(setOffersDataLoadingStatus(false));
+ dispatch(loadOffers(data));
+ },
+);
+
+export const checkAuthAction = createAsyncThunk(
+ 'CHECK_AUTH_ACTION',
+ async (_arg, { dispatch, extra: api }) => {
+ try {
+ await api.get(APIRoute.Login);
+ dispatch(requireAuthorization(AuthorizationStatus.Auth));
+ } catch {
+ dispatch(requireAuthorization(AuthorizationStatus.NoAuth));
+ }
+ },
+);
+
+export const loginAction = createAsyncThunk(
+ 'LOGIN_ACTION',
+ async ({ email, password }, { dispatch, extra: api }) => {
+ const { data } = await api.post(APIRoute.Login, { email, password });
+ saveToken(data.token);
+ dispatch(requireAuthorization(AuthorizationStatus.Auth));
+ dispatch(loadUserData(data));
+ dispatch(redirectToRoute(AppRoute.Main));
+ },
+);
+
+export const logoutAction = createAsyncThunk(
+ 'LOGOUT_ACTION',
+ async (_arg, { dispatch, extra: api }) => {
+ await api.delete(APIRoute.Logout);
+ dropToken();
+ dispatch(requireAuthorization(AuthorizationStatus.NoAuth));
+ },
+);
diff --git a/src/store/index.ts b/src/store/index.ts
index de49794..b6f6ecd 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -1,6 +1,7 @@
import { configureStore } from '@reduxjs/toolkit';
import { reducer } from './reducer';
import { createAPI } from '../services/api';
+import { redirect } from './middlewares/redirect';
export const api = createAPI();
@@ -11,5 +12,5 @@ export const store = configureStore({
thunk: {
extraArgument: api,
},
- })
+ }).concat(redirect),
});
diff --git a/src/store/middlewares/redirect.ts b/src/store/middlewares/redirect.ts
new file mode 100644
index 0000000..955a510
--- /dev/null
+++ b/src/store/middlewares/redirect.ts
@@ -0,0 +1,17 @@
+import {PayloadAction} from '@reduxjs/toolkit';
+import browserHistory from '../../browser-history';
+import {Middleware} from 'redux';
+import {reducer} from '../reducer';
+
+type Reducer = ReturnType;
+
+export const redirect: Middleware =
+ () =>
+ (next) =>
+ (action: PayloadAction) => {
+ if (action.type === 'REDIRECT_TO_ROUTE') {
+ browserHistory.push(action.payload);
+ }
+
+ return next(action);
+ };
diff --git a/src/store/reducer.ts b/src/store/reducer.ts
index 70300df..9110982 100644
--- a/src/store/reducer.ts
+++ b/src/store/reducer.ts
@@ -1,10 +1,11 @@
import { createReducer } from '@reduxjs/toolkit';
import { City } from '../types/location';
import { Offer } from '../types/offer';
-import { changeChosenOffer, changeCity, changeHighlightedMarker, changeSortOptions, loadOffers, setError, setQuestionsDataLoadingStatus } from './action';
+import { changeChosenOffer, changeCity, changeHighlightedMarker, changeSortOptions, loadOffers, loadUserData, requireAuthorization, setError, setOffersDataLoadingStatus } from './action';
import { filters } from '../utils';
import { Point } from '../types/location';
-import { CITIES } from '../const';
+import { AuthorizationStatus, CITIES } from '../const';
+import { UserData } from '../types/user-data';
type StateType = {
@@ -12,9 +13,11 @@ type StateType = {
offers: Offer[];
sortType: string;
highlightedMarker?: Point;
- chosenOffer: Offer | undefined;
- isQuestionsDataLoading: boolean;
+ chosenOffer?: Offer;
+ isOffersDataLoading: boolean;
error: string | null;
+ authorizationStatus: AuthorizationStatus;
+ userData?: UserData;
}
const initialState: StateType = {
@@ -23,8 +26,10 @@ const initialState: StateType = {
sortType: filters.POPULAR,
highlightedMarker: undefined,
chosenOffer: undefined,
- isQuestionsDataLoading: false,
- error: null
+ isOffersDataLoading: false,
+ error: null,
+ authorizationStatus: AuthorizationStatus.Unknown,
+ userData: undefined
};
const reducer = createReducer(initialState, (builder) => {
@@ -44,11 +49,17 @@ const reducer = createReducer(initialState, (builder) => {
.addCase(changeChosenOffer, (state, action) => {
state.chosenOffer = action.payload;
})
- .addCase(setQuestionsDataLoadingStatus, (state, action) => {
- state.isQuestionsDataLoading = action.payload;
+ .addCase(setOffersDataLoadingStatus, (state, action) => {
+ state.isOffersDataLoading = action.payload;
})
.addCase(setError, (state, action) => {
state.error = action.payload;
+ })
+ .addCase(requireAuthorization, (state, action) => {
+ state.authorizationStatus = action.payload;
+ })
+ .addCase(loadUserData, (state, action) => {
+ state.userData = action.payload;
});
});
diff --git a/src/types/auth-data.ts b/src/types/auth-data.ts
new file mode 100644
index 0000000..545c1e1
--- /dev/null
+++ b/src/types/auth-data.ts
@@ -0,0 +1,4 @@
+export type AuthData = {
+ email: string;
+ password: string;
+ };
diff --git a/src/types/user-data.ts b/src/types/user-data.ts
new file mode 100644
index 0000000..b9b39ed
--- /dev/null
+++ b/src/types/user-data.ts
@@ -0,0 +1,7 @@
+export type UserData = {
+ name: string;
+ email: string;
+ token: string;
+ avatarUrl: string;
+ isPro: boolean;
+ };