diff --git a/package-lock.json b/package-lock.json index ca452cd..13cd997 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,9 +14,10 @@ "history": "5.3.0", "http-status-codes": "2.3.0", "leaflet": "1.7.1", + "prettier": "3.3.3", "react": "18.2.0", "react-dom": "18.2.0", - "react-helmet-async": "1.3.0", + "react-helmet-async": "2.0.5", "react-redux": "8.1.3", "react-router-dom": "6.16.0" }, @@ -41,7 +42,7 @@ "eslint-plugin-react-refresh": "0.4.3", "faker": "5.5.3", "jsdom": "22.1.0", - "typescript": "5.2.2", + "typescript": "^5.6.3", "vite": "4.4.11", "vitest": "0.34.6" } @@ -4754,6 +4755,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5110,6 +5112,20 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/pretty-format": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", @@ -5146,6 +5162,7 @@ "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -5227,19 +5244,16 @@ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" }, "node_modules/react-helmet-async": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.3.0.tgz", - "integrity": "sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-2.0.5.tgz", + "integrity": "sha512-rYUYHeus+i27MvFE+Jaa4WsyBKGkL6qVgbJvSBoX8mbsWoABJXdEO0bZyi0F6i+4f0NuIb8AvqPMj3iXFHkMwg==", "dependencies": { - "@babel/runtime": "^7.12.5", "invariant": "^2.2.4", - "prop-types": "^15.7.2", - "react-fast-compare": "^3.2.0", + "react-fast-compare": "^3.2.2", "shallowequal": "^1.1.0" }, "peerDependencies": { - "react": "^16.6.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.6.0 || ^17.0.0 || ^18.0.0" + "react": "^16.6.0 || ^17.0.0 || ^18.0.0" } }, "node_modules/react-is": { @@ -6122,9 +6136,9 @@ } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", "dev": true, "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 9b0c921..75c7af0 100644 --- a/package.json +++ b/package.json @@ -16,10 +16,10 @@ "history": "5.3.0", "http-status-codes": "2.3.0", "leaflet": "1.7.1", - "prettier": "^3.3.3", + "prettier": "3.3.3", "react": "18.2.0", "react-dom": "18.2.0", - "react-helmet-async": "^2.0.5", + "react-helmet-async": "2.0.5", "react-redux": "8.1.3", "react-router-dom": "6.16.0" }, @@ -44,7 +44,7 @@ "eslint-plugin-react-refresh": "0.4.3", "faker": "5.5.3", "jsdom": "22.1.0", - "typescript": "5.2.2", + "typescript": "5.6.3", "vite": "4.4.11", "vitest": "0.34.6" }, diff --git a/src/DataTypes/RoomType.ts b/src/DataTypes/RoomType.ts deleted file mode 100644 index 86c0b35..0000000 --- a/src/DataTypes/RoomType.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum RoomType { - Apartment = 'Apartment', - Room = 'Room', -} diff --git a/src/Pages/FavoritesPage.tsx b/src/Pages/FavoritesPage.tsx deleted file mode 100644 index e8b0bbd..0000000 --- a/src/Pages/FavoritesPage.tsx +++ /dev/null @@ -1,235 +0,0 @@ -import { Helmet } from 'react-helmet-async'; - -export function FavoritesPage(): React.JSX.Element { - return ( -
-
-
-
-
- - 6 cities logo - -
- -
-
-
- -
- - 6 cities - favorites - -
-
-

Saved listing

- -
-
-
- -
- ); -} diff --git a/src/Pages/OfferPage.tsx b/src/Pages/OfferPage.tsx deleted file mode 100644 index ea7fa45..0000000 --- a/src/Pages/OfferPage.tsx +++ /dev/null @@ -1,488 +0,0 @@ -import { Helmet } from 'react-helmet-async'; - -export function OfferPage(): React.JSX.Element { - return ( -
- - 6 cities - view offer - -
-
-
-
- - 6 cities logo - -
- -
-
-
- -
-
-
-
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
-
-
-
-
- Premium -
-
-

- Beautiful & luxurious studio at great location -

- -
-
-
- - Rating -
- 4.8 -
-
    -
  • - 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

-
-
- Host avatar -
- 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. -

-
-
-
-

- Reviews · 1 -

-
    -
  • -
    -
    - Reviews avatar -
    - Max -
    -
    -
    -
    - - Rating -
    -
    -

    - 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. -

    - -
    -
  • -
-
- -
- - - - - - - - - - - - - - -
- -
-

- To submit review please make sure to set{' '} - rating and describe - your stay with at least{' '} - 50 characters. -

- -
-
-
-
-
-
-
-
-
-

- Other places in the neighbourhood -

-
-
-
- - Place image - -
-
-
-
- €80 - - / night - -
- -
-
-
- - Rating -
-
-

- Wood and stone place -

-

Room

-
-
- - - - -
-
-
-
-
- ); -} diff --git a/src/Pages/favorites-page.tsx b/src/Pages/favorites-page.tsx new file mode 100644 index 0000000..efab44e --- /dev/null +++ b/src/Pages/favorites-page.tsx @@ -0,0 +1,40 @@ +import { Helmet } from 'react-helmet-async'; +import { Layout } from '../components/layout.tsx'; +import { OfferGroup } from '../components/offer/offer-group.tsx'; +import { Offer } from '../dataTypes/offer.ts'; + +interface FavoritesPageProps { + offers: Offer[]; +} + +export function FavoritesPage({ + offers, +}: FavoritesPageProps): React.JSX.Element { + return ( + +
+ + 6 cities - favorites + +
+
+

Saved listing

+
    + {Map.groupBy(offers, (o) => o.city.name) + .entries() + .map(([cityName, offersInCity]) => ( + + )) + .toArray()} + ; +
+
+
+
+
+ ); +} diff --git a/src/Pages/LoginPage.tsx b/src/Pages/login-page.tsx similarity index 100% rename from src/Pages/LoginPage.tsx rename to src/Pages/login-page.tsx diff --git a/src/Pages/MainPage.tsx b/src/Pages/main-page.tsx similarity index 50% rename from src/Pages/MainPage.tsx rename to src/Pages/main-page.tsx index bcae313..44d9244 100644 --- a/src/Pages/MainPage.tsx +++ b/src/Pages/main-page.tsx @@ -1,54 +1,20 @@ -import React from 'react'; -import { PlaceCard } from '../components/PlaceCard.tsx'; -import { RoomType } from '../DataTypes/RoomType.ts'; +import React, { useState } from 'react'; +import { Offer } from '../dataTypes/offer.ts'; +import { OffersList } from '../components/offer/offers-list.tsx'; +import { Layout } from '../components/layout.tsx'; +import { Helmet } from 'react-helmet-async'; +import { Nullable } from 'vitest'; interface MainPageProps { - placeCount: number; + offers: Offer[]; } -export function MainPage({ placeCount }: MainPageProps): React.JSX.Element { +export function MainPage({ offers }: MainPageProps): React.JSX.Element { + const [activeOfferId, setActiveOfferId] = useState>(''); return ( -
-
-
-
-
- - 6 cities logo - -
- -
-
-
- +
+ 6 cities

Cities

@@ -91,7 +57,7 @@ export function MainPage({ placeCount }: MainPageProps): React.JSX.Element {

Places

- {placeCount} places to stay in Amsterdam + {offers.length} places to stay in Amsterdam
Sort by @@ -119,42 +85,12 @@ export function MainPage({ placeCount }: MainPageProps): React.JSX.Element {
-
- - - - - -
+ ) => + setActiveOfferId(offerId) + } + />
@@ -162,6 +98,6 @@ export function MainPage({ placeCount }: MainPageProps): React.JSX.Element {
-
+ ); } diff --git a/src/Pages/NotFoundPage/NotFoundPage.module.css b/src/Pages/not-found-page/not-found-page.module.css similarity index 100% rename from src/Pages/NotFoundPage/NotFoundPage.module.css rename to src/Pages/not-found-page/not-found-page.module.css diff --git a/src/Pages/NotFoundPage/NotFoundPage.tsx b/src/Pages/not-found-page/not-found-page.tsx similarity index 91% rename from src/Pages/NotFoundPage/NotFoundPage.tsx rename to src/Pages/not-found-page/not-found-page.tsx index 28d5664..ce3c619 100644 --- a/src/Pages/NotFoundPage/NotFoundPage.tsx +++ b/src/Pages/not-found-page/not-found-page.tsx @@ -1,5 +1,5 @@ import { Link } from 'react-router-dom'; -import styles from './NotFoundPage.module.css'; +import styles from './not-found-page.module.css'; import { Helmet } from 'react-helmet-async'; export function NotFoundPage(): React.JSX.Element { diff --git a/src/Pages/offer-page.tsx b/src/Pages/offer-page.tsx new file mode 100644 index 0000000..a671867 --- /dev/null +++ b/src/Pages/offer-page.tsx @@ -0,0 +1,195 @@ +import { Helmet } from 'react-helmet-async'; +import { Layout } from '../components/layout.tsx'; +import { OffersList } from '../components/offer/offers-list.tsx'; +import { offerMocks } from '../mocks/offers.ts'; +import { ReviewForm } from '../components/review-form.tsx'; + +export function OfferPage(): React.JSX.Element { + return ( + +
+ 6 cities - offer +
+
+
+
+ Photo studio +
+
+ Photo studio +
+
+ Photo studio +
+
+ Photo studio +
+
+ Photo studio +
+
+ Photo studio +
+
+
+
+
+
+ Premium +
+
+

+ Beautiful & luxurious studio at great location +

+ +
+
+
+ + Rating +
+ 4.8 +
+
    +
  • + 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

+
+
+ Host avatar +
+ 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. +

+
+
+
+

+ Reviews · 1 +

+
    +
  • +
    +
    + Reviews avatar +
    + Max +
    +
    +
    +
    + + Rating +
    +
    +

    + 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. +

    + +
    +
  • +
+ +
+
+
+
+
+
+
+

+ Other places in the neighbourhood +

+
+ +
+
+
+
+
+ ); +} diff --git a/src/components/App.tsx b/src/components/App.tsx deleted file mode 100644 index 827aa5d..0000000 --- a/src/components/App.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { MainPage } from '../Pages/MainPage.tsx'; -import React from 'react'; -import { BrowserRouter, Route, Routes } from 'react-router-dom'; -import { LoginPage } from '../Pages/LoginPage.tsx'; -import { FavoritesPage } from '../Pages/FavoritesPage.tsx'; -import { OfferPage } from '../Pages/OfferPage.tsx'; -import { NotFoundPage } from '../Pages/NotFoundPage/NotFoundPage.tsx'; -import { AuthorizationWrapper } from './AuthorizationWrapper.tsx'; -import { AppRoutes } from '../DataTypes/AppRoutes.tsx'; -import { HelmetProvider } from 'react-helmet-async'; - -interface AppProps { - placeCount: number; -} - -export function App({ placeCount }: AppProps): React.JSX.Element { - return ( - - - - } - /> - } /> - - - - } - /> - } /> - } /> - - - - ); -} diff --git a/src/components/app.tsx b/src/components/app.tsx new file mode 100644 index 0000000..58fd7f6 --- /dev/null +++ b/src/components/app.tsx @@ -0,0 +1,40 @@ +import { MainPage } from '../pages/main-page.tsx'; +import { BrowserRouter, Route, Routes } from 'react-router-dom'; +import { LoginPage } from '../pages/login-page.tsx'; +import { FavoritesPage } from '../pages/favorites-page.tsx'; +import { OfferPage } from '../pages/offer-page.tsx'; +import { NotFoundPage } from '../pages/not-found-page/not-found-page.tsx'; +import { AuthorizationWrapper } from './authorization-wrapper.tsx'; +import { AppRoutes } from '../dataTypes/enums/app-routes.ts'; +import { HelmetProvider } from 'react-helmet-async'; +import { Offer } from '../dataTypes/offer.ts'; + +interface AppProps { + offers: Offer[]; +} + +export function App({ offers }: AppProps): React.JSX.Element { + return ( + + + + } + /> + } /> + + + + } + /> + } /> + } /> + + + + ); +} diff --git a/src/components/AuthorizationWrapper.tsx b/src/components/authorization-wrapper.tsx similarity index 87% rename from src/components/AuthorizationWrapper.tsx rename to src/components/authorization-wrapper.tsx index b0b3603..b7370a5 100644 --- a/src/components/AuthorizationWrapper.tsx +++ b/src/components/authorization-wrapper.tsx @@ -1,12 +1,13 @@ import { Navigate } from 'react-router-dom'; interface AuthorizationWrapperProps { + isAuthorized: boolean; children: React.JSX.Element; } export function AuthorizationWrapper({ + isAuthorized, children, }: AuthorizationWrapperProps): React.JSX.Element { - const isAuthorized = false; return isAuthorized ? children : ; } diff --git a/src/components/layout.tsx b/src/components/layout.tsx new file mode 100644 index 0000000..21bdb6d --- /dev/null +++ b/src/components/layout.tsx @@ -0,0 +1,69 @@ +import { AppRoutes } from '../dataTypes/enums/app-routes.ts'; +import { Link } from 'react-router-dom'; + +interface LayoutProps { + children: React.JSX.Element; + showFooter?: boolean; +} + +export function Layout({ + children, + showFooter, +}: LayoutProps): React.JSX.Element { + return ( +
+
+
+
+
+ + 6 cities logo + +
+ +
+
+
+ {children} + {showFooter && ( + + )} +
+ ); +} diff --git a/src/components/PlaceCard.tsx b/src/components/offer/offer-card.tsx similarity index 62% rename from src/components/PlaceCard.tsx rename to src/components/offer/offer-card.tsx index 527c1e2..b728c02 100644 --- a/src/components/PlaceCard.tsx +++ b/src/components/offer/offer-card.tsx @@ -1,32 +1,45 @@ -import React from 'react'; -import { RoomType } from '../DataTypes/RoomType.ts'; +import { RoomType } from '../../dataTypes/enums/room-type.ts'; +import { Link } from 'react-router-dom'; +import { AppRoutes } from '../../dataTypes/enums/app-routes.ts'; interface PlaceCardProps { + id: string; price: number; type: RoomType; image: string; - description: string; + title: string; + onMouseEnter?: (id: string) => void; + onMouseLeave?: () => void; isPremium?: boolean; - isInBookmarks?: boolean; + isFavorite?: boolean; } -export function PlaceCard({ +export function OfferCard({ + id, price, type, image, - description, + title, + onMouseEnter, + onMouseLeave, isPremium, - isInBookmarks, + isFavorite, }: PlaceCardProps): React.JSX.Element { + const handleMouseEnter = (): void => onMouseEnter?.(id); + const handleMouseLeave = (): void => onMouseLeave?.(); return ( -
+
{isPremium && (
Premium
)}
- + Place image - +
@@ -43,14 +56,14 @@ export function PlaceCard({ / night
@@ -61,7 +74,7 @@ export function PlaceCard({

- {description} + {title}

{type}

diff --git a/src/components/offer/offer-group.tsx b/src/components/offer/offer-group.tsx new file mode 100644 index 0000000..077b834 --- /dev/null +++ b/src/components/offer/offer-group.tsx @@ -0,0 +1,27 @@ +import { Offer } from '../../dataTypes/offer.ts'; +import { OffersList } from './offers-list.tsx'; + +interface OfferGroupProps { + cityName: string; + offers: Offer[]; +} + +export function OfferGroup({ + cityName, + offers, +}: OfferGroupProps): React.JSX.Element { + return ( +
  • + +
    + +
    +
  • + ); +} diff --git a/src/components/offer/offers-list.tsx b/src/components/offer/offers-list.tsx new file mode 100644 index 0000000..4d5e4d6 --- /dev/null +++ b/src/components/offer/offers-list.tsx @@ -0,0 +1,36 @@ +import { Offer } from '../../dataTypes/offer.ts'; +import { OfferCard } from './offer-card.tsx'; +import React from 'react'; +import { Nullable } from 'vitest'; + +interface OffersListProps { + offers: Offer[]; + onActiveOfferChange?: (offerId: Nullable) => void; +} + +export function OffersList({ + offers, + onActiveOfferChange, +}: OffersListProps): React.JSX.Element { + const handleActiveOfferChange = (id: Nullable): void => { + onActiveOfferChange?.(id); + }; + return ( +
    + {offers.map((offer) => ( + handleActiveOfferChange(offer.id)} + onMouseLeave={() => handleActiveOfferChange(null)} + isFavorite={offer.isFavorite} + isPremium={offer.isPremium} + /> + ))} +
    + ); +} diff --git a/src/components/review-form.tsx b/src/components/review-form.tsx new file mode 100644 index 0000000..b556f0d --- /dev/null +++ b/src/components/review-form.tsx @@ -0,0 +1,137 @@ +import { useState } from 'react'; + +type UserReview = { + comment?: string; + rating?: number; +}; + +export function ReviewForm(): React.JSX.Element { + const [review, setReview] = useState(); + const onRatingChange: React.ChangeEventHandler = ( + event, + ): void => setReview({ ...review, rating: +event.target.value }); + const onCommentChange: React.ChangeEventHandler = ( + event, + ): void => setReview({ ...review, comment: event.target.value }); + const isValid = + review?.comment && review?.comment?.length >= 50 && review?.rating; + return ( +
    + +
    + + + + + + + + + + + + + + +
    + +
    +

    + To submit review please make sure to set{' '} + rating and describe your stay + with at least 50 characters. +

    + +
    +
    + ); +} diff --git a/src/dataTypes/city.ts b/src/dataTypes/city.ts new file mode 100644 index 0000000..d60307e --- /dev/null +++ b/src/dataTypes/city.ts @@ -0,0 +1,6 @@ +import { Location } from './location.ts'; + +export type City = { + name: string; + location: Location; +}; diff --git a/src/DataTypes/AppRoutes.tsx b/src/dataTypes/enums/app-routes.ts similarity index 79% rename from src/DataTypes/AppRoutes.tsx rename to src/dataTypes/enums/app-routes.ts index e03dd83..946058b 100644 --- a/src/DataTypes/AppRoutes.tsx +++ b/src/dataTypes/enums/app-routes.ts @@ -1,6 +1,6 @@ export enum AppRoutes { MainPage = '/', Login = '/login', - Offer = '/offer/:id', + Offer = '/offer', Favorites = '/favorites', } diff --git a/src/dataTypes/enums/authorization-status.ts b/src/dataTypes/enums/authorization-status.ts new file mode 100644 index 0000000..3e0b810 --- /dev/null +++ b/src/dataTypes/enums/authorization-status.ts @@ -0,0 +1,5 @@ +export enum AuthorizationStatus { + Authorized, + Unauthorized, + Unknown +} diff --git a/src/dataTypes/enums/room-type.ts b/src/dataTypes/enums/room-type.ts new file mode 100644 index 0000000..10b288f --- /dev/null +++ b/src/dataTypes/enums/room-type.ts @@ -0,0 +1,4 @@ +export enum RoomType { + Apartment = 'apartment', + Room = 'room', +} diff --git a/src/dataTypes/location.ts b/src/dataTypes/location.ts new file mode 100644 index 0000000..5cd6bac --- /dev/null +++ b/src/dataTypes/location.ts @@ -0,0 +1,5 @@ +export type Location = { + latitude: number; + longitude: number; + zoom: number; +} diff --git a/src/dataTypes/offer.ts b/src/dataTypes/offer.ts new file mode 100644 index 0000000..c417e82 --- /dev/null +++ b/src/dataTypes/offer.ts @@ -0,0 +1,16 @@ +import { Location } from './location.ts'; +import { City } from './city.ts'; +import { RoomType } from './enums/room-type.ts'; + +export type Offer = { + id: string; + title: string; + type: RoomType; + price: number; + city: City; + location: Location; + isFavorite: boolean; + isPremium: boolean; + rating: number; + previewImage: string; +}; diff --git a/src/index.tsx b/src/index.tsx index 13f3c27..e7a9153 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,6 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import { App } from './components/App.tsx'; +import { App } from './components/app.tsx'; +import { offerMocks } from './mocks/offers.ts'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement, @@ -8,6 +9,6 @@ const root = ReactDOM.createRoot( root.render( - + , ); diff --git a/src/mocks/offers.ts b/src/mocks/offers.ts new file mode 100644 index 0000000..61424c5 --- /dev/null +++ b/src/mocks/offers.ts @@ -0,0 +1,97 @@ +import { Offer } from '../dataTypes/offer.ts'; +import { RoomType } from '../dataTypes/enums/room-type.ts'; + +export const offerMocks: Offer[] = [ + { + id: '6af6f711-c28d-4121-82cd-e0b462a27f00', + title: 'Beautiful & luxurious studio at great location', + type: RoomType.Apartment, + price: 120, + city: { + name: 'Amsterdam', + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + }, + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + isFavorite: false, + isPremium: false, + rating: 4, + previewImage: 'apartment-01.jpg', + }, + { + id: '6af6f711-c28d-4121-82cd-e0b462a27f33', + title: 'aboba', + type: RoomType.Room, + price: 21412, + city: { + name: 'Amsterdam', + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + }, + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + isFavorite: false, + isPremium: true, + rating: 4, + previewImage: 'apartment-02.jpg', + }, + { + id: '6af6f711-c28d-4121-82cd-e0b462a27f11', + title: 'Beautiful & luxurious studio at great location', + type: RoomType.Room, + price: 14, + city: { + name: 'Amsterdam', + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + }, + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + isFavorite: true, + isPremium: false, + rating: 4, + previewImage: 'apartment-03.jpg', + }, + { + id: '6af6f711-c28d-4121-82cd-e0b462a27f22', + title: 'Beautiful & luxurious studio at great location', + type: RoomType.Apartment, + price: 88, + city: { + name: 'Cologne', + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + }, + location: { + latitude: 52.35514938496378, + longitude: 4.673877537499948, + zoom: 8, + }, + isFavorite: true, + isPremium: true, + rating: 4, + previewImage: 'apartment-02.jpg', + }, +]; diff --git a/tsconfig.json b/tsconfig.json index 61409ab..3fe56f6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "skipLibCheck": true,