лаба 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": [
|
||||
{
|
||||
"id": 1,
|
||||
|
10
laba5/package-lock.json
generated
10
laba5/package-lock.json
generated
@ -8,7 +8,7 @@
|
||||
"name": "lec4",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.1",
|
||||
"axios": "^1.6.5",
|
||||
"bootstrap": "^5.3.2",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
@ -1356,11 +1356,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
|
||||
"integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
|
||||
"version": "1.6.5",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
|
||||
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"follow-redirects": "^1.15.4",
|
||||
"form-data": "^4.0.0",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
"prod": "npm-run-all lint 'vite build' --parallel rest 'vite preview'"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.6.1",
|
||||
"axios": "^1.6.5",
|
||||
"bootstrap": "^5.3.2",
|
||||
"prop-types": "^15.8.1",
|
||||
"react": "^18.2.0",
|
||||
|
@ -4,9 +4,17 @@ import { Toaster } from 'react-hot-toast';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
import { CartProvider } from './components/cart/CartContext.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 {
|
||||
user, setUser, logged, setLogged, curUser, setCurUser,
|
||||
} = appHook();
|
||||
return (
|
||||
<UserContext.Provider value={{
|
||||
user, setUser, logged, setLogged, curUser, setCurUser,
|
||||
}}>
|
||||
<CartProvider>
|
||||
<Navigation routes={routes}></Navigation>
|
||||
<Container className='p-0' as='main' fluid>
|
||||
@ -14,6 +22,7 @@ const App = ({ routes }) => {
|
||||
</Container>
|
||||
<Toaster position='top-center' reverseOrder={true} />
|
||||
</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 { Journal, Cart2 } from 'react-bootstrap-icons';
|
||||
import { Link, useLocation } from 'react-router-dom';
|
||||
import { useContext } from 'react';
|
||||
import UserContext from '../users/UserContext.jsx';
|
||||
import useCart from '../cart/CartHook';
|
||||
import CurrentUserApiService from '../users/CurrenUserApiService';
|
||||
import './Navigation.css';
|
||||
|
||||
const Navigation = ({ routes }) => {
|
||||
const Navigation = () => {
|
||||
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'));
|
||||
|
||||
const {
|
||||
logged, setLogged,
|
||||
} = 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 (
|
||||
<header>
|
||||
<Navbar expand='md' className='my-navbar'>
|
||||
<Container fluid>
|
||||
<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>
|
||||
<Journal className='d-inline-block align-top me-1 logo' />
|
||||
</Navbar.Brand>
|
||||
<Navbar.Brand as={Link} to={'/page1'?.path ?? '/'}>
|
||||
ANNA
|
||||
</Navbar.Brand>
|
||||
<Navbar.Toggle aria-controls='main-navbar' />
|
||||
<Navbar.Collapse id='main-navbar' className='justify-content-end'>
|
||||
{first}
|
||||
{second}
|
||||
{third}
|
||||
</Navbar.Collapse>
|
||||
</Container>
|
||||
</Navbar >
|
||||
</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 = {
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable linebreak-style */
|
||||
import { useEffect, useState } from 'react';
|
||||
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';
|
||||
|
||||
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 React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
@ -11,6 +12,7 @@ import Page2 from './pages/Page2.jsx';
|
||||
import Page3 from './pages/Page3.jsx';
|
||||
import Page4 from './pages/Page4.jsx';
|
||||
import PageEdit from './pages/PageEdit.jsx';
|
||||
import Registration from './pages/Registration.jsx';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@ -27,6 +29,11 @@ const routes = [
|
||||
element: <Page3 />,
|
||||
title: 'Аккаунт',
|
||||
},
|
||||
{
|
||||
path: '/reg',
|
||||
element: <Registration />,
|
||||
title: 'регистрация',
|
||||
},
|
||||
{
|
||||
path: '/page4',
|
||||
element: <Page4 />,
|
||||
|
@ -1,15 +1,42 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import {
|
||||
Container, Col, Row, Form, Button,
|
||||
} from 'react-bootstrap';
|
||||
/* eslint-disable linebreak-style */
|
||||
// import { Link } from 'react-router-dom';
|
||||
// import {
|
||||
// Container, Col, Row, Form, Button,
|
||||
// } from 'react-bootstrap';
|
||||
// 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';
|
||||
|
||||
const Page3 = () => {
|
||||
const {
|
||||
user, handleChange, validated, onSubmit,
|
||||
} = SignInn();
|
||||
return (
|
||||
// <Register />
|
||||
<>
|
||||
<div className="accountPage">
|
||||
<div className="accountPage text-center">
|
||||
<Container>
|
||||
<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>
|
||||
<Row>
|
||||
<Col className="mx-auto">
|
||||
@ -51,9 +78,6 @@ const Page3 = () => {
|
||||
</Col>
|
||||
</Row>
|
||||
</Container>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
</div> */
|
||||
|
||||
export default Page3;
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable linebreak-style */
|
||||
import Lines from '../components/lines/table/Lines.jsx';
|
||||
|
||||
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