From a97e3e6910b337a1874b5aa16cd0ab39c645c305 Mon Sep 17 00:00:00 2001 From: Gurikov Maxim Date: Tue, 12 Nov 2024 14:36:50 +0500 Subject: [PATCH] change solution to use store --- .../{ => favorites-page}/favorites-page.tsx | 6 ++-- src/Pages/{ => login-page}/login-page.tsx | 0 src/Pages/{ => main-page}/main-page.tsx | 34 +++++++++---------- src/Pages/{ => offer-page}/offer-page.tsx | 26 +++++++------- src/components/app.tsx | 8 ++--- src/components/offer/offer-sort-select.tsx | 19 +++++------ src/mocks/offers.ts | 23 +++++++++++++ src/store/actions.ts | 7 ++-- src/store/store.ts | 9 +++-- 9 files changed, 79 insertions(+), 53 deletions(-) rename src/Pages/{ => favorites-page}/favorites-page.tsx (86%) rename src/Pages/{ => login-page}/login-page.tsx (100%) rename src/Pages/{ => main-page}/main-page.tsx (68%) rename src/Pages/{ => offer-page}/offer-page.tsx (82%) diff --git a/src/Pages/favorites-page.tsx b/src/Pages/favorites-page/favorites-page.tsx similarity index 86% rename from src/Pages/favorites-page.tsx rename to src/Pages/favorites-page/favorites-page.tsx index f8a3e67..e605929 100644 --- a/src/Pages/favorites-page.tsx +++ b/src/Pages/favorites-page/favorites-page.tsx @@ -1,7 +1,7 @@ import { Helmet } from 'react-helmet-async'; -import { Layout } from '../components/layout.tsx'; -import { OfferGroup } from '../components/offer/offer-group.tsx'; -import { Offer } from '../dataTypes/offer.ts'; +import { Layout } from '../../components/layout.tsx'; +import { OfferGroup } from '../../components/offer/offer-group.tsx'; +import { Offer } from '../../dataTypes/offer.ts'; interface FavoritesPageProps { offers: Offer[]; diff --git a/src/Pages/login-page.tsx b/src/Pages/login-page/login-page.tsx similarity index 100% rename from src/Pages/login-page.tsx rename to src/Pages/login-page/login-page.tsx diff --git a/src/Pages/main-page.tsx b/src/Pages/main-page/main-page.tsx similarity index 68% rename from src/Pages/main-page.tsx rename to src/Pages/main-page/main-page.tsx index 3f7f3c6..a78219c 100644 --- a/src/Pages/main-page.tsx +++ b/src/Pages/main-page/main-page.tsx @@ -1,26 +1,27 @@ /* eslint-disable react-hooks/exhaustive-deps */ -import React, { useEffect, useState } from 'react'; -import { Offer } from '../dataTypes/offer.ts'; -import { OffersList } from '../components/offer/offers-list.tsx'; -import { Layout } from '../components/layout.tsx'; +import React, { useState } from 'react'; +import { Offer } from '../../dataTypes/offer.ts'; +import { OffersList } from '../../components/offer/offers-list.tsx'; +import { Layout } from '../../components/layout.tsx'; import { Helmet } from 'react-helmet-async'; import { Nullable } from 'vitest'; -import { Map } from '../components/map/map.tsx'; -import { useAppSelector } from '../store/store.ts'; -import { CitiesList } from '../components/cities-list.tsx'; -import { pluralizeAndCombine } from '../utils/string-utils.ts'; -import { OfferSortSelect } from '../components/offer/offer-sort-select.tsx'; +import { Map } from '../../components/map/map.tsx'; +import { useAppSelector } from '../../store/store.ts'; +import { CitiesList } from '../../components/cities-list.tsx'; +import { pluralizeAndCombine } from '../../utils/string-utils.ts'; +import { OfferSortSelect } from '../../components/offer/offer-sort-select.tsx'; export function MainPage(): React.JSX.Element { const [activeOffer, setActiveOffer] = useState>(null); - const [offers, setOffers] = useState([]); const city = useAppSelector((state) => state.city); const unsortedOffers = useAppSelector((state) => state.offers).filter( (offer) => offer.city.name === city.name, ); - useEffect(() => { - setOffers(unsortedOffers); - }, [city]); + const sort = useAppSelector((state) => state.sorting); + const offers = sort(unsortedOffers); + const offersCountCaption = offers.length === 0 + ? 'No places to stay available' + : `${pluralizeAndCombine('place', offers.length)} to stay in ${city.name}`; return (
@@ -33,12 +34,9 @@ export function MainPage(): React.JSX.Element {

Places

- {pluralizeAndCombine('place', offers.length)} to stay in{' '} - {city.name} + {offersCountCaption} - setOffers(sort(offers))} - /> + ) => diff --git a/src/Pages/offer-page.tsx b/src/Pages/offer-page/offer-page.tsx similarity index 82% rename from src/Pages/offer-page.tsx rename to src/Pages/offer-page/offer-page.tsx index 8d649f4..2649246 100644 --- a/src/Pages/offer-page.tsx +++ b/src/Pages/offer-page/offer-page.tsx @@ -1,19 +1,19 @@ import { Helmet } from 'react-helmet-async'; -import { Layout } from '../components/layout.tsx'; -import { OffersList } from '../components/offer/offers-list.tsx'; -import { offerMocks } from '../mocks/offers.ts'; -import { Reviews } from '../components/reviews/reviews.tsx'; -import { reviewMocks } from '../mocks/reviews.ts'; -import { Map } from '../components/map/map.tsx'; +import { Layout } from '../../components/layout.tsx'; +import { OffersList } from '../../components/offer/offers-list.tsx'; +import { offerMocks } from '../../mocks/offers.ts'; +import { Reviews } from '../../components/reviews/reviews.tsx'; +import { reviewMocks } from '../../mocks/reviews.ts'; +import { Map } from '../../components/map/map.tsx'; import React from 'react'; import { useParams } from 'react-router-dom'; -import { OfferInsideItems } from '../components/offer/offer-inside-items.tsx'; -import { detailedOfferMocks } from '../mocks/detailed-offer.ts'; -import { OfferHost } from '../components/offer/offer-host.tsx'; -import { capitalize, pluralizeAndCombine } from '../utils/string-utils.ts'; -import { Rating } from '../components/rating.tsx'; -import { OfferGallery } from '../components/offer/offer-gallery.tsx'; -import { BookmarkButton } from '../components/bookmark-button.tsx'; +import { OfferInsideItems } from '../../components/offer/offer-inside-items.tsx'; +import { detailedOfferMocks } from '../../mocks/detailed-offer.ts'; +import { OfferHost } from '../../components/offer/offer-host.tsx'; +import { capitalize, pluralizeAndCombine } from '../../utils/string-utils.ts'; +import { Rating } from '../../components/rating.tsx'; +import { OfferGallery } from '../../components/offer/offer-gallery.tsx'; +import { BookmarkButton } from '../../components/bookmark-button.tsx'; export function OfferPage(): React.JSX.Element { const offerId = useParams().id; diff --git a/src/components/app.tsx b/src/components/app.tsx index 1d523c1..dccd602 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -1,8 +1,8 @@ -import { MainPage } from '../pages/main-page.tsx'; +import { MainPage } from '../pages/main-page/main-page.tsx'; import { BrowserRouter, Route, Routes } from 'react-router-dom'; -import { LoginPage } from '../pages/login-page.tsx'; -import { FavoritesPage } from '../pages/favorites-page.tsx'; -import { OfferPage } from '../pages/offer-page.tsx'; +import { LoginPage } from '../pages/login-page/login-page.tsx'; +import { FavoritesPage } from '../pages/favorites-page/favorites-page.tsx'; +import { OfferPage } from '../pages/offer-page/offer-page.tsx'; import { NotFoundPage } from '../pages/not-found-page/not-found-page.tsx'; import { AuthorizationWrapper } from './authorization-wrapper.tsx'; import { AppRoutes } from '../dataTypes/enums/app-routes.ts'; diff --git a/src/components/offer/offer-sort-select.tsx b/src/components/offer/offer-sort-select.tsx index 59872dc..9648616 100644 --- a/src/components/offer/offer-sort-select.tsx +++ b/src/components/offer/offer-sort-select.tsx @@ -1,35 +1,32 @@ import React, { useState } from 'react'; import { Offer } from '../../dataTypes/offer.ts'; import { SortOffers } from '../../dataTypes/sort-offers.ts'; - -interface OfferSortSelectProps { - onSortChange: (sort: SortOffers) => void; -} +import { useAppDispatch } from '../../store/store.ts'; +import { setSorting } from '../../store/actions.ts'; const sortingOptions: [string, SortOffers][] = [ ['Popular', (offers: Offer[]) => offers], [ 'Price: low to high', - (offers: Offer[]) => offers.sort((a, b) => a.price - b.price), + (offers: Offer[]) => offers.toSorted((a, b) => a.price - b.price), ], [ 'Price: high to low', - (offers: Offer[]) => offers.sort((a, b) => b.price - a.price), + (offers: Offer[]) => offers.toSorted((a, b) => b.price - a.price), ], [ 'Top rated first', - (offers: Offer[]) => offers.sort((a, b) => b.rating - a.rating), + (offers: Offer[]) => offers.toSorted((a, b) => b.rating - a.rating), ], ]; -export function OfferSortSelect({ - onSortChange, -}: OfferSortSelectProps): React.JSX.Element { +export function OfferSortSelect(): React.JSX.Element { const [isOpen, setIsOpen] = useState(false); const [sortingOption, setSortingOption] = useState('Popular'); + const dispatch = useAppDispatch(); const handleSortChange = (sort: SortOffers, sortingOptionName: string) => { setSortingOption(sortingOptionName); - onSortChange(sort); + dispatch(setSorting(sort)); setIsOpen(false); }; return ( diff --git a/src/mocks/offers.ts b/src/mocks/offers.ts index ed92151..87a63c7 100644 --- a/src/mocks/offers.ts +++ b/src/mocks/offers.ts @@ -94,4 +94,27 @@ export const offerMocks: Offer[] = [ rating: 5, previewImage: 'apartment-02.jpg', }, + { + id: '6af6f711-c28d-4121-82cd-e0b462a27f44', + title: 'amogus', + type: RoomType.Apartment, + price: 88, + city: { + name: 'Paris', + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + }, + location: { + latitude: 48.9, + longitude: 2.4, + zoom: 8, + }, + isFavorite: true, + isPremium: true, + rating: 5, + previewImage: 'apartment-02.jpg', + }, ]; diff --git a/src/store/actions.ts b/src/store/actions.ts index 9eb1142..edd99b1 100644 --- a/src/store/actions.ts +++ b/src/store/actions.ts @@ -1,7 +1,10 @@ import { createAction } from '@reduxjs/toolkit'; import { City } from '../dataTypes/city.ts'; import { Offer } from '../dataTypes/offer.ts'; +import { SortOffers } from '../dataTypes/sort-offers.ts'; -export const changeCity = createAction('mainPage/changeCity'); +export const changeCity = createAction('offers/changeCity'); -export const fillOffers = createAction('mainPage/fillOffers'); +export const setOffers = createAction('offers/setOffers'); + +export const setSorting = createAction('offers/setSorting'); diff --git a/src/store/store.ts b/src/store/store.ts index e797120..a46b772 100644 --- a/src/store/store.ts +++ b/src/store/store.ts @@ -1,13 +1,15 @@ import { configureStore, createReducer } from '@reduxjs/toolkit'; -import { changeCity, fillOffers } from './actions.ts'; +import {changeCity, setOffers, setSorting} from './actions.ts'; import { offerMocks } from '../mocks/offers.ts'; import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; import { AppDispatch, State } from '../dataTypes/store-types.ts'; import { PARIS } from '../consts/cities.ts'; +import {Offer} from '../dataTypes/offer.ts'; const initialState = { city: PARIS, offers: offerMocks, + sorting: (offers: Offer[]) => offers, }; const reducer = createReducer(initialState, (builder) => { @@ -15,8 +17,11 @@ const reducer = createReducer(initialState, (builder) => { .addCase(changeCity, (state, action) => { state.city = action.payload; }) - .addCase(fillOffers, (state, action) => { + .addCase(setOffers, (state, action) => { state.offers = action.payload; + }) + .addCase(setSorting, (state, action) => { + state.sorting = action.payload; }); });