From b67cbc0e27a4ecfee166f08e418fa2e909fc30bb Mon Sep 17 00:00:00 2001 From: Gurikov Maxim Date: Tue, 5 Nov 2024 21:34:28 +0500 Subject: [PATCH] big refractor --- index.html | 1 + src/Pages/main-page.tsx | 9 +- ...und-page.module.css => not-found-page.css} | 8 +- src/Pages/not-found-page/not-found-page.tsx | 8 +- src/Pages/offer-page.tsx | 149 +++++------------- src/components/app.tsx | 2 +- src/components/map/map.tsx | 7 +- src/components/offer/offer-card.tsx | 14 +- src/components/offer/offer-gallery.tsx | 21 +++ src/components/offer/offer-host.tsx | 28 ++++ src/components/offer/offer-inside-items.tsx | 22 +++ src/components/offer/offers-list.tsx | 1 + src/components/rating.tsx | 25 +++ src/components/reviews/review-component.tsx | 14 +- src/components/reviews/review-form.tsx | 3 +- src/components/reviews/reviews.tsx | 2 +- src/dataTypes/detailed-offer.ts | 21 +++ src/dataTypes/enums/authorization-status.ts | 2 +- src/dataTypes/enums/room-type.ts | 4 +- src/dataTypes/location.ts | 2 +- src/mocks/detailed-offer.ts | 141 +++++++++++++++++ src/mocks/reviews.ts | 2 +- src/utils/string-utils.ts | 14 ++ src/utils/username-utils.ts | 3 + 24 files changed, 353 insertions(+), 150 deletions(-) rename src/Pages/not-found-page/{not-found-page.module.css => not-found-page.css} (70%) create mode 100644 src/components/offer/offer-gallery.tsx create mode 100644 src/components/offer/offer-host.tsx create mode 100644 src/components/offer/offer-inside-items.tsx create mode 100644 src/components/rating.tsx create mode 100644 src/dataTypes/detailed-offer.ts create mode 100644 src/mocks/detailed-offer.ts create mode 100644 src/utils/string-utils.ts create mode 100644 src/utils/username-utils.ts diff --git a/index.html b/index.html index 3e079c4..e2bbeb1 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,7 @@ 6 cities + diff --git a/src/Pages/main-page.tsx b/src/Pages/main-page.tsx index d744642..b9e70c1 100644 --- a/src/Pages/main-page.tsx +++ b/src/Pages/main-page.tsx @@ -90,8 +90,7 @@ export function MainPage({ offers }: MainPageProps): React.JSX.Element { ) => - setActiveOffer(offer) - } + setActiveOffer(offer)} isOnMainPage /> @@ -105,9 +104,9 @@ export function MainPage({ offers }: MainPageProps): React.JSX.Element { selectedPoint={ activeOffer ? { - location: activeOffer?.location, - id: activeOffer?.id, - } + location: activeOffer?.location, + id: activeOffer?.id, + } : undefined } isOnMainPage diff --git a/src/Pages/not-found-page/not-found-page.module.css b/src/Pages/not-found-page/not-found-page.css similarity index 70% rename from src/Pages/not-found-page/not-found-page.module.css rename to src/Pages/not-found-page/not-found-page.css index 5155bb6..64dc74f 100644 --- a/src/Pages/not-found-page/not-found-page.module.css +++ b/src/Pages/not-found-page/not-found-page.css @@ -1,20 +1,20 @@ -.container { +.not-found-page { display: flex; flex-direction: column; align-items: center; justify-content: center; } -.title { +.not-found-page__title { text-align: center; } -.link { +.not-found-page__link { color: skyblue; margin: 10px; font-style: italic; } -.link:hover { +.not-found-page__link:hover { text-decoration: underline; font-weight: bold; } diff --git a/src/Pages/not-found-page/not-found-page.tsx b/src/Pages/not-found-page/not-found-page.tsx index ce3c619..05e617a 100644 --- a/src/Pages/not-found-page/not-found-page.tsx +++ b/src/Pages/not-found-page/not-found-page.tsx @@ -1,19 +1,19 @@ import { Link } from 'react-router-dom'; -import styles from './not-found-page.module.css'; import { Helmet } from 'react-helmet-async'; +import {AppRoutes} from '../../dataTypes/enums/app-routes.ts'; export function NotFoundPage(): React.JSX.Element { return ( -
+
404 - not found

404 - Page Not Found

-

+

The page you are looking for might have been removed or is temporarily unavailable.

- + back to main page
diff --git a/src/Pages/offer-page.tsx b/src/Pages/offer-page.tsx index 037a747..58c649b 100644 --- a/src/Pages/offer-page.tsx +++ b/src/Pages/offer-page.tsx @@ -5,74 +5,37 @@ import { offerMocks } from '../mocks/offers.ts'; import { Reviews } from '../components/reviews/reviews.tsx'; import { reviewMocks } from '../mocks/reviews.ts'; import { Map } from '../components/map/map.tsx'; -import React, { useState } from 'react'; -import { Nullable } from 'vitest'; -import { Offer } from '../dataTypes/offer.ts'; +import React from 'react'; +import { useParams } from 'react-router-dom'; +import { OfferInsideItems } from '../components/offer/offer-inside-items.tsx'; +import { detailedOfferMocks } from '../mocks/detailed-offer.ts'; +import { OfferHost } from '../components/offer/offer-host.tsx'; +import { capitalize, pluralizeAndCombine } from '../utils/string-utils.ts'; +import { Rating } from '../components/rating.tsx'; +import { OfferGallery } from '../components/offer/offer-gallery.tsx'; export function OfferPage(): React.JSX.Element { - const [activeOffer, setActiveOffer] = useState>(null); - const offers = offerMocks.slice(0, 3); + const offerId = useParams().id; + const offers = offerMocks.filter((offer) => offer.id !== offerId).slice(0, 3); + const currentOffer = detailedOfferMocks.find( + (offer) => offer.id === offerId, + )!; return (
6 cities - offer
-
-
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
- Photo studio -
-
-
+
-
- Premium -
+ {currentOffer.isPremium && ( +
+ Premium +
+ )}
-

- Beautiful & luxurious studio at great location -

+

{currentOffer.title}

-
-
- - Rating -
- 4.8 -
+
  • - Apartment + {capitalize(currentOffer.type)}
  • - 3 Bedrooms + {pluralizeAndCombine('bedroom', currentOffer.bedrooms)}
  • - Max 4 adults + Max {pluralizeAndCombine('adult', currentOffer.maxAdults)}
- €120 + + €{currentOffer.price} +  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 @@ -158,18 +94,14 @@ export function OfferPage(): React.JSX.Element {

({ + points={[...offers, currentOffer].map((x) => ({ location: x.location, id: x.id, }))} - selectedPoint={ - activeOffer - ? { - location: activeOffer?.location, - id: activeOffer?.id, - } - : undefined - } + selectedPoint={{ + location: currentOffer.location, + id: currentOffer.id, + }} />
@@ -178,10 +110,7 @@ export function OfferPage(): React.JSX.Element { Other places in the neighbourhood
- +
diff --git a/src/components/app.tsx b/src/components/app.tsx index 58fd7f6..35672f6 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -26,7 +26,7 @@ export function App({ offers }: AppProps): React.JSX.Element { + } diff --git a/src/components/map/map.tsx b/src/components/map/map.tsx index 5b7e7c5..6ae3b62 100644 --- a/src/components/map/map.tsx +++ b/src/components/map/map.tsx @@ -59,10 +59,11 @@ export function Map(props: MapProps): React.JSX.Element {
+ > + ); } diff --git a/src/components/offer/offer-card.tsx b/src/components/offer/offer-card.tsx index 9f3d5af..4ae3767 100644 --- a/src/components/offer/offer-card.tsx +++ b/src/components/offer/offer-card.tsx @@ -2,6 +2,7 @@ import { RoomType } from '../../dataTypes/enums/room-type.ts'; import { Link } from 'react-router-dom'; import { AppRoutes } from '../../dataTypes/enums/app-routes.ts'; import cn from 'classnames'; +import { Rating } from '../rating.tsx'; interface PlaceCardProps { id: string; @@ -9,6 +10,7 @@ interface PlaceCardProps { type: RoomType; image: string; title: string; + rating: number; onMouseEnter?: (id: string) => void; onMouseLeave?: () => void; isPremium?: boolean; @@ -22,6 +24,7 @@ export function OfferCard({ type, image, title, + rating, onMouseEnter, onMouseLeave, isPremium, @@ -36,7 +39,7 @@ export function OfferCard({ onMouseLeave={handleMouseLeave} className={cn( 'place-card', - { cities__card: isOnMainPage }, + { 'cities__card': isOnMainPage }, { 'near-places__card': !isOnMainPage }, )} > @@ -80,14 +83,9 @@ export function OfferCard({
-
-
- - Rating -
-
+

- {title} + {title}

{type}

diff --git a/src/components/offer/offer-gallery.tsx b/src/components/offer/offer-gallery.tsx new file mode 100644 index 0000000..a1047be --- /dev/null +++ b/src/components/offer/offer-gallery.tsx @@ -0,0 +1,21 @@ +import React from 'react'; + +interface OfferGalleryProps { + imageSources: string[]; +} + +export function OfferGallery({ + imageSources, +}: OfferGalleryProps): React.JSX.Element { + return ( +
+
+ {imageSources.map((src) => ( +
+ Photo studio +
+ ))} +
+
+ ); +} diff --git a/src/components/offer/offer-host.tsx b/src/components/offer/offer-host.tsx new file mode 100644 index 0000000..e4c288b --- /dev/null +++ b/src/components/offer/offer-host.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import { User } from '../../dataTypes/user.ts'; +import { getFirstName } from '../../utils/username-utils.ts'; + +interface OfferHostProps { + host: User; +} + +export function OfferHost({ host }: OfferHostProps): React.JSX.Element { + return ( + <> +

Meet the host

+
+
+ Host avatar +
+ {getFirstName(host.name)} + {host.isPro && Pro} +
+ + ); +} diff --git a/src/components/offer/offer-inside-items.tsx b/src/components/offer/offer-inside-items.tsx new file mode 100644 index 0000000..793f717 --- /dev/null +++ b/src/components/offer/offer-inside-items.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +interface OfferInsideItemsProps { + items: string[]; +} + +export function OfferInsideItems({ + items, +}: OfferInsideItemsProps): React.JSX.Element { + return ( +
+

What's inside

+
    + {items.map((item) => ( +
  • + {item} +
  • + ))} +
+
+ ); +} diff --git a/src/components/offer/offers-list.tsx b/src/components/offer/offers-list.tsx index 1f9aeef..7d9c3bc 100644 --- a/src/components/offer/offers-list.tsx +++ b/src/components/offer/offers-list.tsx @@ -27,6 +27,7 @@ export function OffersList({ type={offer.type} image={offer.previewImage} title={offer.title} + rating={offer.rating} onMouseEnter={() => handleActiveOfferChange(offer)} onMouseLeave={() => handleActiveOfferChange(null)} isFavorite={offer.isFavorite} diff --git a/src/components/rating.tsx b/src/components/rating.tsx new file mode 100644 index 0000000..7db3415 --- /dev/null +++ b/src/components/rating.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +interface RatingProps { + rating: number; + usePlace: string; + isInOffer?: boolean; +} + +export function Rating({ + rating, + isInOffer, + usePlace, +}: RatingProps): React.JSX.Element { + return ( +
+
+ + Rating +
+ {isInOffer && ( + {rating} + )} +
+ ); +} diff --git a/src/components/reviews/review-component.tsx b/src/components/reviews/review-component.tsx index c5b2b73..1e72ef5 100644 --- a/src/components/reviews/review-component.tsx +++ b/src/components/reviews/review-component.tsx @@ -1,4 +1,7 @@ -interface ReviewProps { +import { getFirstName } from '../../utils/username-utils.ts'; +import { Rating } from '../rating.tsx'; + +interface ReviewProps { comment: string; rating: number; date: Date; @@ -25,15 +28,10 @@ export function ReviewComponent({ alt="Reviews avatar" /> - {userName} + {getFirstName(userName)}
-
-
- - Rating -
-
+

{comment}