Skip to content

Commit

Permalink
module7-task2
Browse files Browse the repository at this point in the history
  • Loading branch information
Mayanzev committed May 3, 2024
1 parent cd9a6aa commit 94c41f6
Show file tree
Hide file tree
Showing 19 changed files with 312 additions and 156 deletions.
5 changes: 5 additions & 0 deletions src/browser-history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {createBrowserHistory} from 'history';

const browserHistory = createBrowserHistory();

export default browserHistory;
24 changes: 13 additions & 11 deletions src/components/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import MainScreen from '../../pages/main-screen/main-screen';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Route, Routes } from 'react-router-dom';
import LoginScreen from '../../pages/login-screen/login-screen.tsx';
import FavoritesScreen from '../../pages/favorites-screen/favorites-screen.tsx';
import NotFoundScreen from '../../pages/not-found-screen/not-found-screen.tsx';
Expand All @@ -8,35 +8,37 @@ import PrivateRoute from '../private-route/private-route.tsx';
import { AppRoute, AuthorizationStatus } from '../../const.ts';
import { useAppSelector } from '../../hooks/index.ts';
import LoadingScreen from '../../pages/loading-screen/loading-screen.tsx';
import HistoryRouter from '../history-route/history-route.tsx';
import browserHistory from '../../browser-history.ts';


function App(): JSX.Element {

const isQuestionsDataLoading = useAppSelector((state) => state.isQuestionsDataLoading);
const isOffersDataLoading = useAppSelector((state) => state.isOffersDataLoading);
const authorizationStatus = useAppSelector((state) => state.authorizationStatus);

if (isQuestionsDataLoading) {
if (isOffersDataLoading || authorizationStatus === AuthorizationStatus.Unknown) {
return (
<LoadingScreen />
);
}

return (
<BrowserRouter>
<HistoryRouter history={browserHistory}>
<Routes>
<Route path="*" element={<NotFoundScreen/>} />
<Route path={AppRoute.Main} element={<MainScreen/>} />
<Route path="*" element={<NotFoundScreen />} />
<Route path={AppRoute.Main} element={<MainScreen />} />
<Route
path={AppRoute.Favorites}
element={
<PrivateRoute authorizationStatus={AuthorizationStatus.Auth} >
<PrivateRoute >
<FavoritesScreen />
</PrivateRoute>
}
/>
<Route path={AppRoute.Login} element={<LoginScreen/>} />
<Route path={AppRoute.Offer} element={<OfferScreen/>} />
<Route path={AppRoute.Login} element={<LoginScreen />} />
<Route path={AppRoute.Offer} element={<OfferScreen />} />
</Routes>
</BrowserRouter>
</HistoryRouter>
);
}
export default App;
23 changes: 23 additions & 0 deletions src/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Link } from 'react-router-dom';
import LoginNavigation from '../login-navigation/login-navigation';
import { AppRoute } from '../../const';

function Header(): JSX.Element {
return (
<header className="header">
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<Link to={AppRoute.Main} className="header__logo-link header__logo-link--active">
<img className="header__logo" src="img/logo.svg" alt="6 cities logo" width="81" height="41" />
</Link>
</div>
<LoginNavigation />
</div>
</div>
</header>
);
}

export default Header;

35 changes: 35 additions & 0 deletions src/components/history-route/history-route.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {useState, useLayoutEffect} from 'react';
import {Router} from 'react-router-dom';
import type {BrowserHistory} from 'history';

export interface HistoryRouterProps {
history: BrowserHistory;
basename?: string;
children?: React.ReactNode;
}

function HistoryRouter({
basename,
children,
history,
}: HistoryRouterProps) {
const [state, setState] = useState({
action: history.action,
location: history.location,
});

useLayoutEffect(() => history.listen(setState), [history]);

return (
<Router
basename={basename}
location={state.location}
navigationType={state.action}
navigator={history}
>
{children}
</Router>
);
}

export default HistoryRouter;
49 changes: 49 additions & 0 deletions src/components/login-navigation/login-navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Link } from 'react-router-dom';
import { logoutAction } from '../../store/api-actions';
import { useAppDispatch, useAppSelector } from '../../hooks';
import { AppRoute, AuthorizationStatus } from '../../const';

function HeaderNavigation(): JSX.Element {
const dispatch = useAppDispatch();
const offers = useAppSelector((state) => state.offers);
const favoriteOffers = offers.filter((offer) => offer.isFavorite);
const userData = useAppSelector((state) => state.userData);
const authorizationStatus = useAppSelector((state) => state.authorizationStatus);
return (
<nav className="header__nav">
{authorizationStatus === AuthorizationStatus.Auth ? (
<ul className="header__nav-list">
<li className="header__nav-item user">
<a className="header__nav-link header__nav-link--profile" >
<div className="header__avatar-wrapper user__avatar-wrapper">
</div>
<Link to={AppRoute.Favorites}>
<span className="header__user-name user__name">{userData?.email}</span>

Check failure on line 21 in src/components/login-navigation/login-navigation.tsx

View workflow job for this annotation

GitHub Actions / Check

Expected indentation of 16 spaces but found 14
<span className="header__favorite-count">{favoriteOffers.length}</span>
</Link>
</a>
</li>
<li className="header__nav-item">
<a className="header__nav-link" onClick={() => dispatch(logoutAction())}>

Check failure on line 27 in src/components/login-navigation/login-navigation.tsx

View workflow job for this annotation

GitHub Actions / Check

Promise-returning function provided to attribute where a void return was expected
<span className="header__signout">Sign out</span>
</a>
</li>
</ul>
) : (
<ul className="header__nav-list">
<li className="header__nav-item user">
<a className="header__nav-link header__nav-link--profile" >
<div className="header__avatar-wrapper user__avatar-wrapper">
</div>
<Link to={AppRoute.Login}>
<span className="header__login">Sign in</span>
</Link>
</a>
</li>
</ul>
)}
</nav>
);
}

export default HeaderNavigation;
5 changes: 3 additions & 2 deletions src/components/private-route/private-route.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {Navigate} from 'react-router-dom';
import { AppRoute, AuthorizationStatus } from '../../const';
import { useAppSelector } from '../../hooks';

type PrivateRouteProps = {
authorizationStatus: AuthorizationStatus;
children: JSX.Element;
}

function PrivateRoute(props: PrivateRouteProps): JSX.Element {
const {authorizationStatus, children} = props;
const {children} = props;
const authorizationStatus = useAppSelector((state) => state.authorizationStatus);
return (
authorizationStatus === AuthorizationStatus.Auth ? children : <Navigate to={AppRoute.Login}/>
);
Expand Down
14 changes: 8 additions & 6 deletions src/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ export const URL_MARKER_STANDART =

export enum APIRoute {
Offers = '/offers',
Login = '/login',
Logout = '/logout'
}

export const CITIES: City[] = [
Expand All @@ -29,47 +31,47 @@ export const CITIES: City[] = [
location: {
latitude: 48.864716,
longitude: 2.349014,
zoom: 11,
zoom: 13,
},
},
{
name: 'Brussels',
location: {
latitude: 50.85034,
longitude: 4.35171,
zoom: 11,
zoom: 13,
},
},
{
name: 'Cologne',
location: {
latitude: 50.935173,
longitude: 6.953101,
zoom: 11,
zoom: 13,
},
},
{
name: 'Amsterdam',
location: {
latitude: 52.3740300,
longitude: 4.8896900,
zoom: 11,
zoom: 13,
},
},
{
name: 'Hamburg',
location: {
latitude: 53.551086,
longitude: 9.993682,
zoom: 11,
zoom: 13,
},
},
{
name: 'Dusseldorf',
location: {
latitude: 51.233334,
longitude: 6.783333,
zoom: 11,
zoom: 13,
},
},
];
Expand Down
3 changes: 2 additions & 1 deletion src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import ReactDOM from 'react-dom/client';
import App from './components/app/app';
import { Provider } from 'react-redux';
import { store } from './store';
import { fetchOffersAction } from './store/api-actions';
import { checkAuthAction, fetchOffersAction } from './store/api-actions';
import ErrorMessage from './components/error-message/error-message';

store.dispatch(fetchOffersAction());
store.dispatch(checkAuthAction());

const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
Expand Down
36 changes: 5 additions & 31 deletions src/pages/favorites-screen/favorites-screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,15 @@ import { Link } from 'react-router-dom';
import { typeOfCardList } from '../../utils';
import OfferList from '../../components/offer-list/offer-list';
import { useAppSelector } from '../../hooks';
import Header from '../../components/header/header';
import { AppRoute } from '../../const';


function FavoritesScreen(): JSX.Element {
const favoriteOffers = useAppSelector((state) => state.offers).filter((offer) => offer.isFavorite);
return (
<div className="page">
<header className="header">
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<Link to="/" className="header__logo-link">
<img className="header__logo" src="img/logo.svg" alt="6 cities logo" width="81" height="41"/>
</Link>
</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>

<Header />
<main className="page__main page__main--favorites">
<div className="page__favorites-container container">
<section className="favorites">
Expand All @@ -57,8 +31,8 @@ function FavoritesScreen(): JSX.Element {
</div>
</main>
<footer className="footer container">
<Link to="/" className="header__logo-link">
<img className="footer__logo" src="img/logo.svg" alt="6 cities logo" width="64" height="33"/>
<Link to={AppRoute.Main} className="header__logo-link">
<img className="footer__logo" src="img/logo.svg" alt="6 cities logo" width="64" height="33" />
</Link>
</footer>
</div>
Expand Down
32 changes: 28 additions & 4 deletions src/pages/login-screen/login-screen.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import { FormEvent, useRef } from 'react';
import { AppRoute } from '../../const';
import { loginAction } from '../../store/api-actions';
import { useAppDispatch } from '../../hooks';
import { Link } from 'react-router-dom';

function LoginScreen(): JSX.Element {
const emailRef = useRef<HTMLInputElement | null>(null);
const passwordRef = useRef<HTMLInputElement | null>(null);

const dispatch = useAppDispatch();

const handleSubmit = (evt: FormEvent<HTMLFormElement>) => {
evt.preventDefault();
if (emailRef.current !== null && passwordRef.current !== null) {
dispatch(
loginAction({
email: emailRef.current.value,
password: passwordRef.current.value
})
);
}
};
return (
<div className="page page--gray page--login">
<header className="header">
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<a className="header__logo-link" href="main.html">
<img className="header__logo" src="img/logo.svg" alt="6 cities logo" width="81" height="41"/>
<Link to={AppRoute.Main}>
<img className="header__logo" src="img/logo.svg" alt="6 cities logo" width="81" height="41" />
</Link>
</a>
</div>
</div>
Expand All @@ -17,14 +41,14 @@ function LoginScreen(): JSX.Element {
<div className="page__login-container container">
<section className="login">
<h1 className="login__title">Sign in</h1>
<form className="login__form form" action="#" method="post">
<form className="login__form form" action="#" method="post" onSubmit={handleSubmit}>
<div className="login__input-wrapper form__input-wrapper">
<label className="visually-hidden">E-mail</label>
<input className="login__input form__input" type="email" name="email" placeholder="Email" required/>
<input className="login__input form__input" type="email" name="email" placeholder="Email" required ref={emailRef} />
</div>
<div className="login__input-wrapper form__input-wrapper">
<label className="visually-hidden">Password</label>
<input className="login__input form__input" type="password" name="password" placeholder="Password" required/>
<input className="login__input form__input" type="password" name="password" placeholder="Password" required ref={passwordRef} />
</div>
<button className="login__submit form__submit button" type="submit">Sign in</button>
</form>
Expand Down
Loading

0 comments on commit 94c41f6

Please sign in to comment.