From c4bd1d52081e7ae7938ade154972ed907286dfeb Mon Sep 17 00:00:00 2001
From: "hani.mohammad"
Date: Sat, 16 Nov 2024 18:22:45 +0300
Subject: [PATCH 1/3] set sort and mark on map
---
src/components/FilterOffers/FilterOffer.tsx | 51 +++++++++++++++++++++
src/components/MainPage/MainPage.tsx | 41 +++++++++--------
src/components/Map/Map.tsx | 46 +++++++++++--------
src/components/Offer/OfferCard.tsx | 10 ++--
src/components/Offer/OfferList.tsx | 5 +-
src/types/types.ts | 7 ++-
6 files changed, 116 insertions(+), 44 deletions(-)
create mode 100644 src/components/FilterOffers/FilterOffer.tsx
diff --git a/src/components/FilterOffers/FilterOffer.tsx b/src/components/FilterOffers/FilterOffer.tsx
new file mode 100644
index 0000000..c1c6c0f
--- /dev/null
+++ b/src/components/FilterOffers/FilterOffer.tsx
@@ -0,0 +1,51 @@
+import React, { useState } from 'react';
+import { SortName } from '../../types/types';
+
+type FilterOfferProps = {
+ currentSort: SortName;
+ onSortChange: (sortType: SortName) => void;
+}
+
+const SORT_TYPES = [
+ { label: 'Popular', value: SortName.popular },
+ { label: 'Price: low to high', value: SortName.lowToHigh },
+ { label: 'Price: high to low', value: SortName.highToLow },
+ { label: 'Top rated first', value: SortName.topRated },
+];
+
+const SORT_ACTIVE = 'places__option--active';
+
+export const FilterOffer: React.FC = ({
+ currentSort,
+ onSortChange,
+}) => {
+ const [isActive, setActive] = useState(false);
+
+ return (
+
+ );
+};
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index 33cbf7c..bffeabb 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -1,10 +1,12 @@
import {FC} from 'react';
+import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import OfferList from '../Offer/OfferList';
import { useAppDispatch } from '../../hooks';
-import { OfferObject,AppRoute, City, CardCssNameList } from '../../types/types';
+import { OfferObject,AppRoute, City, CardCssNameList, SortName } from '../../types/types';
import { changeCity } from '../../action';
import { ListCities } from '../../components/CityList/CityList';
+import { FilterOffer } from '../FilterOffers/FilterOffer';
import Map from '../Map/Map';
type MainPageProps = {
offers: OfferObject[];
@@ -23,7 +25,21 @@ export const MainPage : FC = ({
dispatch(changeCity(cityName));
// dispatch(fillOffers());
};
+ const [activeOffer, setActiveOffer] = useState(null);
+ const [sortType, setSortType] = useState(SortName.popular);
+ const sortedOffers = offers.filter((a) =>a.city.name === currentCity.title).slice().sort((a, b) => {
+ switch (sortType) {
+ case SortName.lowToHigh:
+ return a.price - b.price;
+ case SortName.highToLow:
+ return b.price - a.price;
+ case SortName.topRated:
+ return b.rating - a.rating;
+ default:
+ return 0;
+ }
+ });
return (
diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx
index 0438578..5c64a51 100644
--- a/src/components/Map/Map.tsx
+++ b/src/components/Map/Map.tsx
@@ -1,5 +1,5 @@
import {useRef, useEffect} from 'react';
-import {Icon, Marker, layerGroup} from 'leaflet';
+import leaflet, {Icon} from 'leaflet';
import useMap from '../../hooks/use-map';
import { OfferObject, City } from '../../types/types';
import 'leaflet/dist/leaflet.css';
@@ -14,42 +14,48 @@ const currentCustomIcon = new Icon({
iconSize: [40, 40],
iconAnchor: [20, 40]
});
+
+const activeCustomIcon = new Icon({
+ iconUrl: '../../markup/img/pin-active.svg',
+ iconSize: [40, 40],
+ iconAnchor: [20, 40]
+});
type MainPageProps = {
offers: OfferObject[];
currentCity: City;
selectedPoint: OfferObject;
+ activeOffer: number | null;
};
function Map(props: MainPageProps): JSX.Element {
- const {offers, currentCity,selectedPoint} = props;
+ const {offers, currentCity,activeOffer,selectedPoint} = props;
const mapRef = useRef(null);
const map = useMap(mapRef, currentCity.title);
useEffect(() => {
if (map) {
- const markerLayer = layerGroup().addTo(map);
- offers.forEach((offer) => {
- const marker = new Marker({
- lat: offer.location.latitude,
- lng: offer.location.longitude
- });
- marker
- .setIcon(
- selectedPoint !== undefined && offer.title === selectedPoint.title
- ? currentCustomIcon
- : defaultCustomIcon,
- )
- .addTo(markerLayer);
+ map.eachLayer((layer) => {
+ if (layer instanceof leaflet.Marker) {
+ layer.remove();
+ }
});
- return () => {
- map.removeLayer(markerLayer);
- };
+ offers.forEach((offer) => {
+ leaflet
+ .marker({
+ lat: offer.location.latitude,
+ lng: offer.location.longitude,
+ }, {
+ // eslint-disable-next-line no-nested-ternary
+ icon: activeOffer === offer.id ? activeCustomIcon : selectedPoint !== undefined && offer.title === selectedPoint.title ? currentCustomIcon : defaultCustomIcon,
+ })
+ .addTo(map);
+ });
}
- }, [map, offers,selectedPoint]);
+ }, [map, offers,activeOffer,selectedPoint]);
- return ;
+ return ();
}
export default Map;
diff --git a/src/components/Offer/OfferCard.tsx b/src/components/Offer/OfferCard.tsx
index a0653df..52badfe 100644
--- a/src/components/Offer/OfferCard.tsx
+++ b/src/components/Offer/OfferCard.tsx
@@ -6,16 +6,20 @@ import { useState } from 'react';
type OfferCardProps = {
offer: OfferObject;
cardcssname: string;
+ setActiveOffer?: (id: number | null) => void;
};
export const OfferCard: React.FC = ({
offer,
- cardcssname
+ cardcssname,
+ setActiveOffer,
}) => {
const [ isActiveCard, setActiveCard ] = useState(false);
return (
-
- setActiveCard(!isActiveCard)}
+ setActiveOffer && setActiveOffer(offer.id)}
+ onMouseLeave={() => setActiveOffer && setActiveOffer(null)}
+ onMouseOver={() => setActiveCard(!isActiveCard)}
>
{offer.isPremium && (
diff --git a/src/components/Offer/OfferList.tsx b/src/components/Offer/OfferList.tsx
index 1ac6f8d..e328d81 100644
--- a/src/components/Offer/OfferList.tsx
+++ b/src/components/Offer/OfferList.tsx
@@ -6,9 +6,10 @@ import { OfferObject } from '../../types/types';
type OfferListProps = {
offers: OfferObject[];
cardcssname: string;
+ setActiveOffer?: (id: number | null) => void;
};
-const OfferList = ({ offers, cardcssname}: OfferListProps) => {
+const OfferList = ({ offers, cardcssname,setActiveOffer}: OfferListProps) => {
const [activeOfferId, setActiveOfferId] = useState(null);
return (
@@ -19,7 +20,7 @@ const OfferList = ({ offers, cardcssname}: OfferListProps) => {
onMouseEnter={() => setActiveOfferId(offer.id)}
onMouseLeave={() => setActiveOfferId(null)}
>
-
+
))}
{activeOfferId &&
Active Offer ID: {activeOfferId}
}
diff --git a/src/types/types.ts b/src/types/types.ts
index d24d2c2..d15929e 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -57,7 +57,12 @@ export type UserReview = {
comment: string;
date: Date;
};
-
+export const enum SortName {
+ popular = 'popular',
+ lowToHigh = 'lowToHigh',
+ highToLow = 'highToLow',
+ topRated = 'topRated',
+}
export type Points = Point[];
export type State = ReturnType;
From b6685d455611a92c498ec2fa375f25426bd2dc0e Mon Sep 17 00:00:00 2001
From: "hani.mohammad"
Date: Sat, 16 Nov 2024 18:26:53 +0300
Subject: [PATCH 2/3] set sort and mark on map1
---
src/components/MainPage/MainPage.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index bffeabb..772925e 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -3,7 +3,7 @@ import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import OfferList from '../Offer/OfferList';
import { useAppDispatch } from '../../hooks';
-import { OfferObject,AppRoute, City, CardCssNameList, SortName } from '../../types/types';
+import { OfferObject,AppRoute, City, CardCssNameList, SortName} from '../../types/types';
import { changeCity } from '../../action';
import { ListCities } from '../../components/CityList/CityList';
import { FilterOffer } from '../FilterOffers/FilterOffer';
From 1dc278a8a139af7328129730b5c3703a73b40879 Mon Sep 17 00:00:00 2001
From: "hani.mohammad"
Date: Sat, 16 Nov 2024 18:34:02 +0300
Subject: [PATCH 3/3] set sort and mark on map2
---
src/components/Offer/Offer.tsx | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/components/Offer/Offer.tsx b/src/components/Offer/Offer.tsx
index 7bcf49a..efc208a 100644
--- a/src/components/Offer/Offer.tsx
+++ b/src/components/Offer/Offer.tsx
@@ -5,12 +5,7 @@ import { ReviewList } from '../Reviews/ReviewList';
//import { offers } from '../../mock/offers';
import { OtherPlacesNearby } from '../OtherPlacesNearby/OtherPlacesNearby';
import Map from '../Map/Map';
-import {
- AppRoute,
- UserReview,
- OfferObject,
- City,
-} from '../../types/types';
+import { AppRoute, UserReview, OfferObject, City } from '../../types/types';
type OfferProps = {
reviews: UserReview[];
offers: OfferObject[];
@@ -192,10 +187,7 @@ export const Offer: React.FC = ({
-
+
@@ -203,6 +195,7 @@ export const Offer: React.FC = ({
offers={[...offers]}
selectedPoint={offers[1]}
currentCity={currentCity}
+ activeOffer={offers[1].id}
/>