Skip to content

Commit

Permalink
Реализовал сортировку
Browse files Browse the repository at this point in the history
  • Loading branch information
Shepard-m committed Mar 9, 2024
1 parent 7948b89 commit 1cb285d
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 23 deletions.
5 changes: 3 additions & 2 deletions src/components/list-location.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import { MouseEvent } from 'react';
type ListLocation = {
listLocations: string[];
handleCurrentCityClick: (evt: MouseEvent<HTMLSpanElement>) => void;
currentCity: string;
}

export default function ListLocation({ listLocations, handleCurrentCityClick }: ListLocation) {
export default function ListLocation({ listLocations, handleCurrentCityClick, currentCity }: ListLocation) {
return (
<ul className="locations__list tabs__list" onClick={handleCurrentCityClick}>
{listLocations.map((location) => <Location key={location} city={location} />)}
{listLocations.map((location) => <Location key={location} city={location} isActive={currentCity === location} />)}
</ul>
);
}
7 changes: 4 additions & 3 deletions src/components/location.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
type LocationProps = {
city: string;
isActive: boolean;
}

export default function Location({ city }: LocationProps) {
export default function Location({ city, isActive }: LocationProps) {
return (
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<li className='locations__item'>
<a className={`locations__item-link tabs__item ${isActive ? 'tabs__item--active' : ''}`} href="#">
<span>{city}</span>
</a>
</li>
Expand Down
4 changes: 3 additions & 1 deletion src/components/map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const currentCustomIcon = leaflet.icon({

export default function Map(props: MapProps): JSX.Element {
const { city, offers, selectedOffer } = props;
console.log(city);

const mapRef = useRef(null);
const map = useMap(mapRef, city);

Expand All @@ -51,6 +51,8 @@ export default function Map(props: MapProps): JSX.Element {
mapRef.current = null;
};
}


}, [map, offers, selectedOffer, city]);

return (
Expand Down
15 changes: 15 additions & 0 deletions src/components/places-option.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { SyntheticEvent } from 'react';

type PlacesOptionProps = {
place: string;
handelSortOfferClick: (sortType: string) => void;
}

export default function PlacesOption({ place, handelSortOfferClick }: PlacesOptionProps) {
const onSortOfferClick = (evt: SyntheticEvent) => {
handelSortOfferClick(evt.target.textContent);

Check failure on line 10 in src/components/places-option.tsx

View workflow job for this annotation

GitHub Actions / Check

Unsafe argument of type `any` assigned to a parameter of type `string`

Check failure on line 10 in src/components/places-option.tsx

View workflow job for this annotation

GitHub Actions / build

Property 'textContent' does not exist on type 'EventTarget'.
};
return (
<li className="places__option" tabIndex={0} onClick={onSortOfferClick}>{place}</li>
);
}
15 changes: 15 additions & 0 deletions src/components/places-options.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import PlacesOption from './places-option';
import { placesOption } from '../const';

type PlacesOptionsProps = {
isOpen: boolean;
handelSortOfferClick: (sortType: string) => void;
}

export default function PlacesOptions({ isOpen, handelSortOfferClick }: PlacesOptionsProps) {
return (
<ul className={`places__options places__options--custom ${isOpen && 'places__options--opened'}`}>
{placesOption.map((place) => <PlacesOption key={place} place={place} handelSortOfferClick={handelSortOfferClick} />)}
</ul>
);
}
4 changes: 3 additions & 1 deletion src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ const OptionListCard = {
CITIES_CARD: 'cities__places-list places__list tabs__content',
};

const placesOption = ['Popular', 'Price: low to high', 'Price: high to low', 'Top rated first',];

const URL_MARKER_DEFAULT = '../markup/img/pin.svg';

const URL_MARKER_CURRENT = '../markup/img/pin-active.svg';


const CountStar: number = 5;

export { CountStar, AppRoute, AuthorizationStatus as authorizationStatus, OptionCard, URL_MARKER_DEFAULT, URL_MARKER_CURRENT, OptionListCard, MapSize };
export { CountStar, AppRoute, AuthorizationStatus as authorizationStatus, OptionCard, URL_MARKER_DEFAULT, URL_MARKER_CURRENT, OptionListCard, MapSize, placesOption };
4 changes: 1 addition & 3 deletions src/hooks/useMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ function useMap(
setMap(instance);
}

return () => {
isRenderedRef.current = true;
};
isRenderedRef.current = true;
}, [mapRef, city]);

return map;
Expand Down
28 changes: 18 additions & 10 deletions src/pages/main-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import { OfferPreviews } from '../types/offer-preview';
import { locations } from '../mocks/locations';
import ListLocation from '../components/list-location';
import { useAppDispatch, useAppSelector } from '../hooks';
import { selectCity } from '../store/action';
import { selectCity, sortOffer } from '../store/action';
import { offers } from '../mocks/offers';

import PlacesOptions from '../components/places-options';

export default function MainPage() {
const baseOffers = offers;
Expand All @@ -22,6 +22,10 @@ export default function MainPage() {
null
);

const [isOpenSort, setIsOpenSort] = useState<boolean>(
false
);

const [selectedCity, setSelectedCity] = useState<City>({
name: 'Paris',
location: {
Expand All @@ -31,6 +35,15 @@ export default function MainPage() {
}
});

const handelSortOfferClick = (sortType: string) => {
dispatch(sortOffer(sortType));
setIsOpenSort(!isOpenSort);
};

const handelOpenPlacesClick = () => {
setIsOpenSort(!isOpenSort);
};

const handleListItemHover = (currentCard: OfferPreviews | null) => {
setSelectedOffer(currentCard);
};
Expand All @@ -55,7 +68,7 @@ export default function MainPage() {
<h1 className="visually-hidden">Cities</h1>
<div className="tabs">
<section className="locations container">
<ListLocation listLocations={locations} handleCurrentCityClick={handleCurrentCityClick} />
<ListLocation listLocations={locations} handleCurrentCityClick={handleCurrentCityClick} currentCity={selectedCity.name} />
</section>
</div>
<div className="cities">
Expand All @@ -67,18 +80,13 @@ export default function MainPage() {
<b className="places__found">{selectOffers.length} place{selectOffers.length > 1 ? 's' : ''} to stay in Amsterdam</b>
<form className="places__sorting" action="#" method="get">
<span className="places__sorting-caption">Sort by</span>
<span className="places__sorting-type" tabIndex={0}>
<span className="places__sorting-type" tabIndex={0} onClick={handelOpenPlacesClick}>
Popular
<svg className="places__sorting-arrow" width="7" height="4">
<use xlinkHref="#icon-arrow-select"></use>
</svg>
</span>
<ul className="places__options places__options--custom places__options--opened">
<li className="places__option places__option--active" tabIndex={0}>Popular</li>
<li className="places__option" tabIndex={0}>Price: low to high</li>
<li className="places__option" tabIndex={0}>Price: high to low</li>
<li className="places__option" tabIndex={0}>Top rated first</li>
</ul>
<PlacesOptions isOpen={isOpenSort} handelSortOfferClick={handelSortOfferClick} />
</form>
<ListCards offers={selectOffers} onListItemHover={handleListItemHover} extraClass={OptionListCard.CITIES_CARD} />
</section> : <MainEmpty currentCity={selectedCity} />}
Expand Down
3 changes: 2 additions & 1 deletion src/store/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ import { createAction } from '@reduxjs/toolkit';
import { Offer } from '../types/offer';

const selectCity = createAction<Offer, string>('mainPage/selectCity');
const sortOffer = createAction<string>('mainPage/sortOffer');

export { selectCity };
export { selectCity, sortOffer };
20 changes: 19 additions & 1 deletion src/store/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createReducer } from '@reduxjs/toolkit';
import { selectCity } from './action';
import { selectCity, sortOffer } from './action';
import { offers } from '../mocks/offers';
import { placesOption } from '../const';
import { sortPriceLow, sortPriceHigh, sortRating } from '../utils/utils';

const initialState = {
city: 'Paris',
Expand All @@ -12,6 +14,22 @@ const reducer = createReducer(initialState, (builder) => {
.addCase(selectCity, (state, action) => {
state.city = action.payload.city.name;
state.offers = [...offers].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;
}
});
});

Expand Down
14 changes: 13 additions & 1 deletion src/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,16 @@ function humanizeOrderData(date: string, format: string) {
return date ? dayjs(date).format(format) : '';
}

export { getFavoritesByLocation, humanizeOrderData };
function sortPriceLow(offerA: Offer, offerB: Offer,) {
return offerA.price - offerB.price;
}

function sortPriceHigh(offerA: Offer, offerB: Offer,) {
return offerB.price - offerA.price;
}

function sortRating(offerA: Offer, offerB: Offer,) {
return offerB.rating - offerA.rating;
}

export { getFavoritesByLocation, humanizeOrderData, sortPriceLow, sortPriceHigh, sortRating };

0 comments on commit 1cb285d

Please sign in to comment.