лаба 5, сделала авторизацию и регистрацию
This commit is contained in:
parent
8bf96a862c
commit
7395b0e77b
@ -1,4 +1,57 @@
|
|||||||
{
|
{
|
||||||
|
"currentUser": {
|
||||||
|
"8": ""
|
||||||
|
},
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"email": "anna",
|
||||||
|
"name": "anna",
|
||||||
|
"password": "anna",
|
||||||
|
"id": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a1",
|
||||||
|
"name": "a1",
|
||||||
|
"password": "a1",
|
||||||
|
"id": 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "qwe",
|
||||||
|
"name": "qwe",
|
||||||
|
"password": "qwe",
|
||||||
|
"id": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a8",
|
||||||
|
"name": "a8",
|
||||||
|
"password": "a8",
|
||||||
|
"id": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a8",
|
||||||
|
"name": "a8",
|
||||||
|
"password": "a8",
|
||||||
|
"id": 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a8",
|
||||||
|
"name": "a8",
|
||||||
|
"password": "a8",
|
||||||
|
"id": 6
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a6",
|
||||||
|
"name": "a6",
|
||||||
|
"password": "a6",
|
||||||
|
"id": 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "a7",
|
||||||
|
"name": "a1",
|
||||||
|
"password": "a8",
|
||||||
|
"id": 8
|
||||||
|
}
|
||||||
|
],
|
||||||
"types": [
|
"types": [
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
|
10
laba5/package-lock.json
generated
10
laba5/package-lock.json
generated
@ -8,7 +8,7 @@
|
|||||||
"name": "lec4",
|
"name": "lec4",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.1",
|
"axios": "^1.6.5",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@ -1356,11 +1356,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||||
"integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
|
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.4",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"proxy-from-env": "^1.1.0"
|
"proxy-from-env": "^1.1.0"
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.1",
|
"axios": "^1.6.5",
|
||||||
"bootstrap": "^5.3.2",
|
"bootstrap": "^5.3.2",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
@ -4,9 +4,17 @@ import { Toaster } from 'react-hot-toast';
|
|||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { CartProvider } from './components/cart/CartContext.jsx';
|
import { CartProvider } from './components/cart/CartContext.jsx';
|
||||||
import Navigation from './components/navigation/Navigation.jsx';
|
import Navigation from './components/navigation/Navigation.jsx';
|
||||||
|
import UserContext from './components/users/UserContext.jsx';
|
||||||
|
import appHook from './components/users/AppHook';
|
||||||
|
|
||||||
const App = ({ routes }) => {
|
const App = ({ routes }) => {
|
||||||
|
const {
|
||||||
|
user, setUser, logged, setLogged, curUser, setCurUser,
|
||||||
|
} = appHook();
|
||||||
return (
|
return (
|
||||||
|
<UserContext.Provider value={{
|
||||||
|
user, setUser, logged, setLogged, curUser, setCurUser,
|
||||||
|
}}>
|
||||||
<CartProvider>
|
<CartProvider>
|
||||||
<Navigation routes={routes}></Navigation>
|
<Navigation routes={routes}></Navigation>
|
||||||
<Container className='p-0' as='main' fluid>
|
<Container className='p-0' as='main' fluid>
|
||||||
@ -14,6 +22,7 @@ const App = ({ routes }) => {
|
|||||||
</Container>
|
</Container>
|
||||||
<Toaster position='top-center' reverseOrder={true} />
|
<Toaster position='top-center' reverseOrder={true} />
|
||||||
</CartProvider>
|
</CartProvider>
|
||||||
|
</UserContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,171 +0,0 @@
|
|||||||
/* eslint-disable linebreak-style */
|
|
||||||
import { useRef, useState, useEffect } from 'react';
|
|
||||||
import axios from './api/axios';
|
|
||||||
|
|
||||||
const USER_REGEX = /^[A-z][A-z0-9-_]{3,23}$/;
|
|
||||||
const PWD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%]).{8,24}$/;
|
|
||||||
const REGISTER_URL = '/register';
|
|
||||||
|
|
||||||
const Register = () => {
|
|
||||||
const userRef = useRef();
|
|
||||||
const errRef = useRef();
|
|
||||||
|
|
||||||
const [user, setUser] = useState('');
|
|
||||||
const [validName, setValidName] = useState(false);
|
|
||||||
const [userFocus, setUserFocus] = useState(false);
|
|
||||||
|
|
||||||
const [pwd, setPwd] = useState('');
|
|
||||||
const [validPwd, setValidPwd] = useState(false);
|
|
||||||
const [pwdFocus, setPwdFocus] = useState(false);
|
|
||||||
|
|
||||||
const [matchPwd, setMatchPwd] = useState('');
|
|
||||||
const [validMatch, setValidMatch] = useState(false);
|
|
||||||
const [matchFocus, setMatchFocus] = useState(false);
|
|
||||||
|
|
||||||
const [errMsg, setErrMsg] = useState('');
|
|
||||||
const [success, setSuccess] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
userRef.current.focus();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setValidName(USER_REGEX.test(user));
|
|
||||||
}, [user]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setValidPwd(PWD_REGEX.test(pwd));
|
|
||||||
setValidMatch(pwd === matchPwd);
|
|
||||||
}, [pwd, matchPwd]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setErrMsg('');
|
|
||||||
}, [user, pwd, matchPwd]);
|
|
||||||
|
|
||||||
const handleSubmit = async (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
// if button enabled with JS hack
|
|
||||||
const v1 = USER_REGEX.test(user);
|
|
||||||
const v2 = PWD_REGEX.test(pwd);
|
|
||||||
if (!v1 || !v2) {
|
|
||||||
setErrMsg('Invalid Entry');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const response = await axios.post(
|
|
||||||
REGISTER_URL,
|
|
||||||
JSON.stringify({ user, pwd }),
|
|
||||||
{
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
withCredentials: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
console.log(response?.data);
|
|
||||||
console.log(response?.accessToken);
|
|
||||||
console.log(JSON.stringify(response));
|
|
||||||
setSuccess(true);
|
|
||||||
setUser('');
|
|
||||||
setPwd('');
|
|
||||||
setMatchPwd('');
|
|
||||||
} catch (err) {
|
|
||||||
if (!err?.response) {
|
|
||||||
setErrMsg('No Server Response');
|
|
||||||
} else if (err.response?.status === 409) {
|
|
||||||
setErrMsg('Username Taken');
|
|
||||||
} else {
|
|
||||||
setErrMsg('Registration Failed');
|
|
||||||
}
|
|
||||||
errRef.current.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{success ? (
|
|
||||||
<section>
|
|
||||||
<h1>Success!</h1>
|
|
||||||
<p>
|
|
||||||
<a href="#">Sign In</a>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
) : (
|
|
||||||
<section>
|
|
||||||
<p ref={errRef} className={errMsg ? 'errmsg' : 'offscreen'} aria-live="assertive">{errMsg}</p>
|
|
||||||
<h1>Register</h1>
|
|
||||||
<form onSubmit={handleSubmit}>
|
|
||||||
<label htmlFor="username">
|
|
||||||
Username:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
id="username"
|
|
||||||
ref={userRef}
|
|
||||||
autoComplete="off"
|
|
||||||
onChange={(e) => setUser(e.target.value)}
|
|
||||||
value={user}
|
|
||||||
required
|
|
||||||
aria-invalid={validName ? 'false' : 'true'}
|
|
||||||
aria-describedby="uidnote"
|
|
||||||
onFocus={() => setUserFocus(true)}
|
|
||||||
onBlur={() => setUserFocus(false)}
|
|
||||||
/>
|
|
||||||
<p id="uidnote" className={userFocus && user && !validName ? 'instructions' : 'offscreen'}>
|
|
||||||
4 to 24 characters.<br />
|
|
||||||
Must begin with a letter.<br />
|
|
||||||
Letters, numbers, underscores, hyphens allowed.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<label htmlFor="password">
|
|
||||||
Password:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
id="password"
|
|
||||||
onChange={(e) => setPwd(e.target.value)}
|
|
||||||
value={pwd}
|
|
||||||
required
|
|
||||||
aria-invalid={validPwd ? 'false' : 'true'}
|
|
||||||
aria-describedby="pwdnote"
|
|
||||||
onFocus={() => setPwdFocus(true)}
|
|
||||||
onBlur={() => setPwdFocus(false)}
|
|
||||||
/>
|
|
||||||
<p id="pwdnote" className={pwdFocus && !validPwd ? 'instructions' : 'offscreen'}>
|
|
||||||
Allowed special characters: <span aria-label="exclamation mark">!</span>
|
|
||||||
<span aria-label="at symbol">@</span> <span aria-label="hashtag">#
|
|
||||||
</span> <span aria-label="dollar sign">$</span> <span aria-label="percent">%</span>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<label htmlFor="confirm_pwd">
|
|
||||||
Confirm Password:
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
id="confirm_pwd"
|
|
||||||
onChange={(e) => setMatchPwd(e.target.value)}
|
|
||||||
value={matchPwd}
|
|
||||||
required
|
|
||||||
aria-invalid={validMatch ? 'false' : 'true'}
|
|
||||||
aria-describedby="confirmnote"
|
|
||||||
onFocus={() => setMatchFocus(true)}
|
|
||||||
onBlur={() => setMatchFocus(false)}
|
|
||||||
/>
|
|
||||||
<p id="confirmnote" className={matchFocus && !validMatch ? 'instructions' : 'offscreen'}>
|
|
||||||
Must match the first password input field.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<button disabled={!!(!validName || !validPwd
|
|
||||||
|| !validMatch)}>Sign Up</button>
|
|
||||||
</form>
|
|
||||||
<p>
|
|
||||||
Already registered?<br />
|
|
||||||
<span className="line">
|
|
||||||
<a href="#">Sign In</a>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Register;
|
|
@ -1,5 +0,0 @@
|
|||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
export default axios.create({
|
|
||||||
baseURL: 'http://localhost:3500',
|
|
||||||
});
|
|
@ -2,45 +2,104 @@ import PropTypes from 'prop-types';
|
|||||||
import { Container, Nav, Navbar } from 'react-bootstrap';
|
import { Container, Nav, Navbar } from 'react-bootstrap';
|
||||||
import { Journal, Cart2 } from 'react-bootstrap-icons';
|
import { Journal, Cart2 } from 'react-bootstrap-icons';
|
||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
import UserContext from '../users/UserContext.jsx';
|
||||||
import useCart from '../cart/CartHook';
|
import useCart from '../cart/CartHook';
|
||||||
|
import CurrentUserApiService from '../users/CurrenUserApiService';
|
||||||
import './Navigation.css';
|
import './Navigation.css';
|
||||||
|
|
||||||
const Navigation = ({ routes }) => {
|
const Navigation = () => {
|
||||||
const { getCartSum } = useCart();
|
const { getCartSum } = useCart();
|
||||||
const location = useLocation();
|
const {
|
||||||
const indexPageLink = routes.filter((route) => route.index === false).shift();
|
logged, setLogged,
|
||||||
const pages = routes.filter((route) => Object.prototype.hasOwnProperty.call(route, 'title'));
|
} = useContext(UserContext);
|
||||||
|
let first;
|
||||||
|
let second;
|
||||||
|
let third;
|
||||||
|
const onClick = async () => {
|
||||||
|
localStorage.removeItem('User');
|
||||||
|
localStorage.removeItem('currentUser');
|
||||||
|
await CurrentUserApiService.deleteAll();
|
||||||
|
setLogged(false);
|
||||||
|
};
|
||||||
|
if (!logged) {
|
||||||
|
first = <div className="p-2">
|
||||||
|
<Nav.Link href="/reg" id='textNav'>Регистрация</Nav.Link>
|
||||||
|
</div>;
|
||||||
|
second = <div className="p-2">
|
||||||
|
<Nav.Link href="/page3" id='textNav'>Аккаунт</Nav.Link>
|
||||||
|
</div>;
|
||||||
|
third = <div></div>;
|
||||||
|
} else {
|
||||||
|
first = <div className="p-2">
|
||||||
|
<Nav.Link href="/" id='textNav' onClick={onClick} >Выйти</Nav.Link>
|
||||||
|
</div>;
|
||||||
|
second = <div className="p-2">
|
||||||
|
</div>;
|
||||||
|
third = <div>
|
||||||
|
<Navbar.Brand as={Link} to='/cart'>
|
||||||
|
<Cart2 className='d-inline-block align-top me-1 logo' /> {getCartSum() ?? ''} ₽
|
||||||
|
</Navbar.Brand>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<header>
|
<header>
|
||||||
<Navbar expand='md' className='my-navbar'>
|
<Navbar expand='md' className='my-navbar'>
|
||||||
<Container fluid>
|
<Container fluid>
|
||||||
<Navbar.Brand as={Link} to='/page2'>
|
<Navbar.Brand as={Link} to='/page2'>
|
||||||
<Journal className='d-inline-block align-top me-1 logo' />
|
<Journal className='d-inline-block align-top me-1 logo' />
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
<Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
|
<Navbar.Brand as={Link} to={'/page1'?.path ?? '/'}>
|
||||||
ANNA
|
ANNA
|
||||||
</Navbar.Brand>
|
</Navbar.Brand>
|
||||||
<Navbar.Toggle aria-controls='main-navbar' />
|
<Navbar.Toggle aria-controls='main-navbar' />
|
||||||
<Navbar.Collapse id='main-navbar' className='justify-content-end'>
|
<Navbar.Collapse id='main-navbar' className='justify-content-end'>
|
||||||
<Nav className='me-auto link' activeKey={location.pathname}>
|
{first}
|
||||||
{
|
{second}
|
||||||
pages.map((page) =>
|
{third}
|
||||||
<Nav.Link as={Link} key={page.path} eventKey={page.path} to={page.path ?? '/'}>
|
|
||||||
{page.title}
|
|
||||||
</Nav.Link>)
|
|
||||||
}
|
|
||||||
</Nav>
|
|
||||||
<Nav>
|
|
||||||
<Navbar.Brand as={Link} to='/cart'>
|
|
||||||
<Cart2 className='d-inline-block align-top me-1 logo' /> {getCartSum() ?? ''} ₽
|
|
||||||
</Navbar.Brand>
|
|
||||||
</Nav>
|
|
||||||
</Navbar.Collapse>
|
</Navbar.Collapse>
|
||||||
</Container>
|
</Container>
|
||||||
</Navbar >
|
</Navbar >
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// const { getCartSum } = useCart();
|
||||||
|
// const location = useLocation();
|
||||||
|
// const indexPageLink = routes.filter((route) => route.index === false).shift();
|
||||||
|
// const pages = routes.filter((route) => Object.prototype.hasOwnProperty.call(route, 'title'));
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <header>
|
||||||
|
// <Navbar expand='md' className='my-navbar'>
|
||||||
|
// <Container fluid>
|
||||||
|
// <Navbar.Brand as={Link} to='/page2'>
|
||||||
|
// <Journal className='d-inline-block align-top me-1 logo' />
|
||||||
|
// </Navbar.Brand>
|
||||||
|
// <Navbar.Brand as={Link} to={indexPageLink?.path ?? '/'}>
|
||||||
|
// ANNA
|
||||||
|
// </Navbar.Brand>
|
||||||
|
// <Navbar.Toggle aria-controls='main-navbar' />
|
||||||
|
// <Navbar.Collapse id='main-navbar' className='justify-content-end'>
|
||||||
|
// <Nav className='me-auto link' activeKey={location.pathname}>
|
||||||
|
// {
|
||||||
|
// pages.map((page) =>
|
||||||
|
// <Nav.Link as={Link} key={page.path}
|
||||||
|
// eventKey={page.path} to={page.path ?? '/'}>
|
||||||
|
// {page.title}
|
||||||
|
// </Nav.Link>)
|
||||||
|
// }
|
||||||
|
// </Nav>
|
||||||
|
// <Nav>
|
||||||
|
// <Navbar.Brand as={Link} to='/cart'>
|
||||||
|
// <Cart2 className='d-inline-block align-top
|
||||||
|
// me-1 logo' /> {getCartSum() ?? ''} ₽
|
||||||
|
// </Navbar.Brand>
|
||||||
|
// </Nav>
|
||||||
|
// </Navbar.Collapse>
|
||||||
|
// </Container>
|
||||||
|
// </Navbar >
|
||||||
|
// </header>
|
||||||
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
Navigation.propTypes = {
|
Navigation.propTypes = {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import TypesApiService from '../service/TypesApiService';
|
import TypesApiService from '../service/TypesApiService';
|
||||||
|
|
||||||
|
76
laba5/src/components/types/hooks/UsersHook.js
Normal file
76
laba5/src/components/types/hooks/UsersHook.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import UsersApiService from '../service/UsersApiService';
|
||||||
|
|
||||||
|
export const useUsers = () => {
|
||||||
|
const [users, setUsers] = useState([]);
|
||||||
|
|
||||||
|
const getUsers = async () => {
|
||||||
|
const data = await UsersApiService.getAll();
|
||||||
|
setUsers(data ?? []);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUsers();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return {
|
||||||
|
users,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUserL = (loginEnter) => {
|
||||||
|
let login = loginEnter;
|
||||||
|
const [users, setUser] = useState(null);
|
||||||
|
|
||||||
|
const getUser = async () => {
|
||||||
|
const data = await UsersApiService.getAll(`?login=${login}`);
|
||||||
|
if (data && data.length > 0) {
|
||||||
|
setUser(data[0]);
|
||||||
|
} else {
|
||||||
|
setUser(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUser(login);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handlerLoginChanged = (newLogin) => {
|
||||||
|
login = newLogin;
|
||||||
|
getUser();
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
users,
|
||||||
|
handlerLoginChanged,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useUser = (id) => {
|
||||||
|
const emptyUser = {
|
||||||
|
id: '',
|
||||||
|
login: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
const [user, setUser] = useState({ ...emptyUser });
|
||||||
|
|
||||||
|
const getUser = async (userId = undefined) => {
|
||||||
|
if (userId && userId > 0) {
|
||||||
|
const data = await UsersApiService.get(userId);
|
||||||
|
setUser(data);
|
||||||
|
} else {
|
||||||
|
setUser({ ...emptyUser });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUser(id);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
setUser,
|
||||||
|
};
|
||||||
|
};
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
import ApiService from '../../api/ApiService';
|
import ApiService from '../../api/ApiService';
|
||||||
|
|
||||||
const TypesApiService = new ApiService('types');
|
const TypesApiService = new ApiService('types');
|
||||||
|
6
laba5/src/components/types/service/UsersApiService.js
Normal file
6
laba5/src/components/types/service/UsersApiService.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
|
import ApiService from '../../api/ApiService';
|
||||||
|
|
||||||
|
const UsersApiService = new ApiService('users');
|
||||||
|
|
||||||
|
export default UsersApiService;
|
24
laba5/src/components/users/AppHook.js
Normal file
24
laba5/src/components/users/AppHook.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import useUsers from './UsersHook';
|
||||||
|
|
||||||
|
const appHook = (id) => {
|
||||||
|
const { user, setUser } = useUsers(-1);
|
||||||
|
const [logged, setLogged] = useState(false);
|
||||||
|
const [curUser, setCurUser] = useState(null);
|
||||||
|
const load = async () => {
|
||||||
|
const data = localStorage.getItem('User');
|
||||||
|
if (localStorage.getItem('User') !== null) {
|
||||||
|
setCurUser(data);
|
||||||
|
setLogged(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
load();
|
||||||
|
}, []);
|
||||||
|
return {
|
||||||
|
user, setUser, logged, setLogged, curUser, setCurUser
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default appHook;
|
5
laba5/src/components/users/CurrenUserApiService.js
Normal file
5
laba5/src/components/users/CurrenUserApiService.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import ApiService from '../api/ApiService';
|
||||||
|
|
||||||
|
const CurrentUserApiService = new ApiService('currentUser');
|
||||||
|
|
||||||
|
export default CurrentUserApiService;
|
67
laba5/src/components/users/SignInHook.js
Normal file
67
laba5/src/components/users/SignInHook.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { useState, useContext } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import UsersApiService from './UsersApiService';
|
||||||
|
import UserContext from './UserContext.jsx';
|
||||||
|
import CurrentUserApiService from './CurrenUserApiService';
|
||||||
|
|
||||||
|
const SignInn = () => {
|
||||||
|
const [validated, setValidated] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const {
|
||||||
|
user, setUser, setLogged, setCurUser,
|
||||||
|
} = useContext(UserContext);
|
||||||
|
const onMain = () => {
|
||||||
|
navigate('/page2');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
const inputName = event.target.name;
|
||||||
|
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
||||||
|
setUser({
|
||||||
|
...user,
|
||||||
|
[inputName]: inputValue,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getUserObject = (formData) => {
|
||||||
|
const email = String(formData.email, 30);
|
||||||
|
const password = String(formData.password, 30);
|
||||||
|
return {
|
||||||
|
email: email.toString(),
|
||||||
|
password: password.toString(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
const body = getUserObject(user);
|
||||||
|
const data = await UsersApiService.getAll(`?email=${body.email}`);
|
||||||
|
if (data) {
|
||||||
|
if (body.password === '' || body.email === '') {
|
||||||
|
toast.success('Не введены данные');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (data[0].password === body.password) {
|
||||||
|
toast.success('Успешный вход', { id: 'User' });
|
||||||
|
localStorage.setItem('User', JSON.stringify(data[0]));
|
||||||
|
localStorage.setItem('currentUser', data[0].id);
|
||||||
|
await CurrentUserApiService.create(data[0].id);
|
||||||
|
setCurUser(data[0]);
|
||||||
|
setLogged(true);
|
||||||
|
setValidated(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
const onSubmit = async (event) => {
|
||||||
|
if (await handleSubmit(event)) {
|
||||||
|
onMain();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
user, handleChange, handleSubmit, onSubmit, validated,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SignInn;
|
5
laba5/src/components/users/UserContext.jsx
Normal file
5
laba5/src/components/users/UserContext.jsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { createContext } from 'react';
|
||||||
|
|
||||||
|
const UserContext = createContext(undefined);
|
||||||
|
|
||||||
|
export default UserContext;
|
5
laba5/src/components/users/UsersApiService.js
Normal file
5
laba5/src/components/users/UsersApiService.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import ApiService from '../api/ApiService';
|
||||||
|
|
||||||
|
const UsersApiService = new ApiService('users');
|
||||||
|
|
||||||
|
export default UsersApiService;
|
33
laba5/src/components/users/UsersHook.js
Normal file
33
laba5/src/components/users/UsersHook.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import UsersApiService from './UsersApiService';
|
||||||
|
|
||||||
|
const useUsers = (id) => {
|
||||||
|
const emptyUser = {
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
email: '',
|
||||||
|
password: '',
|
||||||
|
};
|
||||||
|
const [user, setUser] = useState({ ...emptyUser });
|
||||||
|
|
||||||
|
const getUser = async (userId = undefined) => {
|
||||||
|
if (userId && userId > 0) {
|
||||||
|
const data = await UsersApiService.get(userId);
|
||||||
|
setUser(data);
|
||||||
|
} else {
|
||||||
|
setUser({ ...emptyUser });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUser(id);
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
user,
|
||||||
|
setUser,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useUsers;
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
import 'bootstrap/dist/css/bootstrap.min.css';
|
import 'bootstrap/dist/css/bootstrap.min.css';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
@ -11,6 +12,7 @@ import Page2 from './pages/Page2.jsx';
|
|||||||
import Page3 from './pages/Page3.jsx';
|
import Page3 from './pages/Page3.jsx';
|
||||||
import Page4 from './pages/Page4.jsx';
|
import Page4 from './pages/Page4.jsx';
|
||||||
import PageEdit from './pages/PageEdit.jsx';
|
import PageEdit from './pages/PageEdit.jsx';
|
||||||
|
import Registration from './pages/Registration.jsx';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
@ -27,6 +29,11 @@ const routes = [
|
|||||||
element: <Page3 />,
|
element: <Page3 />,
|
||||||
title: 'Аккаунт',
|
title: 'Аккаунт',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/reg',
|
||||||
|
element: <Registration />,
|
||||||
|
title: 'регистрация',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/page4',
|
path: '/page4',
|
||||||
element: <Page4 />,
|
element: <Page4 />,
|
||||||
|
@ -1,15 +1,42 @@
|
|||||||
import { Link } from 'react-router-dom';
|
/* eslint-disable linebreak-style */
|
||||||
import {
|
// import { Link } from 'react-router-dom';
|
||||||
Container, Col, Row, Form, Button,
|
// import {
|
||||||
} from 'react-bootstrap';
|
// Container, Col, Row, Form, Button,
|
||||||
|
// } from 'react-bootstrap';
|
||||||
// import Register from '../components/Register';
|
// import Register from '../components/Register';
|
||||||
|
// import { useState } from 'react';
|
||||||
|
// import {
|
||||||
|
// Button, Form, Container,
|
||||||
|
// } from 'react-bootstrap';
|
||||||
|
// import { Link, useNavigate } from 'react-router-dom';
|
||||||
|
// import { useUserL } from '../components/types/hooks/UsersHook';
|
||||||
|
import { Container, Form, Button } from 'react-bootstrap';
|
||||||
|
import SignInn from '../components/users/SignInHook';
|
||||||
|
import Input from '../components/input/Input.jsx';
|
||||||
|
|
||||||
import './Page3.css';
|
import './Page3.css';
|
||||||
|
|
||||||
const Page3 = () => {
|
const Page3 = () => {
|
||||||
|
const {
|
||||||
|
user, handleChange, validated, onSubmit,
|
||||||
|
} = SignInn();
|
||||||
return (
|
return (
|
||||||
// <Register />
|
<div className="accountPage text-center">
|
||||||
<>
|
<Container>
|
||||||
<div className="accountPage">
|
<Form.Text>
|
||||||
|
<h1>АВТОРИЗАЦИЯ</h1>
|
||||||
|
</Form.Text>
|
||||||
|
<Form id="items-form" noValidate validated={validated} onSubmit={onSubmit}>
|
||||||
|
<Input name='email' type='email' placeholder='Введите почту' onChange={handleChange} value={user.email}></Input>
|
||||||
|
<Input name='password' type='password' placeholder='Введите пароль'onChange={handleChange} value={user.password}></Input>
|
||||||
|
<Button className='my-3' type="submit" variant="outline-secondary">Войти</Button>
|
||||||
|
</Form>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* <div className="accountPage">
|
||||||
<Container>
|
<Container>
|
||||||
<Row>
|
<Row>
|
||||||
<Col className="mx-auto">
|
<Col className="mx-auto">
|
||||||
@ -51,9 +78,6 @@ const Page3 = () => {
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Container>
|
</Container>
|
||||||
</div>
|
</div> */
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Page3;
|
export default Page3;
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
import Lines from '../components/lines/table/Lines.jsx';
|
import Lines from '../components/lines/table/Lines.jsx';
|
||||||
|
|
||||||
const Page4 = () => {
|
const Page4 = () => {
|
||||||
|
78
laba5/src/pages/Registration.jsx
Normal file
78
laba5/src/pages/Registration.jsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/* eslint-disable linebreak-style */
|
||||||
|
import { Container, Form, Button } from 'react-bootstrap';
|
||||||
|
import { useContext, useState } from 'react';
|
||||||
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
import toast from 'react-hot-toast';
|
||||||
|
import Input from '../components/input/Input.jsx';
|
||||||
|
import UserContext from '../components/users/UserContext.jsx';
|
||||||
|
import UsersApiService from '../components/users/UsersApiService';
|
||||||
|
|
||||||
|
const Registration = () => {
|
||||||
|
const [validated, setValidated] = useState(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
const { user, setUser } = useContext(UserContext);
|
||||||
|
const toAuto = () => {
|
||||||
|
navigate('/page3');
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
const inputName = event.target.name;
|
||||||
|
const inputValue = event.target.type === 'checkbox' ? event.target.checked : event.target.value;
|
||||||
|
setUser({
|
||||||
|
...user,
|
||||||
|
[inputName]: inputValue,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const getUserObject = (formData) => {
|
||||||
|
const email = String(formData.email, 10);
|
||||||
|
const name = String(formData.name, 30);
|
||||||
|
const password = String(formData.password, 30);
|
||||||
|
return {
|
||||||
|
email: email.toString(),
|
||||||
|
name: name.toString(),
|
||||||
|
password: password.toString(),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const handleSubmit = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
const body = getUserObject(user);
|
||||||
|
if (body.password === '' || body.email === '' || body.name === '') {
|
||||||
|
toast.success('Введены пустые значения');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (user.id === '') {
|
||||||
|
await UsersApiService.create(body);
|
||||||
|
} else {
|
||||||
|
await UsersApiService.update(user.id, body);
|
||||||
|
}
|
||||||
|
if (body) {
|
||||||
|
toast.success('Регистрация прошла успешно!', { id: 'User' });
|
||||||
|
setValidated(true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
const onSubmit = async (event) => {
|
||||||
|
if (await handleSubmit(event)) {
|
||||||
|
toAuto();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className='accountPage text-center'>
|
||||||
|
<Container>
|
||||||
|
<Form.Text>
|
||||||
|
<h1>РЕГИСТРАЦИЯ</h1>
|
||||||
|
</Form.Text>
|
||||||
|
<Form id="items-form" noValidate validated={validated} onSubmit={onSubmit}>
|
||||||
|
<Input name='name' type='text' label='Имя' placeholder='Введите nick' required onChange={handleChange} value={user.name}></Input>
|
||||||
|
<Input name='email' type='email' label='Почта' placeholder='Введите почту' required onChange={handleChange} value={user.email}></Input>
|
||||||
|
<Input name='password' type='password' label='Пароль' placeholder='Введите пароль' required onChange={handleChange} value={user.password}></Input>
|
||||||
|
<Button className='my-2' type="submit" variant="outline-secondary">Зарегистрироваться</Button>
|
||||||
|
</Form>
|
||||||
|
</Container>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Registration;
|
Loading…
Reference in New Issue
Block a user