Skip to content

Commit 59412e3

Browse files
committed
[10] Формы
Реализованы формы: Профиль, Вход, Регистрация, Операция, Товар
1 parent ac21245 commit 59412e3

27 files changed

+676
-4
lines changed

package-lock.json

Lines changed: 55 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,11 @@
6464
"webpack-dev-server": "^4.15.0"
6565
},
6666
"dependencies": {
67+
"@hookform/resolvers": "^3.10.0",
6768
"clsx": "^1.2.1",
6869
"react": "^18.2.0",
69-
"react-dom": "^18.2.0"
70+
"react-dom": "^18.2.0",
71+
"react-hook-form": "^7.54.2",
72+
"zod": "^3.24.1"
7073
}
7174
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import React from 'react';
2+
import { useForm } from 'react-hook-form';
3+
import { zodResolver } from '@hookform/resolvers/zod';
4+
5+
import { RegularForm } from '../../shared/forms/RegularForm/RegularForm';
6+
import { Button } from '../../shared/button/Button';
7+
import { FormInputField } from '../../shared/forms/FormInputField/FormInputField';
8+
import { FormSelectField, SelectOptionProps } from '../../shared/forms/FormSelectField/FormSelectField';
9+
10+
import { OperationSchemaType, OperationSchema } from './operation-schema';
11+
12+
const costOperationOption: SelectOptionProps = {
13+
text: 'Cost',
14+
value: 'Cost',
15+
};
16+
17+
const profitOperationOption: SelectOptionProps = {
18+
text: 'Profit',
19+
value: 'Profit',
20+
};
21+
22+
export const OperationForm = () => {
23+
const {
24+
register,
25+
handleSubmit,
26+
formState: { errors },
27+
} = useForm<OperationSchemaType>({
28+
shouldUnregister: true,
29+
resolver: zodResolver(OperationSchema),
30+
});
31+
32+
const onSubmit = (data: OperationSchemaType) => {
33+
console.log(data);
34+
};
35+
36+
return (
37+
<RegularForm title="Операция" onSubmit={handleSubmit(onSubmit)}>
38+
<FormSelectField
39+
name="type"
40+
options={[costOperationOption, profitOperationOption]}
41+
register={register}
42+
errors={errors.type}
43+
>
44+
Тип операции
45+
</FormSelectField>
46+
<FormInputField name="name" register={register} type="text" errors={errors.name}>
47+
Название
48+
</FormInputField>
49+
<FormInputField name="category" register={register} type="text" errors={errors.category}>
50+
Категория
51+
</FormInputField>
52+
<FormInputField name="desc" register={register} type="text" errors={errors.desc}>
53+
Описание
54+
</FormInputField>
55+
<FormInputField name="createdAt" register={register} type="date" errors={errors.createdAt}>
56+
Дата
57+
</FormInputField>
58+
<FormInputField name="amount" register={register} isNumber={true} type="number" errors={errors.amount}>
59+
Сумма
60+
</FormInputField>
61+
62+
<Button type="submit">Сохранить</Button>
63+
</RegularForm>
64+
);
65+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { z } from 'zod';
2+
3+
export const OperationSchema = z.object({
4+
name: z.string().nonempty('Обязательное поле'),
5+
desc: z.string().optional(),
6+
createdAt: z.string().nonempty('Обязательное поле'),
7+
amount: z.number({ invalid_type_error: 'Обязательное поле' }).positive('Сумма должна быть больше 0'),
8+
category: z.string().nonempty('Обязательное поле'),
9+
type: z.enum(['Cost', 'Profit']),
10+
});
11+
12+
export type OperationSchemaType = z.infer<typeof OperationSchema>;
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React from 'react';
2+
import { useForm } from 'react-hook-form';
3+
import { zodResolver } from '@hookform/resolvers/zod';
4+
5+
import { RegularForm } from '../../shared/forms/RegularForm/RegularForm';
6+
import { Button } from '../../shared/button/Button';
7+
import { FormInputField } from '../../shared/forms/FormInputField/FormInputField';
8+
9+
import { ProductSchema, ProductSchemaType } from './product-schema';
10+
11+
export const ProductForm = () => {
12+
const {
13+
register,
14+
handleSubmit,
15+
formState: { errors },
16+
} = useForm<ProductSchemaType>({
17+
shouldUnregister: true,
18+
resolver: zodResolver(ProductSchema),
19+
});
20+
21+
const onSubmit = (data: ProductSchemaType) => {
22+
console.log(data);
23+
};
24+
25+
return (
26+
<RegularForm title="Товар" onSubmit={handleSubmit(onSubmit)}>
27+
<FormInputField name="name" register={register} type="text" errors={errors.name}>
28+
Название
29+
</FormInputField>
30+
<FormInputField name="category" register={register} type="text" errors={errors.category}>
31+
Категория
32+
</FormInputField>
33+
<FormInputField name="desc" register={register} type="text" errors={errors.desc}>
34+
Описание
35+
</FormInputField>
36+
<FormInputField name="photo" register={register} type="text" errors={errors.photo}>
37+
Фото
38+
</FormInputField>
39+
<FormInputField name="createdAt" register={register} type="date" errors={errors.createdAt}>
40+
Дата
41+
</FormInputField>
42+
<FormInputField name="oldPrice" register={register} isNumber={true} type="number" errors={errors.oldPrice}>
43+
Старая цена
44+
</FormInputField>
45+
<FormInputField name="price" register={register} isNumber={true} type="number" errors={errors.price}>
46+
Цена
47+
</FormInputField>
48+
<Button type="submit">Сохранить</Button>
49+
</RegularForm>
50+
);
51+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { z } from 'zod';
2+
3+
export const ProductSchema = z.object({
4+
name: z.string().nonempty('Обязательное поле'),
5+
photo: z.string().url('Некорректный URL').nonempty('Обязательное поле'),
6+
desc: z.string().optional(),
7+
createdAt: z.string().nonempty('Обязательное поле'),
8+
oldPrice: z
9+
.number({ invalid_type_error: 'Некорректное значение, введите 0 если значение отсутстувет' })
10+
.min(0, 'Сумма должна быть 0 или больше')
11+
.default(0),
12+
price: z.number({ invalid_type_error: 'Обязательное поле' }).positive('Сумма должна быть больше 0'),
13+
category: z.string().nonempty('Обязательное поле'),
14+
});
15+
16+
export type ProductSchemaType = z.infer<typeof ProductSchema>;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
.container {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 10px;
5+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import React from 'react';
2+
import { useForm } from 'react-hook-form';
3+
import { zodResolver } from '@hookform/resolvers/zod';
4+
5+
import {
6+
ChangeProfileSchema,
7+
ChangeProfileSchemaType,
8+
ChangePasswordSchema,
9+
ChangePasswordSchemaType,
10+
} from './profile-schema';
11+
import { RegularForm } from '../../shared/forms/RegularForm/RegularForm';
12+
import { FormInputField } from '../../shared/forms/FormInputField/FormInputField';
13+
import { FormTextareaField } from '../../shared/forms/FormTextareaField/FormTextareaField';
14+
import { Button } from '../../shared/button/Button';
15+
16+
import s from './ProfileForm.module.scss';
17+
18+
const ChangeProfileForm = () => {
19+
const {
20+
register,
21+
handleSubmit,
22+
formState: { errors },
23+
} = useForm<ChangeProfileSchemaType>({
24+
shouldUnregister: true,
25+
resolver: zodResolver(ChangeProfileSchema),
26+
});
27+
28+
const onSubmit = (data: ChangeProfileSchemaType) => {
29+
console.log(data);
30+
};
31+
32+
return (
33+
<RegularForm title="Изменить профиль" onSubmit={handleSubmit(onSubmit)}>
34+
<FormInputField name="name" register={register} type="text" errors={errors.name}>
35+
Псевдоним
36+
</FormInputField>
37+
<FormTextareaField name="description" register={register} errors={errors.description}>
38+
О себе
39+
</FormTextareaField>
40+
<Button type="submit">Сохранить</Button>
41+
</RegularForm>
42+
);
43+
};
44+
45+
const ChangePasswordForm = () => {
46+
const {
47+
register,
48+
handleSubmit,
49+
formState: { errors },
50+
} = useForm<ChangePasswordSchemaType>({
51+
shouldUnregister: true,
52+
resolver: zodResolver(ChangePasswordSchema),
53+
});
54+
55+
const onSubmit = (data: ChangePasswordSchemaType) => {
56+
console.log(data);
57+
};
58+
59+
return (
60+
<RegularForm title="Изменить пароль" onSubmit={handleSubmit(onSubmit)}>
61+
<FormInputField name="password" register={register} type="password" errors={errors.password}>
62+
Пароль
63+
</FormInputField>
64+
<FormInputField name="newPassword" register={register} type="password" errors={errors.newPassword}>
65+
Новый пароль
66+
</FormInputField>
67+
<FormInputField name="confirmPassword" register={register} type="password" errors={errors.confirmPassword}>
68+
Повторите пароль
69+
</FormInputField>
70+
<Button type="submit">Изменить</Button>
71+
</RegularForm>
72+
);
73+
};
74+
75+
export const ProfileForm = () => (
76+
<div className={s.container}>
77+
<ChangeProfileForm />
78+
<ChangePasswordForm />
79+
</div>
80+
);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { z } from 'zod';
2+
3+
export const ChangeProfileSchema = z.object({
4+
name: z.string().nonempty('Обязательное поле'),
5+
description: z.string(),
6+
});
7+
8+
export type ChangeProfileSchemaType = z.infer<typeof ChangeProfileSchema>;
9+
10+
const passwordZodType = z.string().nonempty('Обязательное поле').min(6, 'Слишком короткий пароль');
11+
12+
export const ChangePasswordSchema = z
13+
.object({
14+
password: passwordZodType,
15+
newPassword: passwordZodType,
16+
confirmPassword: passwordZodType,
17+
})
18+
.refine((data) => data.newPassword === data.confirmPassword, {
19+
message: 'Пароли не совпадают',
20+
path: ['confirmPassword'],
21+
});
22+
23+
export type ChangePasswordSchemaType = z.infer<typeof ChangePasswordSchema>;

0 commit comments

Comments
 (0)