+
+
+ {offer.isPremium}
+
+
+
+ {offer.title}
+
+
+
+
+
+
+ Rating
-
- -
- {offer.type}
-
- -
- {offer.bedrooms} Bedrooms
-
- -
+ {offer.rating}
+
+
+ -
+ {offer.type}
+
+ -
+ {offer.bedrooms} Bedrooms
+
+ -
Max {offer.maxAdults} adults
-
+
+
+
+ €{offer.price}
+ night
+
+
+
What's inside
+
+ {offer.goods.map((good) => (
+ -
+ {good}
+
+ ))}
-
- €{offer.price}
- night
-
-
-
What's inside
-
- {offer.goods.map((good) => (
- -
- {good}
-
- ))}
-
-
-
-
Meet the host
-
-
-
-
-
- {offer.host.name}
-
-
- {offer.host.isPro && 'Pro'}
-
-
-
-
- {offer.description}
-
+
+
+
Meet the host
+
+
+
+
+ {offer.host.name}
+
+
+ {offer.host.isPro && 'Pro'}
+
+
+
+
+ {offer.description}
+
-
- Reviews · {reviews.length}
-
-
-
+
+ Reviews · {reviews.length}
+
+ {isAuth && }
+
-
-
-
-
- Other places in the neighbourhood
-
- {}} />
-
-
-
-
- );
- } else {
- return(
-
- );
- }
+
+
+
+
+ Other places in the neighbourhood
+
+ {}} />
+
+
+
+
+
+ );
}
diff --git a/src/servises/api.ts b/src/servises/api.ts
index 83dfb8f..a717b24 100644
--- a/src/servises/api.ts
+++ b/src/servises/api.ts
@@ -1,7 +1,7 @@
import axios, {AxiosError, AxiosInstance, InternalAxiosRequestConfig} from 'axios';
import {getToken} from './token.ts';
import {store} from '../store';
-import {setAuthorizationStatus} from '../store/action.ts';
+import {setAuthorizationStatus, setDetailOffer} from '../store/action.ts';
import {AuthorizationStatus} from '../const.ts';
const baseURL = 'https://14.design.htmlacademy.pro/six-cities';
@@ -38,6 +38,9 @@ export const createAPI = () : AxiosInstance => {
setAuthorizationStatus(AuthorizationStatus.Unauthorized),
);
}
+ if (error.response && error.response.status === 404) {
+ store.dispatch(setDetailOffer(undefined));
+ }
throw error;
},
);
diff --git a/src/store/action.ts b/src/store/action.ts
index 2578a64..352a3af 100644
--- a/src/store/action.ts
+++ b/src/store/action.ts
@@ -4,12 +4,13 @@ import {Offer} from '../types/offer.ts';
import {DetailOffer} from '../types/detail-offer.ts';
import {Review} from '../types/review.ts';
import {AuthorizationStatus} from '../const.ts';
+import {Nullable} from 'vitest';
export const changeActiveCity = createAction
('offers/changeActiveCity');
export const setOffers = createAction('offers/setOffers');
-export const setDetailOffer = createAction('offers/setDetailOffer');
+export const setDetailOffer = createAction>('offers/setDetailOffer');
export const setNearOffers = createAction('offers/setNearOffers');
diff --git a/src/store/api-actions.ts b/src/store/api-actions.ts
index ee03bf4..b6d38de 100644
--- a/src/store/api-actions.ts
+++ b/src/store/api-actions.ts
@@ -3,11 +3,12 @@ import {AppDispatch, State} from '../types/state.ts';
import {AxiosInstance} from 'axios';
import {Offer} from '../types/offer.ts';
import {apiRoute, AuthorizationStatus} from '../const.ts';
-import {setOffers, setDetailOffer, setNearOffers, setReviews, setAuthorizationStatus} from './action.ts';
+import {setAuthorizationStatus, setDetailOffer, setNearOffers, setOffers, setReviews} from './action.ts';
import {DetailOffer} from '../types/detail-offer.ts';
-import {Review} from '../types/review.ts';
-import {saveToken} from '../servises/token.ts';
+import {Review, ReviewInfo} from '../types/review.ts';
+import {saveToken, dropToken} from '../servises/token.ts';
import {AuthInfo, LoginInfo} from '../types/user.ts';
+import {store} from './index.ts';
export const fetchOffers = createAsyncThunk('auth/login', async (loginInfo, { dispatch, extra: api }) => {
- const response = await api.post(apiRoute.login, loginInfo);
- if (response.status === 200 || response.status === 201) {
- dispatch(setAuthorizationStatus(AuthorizationStatus.Authorized));
- saveToken(response.data.token);
- } else {
- throw response;
+export const sendReview = createAsyncThunk(
+ 'data/fetchReviews', async (reviewInfo, {extra: api}) => {
+ const response = await api.post(`${apiRoute.reviews}/${reviewInfo.offerId}`, {
+ comment: reviewInfo.comment,
+ rating: reviewInfo.rating
+ });
+ if (response.status === 201) {
+ store.dispatch(fetchReviews(reviewInfo.offerId));
+ }
}
-});
+);
-export const checkAuthorization = createAsyncThunk('auth/checkAuthorization', async (_arg, { dispatch, extra: api }) => {
- await api.get(apiRoute.login);
- dispatch(setAuthorizationStatus(AuthorizationStatus.Unauthorized));
-});
+export const login = createAsyncThunk(
+ 'auth/login', async (loginInfo, { dispatch, extra: api }) => {
+ const response = await api.post(apiRoute.login, loginInfo);
+ if (response.status === 200 || response.status === 201) {
+ dispatch(setAuthorizationStatus(AuthorizationStatus.Authorized));
+ saveToken(response.data.token);
+ } else {
+ throw response;
+ }
+ });
-export const logut = createAsyncThunk('auth/logout', async (_arg, { dispatch, extra: api }) => {
- await api.delete(apiRoute.logout);
- dispatch(setAuthorizationStatus(AuthorizationStatus.Unauthorized));
-});
+export const checkAuthorization = createAsyncThunk(
+ 'auth/checkAuthorization', async (_arg, { dispatch, extra: api }) => {
+ const responce = await api.get(apiRoute.login);
+ if (responce.status === 200 || responce.status === 201){
+ dispatch(setAuthorizationStatus(AuthorizationStatus.Authorized));
+ }else {
+ dispatch(setAuthorizationStatus(AuthorizationStatus.Unauthorized));
+ }
+ });
+
+export const logout = createAsyncThunk(
+ 'auth/logout', async (_arg, { dispatch, extra: api }) => {
+ await api.delete(apiRoute.logout);
+ dropToken();
+ dispatch(setAuthorizationStatus(AuthorizationStatus.Unauthorized));
+ });
diff --git a/src/store/reducer.ts b/src/store/reducer.ts
index 952049f..d978964 100644
--- a/src/store/reducer.ts
+++ b/src/store/reducer.ts
@@ -12,11 +12,12 @@ import {City} from '../types/city.ts';
import {Offer} from '../types/offer.ts';
import {DetailOffer} from '../types/detail-offer.ts';
import {Review} from '../types/review.ts';
+import {Nullable} from 'vitest';
type InitialState = {
activeCity: City;
offers: Offer[];
- detailOffer: DetailOffer | null;
+ detailOffer: Nullable;
nearOffers: Offer[];
reviews: Review[];
authorizationStatus: AuthorizationStatus;
diff --git a/src/types/review.ts b/src/types/review.ts
index 3563fe7..4c9006c 100644
--- a/src/types/review.ts
+++ b/src/types/review.ts
@@ -7,3 +7,9 @@ export type Review = {
comment: string;
rating: number;
};
+
+export type ReviewInfo = {
+ offerId: string;
+ comment: string;
+ rating: number;
+};