From 553e6da6db07cfbb6a9088b904bbec5838b99c53 Mon Sep 17 00:00:00 2001 From: RedrockJS Date: Tue, 17 Jun 2025 11:56:31 +0300 Subject: [PATCH] feat: update modal --- README.md | 1 + src/app/layout.tsx | 3 +- src/core/providers/index.ts | 0 src/entities/home/ConsultationOrder/index.ts | 1 - src/entities/home/ConsultationOrder/ui.tsx | 13 -- src/entities/home/callback-order/index.ts | 1 + .../home/callback-order/styles.module.scss | 35 +++++ src/entities/home/callback-order/ui.tsx | 25 ++++ src/entities/home/consultation-modal/index.ts | 1 + .../consultation-modal/styles.module.scss | 29 ++++ src/entities/home/consultation-modal/ui.tsx | 137 ++++++++++++++++++ src/entities/home/consultation-order/index.ts | 1 + src/entities/home/consultation-order/ui.tsx | 18 +++ src/shared/ui/button/button.tsx | 2 +- src/shared/ui/index.ts | 1 + src/shared/ui/modal/close-icon.tsx | 23 +++ src/shared/ui/modal/index.ts | 3 +- src/shared/ui/modal/modal-content.module.scss | 79 ++++++++++ src/shared/ui/modal/modal-content.tsx | 49 +++++++ src/shared/ui/modal/modal.module.scss | 94 +----------- src/shared/ui/modal/modal.tsx | 75 +--------- src/shared/ui/text-area/text-area.module.scss | 8 +- src/views/home/ui/main/main.module.scss | 27 ---- src/views/home/ui/main/main.tsx | 10 +- src/widgets/footer-form/ui.tsx | 4 - 25 files changed, 421 insertions(+), 219 deletions(-) delete mode 100644 src/core/providers/index.ts delete mode 100644 src/entities/home/ConsultationOrder/index.ts delete mode 100644 src/entities/home/ConsultationOrder/ui.tsx create mode 100644 src/entities/home/callback-order/index.ts create mode 100644 src/entities/home/callback-order/styles.module.scss create mode 100644 src/entities/home/callback-order/ui.tsx create mode 100644 src/entities/home/consultation-modal/index.ts create mode 100644 src/entities/home/consultation-modal/styles.module.scss create mode 100644 src/entities/home/consultation-modal/ui.tsx create mode 100644 src/entities/home/consultation-order/index.ts create mode 100644 src/entities/home/consultation-order/ui.tsx create mode 100644 src/shared/ui/modal/close-icon.tsx create mode 100644 src/shared/ui/modal/modal-content.module.scss create mode 100644 src/shared/ui/modal/modal-content.tsx diff --git a/README.md b/README.md index 54662ec..6916a02 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + diff --git a/src/app/layout.tsx b/src/app/layout.tsx index ed599af..2628c05 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -3,6 +3,7 @@ import { Open_Sans } from 'next/font/google'; import '@core/styles/reset.scss'; import '@core/styles/globals.scss'; import { Toaster } from 'react-hot-toast'; +import { ModalProvider } from '@core/providers/modal-provider'; const openSans = Open_Sans({ subsets: ['cyrillic'], @@ -34,7 +35,7 @@ export default function RootLayout({ return ( - {children} + {children} diff --git a/src/core/providers/index.ts b/src/core/providers/index.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/entities/home/ConsultationOrder/index.ts b/src/entities/home/ConsultationOrder/index.ts deleted file mode 100644 index dac7ffd..0000000 --- a/src/entities/home/ConsultationOrder/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default as ConsultationOrder } from './ui'; diff --git a/src/entities/home/ConsultationOrder/ui.tsx b/src/entities/home/ConsultationOrder/ui.tsx deleted file mode 100644 index 5a410bb..0000000 --- a/src/entities/home/ConsultationOrder/ui.tsx +++ /dev/null @@ -1,13 +0,0 @@ -'use client'; -import { Button } from '@shared/ui'; -import toast from 'react-hot-toast'; - -export default function ConsultationOrder() { - const notify = () => toast.success('Заявка на консультацию принята'); - - return ( - - ); -} diff --git a/src/entities/home/callback-order/index.ts b/src/entities/home/callback-order/index.ts new file mode 100644 index 0000000..84a1b20 --- /dev/null +++ b/src/entities/home/callback-order/index.ts @@ -0,0 +1 @@ +export { CallbackOrder } from './ui'; diff --git a/src/entities/home/callback-order/styles.module.scss b/src/entities/home/callback-order/styles.module.scss new file mode 100644 index 0000000..5435b1a --- /dev/null +++ b/src/entities/home/callback-order/styles.module.scss @@ -0,0 +1,35 @@ +.Container { + display: none; + @include iftablet { + display: block; + height: min-content; + } +} + +.Btn { + @include iflaptop { + display: flex; + flex-direction: row; + justify-items: center; + align-items: center; + gap: rem(16px); + height: rem(40px); + padding: rem(20px)!important; + } + + @include ifdesktop { + gap: rem(16px); + height: rem(48px); + padding: rem(24px); + } + + img { + width: rem(30px); + height: rem(30px); + + @include ifdesktop { + width: rem(40px); + height: rem(40px); + } + } +} \ No newline at end of file diff --git a/src/entities/home/callback-order/ui.tsx b/src/entities/home/callback-order/ui.tsx new file mode 100644 index 0000000..aed940a --- /dev/null +++ b/src/entities/home/callback-order/ui.tsx @@ -0,0 +1,25 @@ +'use client'; + +import s from './styles.module.scss'; +import Image from 'next/image'; +import { Button } from '@shared/ui'; +import { useModal } from '@core/providers/modal-provider'; +import { ConsultationModal } from '@/entities/home/consultation-modal'; + +import callBtn from '@public/svg/phone-calling.svg'; + +function CallbackOrder() { + const modal = useModal(); + const openModal = () => modal.showModal(); + + return ( +
+ +
+ ); +} + +export { CallbackOrder }; diff --git a/src/entities/home/consultation-modal/index.ts b/src/entities/home/consultation-modal/index.ts new file mode 100644 index 0000000..e9f2654 --- /dev/null +++ b/src/entities/home/consultation-modal/index.ts @@ -0,0 +1 @@ +export { ConsultationModal } from './ui'; diff --git a/src/entities/home/consultation-modal/styles.module.scss b/src/entities/home/consultation-modal/styles.module.scss new file mode 100644 index 0000000..141e086 --- /dev/null +++ b/src/entities/home/consultation-modal/styles.module.scss @@ -0,0 +1,29 @@ +.Form { + display: flex; + flex-direction: column; + gap: rem(16px); + + @include iflaptop { + gap: rem(20px); + } +} + +.Title { + font-family: $font-open-sans; + font-weight: $font-medium; + font-size: rem(20px); + line-height: 130%; + color: $color-text; + + @include ifdesktop { + font-size: rem(24px); + } +} + +.Description { + font-family: $font-open-sans; + font-weight: $font-regular; + font-size: rem(16px); + line-height: 100%; + color: $color-text; +} \ No newline at end of file diff --git a/src/entities/home/consultation-modal/ui.tsx b/src/entities/home/consultation-modal/ui.tsx new file mode 100644 index 0000000..9a26d42 --- /dev/null +++ b/src/entities/home/consultation-modal/ui.tsx @@ -0,0 +1,137 @@ +import s from './styles.module.scss'; +import { Button, Input } from '@/shared/ui'; +import { PhoneInput, TextArea } 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'; +import { ModalContent } from '@shared/ui/modal/modal-content'; +import { useModal } from '@core/providers/modal-provider'; + +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; + +const defaultValues = { + name: '', + phone: '', + message: '', +}; + +type ConsultationModalProps = { + className?: string; +}; + +function ConsultationModal({}: ConsultationModalProps) { + const { + handleSubmit, + control, + reset, + clearErrors, + formState: { errors }, + } = useForm({ + resolver: zodResolver(FormSchema), + defaultValues, + }); + + const modal = useModal(); + + const onSubmit = async (data: TForm) => { + const payload = { + ...data, + form: 'consultation-modal-form', + }; + + try { + await sendFormFn(payload); + toast.success('Заявка на консультацию принята'); + } catch (e) { + toast.error('Ошибка при отправке заявки...', { + duration: 3000, + }); + } finally { + modal.hideModal(); + reset(defaultValues); + } + }; + + return ( + +
+

+ Мы подскажем, как решить ваши вопросы по пожарной безопасности. +

+ ( + { + clearErrors('name'); + field.onChange(e); + }} + error={errors && errors.name?.message} + /> + )} + /> + ( + { + clearErrors('phone'); + field.onChange(e); + }} + error={errors && errors.phone?.message} + /> + )} + /> +

Кратко опишите интересующий Вас вопрос

+ ( +