From 4a8f60667c10f78b04147a6c22056ef6a76d5f35 Mon Sep 17 00:00:00 2001
From: Nawwar14 <147875072+Nawwar14@users.noreply.github.com>
Date: Thu, 24 Oct 2024 01:19:10 +0300
Subject: [PATCH 1/5] T51V0
---
package-lock.json | 2 +-
src/App.tsx | 35 +
src/components/Favorites/Favorite.tsx | 242 +----
src/components/LoggedRoute/index.tsx | 10 -
src/components/Login/LoginPage.tsx | 116 +--
src/components/Main/main.tsx | 24 -
src/components/MainPage/MainPage.tsx | 27 +-
src/components/MainPageCard/Card.tsx | 40 -
src/components/Offer/Offer.tsx | 903 +++++++++---------
src/components/Offer/OfferCard.tsx | 51 +
src/components/Offer/OfferList.tsx | 38 +
.../SendCommentForm/SendCommentForm.tsx | 60 ++
src/components/User/index.ts | 3 -
src/components/User/interfaces.ts | 11 -
src/components/User/model/index.tsx | 45 -
src/components/User/model/useContext.tsx | 4 -
src/index.tsx | 64 +-
src/mock/offers.ts | 50 +
src/shared/interfaces.ts | 3 -
19 files changed, 793 insertions(+), 935 deletions(-)
create mode 100644 src/App.tsx
delete mode 100644 src/components/LoggedRoute/index.tsx
delete mode 100644 src/components/Main/main.tsx
delete mode 100644 src/components/MainPageCard/Card.tsx
create mode 100644 src/components/Offer/OfferCard.tsx
create mode 100644 src/components/Offer/OfferList.tsx
create mode 100644 src/components/SendCommentForm/SendCommentForm.tsx
delete mode 100644 src/components/User/index.ts
delete mode 100644 src/components/User/interfaces.ts
delete mode 100644 src/components/User/model/index.tsx
delete mode 100644 src/components/User/model/useContext.tsx
create mode 100644 src/mock/offers.ts
delete mode 100644 src/shared/interfaces.ts
diff --git a/package-lock.json b/package-lock.json
index 9e0465f..ff09938 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1524,7 +1524,7 @@
"version": "18.2.11",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.11.tgz",
"integrity": "sha512-zq6Dy0EiCuF9pWFW6I6k6W2LdpUixLE4P6XjXU1QHLfak3GPACQfLwEuHzY5pOYa4hzj1d0GxX/P141aFjZsyg==",
- "devOptional": true,
+ "dev": true,
"dependencies": {
"@types/react": "*"
}
diff --git a/src/App.tsx b/src/App.tsx
new file mode 100644
index 0000000..fe7ebe3
--- /dev/null
+++ b/src/App.tsx
@@ -0,0 +1,35 @@
+import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
+import MainPage from './components/MainPage/MainPage';
+import Favorite from './components/Favorites/Favorite';
+import LoginPage from './components/Login/LoginPage';
+import Offer from './components/Offer/Offer';
+
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+ latitude: number;
+ longitude:number;
+};
+
+type AppProps = {
+ offers: Offer[];
+};
+
+export default function App({ offers }: AppProps) {
+ return (
+
+
+ } />
+ } />
+ } />
+ } />
+
+
+ );
+}
diff --git a/src/components/Favorites/Favorite.tsx b/src/components/Favorites/Favorite.tsx
index 132d12f..b7525f0 100644
--- a/src/components/Favorites/Favorite.tsx
+++ b/src/components/Favorites/Favorite.tsx
@@ -1,228 +1,32 @@
-export const Favorite = () => (
+import OfferCard from '../Offer/OfferCard';
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+};
+type FavoriteProps = {
+ offers: Offer[];
+};
+const Favorite = ({ offers }: FavoriteProps) => (
-
-
- Saved listing
-
-
-
-
-
-
- Premium
-
-
-
-
-
- €180
-
- / night
-
-
-
-
-
-
- In bookmarks
-
-
-
-
-
Apartment
-
-
-
-
-
-
-
-
- €80
-
- / night
-
-
-
-
-
-
- In bookmarks
-
-
-
-
-
Room
-
-
-
-
-
-
-
-
-
-
-
-
-
- €180
-
- / night
-
-
-
-
-
-
- In bookmarks
-
-
-
-
-
Apartment
-
-
-
-
-
+ Saved listings
+
+ {offers.map((offer) => (
+
+ ))}
+
-
);
+
+export default Favorite;
diff --git a/src/components/LoggedRoute/index.tsx b/src/components/LoggedRoute/index.tsx
deleted file mode 100644
index 870c814..0000000
--- a/src/components/LoggedRoute/index.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import {FC} from 'react';
-import { Navigate } from 'react-router-dom';
-import { WithChildren } from '../../shared/interfaces';
-import { useUserContext } from '../User';
-
-export const LoggedRoute:FC = ({ children }) => {
- const { user } = useUserContext();
-
- return user.logged ? children : ;
-};
diff --git a/src/components/Login/LoginPage.tsx b/src/components/Login/LoginPage.tsx
index f60425b..0e1673d 100644
--- a/src/components/Login/LoginPage.tsx
+++ b/src/components/Login/LoginPage.tsx
@@ -1,61 +1,63 @@
-export const LoginPage = () => (
-
-
-
-
-
-
-
-
+export default function LoginPage () {
+ return (
+
-
+
-
-
+
+
+ );
+}
diff --git a/src/components/Main/main.tsx b/src/components/Main/main.tsx
deleted file mode 100644
index 473e0db..0000000
--- a/src/components/Main/main.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import * as React from 'react';
-import { BrowserRouter, Route, Routes } from 'react-router-dom';
-import {MainPage} from '../MainPage/MainPage';
-import { LoginPage } from '../Login/LoginPage';
-import { Offer } from '../Offer/Offer';
-import { Favorite } from '../Favorites/Favorite';
-import { Error404 } from '../Error/Error404';
-import {cardProperties} from '../../index.tsx';
-import { UserContextProvider } from '../User';
-import { LoggedRoute } from '../LoggedRoute';
-
-export const Main: React.FC<{mainPageCardInfo: cardProperties[]}> = ({mainPageCardInfo}) => (
-
-
-
- } />
- } />
- } />
- } />
- } />
-
-
-
-);
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index 47cca7b..ee9a53a 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -1,9 +1,21 @@
import {FC} from 'react';
-import Card from '../MainPageCard/Card.tsx';
-import {cardProperties}from '../../index.tsx';
+import OfferList from '../Offer/OfferList';
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+};
+type MainPageProps = {
+ offers: Offer[];
+};
-export const MainPage : FC<{ CardProps: cardProperties[] }> = ({ CardProps }) =>
+export const MainPage : FC
= ({ offers }) =>
(
@@ -77,7 +89,7 @@ export const MainPage : FC<{ CardProps: cardProperties[] }> = ({ CardProps }) =>
Places
- {CardProps[0].NumberOfPlaces} places to stay in Amsterdam
+ {offers.length} places to stay in Amsterdam
Sort by
@@ -94,10 +106,7 @@ export const MainPage : FC<{ CardProps: cardProperties[] }> = ({ CardProps }) =>
-
-
-
-
+
@@ -108,4 +117,4 @@ export const MainPage : FC<{ CardProps: cardProperties[] }> = ({ CardProps }) =>
);
-
+export default MainPage;
diff --git a/src/components/MainPageCard/Card.tsx b/src/components/MainPageCard/Card.tsx
deleted file mode 100644
index e6c2be1..0000000
--- a/src/components/MainPageCard/Card.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import {cardProperties} from '../../index.tsx';
-function Card(MainPageCardProps:cardProperties):JSX.Element{
- return(
-
- {MainPageCardProps.Premium ?
-
- Premium
-
: null}
-
-
-
-
- €{MainPageCardProps.Price}
- / night
-
-
-
-
-
- To bookmarks
-
-
-
-
-
{MainPageCardProps.ApartsmentType}
-
- );
-}
-export default Card;
diff --git a/src/components/Offer/Offer.tsx b/src/components/Offer/Offer.tsx
index f8602a6..6c9511b 100644
--- a/src/components/Offer/Offer.tsx
+++ b/src/components/Offer/Offer.tsx
@@ -1,478 +1,485 @@
-export const Offer = () => (
-
-
-
-
-
-
-
-
+import SendCommentForm from '../SendCommentForm/SendCommentForm';
+export default function Offer () {
+ return (
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
- Premium
-
-
-
- Beautiful & luxurious studio at great location
-
-
-
-
-
- To bookmarks
-
-
-
-
-
-
Rating
+
+
-
-
- Apartment
-
-
- 3 Bedrooms
-
-
- Max 4 adults
-
-
-
- €120
- night
-
-
-
What's inside
-
- Wi-Fi
- Washing machine
- Towels
- Heating
- Coffee machine
- Baby seat
- Kitchen
- Dishwasher
- Cabel TV
- Fridge
-
-
-
-
Meet the host
-
-
-
+
+
+ Beautiful & luxurious studio at great location
+
+
+
+
+
+ To bookmarks
+
+
+
+
+
+ Rating
-
Angelina
-
Pro
+
4.8
-
-
- A quiet cozy and picturesque that hides behind a a river by
- the unique lightness of Amsterdam. The building is green and
- from 18th century.
-
-
- An independent House, strategically located between Rembrand
- Square and National Opera, but where the bustle of the city
- comes to rest in this alley flowery and colorful.
-
+
+
+ Apartment
+
+
+ 3 Bedrooms
+
+
+ Max 4 adults
+
+
+
+ €120
+ night
-
-
-
- Reviews · 1
-
-
-
-
-
-
-
-
Max
+
+
What's inside
+
+ Wi-Fi
+ Washing machine
+ Towels
+ Heating
+ Coffee machine
+ Baby seat
+ Kitchen
+ Dishwasher
+ Cabel TV
+ Fridge
+
+
+
+
Meet the host
+
+
+
-
-
-
-
- Rating
+ Angelina
+ Pro
+
+
+
+ A quiet cozy and picturesque that hides behind a a river by
+ the unique lightness of Amsterdam. The building is green and
+ from 18th century.
+
+
+ An independent House, strategically located between Rembrand
+ Square and National Opera, but where the bustle of the city
+ comes to rest in this alley flowery and colorful.
+
+
+
+
-
-
-
-
- Your review
-
-
-
-
-
-
-
-
- Other places in the neighbourhood
-
-
-
-
-
-
-
- €80
-
- / night
-
+
+
+
+
+
+
-
-
+
+
+ To submit review please make sure to set{' '}
+ rating and describe
+ your stay with at least{' '}
+ 50 characters .
+
+
-
-
- In bookmarks
-
+ Submit
+
+
+
+
+
+
+
+
+
+
+
+ Other places in the neighbourhood
+
+
+
+
-
-
-
-
Rating
+
+
+
+ €80
+
+ / night
+
+
+
+
+
+
+ In bookmarks
+
+
+
+
+
Room
-
-
Room
-
-
+
-
-
-
-
-
- €132
-
- / night
-
-
-
-
-
-
- To bookmarks
-
+
+
-
-
-
-
Rating
+
+
+
+ €132
+
+ / night
+
+
+
+
+
+
+ To bookmarks
+
+
+
+
+
Apartment
-
-
Apartment
-
-
+
-
-
- Premium
-
-
-
-
-
- €180
-
- / night
-
-
-
-
-
-
- To bookmarks
-
+
+
+ Premium
+
+
-
-
-
-
Rating
+
+
+
+ €180
+
+ / night
+
+
+
+
+
+
+ To bookmarks
+
+
+
+
+
Apartment
-
-
Apartment
-
-
-
-
-
-
-
-);
+
+
+
+
+
+
Reviews
+ {}
+
+
+
+ );
+}
diff --git a/src/components/Offer/OfferCard.tsx b/src/components/Offer/OfferCard.tsx
new file mode 100644
index 0000000..f872325
--- /dev/null
+++ b/src/components/Offer/OfferCard.tsx
@@ -0,0 +1,51 @@
+import { Link } from 'react-router-dom';
+
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+};
+
+type OfferCardProps = {
+ offer: Offer;
+};
+
+const OfferCard = ({ offer }: OfferCardProps) => (
+
+ {offer.isPremium && (
+
+ Premium
+
+ )}
+
+
+
+
+
+
+
+
+ €{offer.price}
+ / night
+
+
+
+
+ {offer.title}
+
+
{offer.type}
+
+
+);
+
+export default OfferCard;
diff --git a/src/components/Offer/OfferList.tsx b/src/components/Offer/OfferList.tsx
new file mode 100644
index 0000000..d84aa13
--- /dev/null
+++ b/src/components/Offer/OfferList.tsx
@@ -0,0 +1,38 @@
+import { useState } from 'react';
+import OfferCard from './OfferCard';
+
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+};
+
+type OfferListProps = {
+ offers: Offer[];
+};
+
+const OfferList = ({ offers }: OfferListProps) => {
+ const [activeOfferId, setActiveOfferId] = useState(null);
+
+ return (
+
+ {offers.map((offer) => (
+
setActiveOfferId(offer.id)}
+ onMouseLeave={() => setActiveOfferId(null)}
+ >
+
+
+ ))}
+
{activeOfferId &&
Active Offer ID: {activeOfferId}
}
+
+ );
+};
+
+export default OfferList;
diff --git a/src/components/SendCommentForm/SendCommentForm.tsx b/src/components/SendCommentForm/SendCommentForm.tsx
new file mode 100644
index 0000000..5c4af3b
--- /dev/null
+++ b/src/components/SendCommentForm/SendCommentForm.tsx
@@ -0,0 +1,60 @@
+import React, { useState } from 'react';
+
+const SendCommentForm = () => {
+ const [rating, setRating] = useState(0);
+ const [comment, setComment] = useState('');
+
+ const handleSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ };
+ const numberofstars = [5, 4, 3, 2, 1];
+ return (
+
+ Your review
+
+ {numberofstars.map((star) => (
+
+ setRating(star)}
+ />
+
+
+
+
+
+
+ ))}
+
+
+ setComment(e.target.value)}
+ />
+
+
+
+ To submit review please make sure to set rating and describe your stay
+ with at least 10 characters .
+
+
+ Submit
+
+
+
+ );
+};
+
+export default SendCommentForm;
diff --git a/src/components/User/index.ts b/src/components/User/index.ts
deleted file mode 100644
index 802fec3..0000000
--- a/src/components/User/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export { useUserContext } from './model/useContext';
-export { UserContext, UserContextProvider } from './model';
-export type { UserData, UserDataContext } from './interfaces';
diff --git a/src/components/User/interfaces.ts b/src/components/User/interfaces.ts
deleted file mode 100644
index 92cbf9a..0000000
--- a/src/components/User/interfaces.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export type UserData = {
- logged: boolean;
- email?: string;
- avatarUrl?: string;
-};
-
-export type UserDataContext = {
- user: UserData;
- logout: () => void;
- login: (email: string, password: string) => boolean;
-};
diff --git a/src/components/User/model/index.tsx b/src/components/User/model/index.tsx
deleted file mode 100644
index 7d3ba66..0000000
--- a/src/components/User/model/index.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { createContext, useMemo, useState,FC } from 'react';
-import { UserData, UserDataContext } from '../interfaces';
-import { WithChildren } from '../../../shared/interfaces';
-
-const defaultUserDataValue = {
- logged: false,
-};
-
-const defaultContextValue: UserDataContext = {
- user: defaultUserDataValue,
- logout: () => {},
- login: () => false,
-};
-
-export const UserContext = createContext(defaultContextValue);
-
-export const UserContextProvider:FC = ({ children }) => {
- const [userData, setUserData] = useState(defaultUserDataValue);
-
- const logout = () => setUserData(defaultUserDataValue);
- const login: UserDataContext['login'] = (email, password) => {
- if (password === '123456') {
- setUserData({
- logged: true,
- email,
- });
- return true;
- }
-
- return false;
- };
-
- const contextValue = useMemo(
- () => ({
- user: userData,
- logout,
- login,
- }),
- [userData],
- );
-
- return (
- {children}
- );
-};
diff --git a/src/components/User/model/useContext.tsx b/src/components/User/model/useContext.tsx
deleted file mode 100644
index 5b5029e..0000000
--- a/src/components/User/model/useContext.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-import { useContext } from 'react';
-import { UserContext } from '.';
-
-export const useUserContext = () => useContext(UserContext);
diff --git a/src/index.tsx b/src/index.tsx
index e17c5bb..36201f0 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,71 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
-import {Main} from './components/Main/main';
-
+import App from './App';
+import { offers } from './mock/offers';
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
-type cardProperties={
- Premium:boolean;
- Price:number;
- Img:string;
- ApartsmentType:string;
- Description:string;
- NumberOfPlaces:number;
-};
-export type {cardProperties};
-
-const mainPageCardInfo:cardProperties[] = [
- {
- Premium:true,
- Price:120,
- Img:'../markup/Img/apartment-01.jpg',
- ApartsmentType:'Apartment',
- Description:'Beautiful & luxurious apartment at great location',
- NumberOfPlaces:132
- },
- {
- Premium:false,
- Price:80,
- Img:'../markup/Img/room.jpg',
- ApartsmentType:'Room',
- Description:'Wood and stone place',
- NumberOfPlaces:0
- },
-
- {
- Premium:false,
- Price:132,
- Img:'../markup/Img/apartment-02.jpg',
- ApartsmentType:'Apartment',
- Description:'Canal View Prinsengracht',
- NumberOfPlaces:0
- },
-
- {
- Premium:true,
- Price:180,
- Img:'../markup/Img/apartment-03.jpg',
- ApartsmentType:'Apartment',
- Description:'Nice, cozy, warm big bed apartment',
- NumberOfPlaces:0
- },
-
- {
- Premium:false,
- Price:80,
- Img:'../markup/Img/room.jpg',
- ApartsmentType:'Room',
- Description:'Wood and stone place',
- NumberOfPlaces:0
- }];
-export default {mainPageCardInfo} ;
-
root.render(
-
-
-
+
);
diff --git a/src/mock/offers.ts b/src/mock/offers.ts
new file mode 100644
index 0000000..1f92cfd
--- /dev/null
+++ b/src/mock/offers.ts
@@ -0,0 +1,50 @@
+export const offers = [
+ {
+ id: 1,
+ title: 'Luxury Apartment in Downtown',
+ price: 250,
+ rating: 4.9,
+ type: 'Apartment',
+ isPremium: true,
+ previewImage: 'img/apartment-01.jpg',
+ NumberOfPlaces: 1,
+ latitude: 52.3909553943508,
+ longitude: 4.85309666406198,
+ },
+ {
+ id: 2,
+ title: 'Cozy House in Suburbs',
+ price: 100,
+ rating: 4.7,
+ type: 'House',
+ isPremium: false,
+ previewImage: 'img/apartment-02.jpg',
+ NumberOfPlaces: 1,
+ latitude: 52.3609553943508,
+ longitude: 4.85309666406198,
+ },
+ {
+ id: 3,
+ title: 'Stylish Studio in City Center',
+ price: 150,
+ rating: 4.8,
+ type: 'Studio',
+ isPremium: false,
+ previewImage: 'img/studio-01.jpg',
+ NumberOfPlaces: 1,
+ latitude: 52.3909553943508,
+ longitude: 4.929309666406198,
+ },
+ {
+ id: 4,
+ title: 'Modern Loft with River View',
+ price: 200,
+ rating: 5.0,
+ type: 'Loft',
+ isPremium: true,
+ previewImage: 'img/studio-01.jpg',
+ NumberOfPlaces: 1,
+ latitude: 52.3809553943508,
+ longitude: 4.939309666406198,
+ },
+];
diff --git a/src/shared/interfaces.ts b/src/shared/interfaces.ts
deleted file mode 100644
index 886fa90..0000000
--- a/src/shared/interfaces.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export type WithChildren = {
- children: JSX.Element;
-};
From b27e81f5f2d93522b040e644b2bbad117c504386 Mon Sep 17 00:00:00 2001
From: Nawwar14 <147875072+Nawwar14@users.noreply.github.com>
Date: Thu, 24 Oct 2024 02:21:11 +0300
Subject: [PATCH 2/5] T51V1
---
src/components/MainPage/MainPage.tsx | 9 +++-
src/components/Map/Map.tsx | 65 ++++++++++++++++++++++++++++
src/const.ts | 5 +++
src/hooks/use-map.tsx | 39 +++++++++++++++++
src/types/types.ts | 14 ++++++
5 files changed, 130 insertions(+), 2 deletions(-)
create mode 100644 src/components/Map/Map.tsx
create mode 100644 src/const.ts
create mode 100644 src/hooks/use-map.tsx
create mode 100644 src/types/types.ts
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index ee9a53a..d790b72 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -1,6 +1,7 @@
import {FC} from 'react';
import OfferList from '../Offer/OfferList';
-
+import Map from '../Map/Map';
+import {City, Points, Point} from '../../types/types';
type Offer = {
id: number;
title: string;
@@ -10,6 +11,8 @@ type Offer = {
isPremium: boolean;
previewImage: string;
NumberOfPlaces: number;
+ latitude: number;
+ longitude:number;
};
type MainPageProps = {
offers: Offer[];
@@ -110,7 +113,9 @@ export const MainPage : FC = ({ offers }) =>
-
+
diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx
new file mode 100644
index 0000000..ac7cff7
--- /dev/null
+++ b/src/components/Map/Map.tsx
@@ -0,0 +1,65 @@
+import {useRef, useEffect} from 'react';
+import {Icon, Marker, layerGroup} from 'leaflet';
+import useMap from '../../hooks/use-map';
+import 'leaflet/dist/leaflet.css';
+type Offer = {
+ id: number;
+ title: string;
+ price: number;
+ rating: number;
+ type: string;
+ isPremium: boolean;
+ previewImage: string;
+ NumberOfPlaces: number;
+ latitude: number;
+ longitude:number;
+};
+const defaultCustomIcon = new Icon({
+ iconUrl: 'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/pin.svg',
+ iconSize: [40, 40],
+ iconAnchor: [20, 40]
+});
+
+const currentCustomIcon = new Icon({
+ iconUrl: 'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/main-pin.svg',
+ iconSize: [40, 40],
+ iconAnchor: [20, 40]
+});
+type MainPageProps = {
+ offers: Offer[];
+ selectedPoint :Offer;
+};
+
+function Map(props: MainPageProps): JSX.Element {
+ const {offers, selectedPoint} = props;
+
+ const mapRef = useRef(null);
+ const map = useMap(mapRef, "Амстердам");
+
+ useEffect(() => {
+ if (map) {
+ const markerLayer = layerGroup().addTo(map);
+ offers.forEach((offer) => {
+ const marker = new Marker({
+ lat: offer.latitude,
+ lng: offer.longitude
+ });
+ marker
+ .setIcon(
+ selectedPoint !== undefined && offer.title === selectedPoint.title
+ ? currentCustomIcon
+ : defaultCustomIcon,
+ )
+ .addTo(markerLayer);
+ });
+
+ return () => {
+ map.removeLayer(markerLayer);
+ };
+ }
+ }, [map, offers]);
+
+ return
;
+}
+
+export default Map;
diff --git a/src/const.ts b/src/const.ts
new file mode 100644
index 0000000..1b7e76b
--- /dev/null
+++ b/src/const.ts
@@ -0,0 +1,5 @@
+export const URL_MARKER_DEFAULT =
+ 'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/pin.svg';
+
+export const URL_MARKER_CURRENT =
+ 'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/main-pin.svg';
diff --git a/src/hooks/use-map.tsx b/src/hooks/use-map.tsx
new file mode 100644
index 0000000..dc12e3a
--- /dev/null
+++ b/src/hooks/use-map.tsx
@@ -0,0 +1,39 @@
+import {useEffect, useState, MutableRefObject, useRef} from 'react';
+import {Map, TileLayer} from 'leaflet';
+
+function useMap(
+ mapRef: MutableRefObject,
+ city: string
+): 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: 52.3,
+ lng: 4.99
+ },
+ 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/types/types.ts b/src/types/types.ts
new file mode 100644
index 0000000..b661606
--- /dev/null
+++ b/src/types/types.ts
@@ -0,0 +1,14 @@
+export type City = {
+ title: string;
+ lat: number;
+ lng: number;
+ zoom: number;
+};
+
+export type Point = {
+ title: string;
+ lat: number;
+ lng: number;
+};
+
+export type Points = Point[];
From 1c8a3fdfa03462c8329cd3d90506acffeebc1081 Mon Sep 17 00:00:00 2001
From: Nawwar14 <147875072+Nawwar14@users.noreply.github.com>
Date: Thu, 24 Oct 2024 02:24:49 +0300
Subject: [PATCH 3/5] T51V2
---
src/components/MainPage/MainPage.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index d790b72..629c6c8 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -1,7 +1,6 @@
import {FC} from 'react';
import OfferList from '../Offer/OfferList';
import Map from '../Map/Map';
-import {City, Points, Point} from '../../types/types';
type Offer = {
id: number;
title: string;
From 9385cf029b097dbf90bab4016f23fa5027f7625f Mon Sep 17 00:00:00 2001
From: Nawwar14 <147875072+Nawwar14@users.noreply.github.com>
Date: Thu, 24 Oct 2024 02:36:40 +0300
Subject: [PATCH 4/5] T51V3
---
src/components/Map/Map.tsx | 4 ++--
src/hooks/use-map.tsx | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx
index ac7cff7..6ce1321 100644
--- a/src/components/Map/Map.tsx
+++ b/src/components/Map/Map.tsx
@@ -34,7 +34,7 @@ function Map(props: MainPageProps): JSX.Element {
const {offers, selectedPoint} = props;
const mapRef = useRef(null);
- const map = useMap(mapRef, "Амстердам");
+ const map = useMap(mapRef, 'Амстердам');
useEffect(() => {
if (map) {
@@ -57,7 +57,7 @@ function Map(props: MainPageProps): JSX.Element {
map.removeLayer(markerLayer);
};
}
- }, [map, offers]);
+ }, [map, offers,selectedPoint]);
return
;
}
diff --git a/src/hooks/use-map.tsx b/src/hooks/use-map.tsx
index dc12e3a..e8f617d 100644
--- a/src/hooks/use-map.tsx
+++ b/src/hooks/use-map.tsx
@@ -29,7 +29,7 @@ function useMap(
instance.addLayer(layer);
setMap(instance);
- isRenderedRef.current = true
+ isRenderedRef.current = true;
}
}, [mapRef, city]);
From f0060abe1e70174ba68eb93870c4da3187eb85fa Mon Sep 17 00:00:00 2001
From: "hani.mohammad"
Date: Sat, 16 Nov 2024 13:22:00 +0300
Subject: [PATCH 5/5] change offer stucture
---
src/App.tsx | 18 ++++-
src/components/Favorites/Favorite.tsx | 16 +++-
src/components/MainPage/MainPage.tsx | 18 ++++-
src/components/Map/Map.tsx | 22 +++--
src/components/Offer/Offer.tsx | 111 +-------------------------
src/components/Offer/OfferCard.tsx | 16 +++-
src/components/Offer/OfferList.tsx | 16 +++-
src/mock/offers.ts | 64 +++++++++++++--
8 files changed, 149 insertions(+), 132 deletions(-)
diff --git a/src/App.tsx b/src/App.tsx
index fe7ebe3..87c602a 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -11,10 +11,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
- latitude: number;
- longitude:number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
type AppProps = {
diff --git a/src/components/Favorites/Favorite.tsx b/src/components/Favorites/Favorite.tsx
index b7525f0..c8d4033 100644
--- a/src/components/Favorites/Favorite.tsx
+++ b/src/components/Favorites/Favorite.tsx
@@ -6,8 +6,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
type FavoriteProps = {
offers: Offer[];
diff --git a/src/components/MainPage/MainPage.tsx b/src/components/MainPage/MainPage.tsx
index 4cd30d9..90845e8 100644
--- a/src/components/MainPage/MainPage.tsx
+++ b/src/components/MainPage/MainPage.tsx
@@ -8,10 +8,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
- latitude: number;
- longitude:number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
type MainPageProps = {
offers: Offer[];
diff --git a/src/components/Map/Map.tsx b/src/components/Map/Map.tsx
index 6ce1321..631251f 100644
--- a/src/components/Map/Map.tsx
+++ b/src/components/Map/Map.tsx
@@ -9,10 +9,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
- latitude: number;
- longitude:number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
const defaultCustomIcon = new Icon({
iconUrl: 'https://assets.htmlacademy.ru/content/intensive/javascript-1/demo/interactive-map/pin.svg',
@@ -41,8 +53,8 @@ function Map(props: MainPageProps): JSX.Element {
const markerLayer = layerGroup().addTo(map);
offers.forEach((offer) => {
const marker = new Marker({
- lat: offer.latitude,
- lng: offer.longitude
+ lat: offer.location.latitude,
+ lng: offer.location.longitude
});
marker
.setIcon(
diff --git a/src/components/Offer/Offer.tsx b/src/components/Offer/Offer.tsx
index 6c9511b..9d5bd83 100644
--- a/src/components/Offer/Offer.tsx
+++ b/src/components/Offer/Offer.tsx
@@ -207,116 +207,7 @@ export default function Offer () {
-
- Your review
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- To submit review please make sure to set{' '}
- rating and describe
- your stay with at least{' '}
- 50 characters .
-
-
- Submit
-
-
+ {}
diff --git a/src/components/Offer/OfferCard.tsx b/src/components/Offer/OfferCard.tsx
index f872325..f644358 100644
--- a/src/components/Offer/OfferCard.tsx
+++ b/src/components/Offer/OfferCard.tsx
@@ -7,8 +7,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
type OfferCardProps = {
diff --git a/src/components/Offer/OfferList.tsx b/src/components/Offer/OfferList.tsx
index d84aa13..32825f3 100644
--- a/src/components/Offer/OfferList.tsx
+++ b/src/components/Offer/OfferList.tsx
@@ -8,8 +8,22 @@ type Offer = {
rating: number;
type: string;
isPremium: boolean;
- previewImage: string;
+ isFavorite: boolean;
NumberOfPlaces: number;
+ previewImage: string;
+ city: {
+ name: string;
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
+ };
+ location: {
+ latitude: number;
+ longitude: number;
+ zoom: number;
+ };
};
type OfferListProps = {
diff --git a/src/mock/offers.ts b/src/mock/offers.ts
index 1f92cfd..b253cd2 100644
--- a/src/mock/offers.ts
+++ b/src/mock/offers.ts
@@ -8,8 +8,20 @@ export const offers = [
isPremium: true,
previewImage: 'img/apartment-01.jpg',
NumberOfPlaces: 1,
- latitude: 52.3909553943508,
- longitude: 4.85309666406198,
+ location: {
+ latitude: 52.3909553943508,
+ longitude: 4.85309666406198,
+ zoom: 0,
+ },
+ city: {
+ name: 'Amsterdam',
+ location: {
+ latitude: 52.35514938496378,
+ longitude: 4.673877537499948,
+ zoom: 8,
+ },
+ },
+ isFavorite: false,
},
{
id: 2,
@@ -20,8 +32,20 @@ export const offers = [
isPremium: false,
previewImage: 'img/apartment-02.jpg',
NumberOfPlaces: 1,
- latitude: 52.3609553943508,
- longitude: 4.85309666406198,
+ location: {
+ latitude: 52.3609553943508,
+ longitude: 4.85309666406198,
+ zoom: 0,
+ },
+ city: {
+ name: 'Amsterdam',
+ location: {
+ latitude: 52.35514938496378,
+ longitude: 4.673877537499948,
+ zoom: 8,
+ },
+ },
+ isFavorite: false,
},
{
id: 3,
@@ -32,8 +56,20 @@ export const offers = [
isPremium: false,
previewImage: 'img/studio-01.jpg',
NumberOfPlaces: 1,
- latitude: 52.3909553943508,
- longitude: 4.929309666406198,
+ location: {
+ latitude: 52.3909553943508,
+ longitude: 4.929309666406198,
+ zoom: 0,
+ },
+ city: {
+ name: 'Amsterdam',
+ location: {
+ latitude: 52.35514938496378,
+ longitude: 4.673877537499948,
+ zoom: 8,
+ },
+ },
+ isFavorite: false,
},
{
id: 4,
@@ -44,7 +80,19 @@ export const offers = [
isPremium: true,
previewImage: 'img/studio-01.jpg',
NumberOfPlaces: 1,
- latitude: 52.3809553943508,
- longitude: 4.939309666406198,
+ location: {
+ latitude: 52.3809553943508,
+ longitude: 4.939309666406198,
+ zoom: 0,
+ },
+ city: {
+ name: 'Amsterdam',
+ location: {
+ latitude: 52.35514938496378,
+ longitude: 4.673877537499948,
+ zoom: 8,
+ },
+ },
+ isFavorite: false,
},
];