auth validation

This commit is contained in:
Виталий Лавшонок
2025-11-23 13:53:48 +03:00
parent dae4584840
commit ee0e44082a
5 changed files with 147 additions and 17 deletions

View File

@@ -27,7 +27,6 @@ const Login = () => {
// После успешного логина
useEffect(() => {
dispatch(setMenuActivePage('account'));
submitClicked;
}, []);
useEffect(() => {
@@ -47,6 +46,21 @@ const Login = () => {
dispatch(loginUser({ username, password }));
};
const getErrorLoginMessage = (): string => {
if (!submitClicked) return '';
if (username == '') return 'Поле не может быть пустым';
if (password == '') return '';
if (status === 'failed')
return 'Неверное имя пользователя и/или пароль';
return '';
};
const getErrorPasswordMessage = (): string => {
if (!submitClicked) return '';
if (password == '') return 'Поле не может быть пустым';
return '';
};
return (
<div className="h-svh w-svw fixed pointer-events-none top-0 left-0 flex items-center justify-center">
<div className="grid gap-[80px] grid-cols-[400px,384px] box-border relative ">
@@ -73,6 +87,7 @@ const Login = () => {
setUsername(v);
}}
placeholder="login"
error={getErrorLoginMessage()}
/>
<Input
name="password"
@@ -84,6 +99,7 @@ const Login = () => {
setPassword(v);
}}
placeholder="abCD1234"
error={getErrorPasswordMessage()}
/>
<div className="flex justify-end mt-[10px]">

View File

@@ -13,6 +13,37 @@ import { SecondaryButton } from '../../../components/button/SecondaryButton';
import { Checkbox } from '../../../components/checkbox/Checkbox';
import { googleLogo } from '../../../assets/icons/input';
function isValidEmail(email: string): boolean {
const pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return pattern.test(email);
}
function isValidLogin(login: string): boolean {
return login.length >= 4 && login.length <= 128;
}
function isValidatePassword(password: string): string {
const errors: string[] = [];
if (password.length < 8 || password.length > 255) {
errors.push('Пароль должен содержать от 8 до 255 символов');
}
if (!/[A-Z]/.test(password)) {
errors.push('Пароль должен содержать хотя бы одну заглавную букву');
}
if (!/[a-z]/.test(password)) {
errors.push('Пароль должен содержать хотя бы одну строчную букву');
}
if (!/[0-9]/.test(password)) {
errors.push('Пароль должен содержать хотя бы одну цифру');
}
return errors.join('\n');
}
const Register = () => {
const dispatch = useAppDispatch();
const navigate = useNavigate();
@@ -23,10 +54,10 @@ const Register = () => {
const [password, setPassword] = useState<string>('');
const [confirmPassword, setConfirmPassword] = useState<string>('');
const [submitClicked, setSubmitClicked] = useState<boolean>(false);
const [politicChecked, setPoliticChecked] = useState<boolean>(false);
const { status, jwt } = useAppSelector((state) => state.auth);
// После успешной регистрации — переход в систему
// const { errors } = useAppSelector((state) => state.auth.register);
useEffect(() => {
dispatch(setMenuActivePage('account'));
@@ -38,18 +69,73 @@ const Register = () => {
const path = from ? from.pathname + from.search : '/home/account';
navigate(path, { replace: true });
}
submitClicked;
}, [jwt]);
const handleRegister = () => {
setSubmitClicked(true);
if (!politicChecked) return;
if (!username || !email || !password || !confirmPassword) return;
if (password !== confirmPassword) return;
if (
!isValidEmail(email) ||
!isValidLogin(username) ||
isValidatePassword(password) != ''
)
return;
dispatch(registerUser({ username, email, password }));
};
const getErrorEmailMessage = (): string => {
if (!submitClicked) return '';
if (email == '') return 'Поле не может быть пустым';
if (!isValidEmail(email)) return 'Почта не валидна';
if (!username || !email || !password || !confirmPassword) return '';
if (password !== confirmPassword) return '';
// if (errors?.Email) {
// return errors.Email.join('\n');
// }
return '';
};
const getErrorLoginMessage = (): string => {
if (!submitClicked) return '';
if (username == '') return 'Поле не может быть пустым';
if (!isValidLogin(username))
return 'Логин дложен быть длиной от 4 до 128 символов';
if (!username || !email || !password || !confirmPassword) return '';
if (password !== confirmPassword) return '';
// if (errors?.Username) {
// return errors.Username.join('\n');
// }
return '';
};
const getErrorPasswordMessage = (): string => {
if (!submitClicked) return '';
if (password == '') return 'Поле не может быть пустым';
const val = isValidatePassword(password);
if (val != '') return val;
if (confirmPassword != password) return 'Пароли не совпадают';
if (!username || !email || !password || !confirmPassword) return '';
// if (errors?.Password) {
// return errors.Password.join('\n');
// }
return '';
};
const getErrorConfirmPasswordMessage = (): string => {
if (!submitClicked) return '';
if (confirmPassword == '') return 'Поле не может быть пустым';
const val = isValidatePassword(confirmPassword);
if (val != '') return val;
if (confirmPassword != password) return 'Пароли не совпадают';
if (!username || !email || !password || !confirmPassword) return '';
return '';
};
return (
<div className="h-svh w-svw fixed pointer-events-none top-0 left-0 flex items-center justify-center">
<div className="grid gap-[80px] grid-cols-[400px,384px] box-border relative ">
@@ -76,6 +162,7 @@ const Register = () => {
setEmail(v);
}}
placeholder="example@gmail.com"
error={getErrorEmailMessage()}
/>
<Input
name="login"
@@ -87,6 +174,7 @@ const Register = () => {
setUsername(v);
}}
placeholder="login"
error={getErrorLoginMessage()}
/>
<Input
name="password"
@@ -98,6 +186,7 @@ const Register = () => {
setPassword(v);
}}
placeholder="abCD1234"
error={getErrorPasswordMessage()}
/>
<Input
name="confirm-password"
@@ -109,23 +198,31 @@ const Register = () => {
setConfirmPassword(v);
}}
placeholder="abCD1234"
error={getErrorConfirmPasswordMessage()}
/>
<div className=" flex items-center mt-[10px] h-[24px]">
<Checkbox
onChange={(value: boolean) => {
value;
setPoliticChecked(value);
}}
className="p-0 w-fit m-[2.75px]"
size="md"
color="secondary"
color={
politicChecked || !submitClicked
? 'secondary'
: 'danger'
}
variant="default"
/>
<span className="text-[14px] font-medium text-liquid-light h-[18px] ml-[10px]">
Я принимаю{' '}
<Link to={'/home'} className={' underline'}>
{/* <Link to={'/home'} className={' underline'}>
политику конфиденциальности
</Link>
</Link> */}
<span className={' underline cursor-pointer'}>
политику конфиденциальности
</span>
</span>
</div>