Skip to content

Commit

Permalink
offerdetails and online comments list and add comment online
Browse files Browse the repository at this point in the history
  • Loading branch information
hanimohammad committed Nov 27, 2024
1 parent d834564 commit e742bde
Show file tree
Hide file tree
Showing 20 changed files with 506 additions and 365 deletions.
18 changes: 15 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,36 @@
import { useEffect } from 'react';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { HelmetProvider } from 'react-helmet-async';
import MainPage from './components/MainPage/MainPage';
import Favorite from './components/Favorites/Favorite';
import LoginPage from './components/Login/LoginPage';
import NotFoundPage from './components/NotFoundPage/NotFoundPage';
import Offer from './components/Offer/Offer';
import { useAppSelector } from './hooks';
import { useAppSelector,useAppDispatch } from './hooks';
import { REVIEWERS } from './mock/reviewers';
import { fetchOfferObjectAction } from './api-actions.ts';
//import LoadingScreen from './components/loading-screen/loading-screen';

export const App: React.FC = () => {
const dispatch = useAppDispatch();

//const isLoading = useAppSelector(getLoadingOfferPage);
const currentCity = useAppSelector((state) => state.currentCity);
const offers = useAppSelector((state) => state.offerPage);
const cities = useAppSelector((state) => state.Cities);
useEffect(() => {
dispatch(fetchOfferObjectAction());
}, [dispatch]);
// eslint-disable-next-line no-unused-expressions

const offerdetails = useAppSelector((state) => state.offerIdDetails);
return (
<HelmetProvider>
<BrowserRouter>
<Routes>
<Route path="/" element={<MainPage currentCity={currentCity.currentCity} cities={cities.cities}/>} />
<Route path="/" element={<MainPage offers={offers.offer} currentCity={currentCity.currentCity} cities={cities.cities}/>} />
<Route path="/login" element={<LoginPage />} />
<Route path="/offer/:id" element={<Offer reviews={REVIEWERS} offers={offers.offer} currentCity={currentCity.currentCity}/>} />
<Route path="/offer/:id" element={(offers.offer?.filter((o) => o.id === offerdetails.offer.id).length) > 0 ? <Offer offerdetails={offerdetails.offer} reviews={REVIEWERS} offers={offers.offer} currentCity={currentCity.currentCity}/> : <NotFoundPage/>} />

Check failure on line 33 in src/App.tsx

View workflow job for this annotation

GitHub Actions / build

Type '{ id: number; user: { name: string; avatar: string; }; rating: number; comment: string; date: Date; }[]' is not assignable to type 'UserReview[]'.
<Route path="/favorites" element={<Favorite offers={offers.offer} />} />
</Routes>
</BrowserRouter>
Expand Down
4 changes: 3 additions & 1 deletion src/action.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createAction } from '@reduxjs/toolkit';
import { OfferObject } from './types/types';
import { OfferObject, OfferIdDetails } from './types/types';
export const changeCity = createAction<string>('ChangeCity');

export const AddOffer = createAction<OfferObject[]>('AddOffer');

export const loadOffers = createAction<OfferObject[]>('data/fetchOffers');

export const loadOfferDetails = createAction<OfferIdDetails>('data/loadOffer');
82 changes: 68 additions & 14 deletions src/api-actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
/* eslint-disable @typescript-eslint/no-shadow */
import { AxiosInstance } from 'axios';
import { createAsyncThunk } from '@reduxjs/toolkit';
import { AppDispatch, State } from './types/types';
import { createAction, createAsyncThunk } from '@reduxjs/toolkit';
import {
AppDispatch,
OfferIdDetails,
State,
UserReview,
UserReviewPost,
} from './types/types';
import { OfferObject } from './types/types';
//import {redirectToRoute} from './action';
//import { saveToken, dropToken } from './token';
Expand All @@ -12,6 +18,10 @@ import { createAPI } from './api';
import { dropToken, saveToken } from './token';

export const api = createAPI();
export const loadOfferNearby = createAction<OfferObject[]>(
'data/loadOfferNearby'
);
export const loadComments = createAction<UserReview[]>('data/loadComments');
export const fetchOfferObjectAction = createAsyncThunk<
OfferObject[],
undefined,
Expand All @@ -24,18 +34,18 @@ export const fetchOfferObjectAction = createAsyncThunk<
const { data } = await api.get<OfferObject[]>(APIRoute.Offers);
return data;
});
/*
export const checkAuthAction = createAsyncThunk<void, undefined, {
dispatch: AppDispatch;
state: State;
extra: AxiosInstance;
}>(
'user/checkAuth',
async (_arg, {extra: api}) => {
await api.get(APIRoute.Login);
},
);
*/
export const fetchOffer = createAsyncThunk<
OfferIdDetails,
string,
{
// dispatch: AppDispatch;
// state: State;
extra: AxiosInstance;
}
>('data/fetchOfferId', async (id, { extra: api }) => {
const { data } = await api.get<OfferIdDetails>(`${APIRoute.Offers}/${id}`);
return data;
});
export const login = createAsyncThunk<
UserAuth,
LoginAuth,
Expand Down Expand Up @@ -70,3 +80,47 @@ export const logout = createAsyncThunk<
await api.delete(APIRoute.Logout);
dropToken();
});

export const fetchOfferNeibourhood = createAsyncThunk<
void,
string,
{
dispatch: AppDispatch;
state: State;
extra: AxiosInstance;
}
>('data/fetchOfferNearby', async (id, { dispatch, extra: api }) => {
const { data } = await api.get<OfferObject[]>(
`${APIRoute.Offers}/${id}/nearby`
);
dispatch(loadOfferNearby(data));
});

export const fetchComments = createAsyncThunk<
void,
string,
{
dispatch: AppDispatch;
state: State;
extra: AxiosInstance;
}
>('data/fetchComments', async (id, { dispatch, extra: api }) => {
const { data } = await api.get<UserReview[]>(`${APIRoute.Comments}/${id}`);
dispatch(loadComments(data));
});

export const postComment = createAsyncThunk<
void,
UserReviewPost,
{
dispatch: AppDispatch;
state: State;
extra: AxiosInstance;
}
>('post/Comment', async ({ comment, rating, id }, { dispatch, extra: api }) => {
const { data } = await api.post<UserReview[]>(`${APIRoute.Comments}/${id}`, {
comment,
rating,
});
dispatch(loadComments(data));
});
31 changes: 14 additions & 17 deletions src/components/MainPage/MainPage.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import {FC} from 'react';
import { useState, useEffect } from 'react';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Spinner from '../spinner/spinner.tsx';
//import Spinner from '../spinner/spinner.tsx';
import OfferList from '../Offer/OfferList';
import { useAppDispatch,useAppSelector } from '../../hooks';
import { AppRoute, City, CardCssNameList, SortName} from '../../types/types';
import { useAppDispatch } from '../../hooks';
import { AppRoute, City, CardCssNameList, SortName, OfferObject} from '../../types/types';
import { changeCity } from '../../action';
import { ListCities } from '../../components/CityList/CityList';
import { FilterOffer } from '../FilterOffers/FilterOffer';
import { getLoadingOfferPage,getOffer } from '../../store/selector';
import { fetchOfferObjectAction } from '../../api-actions.ts';
import Map from '../Map/Map';
type MainPageProps = {
currentCity: City;
cities: City[];
offers: OfferObject[];
};
export const MainPage : FC<MainPageProps> = ({
currentCity,
cities,
offers,
}:MainPageProps) => {
const navigate = useNavigate();
const dispatch = useAppDispatch();
const isLoading = useAppSelector(getLoadingOfferPage);
const offers = useAppSelector(getOffer);
useEffect(() => {
dispatch(fetchOfferObjectAction());
}, [dispatch]);
// const isLoading = useAppSelector(getLoadingOfferPage);
// const offers = useAppSelector(getOffer);
//useEffect(() => {
//dispatch(fetchOfferObjectAction());
//}, [dispatch]);
const handleUserSelectCity = (cityName: string) => {
dispatch(changeCity(cityName));
// dispatch(fillOffers());
};
const [activeOffer, setActiveOffer] = useState<number | null>(null);
const [activeOffer, setActiveOffer] = useState<string | null>(null);

const [sortType, setSortType] = useState<SortName>(SortName.popular);
const sortedOffers = offers?.filter((a) =>a.city.name === currentCity.title).slice().sort((a, b) => {
Expand Down Expand Up @@ -94,11 +94,8 @@ export const MainPage : FC<MainPageProps> = ({
<b className="places__found">
{sortedOffers?.length} places to stay in {currentCity.title}
</b>
{ isLoading ?
<Spinner />
:
<><FilterOffer currentSort={sortType} onSortChange={setSortType} /><div className="cities__places-list places__list tabs__content"><OfferList offers={sortedOffers?.filter((a) => a.city.name === currentCity.title)} cardcssname={CardCssNameList.citiesList} setActiveOffer={setActiveOffer} /></div>
</>}

<FilterOffer currentSort={sortType} onSortChange={setSortType} /><div className="cities__places-list places__list tabs__content"><OfferList offers={sortedOffers?.filter((a) => a.city.name === currentCity.title)} cardcssname={CardCssNameList.citiesList} setActiveOffer={setActiveOffer} /></div>
</section>
<div className="cities__right-section">
<section className="cities__map map">
Expand Down
2 changes: 1 addition & 1 deletion src/components/Map/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type MainPageProps = {
offers: OfferObject[] | undefined;
currentCity: City;
selectedPoint: OfferObject | undefined;
activeOffer: number | null;
activeOffer: string | null;
};

function Map(props: MainPageProps): JSX.Element {
Expand Down
81 changes: 81 additions & 0 deletions src/components/NotFoundPage/NotFoundPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {Link} from 'react-router-dom';

function NotFoundPage():JSX.Element{
return(
<div className="page page--gray page--main">
<header className="header">
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<a className="header__logo-link header__logo-link--active">
<img className="header__logo" src="img/logo.svg" alt="6 cities logo" width="81" height="41"/>
</a>
</div>
<nav className="header__nav">
<ul className="header__nav-list">
<li className="header__nav-item user">
<a className="header__nav-link header__nav-link--profile" href="#">
<div className="header__avatar-wrapper user__avatar-wrapper">
</div>
<span className="header__user-name user__name">[email protected]</span>
<span className="header__favorite-count">3</span>
</a>
</li>
<li className="header__nav-item">
<a className="header__nav-link" href="#">
<span className="header__signout">Sign out</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</header>

<main className="page__main page__main--index">
<h1 className="visually-hidden">Cities</h1>
<div className="tabs">
<section className="locations container">
<ul className="locations__list tabs__list">
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<span>Paris</span>
</a>
</li>
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<span>Cologne</span>
</a>
</li>
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<span>Brussels</span>
</a>
</li>
<li className="locations__item">
<a className="locations__item-link tabs__item tabs__item--active">
<span>Amsterdam</span>
</a>
</li>
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<span>Hamburg</span>
</a>
</li>
<li className="locations__item">
<a className="locations__item-link tabs__item" href="#">
<span>Dusseldorf</span>
</a>
</li>
</ul>
</section>
<h2 style={{ textAlign : 'center'}}>Error 404. Page not found. <Link to = "/"> Back to main page</Link></h2>
<div className="cities__right-section">
<section className="cities__map map"></section>
</div>
</div>
</main>
</div>
);
}
export default NotFoundPage;
Loading

0 comments on commit e742bde

Please sign in to comment.