Skip to content

Commit

Permalink
Merge pull request #5 from uniksssss/module5-task1
Browse files Browse the repository at this point in the history
  • Loading branch information
keksobot authored Nov 5, 2024
2 parents d258b33 + 22210d5 commit 0282a46
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import Offer from './pages/Offer';
import NotFound from './NotFound';
import AppRoute, { AuthorizationStatus } from '../const';
import PrivateRoute from './private-route';
import { OffersType } from '../types/offer';
import { OffersType } from '../types/types';

type AppScreenProps = {
placesCount: number;
Expand Down
2 changes: 1 addition & 1 deletion src/components/favoritesList.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { OffersType } from '../types/offer';
import { OffersType } from '../types/types';
import Card from './pages/Card';

type FavoritesListProps = {
Expand Down
44 changes: 44 additions & 0 deletions src/components/map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useRef, useEffect } from 'react';
import { Icon, Marker, layerGroup } from 'leaflet';
import useMap from '../hooks/use-Map';
import { URL_MARKER_DEFAULT } from '../const';
import 'leaflet/dist/leaflet.css';
import { OffersType } from '../types/types';

type MapProps = {
offers: OffersType[];
selectedOffer: OffersType;
};

const defaultCustomIcon = new Icon({
iconUrl: URL_MARKER_DEFAULT,
iconSize: [40, 40],
iconAnchor: [20, 40],
});

function Map({offers, selectedOffer}: MapProps){
const mapRef = useRef(null);
const map = useMap(mapRef, selectedOffer);

useEffect(() => {
if (map) {
const markerLayer = layerGroup().addTo(map);
offers.forEach((offer) => {
const marker = new Marker({
lat: offer.city.location.latitude,
lng: offer.city.location.longitude
});

marker.setIcon(defaultCustomIcon).addTo(markerLayer);
});

return () => {
map.removeLayer(markerLayer);
};
}
}, [map, offers, selectedOffer]);

return <div style={{ height: '500px' }} ref={mapRef}></div>;
}

export default Map;
2 changes: 1 addition & 1 deletion src/components/offersList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Card from './pages/Card';
import { OffersType } from '../types/offer';
import { OffersType } from '../types/types';

interface OffersListProps {
offers: OffersType[];
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from 'react';
import { OffersType } from '../../types/offer';
import { OffersType } from '../../types/types';
import { Link } from 'react-router-dom';

type CardProps = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/pages/Favorites.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Link } from 'react-router-dom';
import { OffersType } from '../../types/offer';
import { OffersType } from '../../types/types';
import FavoritesList from '../favoritesList';
import Logo from '../Logo';
import { Helmet } from 'react-helmet-async';
Expand Down
12 changes: 9 additions & 3 deletions src/components/pages/MainScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Logo from '../Logo';
import { Helmet } from 'react-helmet-async';
import { OffersType } from '../../types/offer';
import { OffersType } from '../../types/types';
import OffersList from '../offersList';
import { Link } from 'react-router-dom';
import Map from '../map';

type MainScreenProps = {
placesCount: number;
Expand All @@ -19,7 +20,10 @@ function MainScreen({ placesCount, offers }: MainScreenProps) {
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<Link to='/' className="header__logo-link header__logo-link--active">
<Link
to="/"
className="header__logo-link header__logo-link--active"
>
<Logo />
</Link>
</div>
Expand Down Expand Up @@ -123,7 +127,9 @@ function MainScreen({ placesCount, offers }: MainScreenProps) {
</div>
</section>
<div className="cities__right-section">
<section className="cities__map map" />
<section className="cities__map map">
<Map offers={offers} selectedOffer={offers[0]} />
</section>
</div>
<div id="App"></div>
</div>
Expand Down
19 changes: 11 additions & 8 deletions src/const.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
enum AppRoute{
Root = '/',
Login = '/login',
Favorites = '/favorites',
Offer = '/offer/:id'
enum AppRoute {
Root = '/',
Login = '/login',
Favorites = '/favorites',
Offer = '/offer/:id',
}

export enum AuthorizationStatus {
Auth = 'AUTH',
NoAuth = 'NO_AUTH',
Unknown = 'UNKNOWN',
Auth = 'AUTH',
NoAuth = 'NO_AUTH',
Unknown = 'UNKNOWN',
}

export const URL_MARKER_DEFAULT =
'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/pin.svg';

export default AppRoute;
39 changes: 39 additions & 0 deletions src/hooks/use-Map.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { useEffect, useState, MutableRefObject, useRef } from 'react';
import { Map, TileLayer } from 'leaflet';
import { OffersType } from '../types/types';

function useMap(
mapRef: MutableRefObject<HTMLElement | null>,
{city}: OffersType): Map | null{
const [map, setMap] = useState<Map | null>(null);
const isRenderedRef = useRef<boolean>(false);

useEffect(() => {
if (mapRef.current !== null && !isRenderedRef.current) {
const instance = new Map(mapRef.current, {
center: {
lat: city.location.latitude,
lng: city.location.longitude
},
zoom: city.location.zoom
});

const layer = new TileLayer(
'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',
{
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy; <a href="https://carto.com/attributions">CARTO</a>',
}
);

instance.addLayer(layer);

setMap(instance);
isRenderedRef.current = true;
}
}, [mapRef, city.location]);

return map;
}

export default useMap;
34 changes: 33 additions & 1 deletion src/mocks/offers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { OffersType } from '../types/offer';
import { OffersType } from '../types/types';

const offers: OffersType[] = [
{
Expand All @@ -11,6 +11,14 @@ const offers: OffersType[] = [
title: 'Beautiful & luxurious apartment at great location',
type: 'Apartment',
favorite: true,
city: {
name: 'Amsterdam',
location: {
latitude: 52.3909553943508,
longitude: 4.85309666406198,
zoom: 5,
},
},
},
{
id: 2,
Expand All @@ -22,6 +30,14 @@ const offers: OffersType[] = [
title: 'Wood and stone place',
type: 'Room',
favorite: true,
city: {
name: 'Amsterdam',
location: {
latitude: 52.3609553943508,
longitude: 4.85309666406198,
zoom: 5,
},
},
},
{
id: 3,
Expand All @@ -33,6 +49,14 @@ const offers: OffersType[] = [
title: 'Canal View Prinsengracht',
type: 'Apartment',
favorite: true,
city: {
name: 'Amsterdam',
location: {
latitude: 52.3909553943508,
longitude: 4.929309666406198,
zoom: 5,
},
},
},
{
id: 4,
Expand All @@ -44,6 +68,14 @@ const offers: OffersType[] = [
title: 'Nice, cozy, warm big bed apartment',
type: 'Apartment',
favorite: true,
city: {
name: 'Amsterdam',
location: {
latitude: 52.3809553943508,
longitude: 4.939309666406198,
zoom: 100,
},
},
},
];

Expand Down
18 changes: 8 additions & 10 deletions src/types/offer.ts → src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@ export type OffersType = {
title: string;
type: string;
favorite: boolean;
city: {
name: string;
location: {
latitude: number;
longitude: number;
zoom: number;
};
};
};

// export type Review = {
// comment: string;
// date: string;
// id: string;
// rating: number;
// user: User;
// };


0 comments on commit 0282a46

Please sign in to comment.