- {dataOffer.images.map((image: string) => (
+ {offer.images.map((image: string) => (
@@ -52,14 +52,14 @@ export default function OfferPage() {
- {dataOffer.isPremium &&
+ {offer.isPremium &&
Premium
}
- {dataOffer.title}
+ {offer.title}
-
+
-
- {dataOffer.type && dataOffer.type}
+ {offer.type && offer.type}
-
- {dataOffer.bedrooms && `${dataOffer.bedrooms} Bedrooms`}
+ {offer.bedrooms && `${offer.bedrooms} Bedrooms`}
-
- {dataOffer.maxAdults && `Max ${dataOffer.maxAdults} adults`}
+ {offer.maxAdults && `Max ${offer.maxAdults} adults`}
- €{dataOffer.price}
+ €{offer.price}
night
What's inside
- {dataOffer.goods.map((good) => )}
+ {offer.goods.map((good) => )}
Meet the host
-
+
- {dataOffer.host.name}
+ {offer.host.name}
- {dataOffer.host.isPro &&
+ {offer.host.isPro &&
Pro
}
@@ -114,20 +114,20 @@ export default function OfferPage() {
- Reviews · 1
-
+ Reviews · {comments.length}
+
Other places in the neighbourhood
-
+
diff --git a/src/service/api.ts b/src/service/api.ts
new file mode 100644
index 0000000..811032c
--- /dev/null
+++ b/src/service/api.ts
@@ -0,0 +1,13 @@
+import axios, { AxiosInstance } from 'axios';
+
+const BASE_URL = 'https://15.design.htmlacademy.pro/six-cities';
+const REQUEST_TIMEOUT = 5000;
+
+export const createAPI = (): AxiosInstance => {
+ const api = axios.create({
+ baseURL: BASE_URL,
+ timeout: REQUEST_TIMEOUT,
+ });
+
+ return api;
+};
diff --git a/src/store/action.ts b/src/store/action.ts
index 66ea6c7..70cc84a 100644
--- a/src/store/action.ts
+++ b/src/store/action.ts
@@ -1,6 +1,22 @@
import { createAction } from '@reduxjs/toolkit';
+import { Offer } from '../types/offer';
+import { OfferPreviews } from '../types/offer-preview';
+import { Comment } from '../types/comment';
const selectCity = createAction
('mainPage/selectCity');
+
const sortOffer = createAction('mainPage/sortOffer');
-export { selectCity, sortOffer };
+const loadOffer = createAction('data/loadOffers');
+
+const loadComments = createAction('data/loadComments');
+
+const loadFavorite = createAction('data/loadFavorite');
+
+const chooseOffer = createAction('mainPage/chooseOffer');
+
+const chooseId = createAction('mainPage/chooseId');
+
+const setOfferDataLoadingStatus = createAction('data/setOfferDataLoadingStatus');
+
+export { selectCity, sortOffer, loadOffer, setOfferDataLoadingStatus, loadComments, loadFavorite, chooseOffer, chooseId };
diff --git a/src/store/api-action.ts b/src/store/api-action.ts
new file mode 100644
index 0000000..8fb695f
--- /dev/null
+++ b/src/store/api-action.ts
@@ -0,0 +1,71 @@
+import { createAsyncThunk } from '@reduxjs/toolkit';
+import { AppDispatch, State } from '../types/state';
+import { AxiosInstance } from 'axios';
+import { Offer } from '../types/offer';
+import { APIRoute } from '../const';
+import { Comment } from '../types/comment';
+import { loadOffer, setOfferDataLoadingStatus, loadComments, loadFavorite, chooseOffer } from './action';
+
+export const fetchOffersAction = createAsyncThunk(
+ 'data/fetchOffers',
+ async (_arg, { dispatch, extra: api }) => {
+ dispatch(setOfferDataLoadingStatus(true));
+ const { data } = await api.get(APIRoute.OFFERS);
+ dispatch(setOfferDataLoadingStatus(false));
+ dispatch(loadOffer(data));
+ },
+);
+
+export const fetchCommentsAction = createAsyncThunk(
+ 'data/loadComments',
+ async (_arg, { dispatch, getState, extra: api }) => {
+ const state = getState();
+ dispatch(setOfferDataLoadingStatus(true));
+ const { data } = await api.get(`${APIRoute.COMMENTS}/${state.idOffer}`);
+ dispatch(setOfferDataLoadingStatus(false));
+ console.log(data);
+ dispatch(loadComments(data));
+ },
+);
+
+export const fetchOfferAction = createAsyncThunk(
+ 'mainPage/chooseOffer',
+ async (_arg, { dispatch, getState, extra: api }) => {
+ const state = getState();
+ dispatch(setOfferDataLoadingStatus(true));
+ const { data } = await api.get(`${APIRoute.OFFERS}/${state.idOffer}`);
+ dispatch(setOfferDataLoadingStatus(false));
+ console.log(data);
+ dispatch(chooseOffer(data));
+ },
+);
+
+// export const fetchFavoriteAction = createAsyncThunk(
+// 'data/fetchOffers',
+// async (_arg, { dispatch, extra: api }) => {
+// dispatch(setOfferDataLoadingStatus(true));
+// const { data } = await api.get(APIRoute.OFFERS);
+// const { comments } = await api.get(APIRoute.COMMENTS);
+// const { favorite } = await api.get(APIRoute.FAVORITE);
+// const { user } = await api.get(APIRoute.USER);
+// dispatch(setOfferDataLoadingStatus(false));
+// dispatch(loadOffer(data));
+// },
+// );
+
diff --git a/src/store/index.ts b/src/store/index.ts
index b6e9107..979ce10 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -1,6 +1,17 @@
import { configureStore } from '@reduxjs/toolkit';
import { reducer } from './reducer';
+import { createAPI } from '../service/api';
-const store = configureStore({ reducer });
+const api = createAPI();
+
+const store = configureStore({
+ reducer,
+ middleware: (getDefaultMiddleware) =>
+ getDefaultMiddleware({
+ thunk: {
+ extraArgument: api,
+ },
+ })
+});
export { store };
diff --git a/src/store/reducer.ts b/src/store/reducer.ts
index 594c2fb..b526d90 100644
--- a/src/store/reducer.ts
+++ b/src/store/reducer.ts
@@ -1,35 +1,46 @@
import { createReducer } from '@reduxjs/toolkit';
-import { selectCity, sortOffer } from './action';
+import { selectCity, sortOffer, loadOffer, setOfferDataLoadingStatus, loadComments, chooseOffer, chooseId } from './action';
import { offers } from '../mocks/offers';
-import { placesOption } from '../const';
-import { sortPriceLow, sortPriceHigh, sortRating } from '../utils/utils';
+import { sortingOffers } from '../hooks/sort';
+import { LocationCity } from '../const';
+import { Offer } from '../types/offer';
+import { OfferPreviews } from '../types/offer-preview';
+import { Comment } from '../types/comment';
const initialState = {
- city: 'Paris',
- offers: [...offers].filter((offer) => offer.city.name === 'Paris'),
+ city: LocationCity.PARIS,
+ offers: [],
+ initialOffers: [],
+ isOfferDataLoadingStatus: false,
+ comments: [],
+ currentOffer: null,
+ idOffer: null,
};
const reducer = createReducer(initialState, (builder) => {
builder
.addCase(selectCity, (state, action) => {
state.city = action.payload;
- state.offers = [...offers].filter((offer) => offer.city.name === state.city);
+ state.offers = state.initialOffers.filter((offer) => offer.city.name === state.city);
})
.addCase(sortOffer, (state, action) => {
- switch (action.payload) {
- case placesOption[0]:
- state.offers = [...offers].filter((offer) => offer.city.name === state.city);
- break;
- case placesOption[1]:
- state.offers = state.offers.sort(sortPriceHigh);
- break;
- case placesOption[2]:
- state.offers = state.offers.sort(sortPriceLow);
- break;
- case placesOption[3]:
- state.offers = state.offers.sort(sortRating);
- break;
- }
+ state.offers = sortingOffers(action.payload, state.offers, offers);
+ })
+ .addCase(loadOffer, (state, action) => {
+ state.initialOffers = action.payload;
+ state.offers = state.initialOffers.filter((offer) => offer.city.name === state.city);
+ })
+ .addCase(setOfferDataLoadingStatus, (state, action) => {
+ state.isOfferDataLoadingStatus = action.payload;
+ })
+ .addCase(chooseId, (state, action) => {
+ state.idOffer = action.payload;
+ })
+ .addCase(loadComments, (state, action) => {
+ state.comments = action.payload;
+ })
+ .addCase(chooseOffer, (state, action) => {
+ state.currentOffer = action.payload;
});
});
diff --git a/src/types/list-location.ts b/src/types/list-location.ts
new file mode 100644
index 0000000..4a27e86
--- /dev/null
+++ b/src/types/list-location.ts
@@ -0,0 +1,8 @@
+export type listLocation = {
+ PARIS: string;
+ COLOGNE: string;
+ BRUSSELS: string;
+ AMSTERDAM: string;
+ HAMBURG: string;
+ DUSSELDORF: string;
+};
diff --git a/src/utils/utils.ts b/src/utils/utils.ts
index d9bc3b9..d213365 100644
--- a/src/utils/utils.ts
+++ b/src/utils/utils.ts
@@ -1,4 +1,5 @@
import { Offer } from '../types/offer';
+import { OfferPreviews } from '../types/offer-preview';
import dayjs from 'dayjs';
function getFavoritesByLocation(favorites: Offer[]) {
@@ -19,15 +20,15 @@ function humanizeOrderData(date: string, format: string) {
return date ? dayjs(date).format(format) : '';
}
-function sortPriceLow(offerA: Offer, offerB: Offer,) {
+function sortPriceLow(offerA: OfferPreviews, offerB: OfferPreviews,) {
return offerA.price - offerB.price;
}
-function sortPriceHigh(offerA: Offer, offerB: Offer,) {
+function sortPriceHigh(offerA: OfferPreviews, offerB: OfferPreviews,) {
return offerB.price - offerA.price;
}
-function sortRating(offerA: Offer, offerB: Offer,) {
+function sortRating(offerA: OfferPreviews, offerB: OfferPreviews,) {
return offerB.rating - offerA.rating;
}