Skip to content

Commit

Permalink
Добро пожаловать, или посторонним вход воспрещён (часть 1) (#10)
Browse files Browse the repository at this point in the history
* переменовывает переменные
* добавляет авторизацию
* фиксит ошибки
  • Loading branch information
denispan authored Apr 5, 2024
1 parent fb42bab commit c42a674
Show file tree
Hide file tree
Showing 26 changed files with 523 additions and 142 deletions.
64 changes: 45 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@
"history": "5.3.0",
"http-status-codes": "2.3.0",
"leaflet": "1.7.1",
"nanoid": "5.0.3",
"react": "18.2.0",
"react-content-loader": "6.0.3",
"react-dom": "18.2.0",
"react-helmet-async": "1.3.0",
"react-redux": "8.1.3",
"react-router-dom": "6.16.0",
"react-toastify": "10.0.5",
"vite-plugin-rewrite-all": "1.0.2"
},
"devDependencies": {
Expand Down
22 changes: 13 additions & 9 deletions src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import Main from './pages/main/main.tsx';
import {BrowserRouter, Navigate, Route, Routes} from 'react-router-dom';
import NotFound from './pages/not-found/not-found.tsx';
import {AppRoute, AuthorizationStatus, CITIES, DEFAULT_CITY_SLUG} from './const.ts';
import {AppRoute, AuthStatus, CITIES, DEFAULT_CITY_SLUG} from './const.ts';
import Favorites from './pages/favorites/favorites.tsx';
import Offer from './pages/offer/offer.tsx';
import PrivateRoute from './components/private-route/private-route.tsx';
import Login from './pages/login/login.tsx';
import PublicRoute from './components/public-route/public-route.tsx';
import {useActionCreators, useAppSelector} from './hooks/store.ts';
import {userActions, userSelectors} from './store/slices/user.ts';
import {useEffect} from 'react';

function App() {
const {checkAuth} = useActionCreators(userActions);
const authStatus = useAppSelector(userSelectors.authStatus);
useEffect(() => {
checkAuth();
}, [authStatus, checkAuth]);

return (
<BrowserRouter>
Expand All @@ -20,34 +28,30 @@ function App() {
{CITIES.map((city) => (
<Route
key={city.slug}
path={AppRoute.Root + city.name}
path={AppRoute.Root + city.slug}
element={<Main citySlug={city.slug} />}
/>
)
)}
<Route
path={AppRoute.Login}
element={
<PublicRoute
authorizationStatus={AuthorizationStatus.Auth}
>
<PublicRoute>
<Login />
</PublicRoute>
}
/>
<Route
path={AppRoute.Favorites}
element={
<PrivateRoute
authorizationStatus={AuthorizationStatus.Auth}
>
<PrivateRoute>
<Favorites />
</PrivateRoute>
}
/>
<Route
path={`${AppRoute.Offer}/:offerId`}
element={<Offer userAuth={AuthorizationStatus.Auth} />}
element={<Offer userAuth={AuthStatus.Auth} />}
/>
<Route
path="/*"
Expand Down
67 changes: 52 additions & 15 deletions src/components/header/header.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,67 @@
import Logo from '../logo/logo.tsx';
import {Link} from 'react-router-dom';
import {AppRoute} from '../../const.ts';
import {AppRoute, AuthStatus} from '../../const.ts';
import {useActionCreators, useAppSelector} from '../../hooks/store.ts';
import {userActions, userSelectors} from '../../store/slices/user.ts';
import {toast} from 'react-toastify';

function Header() {
const authStatus = useAppSelector(userSelectors.authStatus);
const userInfo = useAppSelector(userSelectors.userInfo);
const {logout} = useActionCreators(userActions);

const logoutHandler = async (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
e.preventDefault();
await logout().unwrap().catch((error: Error) => {
toast.warning(error.message);
});
};

const AuthUserComponent = (
<>
<li className="header__nav-item user">
<Link to={AppRoute.Favorites} className="header__nav-link header__nav-link--profile">
<div className="header__avatar-wrapper user__avatar-wrapper">
{userInfo?.avatarUrl && <img src={userInfo.avatarUrl} alt="avatar"/>}
</div>
{userInfo?.name && <span className="header__user-name user__name">{userInfo.name}</span>}
<span className="header__favorite-count">3</span>
</Link>
</li>
<li className="header__nav-item">
<a
className="header__nav-link"
href="#"
onClick={(e) => {
logoutHandler(e);
}}
>
<span className="header__signout">Sign out</span>
</a>
</li>
</>
);

const NotAuthUserComponent = (
<li className="header__nav-item user">
<Link to={AppRoute.Login} className="header__nav-link header__nav-link--profile">
<div className="header__avatar-wrapper user__avatar-wrapper">
</div>
<span className="header__login">Sign in</span>
</Link>
</li>
);

return (
<header className="header">
<div className="container">
<div className="header__wrapper">
<div className="header__left">
<Logo />
<Logo/>
</div>
<nav className="header__nav">
<ul className="header__nav-list">
<li className="header__nav-item user">
<Link to={AppRoute.Favorites} className="header__nav-link header__nav-link--profile">
<div className="header__avatar-wrapper user__avatar-wrapper">
</div>
<span className="header__user-name user__name">Oliver.conner@gmail.com</span>
<span className="header__favorite-count">3</span>
</Link>
</li>
<li className="header__nav-item">
<a className="header__nav-link" href="#">
<span className="header__signout">Sign out</span>
</a>
</li>
{authStatus === AuthStatus.Auth ? AuthUserComponent : NotAuthUserComponent}
</ul>
</nav>
</div>
Expand Down
59 changes: 59 additions & 0 deletions src/components/login-form/login-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, {useState} from 'react';
import {useActionCreators} from '../../hooks/store.ts';
import {userActions} from '../../store/slices/user.ts';
import {toast} from 'react-toastify';

function LoginForm() {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const {login} = useActionCreators(userActions);

const onSubmitHandler = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
toast.promise(login({email, password}).unwrap(), {
pending: 'Loading',
success: 'Success',
error: 'Error',
});
};

return (
<form
onSubmit={(e) => onSubmitHandler(e)}
className="login__form form"
action="#"
method="post"
>
<div className="login__input-wrapper form__input-wrapper">
<label className="visually-hidden">E-mail</label>
<input
onChange={(evt) => setEmail(evt.target.value)}
className="login__input form__input"
type="email"
name="email"
placeholder="Email"
required
/>
</div>
<div className="login__input-wrapper form__input-wrapper">
<label className="visually-hidden">Password</label>
<input
onChange={(evt) => setPassword(evt.target.value)}
className="login__input form__input"
type="password"
name="password"
placeholder="Password"
required
/>
</div>
<button
className="login__submit form__submit button"
type="submit"
>
Sign in
</button>
</form>
);
}

export default LoginForm;
Loading

0 comments on commit c42a674

Please sign in to comment.