|
@@ -25,12 +25,16 @@ import {
|
|
InputAdornment,
|
|
InputAdornment,
|
|
FormControl,
|
|
FormControl,
|
|
TextField,
|
|
TextField,
|
|
- Slide
|
|
|
|
|
|
+ Slide,
|
|
|
|
+ Tooltip,
|
|
|
|
+ ClickAwayListener
|
|
} from "@mui/material";
|
|
} from "@mui/material";
|
|
|
|
|
|
import {
|
|
import {
|
|
Visibility,
|
|
Visibility,
|
|
- VisibilityOff
|
|
|
|
|
|
+ VisibilityOff,
|
|
|
|
+ Refresh,
|
|
|
|
+ Person
|
|
} from '@mui/icons-material';
|
|
} from '@mui/icons-material';
|
|
|
|
|
|
|
|
|
|
@@ -40,7 +44,6 @@ const Transition = forwardRef(function Transition(props, ref) {
|
|
})
|
|
})
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
// поля ввода и кнопки
|
|
// поля ввода и кнопки
|
|
function LoginForm() {
|
|
function LoginForm() {
|
|
const location = useLocation().pathname === '/';
|
|
const location = useLocation().pathname === '/';
|
|
@@ -50,7 +53,8 @@ function LoginForm() {
|
|
const [data, setData] = useState({ login: '', pass: '', confirmPass: '' })
|
|
const [data, setData] = useState({ login: '', pass: '', confirmPass: '' })
|
|
console.log('data: ', data)
|
|
console.log('data: ', data)
|
|
|
|
|
|
- // модальное окно открытие/закрытие
|
|
|
|
|
|
+
|
|
|
|
+ // модальное окно ошибки при реге открытие/закрытие
|
|
const [open, setOpen] = useState(false);
|
|
const [open, setOpen] = useState(false);
|
|
const openModalAlertWindow = () => {
|
|
const openModalAlertWindow = () => {
|
|
setOpen(true);
|
|
setOpen(true);
|
|
@@ -59,19 +63,49 @@ function LoginForm() {
|
|
setOpen(false);
|
|
setOpen(false);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // Блок проверки логина,пароля
|
|
// регулярка для проверки нового пароля
|
|
// регулярка для проверки нового пароля
|
|
- const pattern = /(?=.*[0-9])(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z])/g
|
|
|
|
|
|
+ const patternPassword = /(?=.*[0-9])(?=.*[!@#$%^&*])(?=.*[a-z])(?=.*[A-Z])/g
|
|
|
|
+ // регулярка для проверки логина на латинские символы и цифры
|
|
|
|
+ const patternLogin = /^[a-zA-Z0-9]+$/
|
|
// указываем минимальную длинну для нового пароля
|
|
// указываем минимальную длинну для нового пароля
|
|
const passLength = 8;
|
|
const passLength = 8;
|
|
|
|
|
|
- let isValidate, isCorrect;
|
|
|
|
|
|
+ let isValidate, isCorrect, isLogin
|
|
|
|
|
|
- ((data.pass.length < passLength) || !(pattern.test(data.pass))) && (isValidate = true);
|
|
|
|
|
|
+ ((patternLogin.test(data.login))) || (isLogin = true);
|
|
|
|
+ ((data.pass.length < passLength) || !(patternPassword.test(data.pass))) && (isValidate = true);
|
|
(data.pass != data.confirmPass) && (isCorrect = true);
|
|
(data.pass != data.confirmPass) && (isCorrect = true);
|
|
|
|
|
|
const validation = (data.login == '') || (data.pass == '')
|
|
const validation = (data.login == '') || (data.pass == '')
|
|
|
|
|
|
|
|
|
|
|
|
+ // функция генерации случайного логина
|
|
|
|
+ function generateRandomLogin() {
|
|
|
|
+ const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
|
|
|
|
+ const length = Math.floor(Math.random() * (10 - 5 + 1) + 5) // генерируем длину слова от 5 до 10 символов
|
|
|
|
+ let word = ''
|
|
|
|
+ for (let i = 0; i < length; i++) {
|
|
|
|
+ word += characters[Math.floor(Math.random() * characters.length)] // выбираем случайный символ из списка доступных символов
|
|
|
|
+ }
|
|
|
|
+ return word
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // генерируем новый пароль при клике на иконку
|
|
|
|
+ function generateLogin() {
|
|
|
|
+ const newLogin = generateRandomLogin()
|
|
|
|
+
|
|
|
|
+ setData({ ...data, login: newLogin })
|
|
|
|
+
|
|
|
|
+ // и проворачиваем иконку
|
|
|
|
+ const rotate = document.getElementById('loginUpdate')
|
|
|
|
+ rotate.classList.add('rotate');
|
|
|
|
+ setTimeout(() => {
|
|
|
|
+ rotate.classList.remove('rotate');
|
|
|
|
+ }, 3000)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
// включаем,выклюаем отображение пароля
|
|
// включаем,выклюаем отображение пароля
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
const [showPassword, setShowPassword] = useState(false);
|
|
const handleClickShowPassword = () => setShowPassword((show) => !show);
|
|
const handleClickShowPassword = () => setShowPassword((show) => !show);
|
|
@@ -87,6 +121,26 @@ function LoginForm() {
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
+ // отрабатывание Tooltips при клике на логин
|
|
|
|
+ const [openToolTipsLogin, setOpenToolTipsLogin] = React.useState(false);
|
|
|
|
+ const handleTooltipCloseLogin = () => {
|
|
|
|
+ setOpenToolTipsLogin(false);
|
|
|
|
+ };
|
|
|
|
+ const handleTooltipOpenLogin = () => {
|
|
|
|
+ setOpenToolTipsLogin(true);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ // отрабатывание Tooltips при клике на пароль
|
|
|
|
+ const [openToolTipsPass, setOpenToolTipsPass] = React.useState(false);
|
|
|
|
+ const handleTooltipClose = () => {
|
|
|
|
+ setOpenToolTipsPass(false);
|
|
|
|
+ };
|
|
|
|
+ const handleTooltipOpen = () => {
|
|
|
|
+ setOpenToolTipsPass(true);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+
|
|
// Thunk регистрация
|
|
// Thunk регистрация
|
|
async function fullRegistration() {
|
|
async function fullRegistration() {
|
|
const token = await store.dispatch(actionFullRegistration(data.login, data.confirmPass))
|
|
const token = await store.dispatch(actionFullRegistration(data.login, data.confirmPass))
|
|
@@ -112,42 +166,116 @@ function LoginForm() {
|
|
<Box sx={{ width: '100%' }}>
|
|
<Box sx={{ width: '100%' }}>
|
|
<form>
|
|
<form>
|
|
<Stack spacing={2}>
|
|
<Stack spacing={2}>
|
|
- <TextField
|
|
|
|
- fullWidth
|
|
|
|
- variant='outlined'
|
|
|
|
- id='login'
|
|
|
|
- label='Логин'
|
|
|
|
- size='normal'
|
|
|
|
- value={data.login}
|
|
|
|
- onChange={e => setData({ ...data, login: e.target.value })}
|
|
|
|
- />
|
|
|
|
-
|
|
|
|
- <FormControl variant="outlined">
|
|
|
|
- <InputLabel htmlFor="outlined-adornment-password">Пароль</InputLabel>
|
|
|
|
- <OutlinedInput
|
|
|
|
- error={isValidate}
|
|
|
|
- fullWidth
|
|
|
|
- id="password"
|
|
|
|
- label="Пароль"
|
|
|
|
- size="normal"
|
|
|
|
- type={showPassword ? 'text' : 'password'}
|
|
|
|
- value={data.pass}
|
|
|
|
- onChange={e => setData({ ...data, pass: e.target.value })}
|
|
|
|
|
|
+ <ClickAwayListener onClickAway={handleTooltipCloseLogin}>
|
|
|
|
+ <div>
|
|
|
|
+ <Tooltip
|
|
|
|
+ PopperProps={{
|
|
|
|
+ disablePortal: true,
|
|
|
|
+ }}
|
|
|
|
+ onClose={handleTooltipClose}
|
|
|
|
+ open={openToolTipsLogin}
|
|
|
|
+ disableFocusListener
|
|
|
|
+ disableHoverListener
|
|
|
|
+ disableTouchListener
|
|
|
|
+ title={!location && 'Сгенерируйте или введите пароль (только латинские буквы и цифры)'}
|
|
|
|
+ arrow
|
|
|
|
+ >
|
|
|
|
+ {/* <TextField
|
|
|
|
+ error={!location && isLogin}
|
|
|
|
+ fullWidth
|
|
|
|
+ variant='outlined'
|
|
|
|
+ id='login'
|
|
|
|
+ label='Логин'
|
|
|
|
+ size='normal'
|
|
|
|
+ value={data.login}
|
|
|
|
+ onChange={e => setData({ ...data, login: e.target.value })}
|
|
|
|
+ onClick={handleTooltipOpenLogin}
|
|
|
|
+ /> */}
|
|
|
|
+ <FormControl
|
|
|
|
+ variant="outlined"
|
|
|
|
+ onClick={handleTooltipOpenLogin}
|
|
|
|
+ >
|
|
|
|
+ <InputLabel htmlFor="outlined-adornment-password">Логин</InputLabel>
|
|
|
|
+ <OutlinedInput
|
|
|
|
+ error={!location && isLogin}
|
|
|
|
+ fullWidth
|
|
|
|
+ id="login"
|
|
|
|
+ label="Логин"
|
|
|
|
+ size="normal"
|
|
|
|
+ type='text'
|
|
|
|
+ value={data.login}
|
|
|
|
+ onChange={e => setData({ ...data, login: e.target.value })}
|
|
|
|
+
|
|
|
|
+ endAdornment={
|
|
|
|
+ <InputAdornment position="end">
|
|
|
|
+ {!location && <IconButton
|
|
|
|
+ aria-label="login"
|
|
|
|
+ onClick={generateLogin}
|
|
|
|
+ edge="end"
|
|
|
|
+ >
|
|
|
|
+ <Refresh id='loginUpdate' />
|
|
|
|
+ </IconButton>}
|
|
|
|
+ {location && <IconButton
|
|
|
|
+ aria-label="login"
|
|
|
|
+ edge="end"
|
|
|
|
+ >
|
|
|
|
+ <Person />
|
|
|
|
+ </IconButton>}
|
|
|
|
+ </InputAdornment>
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </FormControl>
|
|
|
|
+ </Tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ </ClickAwayListener>
|
|
|
|
+
|
|
|
|
+ <ClickAwayListener onClickAway={handleTooltipClose}>
|
|
|
|
+ <div>
|
|
|
|
+ <Tooltip
|
|
|
|
+ PopperProps={{
|
|
|
|
+ disablePortal: true,
|
|
|
|
+ }}
|
|
|
|
+ onClose={handleTooltipClose}
|
|
|
|
+ open={openToolTipsPass}
|
|
|
|
+ disableFocusListener
|
|
|
|
+ disableHoverListener
|
|
|
|
+ disableTouchListener
|
|
|
|
+ title={!location && 'Минимум 8 символов (большие и маленькие латинские буквы, цифры и спецсимволы)'}
|
|
|
|
+ arrow
|
|
|
|
+ >
|
|
|
|
+ <FormControl
|
|
|
|
+ variant="outlined"
|
|
|
|
+ onClick={handleTooltipOpen}
|
|
|
|
+ >
|
|
|
|
+ <InputLabel htmlFor="outlined-adornment-password">Пароль</InputLabel>
|
|
|
|
+ <OutlinedInput
|
|
|
|
+ error={!location && isValidate}
|
|
|
|
+ fullWidth
|
|
|
|
+ id="password"
|
|
|
|
+ label="Пароль"
|
|
|
|
+ size="normal"
|
|
|
|
+ type={showPassword ? 'text' : 'password'}
|
|
|
|
+ value={data.pass}
|
|
|
|
+ onChange={e => setData({ ...data, pass: e.target.value })}
|
|
|
|
+
|
|
|
|
+ endAdornment={
|
|
|
|
+ <InputAdornment position="end">
|
|
|
|
+ <IconButton
|
|
|
|
+ aria-label="visibility"
|
|
|
|
+ onClick={handleClickShowPassword}
|
|
|
|
+ onMouseDown={handleMouseDownPassword}
|
|
|
|
+ edge="end"
|
|
|
|
+ >
|
|
|
|
+ {showPassword ? <VisibilityOff /> : <Visibility />}
|
|
|
|
+ </IconButton>
|
|
|
|
+ </InputAdornment>
|
|
|
|
+ }
|
|
|
|
+ />
|
|
|
|
+ </FormControl>
|
|
|
|
+ </Tooltip>
|
|
|
|
+ </div>
|
|
|
|
+ </ClickAwayListener>
|
|
|
|
|
|
- endAdornment={
|
|
|
|
- <InputAdornment position="end">
|
|
|
|
- <IconButton
|
|
|
|
- aria-label="visibility"
|
|
|
|
- onClick={handleClickShowPassword}
|
|
|
|
- onMouseDown={handleMouseDownPassword}
|
|
|
|
- edge="end"
|
|
|
|
- >
|
|
|
|
- {showPassword ? <VisibilityOff /> : <Visibility />}
|
|
|
|
- </IconButton>
|
|
|
|
- </InputAdornment>
|
|
|
|
- }
|
|
|
|
- />
|
|
|
|
- </FormControl>
|
|
|
|
|
|
|
|
{!location && <FormControl variant="outlined">
|
|
{!location && <FormControl variant="outlined">
|
|
<InputLabel htmlFor="outlined-adornment-password">Подтвердите пароль</InputLabel>
|
|
<InputLabel htmlFor="outlined-adornment-password">Подтвердите пароль</InputLabel>
|
|
@@ -181,7 +309,7 @@ function LoginForm() {
|
|
variant="contained"
|
|
variant="contained"
|
|
disabled={location
|
|
disabled={location
|
|
? (validation || false)
|
|
? (validation || false)
|
|
- : (validation || isCorrect) || false}
|
|
|
|
|
|
+ : (validation || isCorrect || isLogin) || false}
|
|
onClick={location ? fullLogin : fullRegistration}
|
|
onClick={location ? fullLogin : fullRegistration}
|
|
>
|
|
>
|
|
{location
|
|
{location
|