From 34fbdf2224748575c845e74433d36ca7eaf08e05 Mon Sep 17 00:00:00 2001 From: mayonnaise <90057279+Mayanzev@users.noreply.github.com> Date: Sun, 24 Mar 2024 23:36:48 +0300 Subject: [PATCH] module5-task1 --- src/components/map/map.tsx | 41 +++++++++++++++++++++++++++ src/hooks/use-map.tsx | 40 ++++++++++++++++++++++++++ src/mocks/cities.ts | 7 +++++ src/mocks/points.ts | 20 +++++++++++++ src/pages/main-screen/main-screen.tsx | 7 ++++- src/types/city.ts | 5 ++++ src/types/point.ts | 4 +++ 7 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 src/components/map/map.tsx create mode 100644 src/hooks/use-map.tsx create mode 100644 src/mocks/cities.ts create mode 100644 src/mocks/points.ts create mode 100644 src/types/city.ts create mode 100644 src/types/point.ts diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx new file mode 100644 index 0000000..3d92139 --- /dev/null +++ b/src/components/map/map.tsx @@ -0,0 +1,41 @@ +import React, { useEffect } from 'react'; +import { Marker, layerGroup } from 'leaflet'; +import useMap from '../../hooks/use-map'; +import { City } from '../../types/city'; +import { Point } from '../../types/point'; +import 'leaflet/dist/leaflet.css'; + +type MapProps = { + city: City; + points: Point[]; + selectedPoint: Point | undefined; +} + +function Map(props: MapProps): JSX.Element { + const {city, points, selectedPoint} = props; + + const mapRef = React.useRef(null); + const map = useMap(mapRef, city); + + useEffect(() => { + if(map) { + const markerLayer = layerGroup().addTo(map); + points.forEach((point) => { + const marker = new Marker({ + lat: point.lat, + lng: point.lng + }); + marker + .addTo(markerLayer); + }); + + return () => { + map.removeLayer(markerLayer); + }; + } + }, [map, points, selectedPoint]); + + return
; +} + +export default Map; diff --git a/src/hooks/use-map.tsx b/src/hooks/use-map.tsx new file mode 100644 index 0000000..55d6bea --- /dev/null +++ b/src/hooks/use-map.tsx @@ -0,0 +1,40 @@ +import { useEffect, useState, MutableRefObject, useRef } from 'react'; +import { Map, TileLayer } from 'leaflet'; +import { City } from '../types/city'; + +function useMap( + mapRef: MutableRefObject, + city: City +): Map | null { + const [map, setMap] = useState(null); + const isRenderedRef = useRef(false); + + useEffect(() => { + if (mapRef.current !== null && !isRenderedRef.current) { + const instance = new Map(mapRef.current, { + center: { + lat: city.lat, + lng: city.lng + }, + zoom: 10 + }); + + const layer = new TileLayer( + 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png', + { + attribution: + '© OpenStreetMap contributors © CARTO' + } + ); + + instance.addLayer(layer); + + setMap(instance); + isRenderedRef.current = true; + } + }, [mapRef, city]); + + return map; +} + +export default useMap; diff --git a/src/mocks/cities.ts b/src/mocks/cities.ts new file mode 100644 index 0000000..b6a938c --- /dev/null +++ b/src/mocks/cities.ts @@ -0,0 +1,7 @@ +import { City } from '../types/city'; + +export const AMSTERDAM: City = { + title: 'Amsterdam', + lat: 52.3740300, + lng: 4.8896900 +}; diff --git a/src/mocks/points.ts b/src/mocks/points.ts new file mode 100644 index 0000000..685d8d7 --- /dev/null +++ b/src/mocks/points.ts @@ -0,0 +1,20 @@ +import { Point } from '../types/point'; + +export const POINTS: Point[] = [ + { + lat: 52.3909553943508, + lng: 4.85309666406198 + }, + { + lat: 52.3609553943508, + lng: 4.85309666406198 + }, + { + lat: 52.3909553943508, + lng: 4.929309666406198 + }, + { + lat: 52.3809553943508, + lng: 4.939309666406198 + }, +]; diff --git a/src/pages/main-screen/main-screen.tsx b/src/pages/main-screen/main-screen.tsx index ca5edb0..b2d2ff7 100644 --- a/src/pages/main-screen/main-screen.tsx +++ b/src/pages/main-screen/main-screen.tsx @@ -1,6 +1,9 @@ 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'; type MainScreenProps = { placesCount: number; @@ -102,7 +105,9 @@ function MainScreen({placesCount, offers}: MainScreenProps): JSX.Element {
-
+
+ +
diff --git a/src/types/city.ts b/src/types/city.ts new file mode 100644 index 0000000..ffb0eb8 --- /dev/null +++ b/src/types/city.ts @@ -0,0 +1,5 @@ +export type City = { + title: string; + lat: number; + lng: number; +}; diff --git a/src/types/point.ts b/src/types/point.ts new file mode 100644 index 0000000..04a0b11 --- /dev/null +++ b/src/types/point.ts @@ -0,0 +1,4 @@ +export type Point = { + lat: number; + lng: number; + };