Dev #1
@@ -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;
|
||||
};
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function CallbackForm({ pageName }: CallbackFormProps) {
|
||||
return (
|
||||
<div className={s.Container}>
|
||||
<h3 className={s.Title}>Узнать точную стоимость и срок экспертизы</h3>
|
||||
<form className={s.Form}>
|
||||
<Input variant={'ghost'} fullWidth placeholder='Ваше имя' />
|
||||
<PhoneInput
|
||||
<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>
|
||||
Узнать
|
||||
|
||||
@@ -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
|
||||
<form className={s.Form} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'name'}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
{...field}
|
||||
placeholder='Имя'
|
||||
variant={'ghost'}
|
||||
placeholder={'+7 999 123-45-67'}
|
||||
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>
|
||||
Записаться
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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} />
|
||||
|
||||
Reference in New Issue
Block a user