Skip to content

Commit

Permalink
Merge pull request #247 from Pet-projects-CodePET/fix/yup-to-zod
Browse files Browse the repository at this point in the history
add zod shcemes, separate regex into single file, change form types
  • Loading branch information
danilastepanov authored Aug 14, 2024
2 parents 5d6dbd0 + aff7ff5 commit 284e0b4
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 146 deletions.
4 changes: 2 additions & 2 deletions src/shared/ui/form/form.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import React, { FC } from 'react';
import { yupResolver } from '@hookform/resolvers/yup';
import { zodResolver } from '@hookform/resolvers/zod';
import { FormProvider, useForm } from 'react-hook-form';
import styles from './form.module.scss';
import type { FormProps } from './types';
Expand All @@ -15,7 +15,7 @@ export const Form: FC<FormProps> = ({
}) => {
const methods = useForm({
shouldUnregister: true,
resolver: schema ? yupResolver(schema) : undefined,
resolver: schema ? zodResolver(schema) : undefined,
});

const {
Expand Down
4 changes: 2 additions & 2 deletions src/shared/ui/form/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { HTMLAttributes, ReactNode, FormEventHandler } from 'react';
import * as yup from 'yup';
import * as z from 'zod';
import { IUser } from '@/services/models/IUser';

export type FormProps = HTMLAttributes<HTMLFormElement> & {
children: ReactNode;
extraClass?: string;
schema?: yup.AnyObjectSchema;
schema?: z.ZodEffects<z.AnyZodObject> | z.AnyZodObject;
onSubmit: FormEventHandler<HTMLFormElement> & ((data: IUser) => void);
};
58 changes: 27 additions & 31 deletions src/shared/utils/validation-schemas/form-change-password-schema.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,32 @@
import * as yup from 'yup';
import { z } from 'zod';
import { passwordRegex } from '@/utils/regex-consts';

const FormChangePasswordSchema = yup.object().shape({
password: yup
.string()
.required('Поле обязательно для заполнения')
.min(8, 'Длина поля от 8 до 20 символов')
.max(20, 'Длина поля от 8 до 20 символов')
.matches(
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/,
'Проверьте правильность ввода'
),
const FormChangePasswordSchema = z
.object({
password: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' })
.regex(/[u00AE]/, 'Проверьте правильность ввода'),

newPassword: yup
.string()
.required('Поле обязательно для заполнения')
.min(8, 'Длина поля от 8 до 20 символов')
.max(20, 'Длина поля от 8 до 20 символов')
.matches(
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/,
'Проверьте правильность ввода'
),
newPassword: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' })
.regex(passwordRegex, 'Проверьте правильность ввода'),

repeatNewPassword: yup
.string()
.required('Поле обязательно для заполнения')
.min(8, 'Проверьте правильность ввода')
.max(20, 'Проверьте правильность ввода')
.matches(
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/,
'Проверьте правильность ввода'
)
.oneOf([yup.ref('newPassword')], 'Пароль не совпадает с введенным'),
});
reapeatPassword: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' })
.regex(passwordRegex, 'Проверьте правильность ввода'),
})
.refine((e) => e.newPassword === e.reapeatPassword, {
message: 'Пароль не совпадает с введенным',
path: ['reapeatPassword'],
});

export default FormChangePasswordSchema;
50 changes: 25 additions & 25 deletions src/shared/utils/validation-schemas/form-login-schema.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
import * as yup from 'yup';
import { z } from 'zod';
import {
generalEmailRegex,
noSpecialCharEmailRegex,
limitedCharEmailRegex,
passwordRegex,
} from '@/utils/regex-consts';

const schema = yup.object().shape({
email: yup
const schema = z.object({
email: z
.string()
.required('Поле обязательно для заполнения')
.email('Проверьте правильность ввода')
.min(1, { message: 'Поле обязательно для заполнения' })
.email({ message: 'Проверьте правильность ввода' })
.min(6, { message: 'Длина поля от 6 до 256 символов' })
.max(256, { message: 'Длина поля от 6 до 256 символов' })
.trim()
.min(6, 'Проверьте правильность ввода')
.max(256, 'Проверьте правильность ввода')
.matches(
/^[a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]@[a-zA-Z0-9-]+(?:\.[a-zA-Zа-яА-Я0-9-]+)*\.[a-zA-Zа-яА-Я-]{2,}$/,
'Проверьте правильность ввода'
)
.matches(
/^[^/[!"#$%&'()*+,/:;<=>?[\\\]^`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]*$/,
'Проверьте правильность ввода'
)
.matches(/^[a-zA-Zа-яА-Я0-9-._@]*$/, 'Только буквы (A-z, А-я), цифры (0-9)')
.max(256, 'Проверьте правильность ввода'),
password: yup
.regex(generalEmailRegex, { message: 'Проверьте правильность ввода' })
.regex(noSpecialCharEmailRegex, { message: 'Проверьте правильность ввода' })
.regex(limitedCharEmailRegex, {
message: 'Только буквы (A-z, А-я), цифры (0-9)',
}),

password: z
.string()
.trim()
.required('Поле обязательно для заполнения')
.min(8, 'Проверьте правильность ввода')
.max(20, 'Проверьте правильность ввода')
.matches(
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/,
'Проверьте правильность ввода'
),
.min(1, { message: 'Поле обязательно для заполнения' })
.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' })
.regex(passwordRegex, { message: 'Проверьте правильность ввода' }),
});

export default schema;
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import * as yup from 'yup';
import { z } from 'zod';
import {
generalEmailRegex,
noSpecialCharEmailRegex,
limitedCharEmailRegex,
} from '@/utils/regex-consts';

const schema = yup.object().shape({
email: yup
const schema = z.object({
email: z
.string()
.required('Поле обязательно для заполнения')
.email('Проверьте правильность ввода')
.min(1, { message: 'Поле обязательно для заполнения' })
.email({ message: 'Проверьте правильность ввода' })
.min(6, { message: 'Проверьте правильность ввода' })
.max(256, { message: 'Проверьте правильность ввода' })
.trim()
.min(6, 'Проверьте правильность ввода')
.max(256, 'Проверьте правильность ввода')
.matches(
/^[a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]@[a-zA-Z0-9-]+(?:\.[a-zA-Zа-яА-Я0-9-]+)*\.[a-zA-Zа-яА-Я-]{2,}$/,
'Проверьте правильность ввода'
)
.matches(
/^[^/[!"#$%&'()*+,/:;<=>?[\\\]^`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]*$/,
'Проверьте правильность ввода'
)
.matches(/^[a-zA-Zа-яА-Я0-9-._@]*$/, 'Только буквы (A-z, А-я), цифры (0-9)')
.max(256, 'Проверьте правильность ввода'),
.regex(generalEmailRegex, { message: 'Проверьте правильность ввода' })
.regex(noSpecialCharEmailRegex, { message: 'Проверьте правильность ввода' })
.regex(limitedCharEmailRegex, {
message: 'Только буквы (A-z, А-я), цифры (0-9)',
}),
});
export default schema;
137 changes: 68 additions & 69 deletions src/shared/utils/validation-schemas/form-signup-schema.ts
Original file line number Diff line number Diff line change
@@ -1,70 +1,69 @@
import * as yup from 'yup';
import {
generalEmailRegex,
noSpecialCharEmailRegex,
limitedCharEmailRegex,
passwordRegex,
} from '@/utils/regex-consts';
import { z } from 'zod';

const schema = yup.object().shape({
email: yup
.string()
.required('Поле обязательно для заполнения')
.min(6, 'Длина поля от 6 до 256 символов')
.max(256, 'Длина поля от 6 до 256 символов')
.trim()
.matches(
/^[^/[!"#$%&'()*+,/:;<=>?[\\\]^`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]*$/,
'Только дефис, точка, нижнее подчеркивание'
)
.matches(/^[a-zA-Zа-яА-Я0-9-._@]*$/, 'Только буквы (A-z, А-я), цифры (0-9)')
.email('Введите корректный E-mail')
.matches(
/^[a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]@[a-zA-Z0-9_-]+(?:\.[a-zA-Zа-яА-Я0-9_-]+)*\.[a-zA-Zа-яА-Я_-]{2,}$/,
'Введите корректный E-mail'
),
username: yup
.string()
.required('Поле обязательно для заполнения')
.trim()
.min(2, 'Длина поля от 2 до 30 символов')
.max(30, 'Длина поля от 2 до 30 символов')
.matches(/^[a-zA-Zа-яА-Я0-9-._@]*$/, 'Только буквы (A-z, А-я), цифры (0-9)')
.matches(
/^[^/[!"#$%&'()*+,/:;<=>?[\\\]^`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]*$/,
'Только дефис, точка, нижнее подчеркивание'
)
.test('no-consecutive-dashes', 'Введите корректную фамилию', (value) => {
if (typeof value !== 'string') {
return true;
}
return !/--/.test(value.replace(/\s/g, ''));
})
.test(
'no-spaces-between-dashes',
'Введите никнейм без пробелов',
(value) => {
if (typeof value !== 'string') {
return true;
}
if (/\s/.test(value)) {
value.replace(/\s/g, '');
}
return !/\s/.test(value);
}
),
password: yup
.string()
.trim()
.required('Поле обязательно для заполнения')
.min(8, 'Длина поля от 8 до 20 символов')
.max(20, 'Длина поля от 8 до 20 символов')
.matches(
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/,
'Только буквы (A-z, А-я), цифры (0-9), спецсимволы'
),
/* eslint-disable */
re_password: yup
/* eslint-enable */
.string()
.trim()
.required('Поле обязательно для заполнения')
.min(8, 'Длина поля от 8 до 20 символов')
.max(20, 'Длина поля от 8 до 20 символов')
.oneOf([yup.ref('password')], 'Пароли не совпадают'),
});
export default schema;
const noConsecutiveDashes = (value: string) =>
!/--/.test(value.replace(/\s/g, ''));
const noSpacesBetweenDashes = (value: string) =>
!/\s/.test(value.replace(/\s/g, ''));

const FormSchema = z
.object({
email: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.email({ message: 'Проверьте правильность ввода' })
.min(6, { message: 'Длина поля от 6 до 256 символов' })
.max(256, { message: 'Длина поля от 6 до 256 символов' })
.trim()
.regex(generalEmailRegex, { message: 'Проверьте правильность ввода' })
.regex(noSpecialCharEmailRegex, {
message: 'Проверьте правильность ввода',
})
.regex(limitedCharEmailRegex, {
message: 'Только буквы (A-z, А-я), цифры (0-9)',
}),

username: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.min(2, { message: 'Длина поля от 2 до 30 символов' })
.max(30, { message: 'Длина поля от 2 до 30 символов' })
.trim()
.regex(limitedCharEmailRegex, {
message: 'Только буквы (A-z, А-я), цифры (0-9)',
})
.regex(noSpecialCharEmailRegex, {
message: 'Только дефис, точка, нижнее подчеркивание',
})
.refine(noConsecutiveDashes, { message: 'Введите корректную фамилию' })
.refine(noSpacesBetweenDashes, {
message: 'Введите никнейм без пробелов',
}),
password: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })
.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' })
.regex(passwordRegex, {
message: 'Только буквы (A-z, А-я), цифры (0-9), спецсимволы',
}),

// eslint-disable-next-line camelcase
re_password: z
.string()
.min(1, { message: 'Поле обязательно для заполнения' })

.min(8, { message: 'Длина поля от 8 до 20 символов' })
.max(20, { message: 'Длина поля от 8 до 20 символов' }),
})
.refine((val) => val.password === val.re_password, {
message: 'Пароли не совпадают',
path: ['re_password'],
});

export default FormSchema;
8 changes: 8 additions & 0 deletions src/utils/regex-consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const generalEmailRegex =
/^[a-zA-Z0-9][a-zA-Z0-9_.-]*[a-zA-Z0-9]@[a-zA-Z0-9-]+(?:\.[a-zA-Zа-яА-Я0-9-]+)*\.[a-zA-Zа-яА-Я-]{2,}$/;
export const noSpecialCharEmailRegex =
/^[^/[!"#$%&'()*+,/:;<=>?[\\\]^`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]*$/;
export const limitedCharEmailRegex = /^[a-zA-Zа-яА-Я0-9-._@]*$/;

export const passwordRegex =
/[a-zA-Zа-яА-Я0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~\u2116\u0024\u20AC\u00A3\u00A5\u20BD\u00A9\u2122\u00AE]$/;

0 comments on commit 284e0b4

Please sign in to comment.