131 lines
3.7 KiB
TypeScript
131 lines
3.7 KiB
TypeScript
'use client';
|
||
|
||
import s from './styles.module.scss';
|
||
import { Button, Input, Mark, PhoneInput, TextArea } from '@shared/ui';
|
||
import toast from 'react-hot-toast';
|
||
import { Controller, useForm } from 'react-hook-form';
|
||
import { zodResolver } from '@hookform/resolvers/zod';
|
||
import { z } from 'zod';
|
||
import { sendFormFn } from '@shared/api/api.service';
|
||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||
import Link from 'next/link';
|
||
|
||
const FormSchema = z.object({
|
||
name: z
|
||
.string()
|
||
.min(3, { message: 'Поле должно содержать не менее 3-х букв' })
|
||
.regex(/^[A-Za-zА-Яа-яЁё]+(?:[ '-][A-Za-zА-Яа-яЁё]+)*$/, {
|
||
message: 'Поле содержит некорректные символы',
|
||
}),
|
||
phone: z.string().refine(isValidPhoneNumber, 'Некорректный номер телефона'),
|
||
message: z
|
||
.string()
|
||
.min(21, { message: 'Оставьте сообщение мин. 20 символов' }),
|
||
});
|
||
type TForm = z.infer<typeof FormSchema>;
|
||
|
||
const defaultValues = {
|
||
name: '',
|
||
phone: '',
|
||
message: '',
|
||
};
|
||
|
||
export default function FooterForm() {
|
||
const {
|
||
handleSubmit,
|
||
control,
|
||
reset,
|
||
clearErrors,
|
||
formState: { errors },
|
||
} = useForm<TForm>({
|
||
resolver: zodResolver(FormSchema),
|
||
defaultValues,
|
||
});
|
||
|
||
const onSubmit = async (data: TForm) => {
|
||
const payload = {
|
||
...data,
|
||
form: 'footer-form',
|
||
};
|
||
|
||
try {
|
||
await sendFormFn(payload);
|
||
toast.success('Заявка на консультацию принята');
|
||
reset(defaultValues);
|
||
} catch (e) {
|
||
toast.error('Ошибка при отправке заявки...', {
|
||
duration: 3000,
|
||
});
|
||
}
|
||
};
|
||
|
||
return (
|
||
<form className={s.Form} onSubmit={handleSubmit(onSubmit)}>
|
||
<h2 className={s.Header}>
|
||
Давайте <Mark>обсудим</Mark> ваши задачи
|
||
</h2>
|
||
<Controller
|
||
control={control}
|
||
name={'name'}
|
||
render={({ field }) => (
|
||
<Input
|
||
{...field}
|
||
variant='ghost'
|
||
placeholder={'Ваше имя'}
|
||
fullWidth
|
||
onChange={(e) => {
|
||
clearErrors('name');
|
||
field.onChange(e);
|
||
}}
|
||
error={errors && errors.name?.message}
|
||
errorTextColor={'#ff9191'}
|
||
/>
|
||
)}
|
||
/>
|
||
<Controller
|
||
control={control}
|
||
name={'phone'}
|
||
render={({ field }) => (
|
||
<PhoneInput
|
||
{...field}
|
||
variant='ghost'
|
||
placeholder={'+7 (999) 123-45-67'}
|
||
fullWidth
|
||
onChange={(e) => {
|
||
clearErrors('phone');
|
||
field.onChange(e);
|
||
}}
|
||
error={errors && errors.phone?.message}
|
||
errorTextColor={'#ff9191'}
|
||
/>
|
||
)}
|
||
/>
|
||
<Controller
|
||
control={control}
|
||
name={'message'}
|
||
render={({ field }) => (
|
||
<TextArea
|
||
{...field}
|
||
variant='ghost'
|
||
placeholder={'Кратко опишите вашу задачу'}
|
||
fullWidth
|
||
id='story'
|
||
name='story'
|
||
rows={6}
|
||
error={errors && errors.message?.message}
|
||
errorTextColor={'#ff9191'}
|
||
/>
|
||
)}
|
||
/>
|
||
<span className={s.Agreement}>
|
||
Нажимая на кнопку, вы даете согласие на обработку своих персональных
|
||
данных и соглашаетесь с
|
||
<Link href={'/privacy-policy'}> Политикой конфиденциальности</Link>
|
||
</span>
|
||
<Button className={s.SendBtn} variant='orange' fullWidth>
|
||
Отправить
|
||
</Button>
|
||
</form>
|
||
);
|
||
}
|