Repository: htmlacademy-react/254709-six-cities-3
Pull request #4: Обратная сторона реальности
Author: login: generalofgotei
Created: 2025-05-07T02:26:26Z | Merged: 2025-05-08T07:06:08Z

- Добавит моковые отзывы и офферы
- Прокинет моки через индекс на главную, на страницы предложений и в избранное
- Настроит роутинг
- Добавит состояние на наведенный оффер
- Добавит состояние формы

---
:mortar_board: [Обратная сторона реальности](https://up.htmlacademy.ru/react-individual/3/user/254709/tasks/6)


Diff:
diff --git a/src/components/app/app.tsx b/src/components/app/app.tsx
index d127926..af39b6f 100644
--- a/src/components/app/app.tsx
+++ b/src/components/app/app.tsx
@@ -1,6 +1,8 @@
 import { Route, Routes, BrowserRouter } from 'react-router-dom';
 import { HelmetProvider } from 'react-helmet-async';
 import { AppRoute, AuthorizationStatus } from '../../const';
+import { OffersType } from '../../mocks/offers';
+import { ReviewsType } from '../../mocks/reviews';
 import Layout from '../layout/layout';
 import Main from '../../pages/main/main';
 import Login from '../../pages/login/login';
@@ -10,11 +12,12 @@ import NotFound from '../../pages/not-found/not-found';
 import PrivateRoute from '../private-route/private-route';
 
 type AppProps = {
-  offersCount: number;
   authorizationStatus: typeof AuthorizationStatus[keyof typeof AuthorizationStatus];
+  offers: OffersType;
+  reviews: ReviewsType;
 };
 
-const App = ({ offersCount, authorizationStatus }: AppProps): JSX.Element => (
+const App = ({ authorizationStatus, offers, reviews }: AppProps): JSX.Element => (
   <HelmetProvider>
     <BrowserRouter>
       <Routes>
@@ -22,17 +25,17 @@ const App = ({ offersCount, authorizationStatus }: AppProps): JSX.Element => (
           path={AppRoute.Main}
           element={<Layout authorizationStatus={authorizationStatus}/>}
         >
-          <Route index element={<Main offersCount={offersCount} />} />
+          <Route index element={<Main offers={offers}/>} />
           <Route path={AppRoute.Login} element={<Login />} />
           <Route
             path={AppRoute.Favorites}
             element={
               <PrivateRoute authorizationStatus={authorizationStatus}>
-                <Favorites />
+                <Favorites favoriteOffers = {offers.filter((offer) => offer.isFavorite === true)}/>
               </PrivateRoute>
             }
           />
-          <Route path={AppRoute.Offer} element={<Offer />} />
+          <Route path={`${AppRoute.Offer}/:id`} element={<Offer authorizationStatus={authorizationStatus} offers={offers} reviews={reviews}/>} />
           <Route path="*" element={<NotFound />} />
         </Route>
       </Routes>
diff --git a/src/components/card/card.tsx b/src/components/card/card.tsx
index fe09090..7f9921e 100644
--- a/src/components/card/card.tsx
+++ b/src/components/card/card.tsx
@@ -1,44 +1,83 @@
-const Card = (): JSX.Element => (
-  <article className="cities__card place-card">
-    <div className="place-card__mark">
-      <span>Premium</span>
-    </div>
-    <div className="cities__image-wrapper place-card__image-wrapper">
-      <a href="#">
-        <img
-          className="place-card__image"
-          src="img/apartment-01.jpg"
-          width="260"
-          height="200"
-          alt="Place image"
-        />
-      </a>
-    </div>
-    <div className="place-card__info">
-      <div className="place-card__price-wrapper">
-        <div className="place-card__price">
-          <b className="place-card__price-value">&euro;120</b>
-          <span className="place-card__price-text">&#47;&nbsp;night</span>
+import { Link } from 'react-router-dom';
+import { AppRoute } from '../../const';
+import { OfferType } from '../../mocks/offers';
+import { calculateRating } from '../../utils';
+
+type CardProps = {
+  offer: OfferType;
+  handleHover: (offer?: OfferType) => void;
+};
+
+const Card = ({ offer, handleHover }: CardProps): JSX.Element => {
+  const {
+    isFavorite,
+    id,
+    isPremium,
+    previewImage,
+    price,
+    rating,
+    title,
+    type,
+  } = offer;
+  const handleMouseOn = () => {
+    handleHover(offer);
+  };
+
+  const handleMouseOff = () => {
+    handleHover();
+  };
+  return (
+    <article
+      className="cities__card place-card"
+      onMouseEnter={handleMouseOn}
+      onMouseLeave={handleMouseOff}
+    >
+      {isPremium && (
+        <div className="place-card__mark">
+          <span>Premium</span>
         </div>
-        <button className="place-card__bookmark-button button" type="button">
-          <svg className="place-card__bookmark-icon" width="18" height="19">
-            <use xlinkHref="#icon-bookmark"></use>
-          </svg>
-          <span className="visually-hidden">To bookmarks</span>
-        </button>
+      )}
+      <div className="cities__image-wrapper place-card__image-wrapper">
+        <Link to={`${AppRoute.Offer}/${id}`}>
+          <img
+            className="place-card__image"
+            src={previewImage}
+            width="260"
+            height="200"
+            alt="Place image"
+          />
+        </Link>
       </div>
-      <div className="place-card__rating rating">
-        <div className="place-card__stars rating__stars">
-          <span style={{ width: '80%' }}></span>
-          <span className="visually-hidden">Rating</span>
+      <div className="place-card__info">
+        <div className="place-card__price-wrapper">
+          <div className="place-card__price">
+            <b className="place-card__price-value">&euro;{price}</b>
+            <span className="place-card__price-text">&#47;&nbsp;night</span>
+          </div>
+          <button
+            className={`place-card__bookmark-button button ${isFavorite && 'place-card__bookmark-button--active'}`}
+          >
+            <svg className="place-card__bookmark-icon" width="18" height="19">
+              <use xlinkHref="#icon-bookmark"></use>
+            </svg>
+            <span className="visually-hidden">
+              {isFavorite ? 'In bookmarks' : 'To bookmarks'}
+            </span>
+          </button>
+        </div>
+        <div className="place-card__rating rating">
+          <div className="place-card__stars rating__stars">
+            <span style={{ width: `${calculateRating(rating)}` }} />
+            <span className="visually-hidden">Rating</span>
+          </div>
         </div>
+        <h2 className="place-card__name">
+          <a href="#">{title}</a>
+        </h2>
+        <p className="place-card__type">{type}</p>
       </div>
-      <h2 className="place-card__name">
-        <a href="#">Beautiful &amp; luxurious apartment at great location</a>
-      </h2>
-      <p className="place-card__type">Apartment</p>
-    </div>
-  </article>
-);
+    </article>
+  );
+};
 
 export default Card;
diff --git a/src/components/favorite-card/favorite-card.tsx b/src/components/favorite-card/favorite-card.tsx
new file mode 100644
index 0000000..c28a339
--- /dev/null
+++ b/src/components/favorite-card/favorite-card.tsx
@@ -0,0 +1,62 @@
+import { Link } from 'react-router-dom';
+import { OfferType } from '../../mocks/offers';
+import { calculateRating } from '../../utils';
+import { AppRoute } from '../../const';
+
+type PlaceCardProps = {
+  offer: OfferType;
+};
+
+export const FavoriteCard = ({ offer }: PlaceCardProps) => {
+  const { id, title, type, price, previewImage, isFavorite, isPremium, rating } = offer;
+
+  return (
+    <article className='favorites__card place-card'>
+      {isPremium && (
+        <div className='place-card__mark'>
+          <span>Premium</span>
+        </div>
+      )}
+      <div className='favorites__image-wrapper place-card__image-wrapper'>
+        <Link to={`${AppRoute.Offer}/${id}`}>
+          <img
+            className="place-card__image"
+            src={previewImage}
+            width='150 : 260'
+            height='110 : 200'
+            alt={title}
+          />
+        </Link>
+      </div>
+      <div className={'favorites__card-info place-card__info'}>
+        <div className="place-card__price-wrapper">
+          <div className="place-card__price">
+            <b className="place-card__price-value">&euro;{price}</b>
+            <span className="place-card__price-text">&#47;&nbsp;night</span>
+          </div>
+          <button
+            className={`place-card__bookmark-button ${isFavorite ? 'place-card__bookmark-button--active' : ''} button`}
+            type="button"
+          >
+            <svg className="place-card__bookmark-icon" width="18" height="19">
+              <use xlinkHref="#icon-bookmark"></use>
+            </svg>
+            <span className="visually-hidden">
+              {isFavorite ? 'In bookmarks' : 'To bookmarks'}
+            </span>
+          </button>
+        </div>
+        <div className="place-card__rating rating">
+          <div className="place-card__stars rating__stars">
+            <span style={{ width: `${calculateRating(rating)}` }}></span>
+            <span className="visually-hidden">Rating</span>
+          </div>
+        </div>
+        <h2 className="place-card__name">
+          <Link to={`${AppRoute.Offer}/${id}`}>{title}</Link>
+        </h2>
+        <p className="place-card__type">{type.charAt(0).toUpperCase() + type.slice(1)}</p>
+      </div>
+    </article>
+  );
+};
diff --git a/src/components/favorite-item/favorite-item.tsx b/src/components/favorite-item/favorite-item.tsx
new file mode 100644
index 0000000..3a432cd
--- /dev/null
+++ b/src/components/favorite-item/favorite-item.tsx
@@ -0,0 +1,28 @@
+import { FavoriteCard } from '../favorite-card/favorite-card';
+import { OffersType } from '../../mocks/offers';
+
+
+type FavoriteItemProps = {
+  cityName: string;
+  offers: OffersType;
+};
+
+export const FavoriteItem = ({ cityName, offers }: FavoriteItemProps) => (
+  <li className="favorites__locations-items">
+    <div className="favorites__locations locations locations--current">
+      <div className="locations__item">
+        <a className="locations__item-link" href="#">
+          <span>{cityName}</span>
+        </a>
+      </div>
+    </div>
+    <div className="favorites__places">
+      {offers.map((offer) => (
+        <FavoriteCard
+          key={offer.id}
+          offer={offer}
+        />
+      ))}
+    </div>
+  </li>
+);
diff --git a/src/components/favoriteList/favorite-list.tsx b/src/components/favoriteList/favorite-list.tsx
new file mode 100644
index 0000000..6c05dbd
--- /dev/null
+++ b/src/components/favoriteList/favorite-list.tsx
@@ -0,0 +1,36 @@
+import { FavoriteItem } from '../favorite-item/favorite-item';
+import { OffersType } from '../../mocks/offers';
+
+type FavoriteListProps = {
+  favoriteOffers: OffersType;
+};
+
+type OffersByCityType = {
+  [city: string]: OffersType;
+};
+
+export const FavoriteList = ({ favoriteOffers }: FavoriteListProps): JSX.Element => {
+  const offersByCity: OffersByCityType =
+    favoriteOffers.reduce((acc, offer) => {
+      const cityName = offer.city.name;
+      if (!acc[cityName]) {
+        acc[cityName] = [];
+      }
+      acc[cityName].push(offer);
+      return acc;
+    }, {} as OffersByCityType);
+
+  const cities = Object.keys(offersByCity);
+
+  return (
+    <ul className="favorites__list">
+      {cities.map((cityName) => (
+        <FavoriteItem
+          key={cityName}
+          cityName={cityName}
+          offers={offersByCity[cityName]}
+        />
+      ))}
+    </ul>
+  );
+};
diff --git a/src/components/offer-section/offer-section.tsx b/src/components/offer-section/offer-section.tsx
new file mode 100644
index 0000000..f4e6c2c
--- /dev/null
+++ b/src/components/offer-section/offer-section.tsx
@@ -0,0 +1,55 @@
+import { useState } from 'react';
+import { OffersType } from '../../mocks/offers';
+import { OfferType } from '../../mocks/offers';
+import Card from '../card/card';
+import { Nullable } from 'vitest';
+
+type OfferSectionProps = {
+  offers: OffersType;
+};
+const OfferSection = ({
+  offers,
+}: OfferSectionProps): JSX.Element => {
+  const [, setActiveOffer] = useState<Nullable<OfferType>>(null);
+
+  const handleHover = (offer?: OfferType) => {
+    setActiveOffer(offer || null);
+  };
+
+  return (
+    <section className="cities__places places">
+      <h2 className="visually-hidden">Places</h2>
+      <b className="places__found">{offers.length} places to stay in Amsterdam</b>
+      <form className="places__sorting" action="#" method="get">
+        <span className="places__sorting-caption">Sort by</span>
+        <span className="places__sorting-type" tabIndex={0}>
+          Popular
+          <svg className="places__sorting-arrow" width="7" height="4">
+            <use xlinkHref="#icon-arrow-select"></use>
+          </svg>
+        </span>
+        <ul className="places__options places__options--custom places__options--opened">
+          <li className="places__option places__option--active" tabIndex={0}>
+            Popular
+          </li>
+          <li className="places__option" tabIndex={0}>
+            Price: low to high
+          </li>
+          <li className="places__option" tabIndex={0}>
+            Price: high to low
+          </li>
+          <li className="places__option" tabIndex={0}>
+            Top rated first
+          </li>
+        </ul>
+      </form>
+      <div className="cities__places-list places__list tabs__content">
+        {offers.map((offer) => (
+          <Card key={offer.id} offer={offer} handleHover = {handleHover} />
+        ))}
+      </div>
+    </section>
+  );
+};
+
+export default OfferSection;
diff --git a/src/components/review-form/review-form.tsx b/src/components/review-form/review-form.tsx
new file mode 100644
index 0000000..e7e0b51
--- /dev/null
+++ b/src/components/review-form/review-form.tsx
@@ -0,0 +1,70 @@
+import { ReactEventHandler, useState, Fragment } from 'react';
+import { rating } from '../../const';
+
+type handleChangeType = ReactEventHandler<
+  HTMLInputElement | HTMLTextAreaElement
+>;
+
+const ReviewForm = (): JSX.Element => {
+  const [review, setReview] = useState({ rating: 0, review: '' });
+
+  const handleChange: handleChangeType = (evt) => {
+    const { name, value } = evt.currentTarget;
+    setReview({ ...review, [name]: value });
+  };
+
+  return (
+    <form className="reviews__form form" action="#" method="post">
+      <label className="reviews__label form__label" htmlFor="review">
+        Your review
+      </label>
+      <div className="reviews__rating-form form__rating">
+        {rating.map(({ value, label }) => (
+          <Fragment key={value}>
+            <input
+              className="form__rating-input visually-hidden"
+              name="rating"
+              value={value}
+              id={`${value}-stars`}
+              type="radio"
+              onChange={handleChange}
+            />
+            <label
+              htmlFor={`${value}-stars`}
+              className="reviews__rating-label form__rating-label"
+              title={label}
+            >
+              <svg className="form__star-image" width="37" height="33">
+                <use xlinkHref="#icon-star"></use>
+              </svg>
+            </label>
+          </Fragment>
+        ))}
+      </div>
+
+      <textarea
+        className="reviews__textarea form__textarea"
+        id="review"
+        name="review"
+        placeholder="Tell how was your stay, what you like and what can be improved"
+        onChange={handleChange}
+      />
+      <div className="reviews__button-wrapper">
+        <p className="reviews__help">
+          To submit review please make sure to set{' '}
+          <span className="reviews__star">rating</span> and describe your stay
+          with at least <b className="reviews__text-amount">50 characters</b>.
+        </p>
+        <button
+          className="reviews__submit form__submit button"
+          type="submit"
+          disabled={review.review.length < 50 || review.rating === 0}
+        >
+          Submit
+        </button>
+      </div>
+    </form>
+  );
+};
+
+export default ReviewForm;
diff --git a/src/components/review-item/review-item.tsx b/src/components/review-item/review-item.tsx
new file mode 100644
index 0000000..3af25f4
--- /dev/null
+++ b/src/components/review-item/review-item.tsx
@@ -0,0 +1,43 @@
+import { ReviewType } from '../../mocks/reviews';
+import { calculateRating } from '../../utils';
+import { getHumanDate } from '../../utils';
+
+type ReviewItemProps = {
+  review: ReviewType;
+};
+
+const ReviewItem = ({ review }: ReviewItemProps): JSX.Element => {
+  const { date, user, comment, rating } = review;
+  return (
+    <li className="reviews__item">
+      <div className="reviews__user user">
+        <div className="reviews__avatar-wrapper user__avatar-wrapper">
+          <img
+            className="reviews__avatar user__avatar"
+            src={user.avatarUrl}
+            width={54}
+            height={54}
+            alt="Reviews avatar"
+          />
+        </div>
+        <span className="reviews__user-name">{user.name}</span>
+      </div>
+      <div className="reviews__info">
+        <div className="reviews__rating rating">
+          <div className="reviews__stars rating__stars">
+            <span style={{ width: `${calculateRating(rating)}` }} />
+            <span className="visually-hidden">Rating</span>
+          </div>
+        </div>
+        <p className="reviews__text">
+          {comment}
+        </p>
+        <time className="reviews__time" dateTime={getHumanDate(date).dateTime}>
+          {getHumanDate(date).monthYear}
+        </time>
+      </div>
+    </li>
+  );
+};
+
+export default ReviewItem;
diff --git a/src/components/review-list/review-list.tsx b/src/components/review-list/review-list.tsx
new file mode 100644
index 0000000..63cb929
--- /dev/null
+++ b/src/components/review-list/review-list.tsx
@@ -0,0 +1,23 @@
+import ReviewItem from '../review-item/review-item';
+import ReviewForm from '../review-form/review-form';
+import { AuthorizationStatus } from '../../const';
+import { ReviewsType } from '../../mocks/reviews';
+
+type ReviewListProps = {
+  authorizationStatus: (typeof AuthorizationStatus)[keyof typeof AuthorizationStatus];
+  reviews: ReviewsType;
+};
+
+const ReviewList = ({ authorizationStatus, reviews }: ReviewListProps): JSX.Element => (
+  <section className="offer__reviews reviews">
+    <h2 className="reviews__title">
+      Reviews · <span className="reviews__amount">{reviews.length}</span>
+    </h2>
+    <ul className="reviews__list">
+      {reviews.map((review) => (<ReviewItem key={review.id} review={review}/>))}
+    </ul>
+    {authorizationStatus === 'AUTH' && <ReviewForm />}
+  </section>
+);
+
+export default ReviewList;
diff --git a/src/const.tsx b/src/const.ts
similarity index 59%
rename from src/const.tsx
rename to src/const.ts
index 550a5ad..0ed55b0 100644
--- a/src/const.tsx
+++ b/src/const.ts
@@ -2,7 +2,7 @@ export const AppRoute = {
   Main: '/',
   Login: '/login',
   Favorites: '/favorites',
-  Offer: '/offer/:id',
+  Offer: '/offer',
 } as const;
 
 export const AuthorizationStatus = {
@@ -11,10 +11,6 @@ export const AuthorizationStatus = {
   Unknown: 'UNKNOWN',
 } as const;
 
-export const Setting = {
-  OffersCount: 5,
-} as const;
-
 export const Cities = [
   'Paris',
   'Cologne',
@@ -23,3 +19,11 @@ export const Cities = [
   'Hamburg',
   'Dusseldorf',
 ] as const;
+
+export const rating = [
+  { value: 5, label: 'perfect' },
+  { value: 4, label: 'good' },
+  { value: 3, label: 'not bad' },
+  { value: 2, label: 'badly' },
+  { value: 1, label: 'terribly' },
+] as const;
diff --git a/src/index.tsx b/src/index.tsx
index 4d0af4c..8cfbc90 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -1,8 +1,9 @@
 import React from 'react';
 import ReactDOM from 'react-dom/client';
 import App from './components/app/app';
-import { Setting, AuthorizationStatus } from './const';
-
+import { AuthorizationStatus } from './const';
+import { offers } from './mocks/offers';
+import { reviews } from './mocks/reviews';
 
 const root = ReactDOM.createRoot(
   document.getElementById('root') as HTMLElement
@@ -10,6 +11,6 @@ const root = ReactDOM.createRoot(
 
 root.render(
   <React.StrictMode>
-    <App offersCount={Setting.OffersCount} authorizationStatus={AuthorizationStatus.Auth}/>
+    <App authorizationStatus={AuthorizationStatus.Auth} offers={offers} reviews={reviews}/>
   </React.StrictMode>
 );
diff --git a/src/mocks/offers.ts b/src/mocks/offers.ts
new file mode 100644
index 0000000..965f393
--- /dev/null
+++ b/src/mocks/offers.ts
@@ -0,0 +1,143 @@
+type Location = {
+  latitude: number;
+  longitude: number;
+  zoom: number;
+};
+
+type City = {
+  name: string;
+  location: Location;
+};
+
+export type OfferType = {
+  id: string;
+  title: string;
+  type: string;
+  price: number;
+  previewImage: string;
+  city: City;
+  location: Location;
+  isFavorite: boolean;
+  isPremium: boolean;
+  rating: number;
+};
+
+export type OffersType = OfferType[];
+
+export const offers: OffersType = [
+  {
+    id: 'de5c9e75-6ce8-4b69-b89f-77ee33bf584c',
+    title: 'The house among olive ',
+    type: 'room',
+    price: 187,
+    previewImage: 'https://15.design.htmlacademy.pro/static/hotel/11.jpg',
+    city: {
+      name: 'Amsterdam',
+      location: {
+        latitude: 52.37454,
+        longitude: 4.897976,
+        zoom: 13,
+      },
+    },
+    location: {
+      latitude: 52.36554,
+      longitude: 4.911976,
+      zoom: 16,
+    },
+    isFavorite: false,
+    isPremium: true,
+    rating: 2.2,
+  },
+  {
+    id: '7ff6f3ee-a2d4-4c05-9f83-ff1a6c3abf3c',
+    title: 'Tile House',
+    type: 'hotel',
+    price: 110,
+    previewImage: 'https://15.design.htmlacademy.pro/static/hotel/4.jpg',
+    city: {
+      name: 'Amsterdam',
+      location: {
+        latitude: 52.37454,
+        longitude: 4.897976,
+        zoom: 13,
+      },
+    },
+    location: {
+      latitude: 52.385540000000006,
+      longitude: 4.902976,
+      zoom: 16,
+    },
+    isFavorite: false,
+    isPremium: true,
+    rating: 4.3,
+  },
+  {
+    id: 'ddad17fe-8d37-4585-a5db-fe26b195a741',
+    title: 'The Pondhouse - A Magical Place',
+    type: 'hotel',
+    price: 174,
+    previewImage: 'https://15.design.htmlacademy.pro/static/hotel/7.jpg',
+    city: {
+      name: 'Amsterdam',
+      location: {
+        latitude: 52.37454,
+        longitude: 4.897976,
+        zoom: 13,
+      },
+    },
+    location: {
+      latitude: 52.397540000000006,
+      longitude: 4.9099759999999995,
+      zoom: 16,
+    },
+    isFavorite: true,
+    isPremium: true,
+    rating: 4,
+  },
+  {
+    id: 'b6a0c99a-d1bd-4290-9449-360a0d50258b',
+    title: 'Penthouse, 4-5 rooms + 5 balconies',
+    type: 'hotel',
+    price: 110,
+    previewImage: 'https://15.design.htmlacademy.pro/static/hotel/13.jpg',
+    city: {
+      name: 'Amsterdam',
+      location: {
+        latitude: 52.37454,
+        longitude: 4.897976,
+        zoom: 13,
+      },
+    },
+    location: {
+      latitude: 52.37454,
+      longitude: 4.881976,
+      zoom: 16,
+    },
+    isFavorite: false,
+    isPremium: false,
+    rating: 4.4,
+  },
+  {
+    id: '47a4fe02-18e5-4ff6-a139-4f5559021caa',
+    title: 'Waterfront with extraordinary view',
+    type: 'room',
+    price: 202,
+    previewImage: 'https://15.design.htmlacademy.pro/static/hotel/3.jpg',
+    city: {
+      name: 'Amsterdam',
+      location: {
+        latitude: 52.37454,
+        longitude: 4.897976,
+        zoom: 13,
+      },
+    },
+    location: {
+      latitude: 52.367540000000005,
+      longitude: 4.883976,
+      zoom: 16,
+    },
+    isFavorite: false,
+    isPremium: true,
+    rating: 3.4,
+  },
+];
diff --git a/src/mocks/reviews.ts b/src/mocks/reviews.ts
new file mode 100644
index 0000000..7027c87
--- /dev/null
+++ b/src/mocks/reviews.ts
@@ -0,0 +1,29 @@
+type User = {
+  name: string;
+  avatarUrl: string;
+  isPro: boolean;
+};
+export type ReviewType = {
+  id: string;
+  date: string;
+  user: User;
+  comment: string;
+  rating: number;
+};
+
+export type ReviewsType = ReviewType[];
+
+export const reviews: ReviewsType = [
+  {
+    id: 'b67ddfd5-b953-4a30-8c8d-bd083cd6b62a',
+    date: '2019-05-08T14:13:56.569Z',
+    user: {
+      name: 'Oliver Conner',
+      avatarUrl: 'https://url-to-image/image.png',
+      isPro: false,
+    },
+    comment:
+      'A quiet cozy and picturesque that hides behind a a river by the unique lightness of Amsterdam.',
+    rating: 4,
+  },
+];
diff --git a/src/pages/favorites/favorites.tsx b/src/pages/favorites/favorites.tsx
index 53a3138..7c07677 100644
--- a/src/pages/favorites/favorites.tsx
+++ b/src/pages/favorites/favorites.tsx
@@ -1,7 +1,13 @@
 import Footer from '../../components/footer/footer';
+import { FavoriteList } from '../../components/favoriteList/favorite-list';
 import { Helmet } from 'react-helmet-async';
+import { OffersType } from '../../mocks/offers';
 
-const Favorites = (): JSX.Element => (
+type FavoritesProps = {
+  favoriteOffers: OffersType;
+};
+
+const Favorites = ({ favoriteOffers }: FavoritesProps): JSX.Element => (
   <div className="page">
     <Helmet>
       <title>6 cities: favorites</title>
@@ -11,173 +17,7 @@ const Favorites = (): JSX.Element => (
       <div className="page__favorites-container container">
         <section className="favorites">
           <h1 className="favorites__title">Saved listing</h1>
-          <ul className="favorites__list">
-            <li className="favorites__locations-items">
-              <div className="favorites__locations locations locations--current">
-                <div className="locations__item">
-                  <a className="locations__item-link" href="#">
-                    <span>Amsterdam</span>
-                  </a>
-                </div>
-              </div>
-              <div className="favorites__places">
-                <article className="favorites__card place-card">
-                  <div className="place-card__mark">
-                    <span>Premium</span>
-                  </div>
-                  <div className="favorites__image-wrapper place-card__image-wrapper">
-                    <a href="#">
-                      <img
-                        className="place-card__image"
-                        src="img/apartment-small-03.jpg"
-                        width="150"
-                        height="110"
-                        alt="Place image"
-                      />
-                    </a>
-                  </div>
-                  <div className="favorites__card-info place-card__info">
-                    <div className="place-card__price-wrapper">
-                      <div className="place-card__price">
-                        <b className="place-card__price-value">&euro;180</b>
-                        <span className="place-card__price-text">
-                          &#47;&nbsp;night
-                        </span>
-                      </div>
-                      <button
-                        className="place-card__bookmark-button place-card__bookmark-button--active button"
-                        type="button"
-                      >
-                        <svg
-                          className="place-card__bookmark-icon"
-                          width="18"
-                          height="19"
-                        >
-                          <use xlinkHref="#icon-bookmark"></use>
-                        </svg>
-                        <span className="visually-hidden">In bookmarks</span>
-                      </button>
-                    </div>
-                    <div className="place-card__rating rating">
-                      <div className="place-card__stars rating__stars">
-                        <span style={{width: '100%'}}></span>
-                        <span className="visually-hidden">Rating</span>
-                      </div>
-                    </div>
-                    <h2 className="place-card__name">
-                      <a href="#">Nice, cozy, warm big bed apartment</a>
-                    </h2>
-                    <p className="place-card__type">Apartment</p>
-                  </div>
-                </article>
-
-                <article className="favorites__card place-card">
-                  <div className="favorites__image-wrapper place-card__image-wrapper">
-                    <a href="#">
-                      <img
-                        className="place-card__image"
-                        src="img/room-small.jpg"
-                        width="150"
-                        height="110"
-                        alt="Place image"
-                      />
-                    </a>
-                  </div>
-                  <div className="favorites__card-info place-card__info">
-                    <div className="place-card__price-wrapper">
-                      <div className="place-card__price">
-                        <b className="place-card__price-value">&euro;80</b>
-                        <span className="place-card__price-text">
-                          &#47;&nbsp;night
-                        </span>
-                      </div>
-                      <button
-                        className="place-card__bookmark-button place-card__bookmark-button--active button"
-                        type="button"
-                      >
-                        <svg
-                          className="place-card__bookmark-icon"
-                          width="18"
-                          height="19"
-                        >
-                          <use xlinkHref="#icon-bookmark"></use>
-                        </svg>
-                        <span className="visually-hidden">In bookmarks</span>
-                      </button>
-                    </div>
-                    <div className="place-card__rating rating">
-                      <div className="place-card__stars rating__stars">
-                        <span style={{width: '80%'}}></span>
-                        <span className="visually-hidden">Rating</span>
-                      </div>
-                    </div>
-                    <h2 className="place-card__name">
-                      <a href="#">Wood and stone place</a>
-                    </h2>
-                    <p className="place-card__type">Room</p>
-                  </div>
-                </article>
-              </div>
-            </li>
-
-            <li className="favorites__locations-items">
-              <div className="favorites__locations locations locations--current">
-                <div className="locations__item">
-                  <a className="locations__item-link" href="#">
-                    <span>Cologne</span>
-                  </a>
-                </div>
-              </div>
-              <div className="favorites__places">
-                <article className="favorites__card place-card">
-                  <div className="favorites__image-wrapper place-card__image-wrapper">
-                    <a href="#">
-                      <img
-                        className="place-card__image"
-                        src="img/apartment-small-04.jpg"
-                        width="150"
-                        height="110"
-                        alt="Place image"
-                      />
-                    </a>
-                  </div>
-                  <div className="favorites__card-info place-card__info">
-                    <div className="place-card__price-wrapper">
-                      <div className="place-card__price">
-                        <b className="place-card__price-value">&euro;180</b>
-                        <span className="place-card__price-text">
-                          &#47;&nbsp;night
-                        </span>
-                      </div>
-                      <button
-                        className="place-card__bookmark-button place-card__bookmark-button--active button"
-                        type="button"
-                      >
-                        <svg
-                          className="place-card__bookmark-icon"
-                          width="18"
-                          height="19"
-                        >
-                          <use xlinkHref="#icon-bookmark"></use>
-                        </svg>
-                        <span className="visually-hidden">In bookmarks</span>
-                      </button>
-                    </div>
-                    <div className="place-card__rating rating">
-                      <div className="place-card__stars rating__stars">
-                        <span style={{width: '80%'}}></span>
-                        <span className="visually-hidden">Rating</span>
-                      </div>
-                    </div>
-                    <h2 className="place-card__name">
-                      <a href="#">White castle</a>
-                    </h2>
-                    <p className="place-card__type">Apartment</p>
-                  </div>
-                </article>
-              </div>
-            </li>
-          </ul>
+          <FavoriteList favoriteOffers={ favoriteOffers } />
         </section>
       </div>
     </main>
@@ -187,4 +27,3 @@ const Favorites = (): JSX.Element => (
 );
 
 export default Favorites;
-
diff --git a/src/pages/main/main.tsx b/src/pages/main/main.tsx
index 41163d7..43c6ca5 100644
--- a/src/pages/main/main.tsx
+++ b/src/pages/main/main.tsx
@@ -1,12 +1,13 @@
-import Card from '../../components/card/card';
 import NavItem from '../../components/nav-item/nav-item';
+import OfferSection from '../../components/offer-section/offer-section';
 import { Helmet } from 'react-helmet-async';
+import { OffersType } from '../../mocks/offers';
 
 type MainProps = {
-  offersCount: number;
+  offers: OffersType;
 };
 
-const Main = ({ offersCount }: MainProps): JSX.Element => (
+const Main = ({ offers }: MainProps): JSX.Element => (
   <div className="page page--gray page--main">
     <Helmet>
       <title>6 cities</title>
@@ -19,47 +20,9 @@ const Main = ({ offersCount }: MainProps): JSX.Element => (
 
       <div className="cities">
         <div className="cities__places-container container">
-          <section className="cities__places places">
-            <h2 className="visually-hidden">Places</h2>
-            <b className="places__found">
-              {offersCount} places to stay in Amsterdam
-            </b>
-            <form className="places__sorting" action="#" method="get">
-              <span className="places__sorting-caption">Sort by</span>
-              <span className="places__sorting-type" tabIndex={0}>
-                Popular
-                <svg className="places__sorting-arrow" width="7" height="4">
-                  <use xlinkHref="#icon-arrow-select"></use>
-                </svg>
-              </span>
-              <ul className="places__options places__options--custom places__options--opened">
-                <li
-                  className="places__option places__option--active"
-                  tabIndex={0}
-                >
-                  Popular
-                </li>
-                <li className="places__option" tabIndex={0}>
-                  Price: low to high
-                </li>
-                <li className="places__option" tabIndex={0}>
-                  Price: high to low
-                </li>
-                <li className="places__option" tabIndex={0}>
-                  Top rated first
-                </li>
-              </ul>
-            </form>
-            <div className="cities__places-list places__list tabs__content">
 
-              <Card />
-              <Card />
-              <Card />
-              <Card />
-              <Card />
+          <OfferSection offers={offers}/>
 
-            </div>
-          </section>
           <div className="cities__right-section">
             <section className="cities__map map"></section>
           </div>
diff --git a/src/pages/offer/offer.tsx b/src/pages/offer/offer.tsx
index a867a55..e9e0654 100644
--- a/src/pages/offer/offer.tsx
+++ b/src/pages/offer/offer.tsx
@@ -1,432 +1,330 @@
-const Offer = () => (
-  <div className="page">
+import { useParams } from 'react-router-dom';
+import NotFound from '../not-found/not-found';
+import ReviewList from '../../components/review-list/review-list';
+import { AuthorizationStatus } from '../../const';
+import { OffersType } from '../../mocks/offers';
+import { ReviewsType } from '../../mocks/reviews';
+import { calculateRating } from '../../utils';
 
-    <main className="page__main page__main--offer">
-      <section className="offer">
-        <div className="offer__gallery-container container">
-          <div className="offer__gallery">
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/room.jpg"
-                alt="Photo studio"
-              />
-            </div>
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/apartment-01.jpg"
-                alt="Photo studio"
-              />
-            </div>
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/apartment-02.jpg"
-                alt="Photo studio"
-              />
-            </div>
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/apartment-03.jpg"
-                alt="Photo studio"
-              />
-            </div>
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/studio-01.jpg"
-                alt="Photo studio"
-              />
-            </div>
-            <div className="offer__image-wrapper">
-              <img
-                className="offer__image"
-                src="img/apartment-01.jpg"
-                alt="Photo studio"
-              />
+type OfferProps = {
+  authorizationStatus: (typeof AuthorizationStatus)[keyof typeof AuthorizationStatus];
+  offers: OffersType;
+  reviews: ReviewsType;
+};
+
+const Offer = ({ authorizationStatus, offers, reviews }: OfferProps) => {
+  const id = useParams().id;
+  const currentOffer = offers.find((offer) => offer.id === id);
+  if (!currentOffer) {
+    return <NotFound />;
+  }
+  const {
+    isFavorite,
+    isPremium,
+    price,
+    rating,
+    title,
+    type,
+  } = currentOffer;
+  return (
+    <div className="page">
+      <main className="page__main page__main--offer">
+        <section className="offer">
+          <div className="offer__gallery-container container">
+            <div className="offer__gallery">
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/room.jpg"
+                  alt="Photo studio"
+                />
+              </div>
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/apartment-01.jpg"
+                  alt="Photo studio"
+                />
+              </div>
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/apartment-02.jpg"
+                  alt="Photo studio"
+                />
+              </div>
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/apartment-03.jpg"
+                  alt="Photo studio"
+                />
+              </div>
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/studio-01.jpg"
+                  alt="Photo studio"
+                />
+              </div>
+              <div className="offer__image-wrapper">
+                <img
+                  className="offer__image"
+                  src="img/apartment-01.jpg"
+                  alt="Photo studio"
+                />
+              </div>
             </div>
           </div>
-        </div>
-        <div className="offer__container container">
-          <div className="offer__wrapper">
-            <div className="offer__mark">
-              <span>Premium</span>
-            </div>
-            <div className="offer__name-wrapper">
-              <h1 className="offer__name">
-                Beautiful &amp; luxurious studio at great location
-              </h1>
-              <button className="offer__bookmark-button button" type="button">
-                <svg className="offer__bookmark-icon" width={31} height={33}>
-                  <use xlinkHref="#icon-bookmark" />
-                </svg>
-                <span className="visually-hidden">To bookmarks</span>
-              </button>
-            </div>
-            <div className="offer__rating rating">
-              <div className="offer__stars rating__stars">
-                <span style={{ width: '80%' }} />
-                <span className="visually-hidden">Rating</span>
+          <div className="offer__container container">
+            <div className="offer__wrapper">
+              {isPremium && (
+                <div className="offer__mark">
+                  <span>Premium</span>
+                </div>
+              )}
+              <div className="offer__name-wrapper">
+                <h1 className="offer__name">
+                  {title}
+                </h1>
+                <button
+                  className={`offer__bookmark-button button ${
+                    isFavorite && 'offer__bookmark-button--active'}`}
+                  type="button"
+                >
+                  <svg className="offer__bookmark-icon" width={31} height={33}>
+                    <use xlinkHref="#icon-bookmark" />
+                  </svg>
+                  <span className="visually-hidden">
+                    {isFavorite ? 'In bookmarks' : 'To bookmarks'}
+                  </span>
+                </button>
               </div>
-              <span className="offer__rating-value rating__value">4.8</span>
-            </div>
-            <ul className="offer__features">
-              <li className="offer__feature offer__feature--entire">
-                Apartment
-              </li>
-              <li className="offer__feature offer__feature--bedrooms">
-                3 Bedrooms
-              </li>
-              <li className="offer__feature offer__feature--adults">
-                Max 4 adults
-              </li>
-            </ul>
-            <div className="offer__price">
-              <b className="offer__price-value">€120</b>
-              <span className="offer__price-text">&nbsp;night</span>
-            </div>
-            <div className="offer__inside">
-              <h2 className="offer__inside-title">What&apos;s inside</h2>
-              <ul className="offer__inside-list">
-                <li className="offer__inside-item">Wi-Fi</li>
-                <li className="offer__inside-item">Washing machine</li>
-                <li className="offer__inside-item">Towels</li>
-                <li className="offer__inside-item">Heating</li>
-                <li className="offer__inside-item">Coffee machine</li>
-                <li className="offer__inside-item">Baby seat</li>
-                <li className="offer__inside-item">Kitchen</li>
-                <li className="offer__inside-item">Dishwasher</li>
-                <li className="offer__inside-item">Cabel TV</li>
-                <li className="offer__inside-item">Fridge</li>
-              </ul>
-            </div>
-            <div className="offer__host">
-              <h2 className="offer__host-title">Meet the host</h2>
-              <div className="offer__host-user user">
-                <div className="offer__avatar-wrapper offer__avatar-wrapper--pro user__avatar-wrapper">
-                  <img
-                    className="offer__avatar user__avatar"
-                    src="img/avatar-angelina.jpg"
-                    width={74}
-                    height={74}
-                    alt="Host avatar"
-                  />
+              <div className="offer__rating rating">
+                <div className="offer__stars rating__stars">
+                  <span style={{ width: `${calculateRating(rating)}` }}/>
+                  <span className="visually-hidden">Rating</span>
                 </div>
-                <span className="offer__user-name">Angelina</span>
-                <span className="offer__user-status">Pro</span>
+                <span className="offer__rating-value rating__value">{rating}</span>
+              </div>
+              <ul className="offer__features">
+                <li className="offer__feature offer__feature--entire">
+                  {type}
+                </li>
+                <li className="offer__feature offer__feature--bedrooms">
+                  3 Bedrooms
+                </li>
+                <li className="offer__feature offer__feature--adults">
+                  Max 4 adults
+                </li>
+              </ul>
+              <div className="offer__price">
+                <b className="offer__price-value">€{price}</b>
+                <span className="offer__price-text">&nbsp;night</span>
               </div>
-              <div className="offer__description">
-                <p className="offer__text">
-                  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.
-                </p>
-                <p className="offer__text">
-                  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.
-                </p>
+              <div className="offer__inside">
+                <h2 className="offer__inside-title">What&apos;s inside</h2>
+                <ul className="offer__inside-list">
+                  <li className="offer__inside-item">Wi-Fi</li>
+                  <li className="offer__inside-item">Washing machine</li>
+                  <li className="offer__inside-item">Towels</li>
+                  <li className="offer__inside-item">Heating</li>
+                  <li className="offer__inside-item">Coffee machine</li>
+                  <li className="offer__inside-item">Baby seat</li>
+                  <li className="offer__inside-item">Kitchen</li>
+                  <li className="offer__inside-item">Dishwasher</li>
+                  <li className="offer__inside-item">Cabel TV</li>
+                  <li className="offer__inside-item">Fridge</li>
+                </ul>
+              </div>
+              <div className="offer__host">
+                <h2 className="offer__host-title">Meet the host</h2>
+                <div className="offer__host-user user">
+                  <div className="offer__avatar-wrapper offer__avatar-wrapper--pro user__avatar-wrapper">
+                    <img
+                      className="offer__avatar user__avatar"
+                      src="img/avatar-angelina.jpg"
+                      width={74}
+                      height={74}
+                      alt="Host avatar"
+                    />
+                  </div>
+                  <span className="offer__user-name">Angelina</span>
+                  <span className="offer__user-status">Pro</span>
+                </div>
+                <div className="offer__description">
+                  <p className="offer__text">
+                    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.
+                  </p>
+                  <p className="offer__text">
+                    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.
+                  </p>
+                </div>
               </div>
+
+              <ReviewList authorizationStatus = { authorizationStatus } reviews={reviews}/>
+
             </div>
-            <section className="offer__reviews reviews">
-              <h2 className="reviews__title">
-                Reviews · <span className="reviews__amount">1</span>
-              </h2>
-              <ul className="reviews__list">
-                <li className="reviews__item">
-                  <div className="reviews__user user">
-                    <div className="reviews__avatar-wrapper user__avatar-wrapper">
-                      <img
-                        className="reviews__avatar user__avatar"
-                        src="img/avatar-max.jpg"
-                        width={54}
-                        height={54}
-                        alt="Reviews avatar"
-                      />
+          </div>
+          <section className="offer__map map" />
+        </section>
+        <div className="container">
+          <section className="near-places places">
+            <h2 className="near-places__title">
+              Other places in the neighbourhood
+            </h2>
+            <div className="near-places__list places__list">
+              <article className="near-places__card place-card">
+                <div className="near-places__image-wrapper place-card__image-wrapper">
+                  <a href="#">
+                    <img
+                      className="place-card__image"
+                      src="img/room.jpg"
+                      width={260}
+                      height={200}
+                      alt="Place image"
+                    />
+                  </a>
+                </div>
+                <div className="place-card__info">
+                  <div className="place-card__price-wrapper">
+                    <div className="place-card__price">
+                      <b className="place-card__price-value">€80</b>
+                      <span className="place-card__price-text">
+                        /&nbsp;night
+                      </span>
                     </div>
-                    <span className="reviews__user-name">Max</span>
+                    <button
+                      className="place-card__bookmark-button place-card__bookmark-button--active button"
+                      type="button"
+                    >
+                      <svg
+                        className="place-card__bookmark-icon"
+                        width={18}
+                        height={19}
+                      >
+                        <use xlinkHref="#icon-bookmark" />
+                      </svg>
+                      <span className="visually-hidden">In bookmarks</span>
+                    </button>
                   </div>
-                  <div className="reviews__info">
-                    <div className="reviews__rating rating">
-                      <div className="reviews__stars rating__stars">
-                        <span style={{ width: '80%' }} />
-                        <span className="visually-hidden">Rating</span>
-                      </div>
+                  <div className="place-card__rating rating">
+                    <div className="place-card__stars rating__stars">
+                      <span style={{ width: '80%' }} />
+                      <span className="visually-hidden">Rating</span>
                     </div>
-                    <p className="reviews__text">
-                      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.
-                    </p>
-                    <time className="reviews__time" dateTime="2019-04-24">
-                      April 2019
-                    </time>
                   </div>
-                </li>
-              </ul>
-              <form className="reviews__form form" action="#" method="post">
-                <label className="reviews__label form__label" htmlFor="review">
-                  Your review
-                </label>
-                <div className="reviews__rating-form form__rating">
-                  <input
-                    className="form__rating-input visually-hidden"
-                    name="rating"
-                    defaultValue={5}
-                    id="5-stars"
-                    type="radio"
-                  />
-                  <label
-                    htmlFor="5-stars"
-                    className="reviews__rating-label form__rating-label"
-                    title="perfect"
-                  >
-                    <svg className="form__star-image" width={37} height={33}>
-                      <use xlinkHref="#icon-star" />
-                    </svg>
-                  </label>
-                  <input
-                    className="form__rating-input visually-hidden"
-                    name="rating"
-                    defaultValue={4}
-                    id="4-stars"
-                    type="radio"
-                  />
-                  <label
-                    htmlFor="4-stars"
-                    className="reviews__rating-label form__rating-label"
-                    title="good"
-                  >
-                    <svg className="form__star-image" width={37} height={33}>
-                      <use xlinkHref="#icon-star" />
-                    </svg>
-                  </label>
-                  <input
-                    className="form__rating-input visually-hidden"
-                    name="rating"
-                    defaultValue={3}
-                    id="3-stars"
-                    type="radio"
-                  />
-                  <label
-                    htmlFor="3-stars"
-                    className="reviews__rating-label form__rating-label"
-                    title="not bad"
-                  >
-                    <svg className="form__star-image" width={37} height={33}>
-                      <use xlinkHref="#icon-star" />
-                    </svg>
-                  </label>
-                  <input
-                    className="form__rating-input visually-hidden"
-                    name="rating"
-                    defaultValue={2}
-                    id="2-stars"
-                    type="radio"
-                  />
-                  <label
-                    htmlFor="2-stars"
-                    className="reviews__rating-label form__rating-label"
-                    title="badly"
-                  >
-                    <svg className="form__star-image" width={37} height={33}>
-                      <use xlinkHref="#icon-star" />
-                    </svg>
-                  </label>
-                  <input
-                    className="form__rating-input visually-hidden"
-                    name="rating"
-                    defaultValue={1}
-                    id="1-star"
-                    type="radio"
-                  />
-                  <label
-                    htmlFor="1-star"
-                    className="reviews__rating-label form__rating-label"
-                    title="terribly"
-                  >
-                    <svg className="form__star-image" width={37} height={33}>
-                      <use xlinkHref="#icon-star" />
-                    </svg>
-                  </label>
+                  <h2 className="place-card__name">
+                    <a href="#">Wood and stone place</a>
+                  </h2>
+                  <p className="place-card__type">Room</p>
                 </div>
-                <textarea
-                  className="reviews__textarea form__textarea"
-                  id="review"
-                  name="review"
-                  placeholder="Tell how was your stay, what you like and what can be improved"
-                  defaultValue={''}
-                />
-                <div className="reviews__button-wrapper">
-                  <p className="reviews__help">
-                    To submit review please make sure to set{' '}
-                    <span className="reviews__star">rating</span> and describe
-                    your stay with at least{' '}
-                    <b className="reviews__text-amount">50 characters</b>.
-                  </p>
-                  <button
-                    className="reviews__submit form__submit button"
-                    type="submit"
-                    disabled
-                  >
-                    Submit
-                  </button>
+              </article>
+              <article className="near-places__card place-card">
+                <div className="near-places__image-wrapper place-card__image-wrapper">
+                  <a href="#">
+                    <img
+                      className="place-card__image"
+                      src="img/apartment-02.jpg"
+                      width={260}
+                      height={200}
+                      alt="Place image"
+                    />
+                  </a>
                 </div>
-              </form>
-            </section>
-          </div>
-        </div>
-        <section className="offer__map map" />
-      </section>
-      <div className="container">
-        <section className="near-places places">
-          <h2 className="near-places__title">
-            Other places in the neighbourhood
-          </h2>
-          <div className="near-places__list places__list">
-            <article className="near-places__card place-card">
-              <div className="near-places__image-wrapper place-card__image-wrapper">
-                <a href="#">
-                  <img
-                    className="place-card__image"
-                    src="img/room.jpg"
-                    width={260}
-                    height={200}
-                    alt="Place image"
-                  />
-                </a>
-              </div>
-              <div className="place-card__info">
-                <div className="place-card__price-wrapper">
-                  <div className="place-card__price">
-                    <b className="place-card__price-value">€80</b>
-                    <span className="place-card__price-text">/&nbsp;night</span>
-                  </div>
-                  <button
-                    className="place-card__bookmark-button place-card__bookmark-button--active button"
-                    type="button"
-                  >
-                    <svg
-                      className="place-card__bookmark-icon"
-                      width={18}
-                      height={19}
+                <div className="place-card__info">
+                  <div className="place-card__price-wrapper">
+                    <div className="place-card__price">
+                      <b className="place-card__price-value">€132</b>
+                      <span className="place-card__price-text">
+                        /&nbsp;night
+                      </span>
+                    </div>
+                    <button
+                      className="place-card__bookmark-button button"
+                      type="button"
                     >
-                      <use xlinkHref="#icon-bookmark" />
-                    </svg>
-                    <span className="visually-hidden">In bookmarks</span>
-                  </button>
-                </div>
-                <div className="place-card__rating rating">
-                  <div className="place-card__stars rating__stars">
-                    <span style={{ width: '80%' }} />
-                    <span className="visually-hidden">Rating</span>
+                      <svg
+                        className="place-card__bookmark-icon"
+                        width={18}
+                        height={19}
+                      >
+                        <use xlinkHref="#icon-bookmark" />
+                      </svg>
+                      <span className="visually-hidden">To bookmarks</span>
+                    </button>
                   </div>
-                </div>
-                <h2 className="place-card__name">
-                  <a href="#">Wood and stone place</a>
-                </h2>
-                <p className="place-card__type">Room</p>
-              </div>
-            </article>
-            <article className="near-places__card place-card">
-              <div className="near-places__image-wrapper place-card__image-wrapper">
-                <a href="#">
-                  <img
-                    className="place-card__image"
-                    src="img/apartment-02.jpg"
-                    width={260}
-                    height={200}
-                    alt="Place image"
-                  />
-                </a>
-              </div>
-              <div className="place-card__info">
-                <div className="place-card__price-wrapper">
-                  <div className="place-card__price">
-                    <b className="place-card__price-value">€132</b>
-                    <span className="place-card__price-text">/&nbsp;night</span>
+                  <div className="place-card__rating rating">
+                    <div className="place-card__stars rating__stars">
+                      <span style={{ width: '80%' }} />
+                      <span className="visually-hidden">Rating</span>
+                    </div>
                   </div>
-                  <button
-                    className="place-card__bookmark-button button"
-                    type="button"
-                  >
-                    <svg
-                      className="place-card__bookmark-icon"
-                      width={18}
-                      height={19}
-                    >
-                      <use xlinkHref="#icon-bookmark" />
-                    </svg>
-                    <span className="visually-hidden">To bookmarks</span>
-                  </button>
+                  <h2 className="place-card__name">
+                    <a href="#">Canal View Prinsengracht</a>
+                  </h2>
+                  <p className="place-card__type">Apartment</p>
                 </div>
-                <div className="place-card__rating rating">
-                  <div className="place-card__stars rating__stars">
-                    <span style={{ width: '80%' }} />
-                    <span className="visually-hidden">Rating</span>
-                  </div>
+              </article>
+              <article className="near-places__card place-card">
+                <div className="place-card__mark">
+                  <span>Premium</span>
                 </div>
-                <h2 className="place-card__name">
-                  <a href="#">Canal View Prinsengracht</a>
-                </h2>
-                <p className="place-card__type">Apartment</p>
-              </div>
-            </article>
-            <article className="near-places__card place-card">
-              <div className="place-card__mark">
-                <span>Premium</span>
-              </div>
-              <div className="near-places__image-wrapper place-card__image-wrapper">
-                <a href="#">
-                  <img
-                    className="place-card__image"
-                    src="img/apartment-03.jpg"
-                    width={260}
-                    height={200}
-                    alt="Place image"
-                  />
-                </a>
-              </div>
-              <div className="place-card__info">
-                <div className="place-card__price-wrapper">
-                  <div className="place-card__price">
-                    <b className="place-card__price-value">€180</b>
-                    <span className="place-card__price-text">/&nbsp;night</span>
-                  </div>
-                  <button
-                    className="place-card__bookmark-button button"
-                    type="button"
-                  >
-                    <svg
-                      className="place-card__bookmark-icon"
-                      width={18}
-                      height={19}
-                    >
-                      <use xlinkHref="#icon-bookmark" />
-                    </svg>
-                    <span className="visually-hidden">To bookmarks</span>
-                  </button>
+                <div className="near-places__image-wrapper place-card__image-wrapper">
+                  <a href="#">
+                    <img
+                      className="place-card__image"
+                      src="img/apartment-03.jpg"
+                      width={260}
+                      height={200}
+                      alt="Place image"
+                    />
+                  </a>
                 </div>
-                <div className="place-card__rating rating">
-                  <div className="place-card__stars rating__stars">
-                    <span style={{ width: '100%' }} />
-                    <span className="visually-hidden">Rating</span>
+                <div className="place-card__info">
+                  <div className="place-card__price-wrapper">
+                    <div className="place-card__price">
+                      <b className="place-card__price-value">€180</b>
+                      <span className="place-card__price-text">
+                        /&nbsp;night
+                      </span>
+                    </div>
+                    <button
+                      className="place-card__bookmark-button button"
+                      type="button"
+                    >
+                      <svg
+                        className="place-card__bookmark-icon"
+                        width={18}
+                        height={19}
+                      >
+                        <use xlinkHref="#icon-bookmark" />
+                      </svg>
+                      <span className="visually-hidden">To bookmarks</span>
+                    </button>
+                  </div>
+                  <div className="place-card__rating rating">
+                    <div className="place-card__stars rating__stars">
+                      <span style={{ width: '100%' }} />
+                      <span className="visually-hidden">Rating</span>
+                    </div>
                   </div>
+                  <h2 className="place-card__name">
+                    <a href="#">Nice, cozy, warm big bed apartment</a>
+                  </h2>
+                  <p className="place-card__type">Apartment</p>
                 </div>
-                <h2 className="place-card__name">
-                  <a href="#">Nice, cozy, warm big bed apartment</a>
-                </h2>
-                <p className="place-card__type">Apartment</p>
-              </div>
-            </article>
-          </div>
-        </section>
-      </div>
-    </main>
-  </div>
-);
+              </article>
+            </div>
+          </section>
+        </div>
+      </main>
+    </div>
+  );
+};
 
 export default Offer;
-
diff --git a/src/utils.ts b/src/utils.ts
new file mode 100644
index 0000000..54bdd27
--- /dev/null
+++ b/src/utils.ts
@@ -0,0 +1,18 @@
+export const calculateRating = (rating: number): string => `${(rating / 5) * 100}%`;
+
+export const getHumanDate = (isoDate: string) => {
+  const date = new Date(isoDate);
+
+  const dateTime = date.toISOString().split('T')[0];
+
+  const month = date.toLocaleString('en-US', { month: 'long' });
+  const year = date.getFullYear();
+  const monthYear = `${month} ${year}`;
+
+  return {
+    dateTime,
+    monthYear
+  };
+};
+
+


Reviews:
user: login: AlSudar
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T07:02:26Z
user: login: AlSudar
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T07:03:00Z
user: login: AlSudar
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T07:03:24Z

Review comments:
diff_hunk: @@ -1,44 +1,83 @@
-const Card = (): JSX.Element => (
-  <article className="cities__card place-card">
-    <div className="place-card__mark">
-      <span>Premium</span>
-    </div>
-    <div className="cities__image-wrapper place-card__image-wrapper">
-      <a href="#">
-        <img
-          className="place-card__image"
-          src="img/apartment-01.jpg"
-          width="260"
-          height="200"
-          alt="Place image"
-        />
-      </a>
-    </div>
-    <div className="place-card__info">
-      <div className="place-card__price-wrapper">
-        <div className="place-card__price">
-          <b className="place-card__price-value">&euro;120</b>
-          <span className="place-card__price-text">&#47;&nbsp;night</span>
+import { Link } from 'react-router-dom';
+import { AppRoute } from '../../const';
+import { OfferType } from '../../mocks/offers';
+import { calculateRating } from '../../utils';
+
+type CardProps = {
+  offer: OfferType;
+  handleHover: (offer?: OfferType) => void;
+};
+
+const Card = ({ offer, handleHover }: CardProps): JSX.Element => {
+  const {
+    isFavorite,
+    id,
+    isPremium,
+    previewImage,
+    price,
+    rating,
+    title,
+    type,
+  } = offer;
+  const handleMouseOn = () => {
path: src/components/card/card.tsx
user: login: AlSudar
body: можно в одну строчку записать - `const handleMouseOn = () => handleHover(offer);`
created_at: 2025-05-08T07:02:26Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,62 @@
+import { Link } from 'react-router-dom';
+import { OfferType } from '../../mocks/offers';
+import { calculateRating } from '../../utils';
+import { AppRoute } from '../../const';
+
+type PlaceCardProps = {
+  offer: OfferType;
+};
+
+export const FavoriteCard = ({ offer }: PlaceCardProps) => {
+  const { id, title, type, price, previewImage, isFavorite, isPremium, rating } = offer;
+
+  return (
+    <article className='favorites__card place-card'>
+      {isPremium && (
+        <div className='place-card__mark'>
+          <span>Premium</span>
+        </div>
+      )}
+      <div className='favorites__image-wrapper place-card__image-wrapper'>
+        <Link to={`${AppRoute.Offer}/${id}`}>
+          <img
+            className="place-card__image"
+            src={previewImage}
+            width='150 : 260'
path: src/components/favorite-card/favorite-card.tsx
user: login: AlSudar
body: тут как будто бы забыл тернарник написать
created_at: 2025-05-08T07:03:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,62 @@
+import { Link } from 'react-router-dom';
+import { OfferType } from '../../mocks/offers';
+import { calculateRating } from '../../utils';
+import { AppRoute } from '../../const';
+
+type PlaceCardProps = {
+  offer: OfferType;
+};
+
+export const FavoriteCard = ({ offer }: PlaceCardProps) => {
+  const { id, title, type, price, previewImage, isFavorite, isPremium, rating } = offer;
+
+  return (
+    <article className='favorites__card place-card'>
+      {isPremium && (
+        <div className='place-card__mark'>
+          <span>Premium</span>
+        </div>
+      )}
+      <div className='favorites__image-wrapper place-card__image-wrapper'>
+        <Link to={`${AppRoute.Offer}/${id}`}>
+          <img
+            className="place-card__image"
+            src={previewImage}
+            width='150 : 260'
+            height='110 : 200'
+            alt={title}
+          />
+        </Link>
+      </div>
+      <div className={'favorites__card-info place-card__info'}>
+        <div className="place-card__price-wrapper">
+          <div className="place-card__price">
+            <b className="place-card__price-value">&euro;{price}</b>
+            <span className="place-card__price-text">&#47;&nbsp;night</span>
+          </div>
+          <button
+            className={`place-card__bookmark-button ${isFavorite ? 'place-card__bookmark-button--active' : ''} button`}
path: src/components/favorite-card/favorite-card.tsx
user: login: AlSudar
body: isFavorite && 'place-card__bookmark-button--active' - тут вроде так можно 
created_at: 2025-05-08T07:03:24Z
author_association: CONTRIBUTOR

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-07T02:27:02Z
body: Ваш пулреквест опубликован. Посмотреть можно [здесь](https://htmlacademy-react.github.io/254709-six-cities-3/4/)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-07T02:49:50Z
body: Ваш пулреквест опубликован. Посмотреть можно [здесь](https://htmlacademy-react.github.io/254709-six-cities-3/4/)
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-07T02:59:28Z
body: Ваш пулреквест опубликован. Посмотреть можно [здесь](https://htmlacademy-react.github.io/254709-six-cities-3/4/)
author_association: NONE