From f2756c70eb088b6bb83fdd7000b9b51776495436 Mon Sep 17 00:00:00 2001 From: mayonnaise <90057279+Mayanzev@users.noreply.github.com> Date: Tue, 16 Apr 2024 22:44:27 +0300 Subject: [PATCH] module6-task1 --- src/components/app/app.tsx | 10 +--- src/components/city-list/city-list.tsx | 28 +++++++++ .../offer-card.tsx} | 4 +- src/components/offer-list/offer-list.tsx | 4 +- src/hooks/index.ts | 6 ++ src/index.tsx | 7 ++- src/mocks/cities.ts | 37 ++++++++++-- src/mocks/offers.ts | 18 ++++-- src/pages/main-screen/main-screen.tsx | 57 ++++--------------- src/pages/offer-screen/offer-screen.tsx | 4 +- src/store/action.ts | 8 +++ src/store/index.ts | 4 ++ src/store/reducer.ts | 28 +++++++++ src/types/offer.ts | 4 ++ src/types/state.ts | 5 ++ 15 files changed, 155 insertions(+), 69 deletions(-) create mode 100644 src/components/city-list/city-list.tsx rename src/components/{city-card/city-card.tsx => offer-card/offer-card.tsx} (95%) create mode 100644 src/hooks/index.ts create mode 100644 src/store/action.ts create mode 100644 src/store/index.ts create mode 100644 src/store/reducer.ts create mode 100644 src/types/state.ts diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx index 4b90a80..58c794b 100644 --- a/src/components/app/app.tsx +++ b/src/components/app/app.tsx @@ -9,17 +9,13 @@ import { AppRoute, AuthorizationStatus } from '../../const.ts'; import { Offer } from '../../types/offer'; import { OFFERS } from '../../mocks/offers.ts'; -type AppScreenProps = { - placesCount: number; -} - -function App({placesCount}: AppScreenProps): JSX.Element { +function App(): JSX.Element { const favourites: Offer[] = OFFERS.filter((o) => o.isFavorite); return ( } /> - } /> + } /> } /> - } /> + } /> ); diff --git a/src/components/city-list/city-list.tsx b/src/components/city-list/city-list.tsx new file mode 100644 index 0000000..4d11ef8 --- /dev/null +++ b/src/components/city-list/city-list.tsx @@ -0,0 +1,28 @@ +import { City } from '../../types/city'; +import { useAppDispatch } from '../../hooks'; +import { changeCity } from '../../store/action'; +import { CITIES } from '../../mocks/cities'; + +type CityListProps = { + chosenCity: City; +} + +function CityList({chosenCity}: CityListProps): JSX.Element { + const dispatch = useAppDispatch(); + const handleCityChange = (city: City) => { + dispatch(changeCity(city)); + }; + return( + + ); +} + +export default CityList; \ No newline at end of file diff --git a/src/components/city-card/city-card.tsx b/src/components/offer-card/offer-card.tsx similarity index 95% rename from src/components/city-card/city-card.tsx rename to src/components/offer-card/offer-card.tsx index 4cf4c8e..eb4aec7 100644 --- a/src/components/city-card/city-card.tsx +++ b/src/components/offer-card/offer-card.tsx @@ -6,7 +6,7 @@ type OfferProps = { cardType: string; } -function CityCard({offer, cardType}: OfferProps): JSX.Element { +function OfferCard({offer, cardType}: OfferProps): JSX.Element { return (
{offer.isPremium ? ( @@ -46,4 +46,4 @@ function CityCard({offer, cardType}: OfferProps): JSX.Element {
); } -export default CityCard; +export default OfferCard; diff --git a/src/components/offer-list/offer-list.tsx b/src/components/offer-list/offer-list.tsx index 8df4174..296b403 100644 --- a/src/components/offer-list/offer-list.tsx +++ b/src/components/offer-list/offer-list.tsx @@ -1,6 +1,6 @@ import { listToCard, typeOfCardList } from '../../const'; import { Offer } from '../../types/offer'; -import CityCard from '../city-card/city-card'; +import OfferCard from '../offer-card/offer-card'; type OfferListProps = { offers: Offer[]; @@ -12,7 +12,7 @@ function OfferList({offers, listType}: OfferListProps): JSX.Element { return (
{offers.map((offer) => ( - + ))}
); diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 0000000..33d597f --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1,6 @@ +import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'; +import type { State, AppDispatch } from '../types/state'; + +export const useAppDispatch = () => useDispatch(); + +export const useAppSelector: TypedUseSelectorHook = useSelector; \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index 135d8c4..ddf385a 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,8 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './components/app/app'; -import { Settings } from './const'; +import { Provider } from 'react-redux'; +import { store } from './store'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement @@ -9,6 +10,8 @@ const root = ReactDOM.createRoot( root.render( - + + + ); diff --git a/src/mocks/cities.ts b/src/mocks/cities.ts index b6a938c..3fd1a29 100644 --- a/src/mocks/cities.ts +++ b/src/mocks/cities.ts @@ -1,7 +1,34 @@ import { City } from '../types/city'; -export const AMSTERDAM: City = { - title: 'Amsterdam', - lat: 52.3740300, - lng: 4.8896900 -}; +export const CITIES: City[] = [ + { + title: 'Paris', + lat: 52.3740300, + lng: 4.8896900 + }, + { + title: 'Brussels', + lat: 52.3740300, + lng: 4.8896900 + }, + { + title: 'Cologne', + lat: 52.3740300, + lng: 4.8896900 + }, + { + title: 'Amsterdam', + lat: 52.3740300, + lng: 4.8896900 + }, + { + title: 'Hamburg', + lat: 52.3740300, + lng: 4.8896900 + }, + { + title: 'Dusseldorf', + lat: 52.3740300, + lng: 4.8896900 + }, +]; diff --git a/src/mocks/offers.ts b/src/mocks/offers.ts index 6cf9555..17b7543 100644 --- a/src/mocks/offers.ts +++ b/src/mocks/offers.ts @@ -1,4 +1,6 @@ import { Offer } from '../types/offer'; +import { CITIES } from './cities'; +import { POINTS } from './points'; import { REVIEWS } from './reviews'; export const OFFERS: Offer[] = [ @@ -11,7 +13,9 @@ export const OFFERS: Offer[] = [ type: 'Apartment', isFavorite: false, rating: 4, - reviews: [REVIEWS[0]] + reviews: [REVIEWS[0], REVIEWS[1]], + city: CITIES[0], + point: POINTS[0] }, { id: '2', @@ -22,7 +26,9 @@ export const OFFERS: Offer[] = [ type: 'Room', isFavorite: true, rating: 4, - reviews: [REVIEWS[1]] + reviews: [REVIEWS[1]], + city: CITIES[1], + point: POINTS[1] }, { id: '3', @@ -33,7 +39,9 @@ export const OFFERS: Offer[] = [ type: 'Apartment', isFavorite: false, rating: 4.7, - reviews: [REVIEWS[2]] + reviews: [REVIEWS[2]], + city: CITIES[0], + point: POINTS[2] }, { id: '4', @@ -44,6 +52,8 @@ export const OFFERS: Offer[] = [ type: 'Apartment', isFavorite: true, rating: 5, - reviews: [REVIEWS[3]] + reviews: [REVIEWS[3]], + city: CITIES[3], + point: POINTS[3] }, ]; diff --git a/src/pages/main-screen/main-screen.tsx b/src/pages/main-screen/main-screen.tsx index 22e0a69..4b066f2 100644 --- a/src/pages/main-screen/main-screen.tsx +++ b/src/pages/main-screen/main-screen.tsx @@ -1,17 +1,15 @@ -import { Offer } from '../../types/offer'; import OfferList from '../../components/offer-list/offer-list'; import { Link } from 'react-router-dom'; import Map from '../../components/map/map'; -import { POINTS } from '../../mocks/points'; -import { AMSTERDAM } from '../../mocks/cities'; import { typeOfCardList } from '../../const'; +import { useAppSelector } from '../../hooks'; +import CityList from '../../components/city-list/city-list'; -type MainScreenProps = { - placesCount: number; - offers: Offer[]; - } - -function MainScreen({placesCount, offers}: MainScreenProps): JSX.Element { +function MainScreen(): JSX.Element { + const [city, offers] = useAppSelector((state) => [state.city, state.offers]); + const chosenOffers = offers.filter((offer) => offer.city === city); + const points = chosenOffers.map((offer) => offer.point); + const favoriteOffers = offers.filter((offer) => offer.isFavorite); return (
@@ -30,7 +28,7 @@ function MainScreen({placesCount, offers}: MainScreenProps): JSX.Element {
Oliver.conner@gmail.com - 3 + {favoriteOffers.length} @@ -49,45 +47,14 @@ function MainScreen({placesCount, offers}: MainScreenProps): JSX.Element {

Cities

- +

Places

- {placesCount} places to stay in Amsterdam + {chosenOffers.length} places to stay in {city.title}
Sort by @@ -103,11 +70,11 @@ function MainScreen({placesCount, offers}: MainScreenProps): JSX.Element {
  • Top rated first
  • - +
    - +
    diff --git a/src/pages/offer-screen/offer-screen.tsx b/src/pages/offer-screen/offer-screen.tsx index ab72538..06af9b0 100644 --- a/src/pages/offer-screen/offer-screen.tsx +++ b/src/pages/offer-screen/offer-screen.tsx @@ -2,7 +2,7 @@ import { Link } from 'react-router-dom'; import ReviewsList from '../../components/reviews-list/reviews-list'; import { OFFERS } from '../../mocks/offers'; import { Offer } from '../../types/offer'; -import { AMSTERDAM } from '../../mocks/cities'; +import { CITIES } from '../../mocks/cities'; import { POINTS } from '../../mocks/points'; import Map from '../../components/map/map'; import OfferList from '../../components/offer-list/offer-list'; @@ -168,7 +168,7 @@ function OfferScreen({offer}: OfferScreenProps): JSX.Element {
    - +
    diff --git a/src/store/action.ts b/src/store/action.ts new file mode 100644 index 0000000..dc00bbf --- /dev/null +++ b/src/store/action.ts @@ -0,0 +1,8 @@ +import { createAction } from "@reduxjs/toolkit"; +import { City } from "../types/city"; + +export const getOffers = createAction('OFFERS_GET') + +export const changeCity = createAction('CITY_CHANGE', (value: City) => ({ + payload: value +})); \ No newline at end of file diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 0000000..faeda0c --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,4 @@ +import { configureStore } from '@reduxjs/toolkit'; +import { reducer } from './reducer'; + +export const store = configureStore({reducer}); \ No newline at end of file diff --git a/src/store/reducer.ts b/src/store/reducer.ts new file mode 100644 index 0000000..d64484d --- /dev/null +++ b/src/store/reducer.ts @@ -0,0 +1,28 @@ +import { createReducer } from '@reduxjs/toolkit'; +import { CITIES } from '../mocks/cities'; +import { OFFERS } from '../mocks/offers'; +import { City } from '../types/city'; +import { Offer } from '../types/offer'; +import { changeCity, getOffers } from './action'; + +type StateType = { + city: City; + offers: Offer[] + } + +const initialState: StateType = { + city: CITIES[0], + offers: OFFERS + }; + +const reducer = createReducer(initialState, (builder) => { + builder + .addCase(getOffers, (state) => { + state.offers = OFFERS; + }) + .addCase(changeCity, (state, action) => { + state.city = action.payload; + }); +}); + +export {reducer}; \ No newline at end of file diff --git a/src/types/offer.ts b/src/types/offer.ts index cbe3352..9811de6 100644 --- a/src/types/offer.ts +++ b/src/types/offer.ts @@ -1,4 +1,6 @@ +import { Point } from './point'; import { Review } from '../types/review'; +import { City } from './city'; export type Offer = { id: string; @@ -10,4 +12,6 @@ export type Offer = { isFavorite: boolean; rating: number; reviews: Review[]; + city: City; + point: Point; }; diff --git a/src/types/state.ts b/src/types/state.ts new file mode 100644 index 0000000..c45a265 --- /dev/null +++ b/src/types/state.ts @@ -0,0 +1,5 @@ +import { store } from '../store/index.js'; + +export type State = ReturnType; + +export type AppDispatch = typeof store.dispatch;