fix: update form
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
.Container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.Phone {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
@include iftablet{
|
||||
}
|
||||
@include iflaptop{
|
||||
padding-left: rem(16px);
|
||||
}
|
||||
@include ifdesktop{
|
||||
padding-left: rem(32px);
|
||||
}
|
||||
}
|
||||
|
||||
.Button {
|
||||
position: absolute;
|
||||
z-index: 3;
|
||||
right: rem(2px);
|
||||
top: calc(50% - 1.2rem);
|
||||
min-height: calc(100% - .25rem);
|
||||
|
||||
@include iftablet{
|
||||
top: calc(50% - 1.2rem);
|
||||
right: rem(3px);
|
||||
}
|
||||
|
||||
@include iflaptop{
|
||||
top: calc(50% - 1.4rem);
|
||||
right: rem(4px);
|
||||
}
|
||||
|
||||
@include ifdesktop{
|
||||
top: calc(50% - 1.6rem);
|
||||
right: rem(2px);
|
||||
}
|
||||
}
|
||||
84
src/widgets/advanced-phone-input/advanced-phone-input.tsx
Normal file
84
src/widgets/advanced-phone-input/advanced-phone-input.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
'use client';
|
||||
|
||||
import s from './advanced-phone-input.module.scss';
|
||||
import { clsx } from 'clsx';
|
||||
import { Button, PhoneInput } from '@shared/ui';
|
||||
import { z } from 'zod';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import toast from 'react-hot-toast';
|
||||
import { sendFormFn } from '@shared/api/api.service';
|
||||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||
|
||||
type AdvancedPhoneInputProps = {
|
||||
containerClassName?: string;
|
||||
};
|
||||
|
||||
const FormSchema = z.object({
|
||||
phone: z.string().refine(isValidPhoneNumber, 'Некорректный номер телефона'),
|
||||
});
|
||||
type TForm = z.infer<typeof FormSchema>;
|
||||
|
||||
const defaultValues = {
|
||||
phone: '',
|
||||
};
|
||||
|
||||
export default function AdvancedPhoneInput({
|
||||
containerClassName,
|
||||
}: AdvancedPhoneInputProps) {
|
||||
const {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
const onSubmit = async (data: TForm) => {
|
||||
const payload = {
|
||||
...data,
|
||||
form: 'offer-request-form-desktop',
|
||||
};
|
||||
|
||||
try {
|
||||
await sendFormFn(payload);
|
||||
toast.success('Заявка на консультацию принята');
|
||||
reset(defaultValues);
|
||||
} catch (e) {
|
||||
toast.error('Ошибка при отправке заявки...', {
|
||||
duration: 3000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form
|
||||
className={clsx(containerClassName, s.Container)}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'phone'}
|
||||
render={({ field }) => (
|
||||
<PhoneInput
|
||||
{...field}
|
||||
className={s.Phone}
|
||||
placeholder={'+7 (999) 123-45-67'}
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.phone?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Button className={s.Button} variant='orange'>
|
||||
Отправить заявку
|
||||
</Button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
1
src/widgets/advanced-phone-input/index.ts
Normal file
1
src/widgets/advanced-phone-input/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as AdvancedPhoneInput } from './advanced-phone-input';
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import s from './styles.module.scss';
|
||||
import { Button, Input } from '@shared/ui';
|
||||
import { Button, Input, PhoneInput } from '@shared/ui';
|
||||
import Image from 'next/image';
|
||||
import toast from 'react-hot-toast';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
@@ -10,10 +10,16 @@ import { z } from 'zod';
|
||||
|
||||
import bgForm from '@public/images/bg-form.jpg';
|
||||
import { sendFormFn } from '@shared/api/api.service';
|
||||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string().min(3),
|
||||
phone: z.string(),
|
||||
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>;
|
||||
|
||||
@@ -27,6 +33,7 @@ export default function ContactsForm() {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
mode: 'onSubmit',
|
||||
@@ -75,18 +82,33 @@ export default function ContactsForm() {
|
||||
control={control}
|
||||
name={'name'}
|
||||
render={({ field }) => (
|
||||
<Input {...field} type='text' placeholder='Ваше имя' fullWidth />
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={'Ваше имя'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('name');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.name?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'phone'}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
<PhoneInput
|
||||
{...field}
|
||||
type='text'
|
||||
placeholder='+7 (999) 123 45 67'
|
||||
placeholder={'+7 (999) 123-45-67'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.phone?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import s from './styles.module.scss';
|
||||
import { Button, Input, Mark, TextArea } from '@shared/ui';
|
||||
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';
|
||||
@@ -9,11 +9,19 @@ import { z } from 'zod';
|
||||
|
||||
import man from '@public/images/footer-man.png';
|
||||
import { sendFormFn } from '@shared/api/api.service';
|
||||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string().min(3),
|
||||
phone: z.string(),
|
||||
message: z.string(),
|
||||
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>;
|
||||
|
||||
@@ -28,6 +36,7 @@ export default function FooterForm() {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
mode: 'onSubmit',
|
||||
@@ -67,6 +76,12 @@ export default function FooterForm() {
|
||||
variant='ghost'
|
||||
placeholder={'Ваше имя'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('name');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.name?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -74,11 +89,17 @@ export default function FooterForm() {
|
||||
control={control}
|
||||
name={'phone'}
|
||||
render={({ field }) => (
|
||||
<Input
|
||||
<PhoneInput
|
||||
{...field}
|
||||
variant='ghost'
|
||||
placeholder={'+7 999 1234567'}
|
||||
placeholder={'+7 (999) 123-45-67'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.phone?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -94,6 +115,8 @@ export default function FooterForm() {
|
||||
id='story'
|
||||
name='story'
|
||||
rows={6}
|
||||
error={errors && errors.message?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -4,3 +4,4 @@ export { LicenseForm } from './license-form';
|
||||
export { LicenseSlider } from './license-slider';
|
||||
export { OfferForm } from './offer-form';
|
||||
export { OfferRequestForm } from './offer-request';
|
||||
export { AdvancedPhoneInput } from './advanced-phone-input';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import s from './styles.module.scss';
|
||||
import { Button, Input } from '@shared/ui';
|
||||
import { Button, Input, PhoneInput } from '@shared/ui';
|
||||
import Image from 'next/image';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
@@ -10,11 +10,18 @@ import { z } from 'zod';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { sendFormFn } from '@shared/api/api.service';
|
||||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string().min(3),
|
||||
phone: z.string(),
|
||||
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 = {
|
||||
@@ -27,6 +34,7 @@ export default function LicenseForm() {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
mode: 'onSubmit',
|
||||
@@ -77,14 +85,34 @@ export default function LicenseForm() {
|
||||
control={control}
|
||||
name={'name'}
|
||||
render={({ field }) => (
|
||||
<Input {...field} placeholder={'Ваше имя'} fullWidth />
|
||||
<Input
|
||||
{...field}
|
||||
placeholder={'Ваше имя'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('name');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.name?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'phone'}
|
||||
render={({ field }) => (
|
||||
<Input {...field} placeholder={'+7 (999) 123 45 67'} fullWidth />
|
||||
<PhoneInput
|
||||
{...field}
|
||||
placeholder={'+7 (999) 123-45-67'}
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.phone?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Button variant='orange' fullWidth>
|
||||
|
||||
@@ -30,10 +30,9 @@ export default function OfferForm() {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
mode: 'onSubmit',
|
||||
reValidateMode: 'onBlur',
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues,
|
||||
});
|
||||
@@ -66,6 +65,11 @@ export default function OfferForm() {
|
||||
className={s.Unit}
|
||||
type='text'
|
||||
placeholder='Ваше имя'
|
||||
error={errors && errors.name?.message}
|
||||
onChange={(e) => {
|
||||
clearErrors('name');
|
||||
field.onChange(e);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
@@ -78,6 +82,11 @@ export default function OfferForm() {
|
||||
className={s.Unit}
|
||||
type='text'
|
||||
placeholder='+7 999 123-45-67'
|
||||
error={errors && errors.phone?.message}
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: rem(12px);
|
||||
gap: rem(20px);
|
||||
z-index: 2;
|
||||
max-width: rem(400px);
|
||||
@include iftablet{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import s from './styles.module.scss';
|
||||
import { AdvancedPhoneInput, Button, Input } from '@shared/ui';
|
||||
import { Button, Input, PhoneInput } from '@shared/ui';
|
||||
import Image from 'next/image';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
@@ -9,12 +9,18 @@ import { z } from 'zod';
|
||||
import toast from 'react-hot-toast';
|
||||
|
||||
import bgForm from '@public/images/bg-form.jpg';
|
||||
import { useState } from 'react';
|
||||
import { AdvancedPhoneInput } from '@/widgets';
|
||||
import { sendFormFn } from '@shared/api/api.service';
|
||||
import { isValidPhoneNumber } from 'libphonenumber-js/min';
|
||||
|
||||
const FormSchema = z.object({
|
||||
name: z.string().min(3),
|
||||
phone: z.string(),
|
||||
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>;
|
||||
|
||||
@@ -28,6 +34,7 @@ export default function OfferRequest() {
|
||||
handleSubmit,
|
||||
control,
|
||||
reset,
|
||||
clearErrors,
|
||||
formState: { errors },
|
||||
} = useForm<TForm>({
|
||||
mode: 'onSubmit',
|
||||
@@ -36,12 +43,10 @@ export default function OfferRequest() {
|
||||
defaultValues,
|
||||
});
|
||||
|
||||
const [inputPhone, setInputPhone] = useState('');
|
||||
|
||||
const onSubmitForm = async (data: TForm) => {
|
||||
const onSubmit = async (data: TForm) => {
|
||||
const payload = {
|
||||
...data,
|
||||
form: 'offer-request-form',
|
||||
form: 'offer-request-form-mobile',
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -55,23 +60,6 @@ export default function OfferRequest() {
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmitPhone = async (phone: string) => {
|
||||
const payload = {
|
||||
phone: phone,
|
||||
form: 'offer-request-form',
|
||||
};
|
||||
|
||||
try {
|
||||
await sendFormFn(payload);
|
||||
toast.success('Заявка на консультацию принята');
|
||||
setInputPhone('');
|
||||
} catch (e) {
|
||||
toast.error('Ошибка при отправке заявки...', {
|
||||
duration: 3000,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={s.Form}>
|
||||
<Image
|
||||
@@ -88,28 +76,40 @@ export default function OfferRequest() {
|
||||
<h3 className={s.Title}>Оставьте заявку на бесплатную консультацию</h3>
|
||||
</div>
|
||||
<div className={s.PanelRight}>
|
||||
<AdvancedPhoneInput
|
||||
value={inputPhone}
|
||||
onChange={(e) => setInputPhone(e.target.value)}
|
||||
onClick={() => onSubmitPhone(inputPhone)}
|
||||
containerClassName={s.AdvPhoneInput}
|
||||
text='Отправить заявку'
|
||||
placeholder={'+7 (999) 123 45 67'}
|
||||
/>
|
||||
<AdvancedPhoneInput containerClassName={s.AdvPhoneInput} />
|
||||
|
||||
<form className={s.MobileBtns} onSubmit={handleSubmit(onSubmitForm)}>
|
||||
<form className={s.MobileBtns} onSubmit={handleSubmit(onSubmit)}>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'name'}
|
||||
render={({ field }) => (
|
||||
<Input {...field} placeholder='Ваше имя' fullWidth />
|
||||
<Input
|
||||
{...field}
|
||||
placeholder='Ваше имя'
|
||||
fullWidth
|
||||
onChange={(e) => {
|
||||
clearErrors('name');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.name?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Controller
|
||||
control={control}
|
||||
name={'phone'}
|
||||
render={({ field }) => (
|
||||
<Input {...field} placeholder='+7 999 123 45 67' fullWidth />
|
||||
<PhoneInput
|
||||
{...field}
|
||||
placeholder='+7 (999) 123-45-67'
|
||||
onChange={(e) => {
|
||||
clearErrors('phone');
|
||||
field.onChange(e);
|
||||
}}
|
||||
error={errors && errors.phone?.message}
|
||||
errorTextColor={'#ff9191'}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<Button variant='orange' fullWidth>
|
||||
|
||||
Reference in New Issue
Block a user