fix: add forms sending

This commit is contained in:
2025-07-07 16:18:35 +03:00
parent 8def3b0d99
commit be57858e90
4 changed files with 196 additions and 22 deletions

View File

@@ -1,20 +1,103 @@
'use client';
import s from './styles.module.scss';
import { Button, Input, PhoneInput } from '@shared/ui';
import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { isValidPhoneNumber } from 'libphonenumber-js/min';
import { z } from 'zod';
import { sendFormFn } from '@shared/api/api.service';
import toast from 'react-hot-toast';
type CallbackFormProps = {
pageName: string;
pageName?: string;
};
function CallbackForm({ pageName }: CallbackFormProps) {
const FormSchema = z.object({
name: z
.string()
.min(3, { message: 'Поле должно содержать не менее 3-х букв' })
.regex(/^[A-Za-zА-Яа-яЁё]+(?:[ '-][A-Za-zА-Яа-яЁё]+)*$/, {
message: 'Поле содержит некорректные символы',
}),
phone: z.string().refine(isValidPhoneNumber, 'Некорректный номер телефона'),
});
type TForm = z.infer<typeof FormSchema>;
const defaultValues = {
name: '',
phone: '',
};
function CallbackForm({ pageName = 'noname-form' }: CallbackFormProps) {
const {
handleSubmit,
control,
reset,
clearErrors,
formState: { errors },
} = useForm<TForm>({
mode: 'onSubmit',
reValidateMode: 'onBlur',
resolver: zodResolver(FormSchema),
defaultValues,
});
const onSubmit = async (data: TForm) => {
const payload = {
...data,
form: pageName,
};
try {
await sendFormFn(payload);
toast.success('Заявка на консультацию принята');
reset(defaultValues);
} catch (e) {
toast.error('Ошибка при отправке заявки...', {
duration: 3000,
});
}
};
return (
<div className={s.Container}>
<h3 className={s.Title}>Узнать точную стоимость и срок экспертизы</h3>
<form className={s.Form}>
<Input variant={'ghost'} fullWidth placeholder='Ваше имя' />
<PhoneInput
variant={'ghost'}
fullWidth
placeholder='+7 999 123-45-67'
<form className={s.Form} onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name={'name'}
render={({ field }) => (
<Input
{...field}
placeholder='Ваше имя'
variant={'ghost'}
fullWidth
onChange={(e) => {
clearErrors('name');
field.onChange(e);
}}
error={errors && errors.name?.message}
/>
)}
/>
<Controller
control={control}
name={'phone'}
render={({ field }) => (
<PhoneInput
{...field}
placeholder='+7 999 123-45-67'
variant={'ghost'}
fullWidth
onChange={(e) => {
clearErrors('phone');
field.onChange(e);
}}
error={errors && errors.phone?.message}
/>
)}
/>
<Button variant={'white'} fullWidth>
Узнать

View File

@@ -1,22 +1,112 @@
'use client';
import s from './styles.module.scss';
import Image from 'next/image';
import { TExpert } from '@/shared/types/expert';
import { Button, Input, PhoneInput } from '@shared/ui';
import { z } from 'zod';
import { isValidPhoneNumber } from 'libphonenumber-js/min';
import { Controller, useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { sendFormFn } from '@shared/api/api.service';
import toast from 'react-hot-toast';
type ConsultationProps = TExpert;
type ConsultationProps = {
pageName?: string;
} & TExpert;
const FormSchema = z.object({
name: z
.string()
.min(3, { message: 'Поле должно содержать не менее 3-х букв' })
.regex(/^[A-Za-zА-Яа-яЁё]+(?:[ '-][A-Za-zА-Яа-яЁё]+)*$/, {
message: 'Поле содержит некорректные символы',
}),
phone: z.string().refine(isValidPhoneNumber, 'Некорректный номер телефона'),
});
type TForm = z.infer<typeof FormSchema>;
const defaultValues = {
name: '',
phone: '',
};
function Consultation({
pageName = 'noname-form',
name,
position,
photo,
}: ConsultationProps) {
const {
handleSubmit,
control,
reset,
clearErrors,
formState: { errors },
} = useForm<TForm>({
mode: 'onSubmit',
reValidateMode: 'onBlur',
resolver: zodResolver(FormSchema),
defaultValues,
});
const onSubmit = async (data: TForm) => {
const payload = {
...data,
form: pageName,
};
try {
await sendFormFn(payload);
toast.success('Заявка на консультацию принята');
reset(defaultValues);
} catch (e) {
toast.error('Ошибка при отправке заявки...', {
duration: 3000,
});
}
};
function Consultation({ name, position, photo }: ConsultationProps) {
return (
<section className={s.Consultation}>
<div className={s.Container}>
<div className={s.Block}>
<h3 className={s.Header}>Бесплатная консультация специалиста</h3>
<form className={s.Form}>
<Input variant={'ghost'} placeholder={'Имя'} fullWidth />
<PhoneInput
variant={'ghost'}
placeholder={'+7 999 123-45-67'}
fullWidth
<form className={s.Form} onSubmit={handleSubmit(onSubmit)}>
<Controller
control={control}
name={'name'}
render={({ field }) => (
<Input
{...field}
placeholder='Имя'
variant={'ghost'}
fullWidth
onChange={(e) => {
clearErrors('name');
field.onChange(e);
}}
error={errors && errors.name?.message}
/>
)}
/>
<Controller
control={control}
name={'phone'}
render={({ field }) => (
<PhoneInput
{...field}
placeholder={'+7 999 123-45-67'}
variant={'ghost'}
fullWidth
onChange={(e) => {
clearErrors('phone');
field.onChange(e);
}}
error={errors && errors.phone?.message}
/>
)}
/>
<Button variant={'white'} fullWidth>
Записаться

View File

@@ -5,9 +5,10 @@ import { CallbackForm } from '@/entities';
type RelatedArticlesProps = {
related: TRelatedArticles[];
pageName?: string;
};
function RelatedArticles({ related }: RelatedArticlesProps) {
function RelatedArticles({ related, pageName }: RelatedArticlesProps) {
return (
<section className={s.Related}>
<div className={s.Container}>
@@ -27,7 +28,7 @@ function RelatedArticles({ related }: RelatedArticlesProps) {
</div>
))}
</div>
<CallbackForm pageName='Автотехническая экспертиза' />
<CallbackForm pageName={pageName} />
</div>
<div />
</div>

View File

@@ -5,7 +5,7 @@ import { Breadcrumbs, PartnersSlider } from '@/widgets';
import { sidebarData } from './model/sidebar';
import { relatedArticlesData } from './model/relatedArticles';
import { expertData } from './model/expert';
import { breadcrumbData } from './model/breadcrums';
import { breadcrumbData, PAGE_NAME } from './model/breadcrums';
function AutoTech() {
return (
@@ -58,7 +58,7 @@ function AutoTech() {
</li>
</ul>
<CallbackForm pageName='Автотехническая экспертиза' />
<CallbackForm pageName={PAGE_NAME} />
<h3 className={s.Header}>Документы, необходимые для экспертизы:</h3>
<p className={s.Text}>
@@ -95,8 +95,8 @@ function AutoTech() {
</div>
</section>
<Consultation {...expertData} />
<RelatedArticles related={relatedArticlesData} />
<Consultation {...expertData} pageName={PAGE_NAME} />
<RelatedArticles related={relatedArticlesData} pageName={PAGE_NAME} />
<section className={s.Partners}>
<div className={s.Divider}>
<span className={s.Separator} />