From 1ac07fe51abcc2a41d4d2fb741b7b304969040c4 Mon Sep 17 00:00:00 2001 From: zojgame Date: Wed, 3 Apr 2024 14:09:48 +0500 Subject: [PATCH] Refactoring --- src/Projects/MobileProjects.tsx | 2 +- src/app/page.tsx | 678 +----------------- src/components/AnalyzeUsers.tsx | 45 ++ .../{ => CalcRangeSlider}/CalcRangeSlider.css | 0 .../{ => CalcRangeSlider}/CalcRangeSlider.tsx | 0 src/components/ContactUs.tsx | 97 +++ .../{ => ContactsForm}/ContactsForm.css | 0 .../{ => ContactsForm}/ContactsForm.tsx | 16 +- .../{ => EffeciencyCalculator}/Calc.tsx | 10 +- .../{ => EffeciencyCalculator}/CalcSelect.tsx | 4 +- .../EffeciencyCalculator.tsx | 37 + src/components/{ => Examples}/ExampleCard.tsx | 0 src/components/Examples/Examples.tsx | 47 ++ src/components/ExcursionVR.tsx | 91 +++ src/components/{ => Features}/FeatureItem.tsx | 2 +- .../{ => Features}/FeatureVideoViewBox.tsx | 2 +- src/components/Features/Features.tsx | 66 ++ .../{ => Features}/VideoSliderMobile.tsx | 6 +- src/components/Footer.tsx | 55 ++ src/components/Header.tsx | 46 ++ src/components/Showreel.tsx | 54 ++ src/components/Stats.tsx | 99 +++ src/components/Stream/Stream.tsx | 85 +++ src/components/{ => Stream}/StreamButton.tsx | 6 +- src/components/icons/LoadingIcon.tsx | 28 + src/components/modals/FeedbackModal.tsx | 2 +- src/types/IconProps.ts | 5 + 27 files changed, 803 insertions(+), 680 deletions(-) create mode 100644 src/components/AnalyzeUsers.tsx rename src/components/{ => CalcRangeSlider}/CalcRangeSlider.css (100%) rename src/components/{ => CalcRangeSlider}/CalcRangeSlider.tsx (100%) create mode 100644 src/components/ContactUs.tsx rename src/components/{ => ContactsForm}/ContactsForm.css (100%) rename src/components/{ => ContactsForm}/ContactsForm.tsx (95%) rename src/components/{ => EffeciencyCalculator}/Calc.tsx (98%) rename src/components/{ => EffeciencyCalculator}/CalcSelect.tsx (96%) create mode 100644 src/components/EffeciencyCalculator/EffeciencyCalculator.tsx rename src/components/{ => Examples}/ExampleCard.tsx (100%) create mode 100644 src/components/Examples/Examples.tsx create mode 100644 src/components/ExcursionVR.tsx rename src/components/{ => Features}/FeatureItem.tsx (97%) rename src/components/{ => Features}/FeatureVideoViewBox.tsx (95%) create mode 100644 src/components/Features/Features.tsx rename src/components/{ => Features}/VideoSliderMobile.tsx (95%) create mode 100644 src/components/Footer.tsx create mode 100644 src/components/Header.tsx create mode 100644 src/components/Showreel.tsx create mode 100644 src/components/Stats.tsx create mode 100644 src/components/Stream/Stream.tsx rename src/components/{ => Stream}/StreamButton.tsx (94%) create mode 100644 src/components/icons/LoadingIcon.tsx create mode 100644 src/types/IconProps.ts diff --git a/src/Projects/MobileProjects.tsx b/src/Projects/MobileProjects.tsx index cf84f37..951702c 100644 --- a/src/Projects/MobileProjects.tsx +++ b/src/Projects/MobileProjects.tsx @@ -4,7 +4,7 @@ import ProjectCard from "@components/ProjectCard"; import { IProject } from "../types/IProject"; import { SortedProject } from "../types/SortedProject"; import LabelCard from "@components/LabelCart"; -import { getTime, getYear } from "date-fns"; +import { getYear } from "date-fns"; interface IProjectsProps { projects: IProject[]; diff --git a/src/app/page.tsx b/src/app/page.tsx index 50b518c..afe28f0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -4,682 +4,50 @@ import "react-rangeslider/lib/index.css"; import "../components/RangeSlider.css"; -import { useState } from "react"; -import FeatureItem from "@components/FeatureItem"; -import StreamButton from "@components/StreamButton"; -import ExampleCard from "@components/ExampleCard"; -import FeatureVideoViewBox from "@components/FeatureVideoViewBox"; -import Button from "@components/Button"; -import Calc from "@components/Calc"; -import Heading2 from "@components/Headings/Heading2"; -import VideoSliderMobile from "@components/VideoSliderMobile"; -import FeedbackForm from "@components/FeedbackForm"; -import useModalStore from "@stores/useModalStore"; -import FeedbackModal from "@components/modals/FeedbackModal"; import ModalContainer from "@components/ModalContainer"; -import MailIcon from "@components/icons/MailIcon"; -import PhoneIcon from "@components/icons/PhoneIcon"; -import VKIcon from "@components/icons/VKIcon"; -import YouTubeIcon from "@components/icons/YouTubeIcon"; -import TelegramIcon from "@components/icons/TelegramIcon"; import Winners from "@components/Winners"; -import { motion } from "framer-motion"; import Reviews from "@components/Reviews"; import Histories from "@components/Histories"; import Projects from "../Projects/Projects"; import Clients from "@components/Clients"; -import { videosFeatures } from "../consts/videoFeatures"; +import Examples from "@components/Examples/Examples"; +import Showreel from "@components/Showreel"; +import Stats from "@components/Stats"; +import Features from "@components/Features/Features"; +import Stream from "@components/Stream/Stream"; +import AnalyzeUsers from "@components/AnalyzeUsers"; +import ExcursionVR from "@components/ExcursionVR"; +import EffeciencyCalculator from "@components/EffeciencyCalculator/EffeciencyCalculator"; +import ContactUs from "@components/ContactUs"; +import Footer from "@components/Footer"; +import Header from "@components/Header"; export default function App() { - const [selectedVideo, setSelectedVideo] = useState( - "/videos/features/virtual_tour.mp4" - ); - - const [setModal] = useModalStore((state) => [state.setModal]); - - const [isBuffering, setIsBuffering] = useState(true); - const [isViewportEntered, setIsViewportEntered] = useState(false); - - const handleOnViewportFeatureEnter = () => { - if (isViewportEntered) return; - - setIsViewportEntered(true); - }; - return (
-
-
-
- - -
-
- +
- {/*
- - -
*/} -
-
- -
-

- Интерактивный инструмент -
- продаж{" "} - для застройщиков -

-

- Помогаем девелоперам эффективно демонстрировать свой объект. - Продавать больше и быстрее. -

-
- -
-
-
- -
-
+
-
- - Продавайте недвижимость -
- - проще и{" "} - - - быстрее - - - {" "} - дороже - -
- -
-

- Мы собрали статистику{" "} - за 13 лет{" "} - работы -
- с застройщиками,{" "} - - реализовав 31 проект - -

- -
- -
-
- -

- Graff.estate -

- -
-
-

На

-

- 18 - - % - -

-

- увеличивает конверсию из консультации в бронирование -

-
- -
-

На

-

- 12 - - % - -

-

- увеличивает конверсию из бронирования в продажу -

-
- -
-

До

-

- 2 - - раз - -

-

- сокращает время -
- реализации проекта -

-
- -
-

До

-

- 4 - - раз - -

-

- сокращает время на подготовку рекламных материалов -

-
-
-
- -
-
- - - - -
- -
- - - -
- -
- -
-
- - -
-
- - Функциональные -
- возможности -
-

- Интерактивная презентация увлекает покупателей и предоставляет - актуальную информацию о жилом комплексе, отвечая на все - вопросы и показывая важные особенности и преимущества объекта -

-
- -
- {videosFeatures.map((video) => ( - setSelectedVideo(video)} - /> - ))} -
-
- - -
+ + + - -
-
-
- - Graff.estate stream — -
- - удаленная -
- демонстрация -
- жилого комплекса -
-
- - - -
-
-
-

- Высокий уровень графики и полное погружение покупателя в - процесс выбора квартиры -

-

- Местоположение и устройство значения не имеют. Нужен только - интернет -

-
-
- -
- - - -
-
- -
- - - -
- -
- -
-
- -
-
-
- - Анализируем -
- - поведение -
- пользователей -
-
-

- Система внутренней аналитики программы собирает информацию о - поведении пользователя и эффективности работы менеджеров для - создания отчета, содержащего необходимые метрики -

-
-
-

- Полученный отчет позволяет сделать процесс демонстрации - жилого комплекса еще эффективнее -

-
-
-
- -
-

- Полученный отчет позволяет сделать процесс демонстрации - жилого комплекса еще эффективнее -

-
-
- -
-
-
- - Экскурсия -
- - в виртуальной -
- реальности -
-
- -
-
-

- Клиент полностью погружается в воссозданную реальность, - чувствует удобство и уровень комфорта -

-
-
-
-
-

- Достаточно надеть шлем виртуальной реальности, чтобы - прогуляться, оценить и ощутить пространство -

- -
- -
- -
- -
-

- Клиент полностью погружается -
- в воссозданную реальность, чувствует -
- удобство и уровень комфорта -

- -
-
- -
- -
-
- -
-
- - Оцените эффективность
- интерактивного -
- инструмента продаж -
-
-

- Мы изучили отраслевую аналитику на рынке продаж новых квартир - и на основе данных собрали калькулятор эффективности продукта -

-

- При использовании проектного финансирования, главное — это - время. Быстрее наполняются эскроу-счета — меньше процент за - использование заемных денег -

-
-
- - - -
- -
-
- + + + + - + {/* */} - -
-
-
-
-

- Свяжитесь -
с нами -

-

- Хотите увеличить конверсию? -
- Давайте обсудим детали! -

-
-
- -
- -
-
-
-
-
-

- Горячая линия -

-
-
- - - -
-
-

- Социальные -
- сети -

- -
-
-
-
-
- -
-
+
-
-
-
-
-
- -
-
-

- - Политика конфиденциальности - - {/* - graff.estate - */} -

-

- © 2023 GRAFF interactive. Все права защищены. -

-
-
- -
-
- -
- RU -
-
-
- -
-
- -
- UAE -
-
-
-
-
-
+
diff --git a/src/components/AnalyzeUsers.tsx b/src/components/AnalyzeUsers.tsx new file mode 100644 index 0000000..2a6491e --- /dev/null +++ b/src/components/AnalyzeUsers.tsx @@ -0,0 +1,45 @@ +import Heading2 from "./Headings/Heading2"; + +const AnalyzeUsers = () => { + return ( +
+
+
+ + Анализируем +
+ + поведение +
+ пользователей +
+
+

+ Система внутренней аналитики программы собирает информацию о + поведении пользователя и эффективности работы менеджеров для + создания отчета, содержащего необходимые метрики +

+
+
+

+ Полученный отчет позволяет сделать процесс демонстрации + жилого комплекса еще эффективнее +

+
+
+
+ +
+

+ Полученный отчет позволяет сделать процесс демонстрации + жилого комплекса еще эффективнее +

+
+
+ ); +}; + +export default AnalyzeUsers; diff --git a/src/components/CalcRangeSlider.css b/src/components/CalcRangeSlider/CalcRangeSlider.css similarity index 100% rename from src/components/CalcRangeSlider.css rename to src/components/CalcRangeSlider/CalcRangeSlider.css diff --git a/src/components/CalcRangeSlider.tsx b/src/components/CalcRangeSlider/CalcRangeSlider.tsx similarity index 100% rename from src/components/CalcRangeSlider.tsx rename to src/components/CalcRangeSlider/CalcRangeSlider.tsx diff --git a/src/components/ContactUs.tsx b/src/components/ContactUs.tsx new file mode 100644 index 0000000..3ada45c --- /dev/null +++ b/src/components/ContactUs.tsx @@ -0,0 +1,97 @@ +import FeedbackForm from "./FeedbackForm"; +import MailIcon from "./icons/MailIcon"; +import PhoneIcon from "./icons/PhoneIcon"; +import TelegramIcon from "./icons/TelegramIcon"; +import VKIcon from "./icons/VKIcon"; +import YouTubeIcon from "./icons/YouTubeIcon"; + +const ContactUs = () => { + return ( +
+
+
+
+

+ Свяжитесь +
с нами +

+

+ Хотите увеличить конверсию? +
+ Давайте обсудим детали! +

+
+
+ +
+ +
+
+
+
+
+

+ Горячая линия +

+
+
+ + + +
+
+

+ Социальные +
+ сети +

+ +
+
+
+
+
+ +
+
+ ); +}; + +export default ContactUs; diff --git a/src/components/ContactsForm.css b/src/components/ContactsForm/ContactsForm.css similarity index 100% rename from src/components/ContactsForm.css rename to src/components/ContactsForm/ContactsForm.css diff --git a/src/components/ContactsForm.tsx b/src/components/ContactsForm/ContactsForm.tsx similarity index 95% rename from src/components/ContactsForm.tsx rename to src/components/ContactsForm/ContactsForm.tsx index aa6b5e8..8e56a7f 100644 --- a/src/components/ContactsForm.tsx +++ b/src/components/ContactsForm/ContactsForm.tsx @@ -1,14 +1,14 @@ import { ChangeEvent, FormEvent, useState } from "react"; -import AsteriskIcon from "./icons/AsteriskIcon"; +import AsteriskIcon from "../icons/AsteriskIcon"; import InputMask from "react-input-mask"; import "./ContactsForm.css"; -import Button from "./Button"; -import SendIcon from "./icons/SendIcon"; -import LoaderIcon from "./icons/LoaderIcon"; -import api from "../utils/api"; -import CheckGradientIcon from "./icons/CheckGradientIcon"; -import useModalStore from "../stores/useModalStore"; -import Close2Icon from "./icons/Close2Icon"; +import Button from "../Button"; +import SendIcon from "../icons/SendIcon"; +import LoaderIcon from "../icons/LoaderIcon"; +import api from "../../utils/api"; +import CheckGradientIcon from "../icons/CheckGradientIcon"; +import useModalStore from "../../stores/useModalStore"; +import Close2Icon from "../icons/Close2Icon"; function ContactsForm() { const [name, setName] = useState(""); diff --git a/src/components/Calc.tsx b/src/components/EffeciencyCalculator/Calc.tsx similarity index 98% rename from src/components/Calc.tsx rename to src/components/EffeciencyCalculator/Calc.tsx index e9f7530..15c79da 100644 --- a/src/components/Calc.tsx +++ b/src/components/EffeciencyCalculator/Calc.tsx @@ -1,12 +1,12 @@ /* eslint-disable react-hooks/exhaustive-deps */ import Slider from "react-rangeslider"; -import Button from "./Button"; +import Button from "../Button"; import CalcSelect from "./CalcSelect"; -import ArrowRightIcon from "./icons/ArrowRightIcon"; -import regionsData from "../assets/regionsData.json"; +import ArrowRightIcon from "../icons/ArrowRightIcon"; +import regionsData from "../../assets/regionsData.json"; import { useEffect, useState } from "react"; -import CloseIcon from "./icons/CloseIcon"; -import api from "../utils/api"; +import CloseIcon from "../icons/CloseIcon"; +import api from "../../utils/api"; interface Region { id: number; diff --git a/src/components/CalcSelect.tsx b/src/components/EffeciencyCalculator/CalcSelect.tsx similarity index 96% rename from src/components/CalcSelect.tsx rename to src/components/EffeciencyCalculator/CalcSelect.tsx index 1fb8707..d74c535 100644 --- a/src/components/CalcSelect.tsx +++ b/src/components/EffeciencyCalculator/CalcSelect.tsx @@ -1,6 +1,6 @@ import { useRef, useState } from "react"; -import ChevronDown from "./icons/ChevronDown"; -import CheckIcon from "./icons/CheckIcon"; +import ChevronDown from "../icons/ChevronDown"; +import CheckIcon from "../icons/CheckIcon"; import { useOnClickOutside } from "usehooks-ts"; interface CalcSelectProps { diff --git a/src/components/EffeciencyCalculator/EffeciencyCalculator.tsx b/src/components/EffeciencyCalculator/EffeciencyCalculator.tsx new file mode 100644 index 0000000..0f13676 --- /dev/null +++ b/src/components/EffeciencyCalculator/EffeciencyCalculator.tsx @@ -0,0 +1,37 @@ +/* eslint-disable @next/next/no-img-element */ +import Calc from "@components/EffeciencyCalculator/Calc"; +import Heading2 from "@components/Headings/Heading2"; + +const EffeciencyCalculator = () => { + return ( +
+
+ + Оцените эффективность
+ интерактивного +
+ инструмента продаж +
+
+

+ Мы изучили отраслевую аналитику на рынке продаж новых квартир и на + основе данных собрали калькулятор эффективности продукта +

+

+ При использовании проектного финансирования, главное — это время. + Быстрее наполняются эскроу-счета — меньше процент за использование + заемных денег +

+
+
+ + + +
+ +
+
+ ); +}; + +export default EffeciencyCalculator; diff --git a/src/components/ExampleCard.tsx b/src/components/Examples/ExampleCard.tsx similarity index 100% rename from src/components/ExampleCard.tsx rename to src/components/Examples/ExampleCard.tsx diff --git a/src/components/Examples/Examples.tsx b/src/components/Examples/Examples.tsx new file mode 100644 index 0000000..f2fbc59 --- /dev/null +++ b/src/components/Examples/Examples.tsx @@ -0,0 +1,47 @@ +import ExampleCard from "./ExampleCard"; + +const Examples = () => { + return ( +
+
+ + + + +
+ +
+ + + +
+ +
+ +
+
+ ); +}; + +export default Examples; diff --git a/src/components/ExcursionVR.tsx b/src/components/ExcursionVR.tsx new file mode 100644 index 0000000..ac2e5f3 --- /dev/null +++ b/src/components/ExcursionVR.tsx @@ -0,0 +1,91 @@ +import useModalStore from "@stores/useModalStore"; +import Button from "./Button"; +import Heading2 from "./Headings/Heading2"; +import FeedbackModal from "./modals/FeedbackModal"; + +/* eslint-disable @next/next/no-img-element */ +const ExcursionVR = () => { + const [setModal] = useModalStore((state) => [state.setModal]); + + const handleBtnClick = () => setModal(); + + return ( +
+
+
+ + Экскурсия +
+ + в виртуальной +
+ реальности +
+
+ +
+
+

+ Клиент полностью погружается в воссозданную реальность, чувствует + удобство и уровень комфорта +

+
+
+
+
+

+ Достаточно надеть шлем виртуальной реальности, чтобы прогуляться, + оценить и ощутить пространство +

+ +
+ +
+ +
+ +
+

+ Клиент полностью погружается +
+ в воссозданную реальность, чувствует +
+ удобство и уровень комфорта +

+ +
+
+ +
+ +
+
+ ); +}; + +export default ExcursionVR; diff --git a/src/components/FeatureItem.tsx b/src/components/Features/FeatureItem.tsx similarity index 97% rename from src/components/FeatureItem.tsx rename to src/components/Features/FeatureItem.tsx index 3c0576b..74c958d 100644 --- a/src/components/FeatureItem.tsx +++ b/src/components/Features/FeatureItem.tsx @@ -1,5 +1,5 @@ /* eslint-disable @next/next/no-img-element */ -import ArrowIcon from "./icons/ArrowIcon"; +import ArrowIcon from "../icons/ArrowIcon"; interface FeatureItemProps { title: string; diff --git a/src/components/FeatureVideoViewBox.tsx b/src/components/Features/FeatureVideoViewBox.tsx similarity index 95% rename from src/components/FeatureVideoViewBox.tsx rename to src/components/Features/FeatureVideoViewBox.tsx index 485a542..21fce6e 100644 --- a/src/components/FeatureVideoViewBox.tsx +++ b/src/components/Features/FeatureVideoViewBox.tsx @@ -1,5 +1,5 @@ import { useRef } from "react"; -import { Video } from "../types/Video"; +import { Video } from "../../types/Video"; interface FeatureVideoViewBoxProps { selectedVideo: string; diff --git a/src/components/Features/Features.tsx b/src/components/Features/Features.tsx new file mode 100644 index 0000000..6f3f4dd --- /dev/null +++ b/src/components/Features/Features.tsx @@ -0,0 +1,66 @@ +import { useState } from "react"; +import { motion } from "framer-motion"; +import FeatureItem from "@components/Features/FeatureItem"; +import FeatureVideoViewBox from "@components/Features/FeatureVideoViewBox"; +import Heading2 from "@components/Headings/Heading2"; +import VideoSliderMobile from "@components/Features/VideoSliderMobile"; +import { videosFeatures } from "../../consts/videoFeatures"; + +const Features = () => { + const [selectedVideo, setSelectedVideo] = useState( + "/videos/features/virtual_tour.mp4" + ); + const [isViewportEntered, setIsViewportEntered] = useState(false); + + const handleOnViewportFeatureEnter = () => { + if (isViewportEntered) return; + + setIsViewportEntered(true); + }; + + return ( + +
+
+ + Функциональные +
+ возможности +
+

+ Интерактивная презентация увлекает покупателей и предоставляет + актуальную информацию о жилом комплексе, отвечая на все вопросы + и показывая важные особенности и преимущества объекта +

+
+ +
+ {videosFeatures.map((video) => ( + setSelectedVideo(video)} + /> + ))} +
+
+ + +
+ ); +}; + +export default Features; diff --git a/src/components/VideoSliderMobile.tsx b/src/components/Features/VideoSliderMobile.tsx similarity index 95% rename from src/components/VideoSliderMobile.tsx rename to src/components/Features/VideoSliderMobile.tsx index 0b4c23c..8d919e8 100644 --- a/src/components/VideoSliderMobile.tsx +++ b/src/components/Features/VideoSliderMobile.tsx @@ -2,10 +2,10 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { motion } from "framer-motion"; import { useEffect, useRef, useState } from "react"; -import ArrowLeftIcon from "./icons/ArrowLeftIcon"; -import ArrowRightIcon from "./icons/ArrowRightIcon"; +import ArrowLeftIcon from "../icons/ArrowLeftIcon"; +import ArrowRightIcon from "../icons/ArrowRightIcon"; import { useSwipeable } from "react-swipeable"; -import { Video } from "../types/Video"; +import { Video } from "../../types/Video"; interface IVideoSliderMobile { isViewportEntered: boolean; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx new file mode 100644 index 0000000..f2b19f1 --- /dev/null +++ b/src/components/Footer.tsx @@ -0,0 +1,55 @@ +/* eslint-disable @next/next/no-img-element */ +const Footer = () => { + return ( +
+
+
+
+
+ +
+
+

+ + Политика конфиденциальности + + {/* + graff.estate + */} +

+

+ © 2023 GRAFF interactive. Все права защищены. +

+
+
+ +
+
+ +
+ RU +
+
+
+ +
+
+ +
+ UAE +
+
+
+
+
+
+ ); +}; + +export default Footer; diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..0d41fe3 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,46 @@ +/* eslint-disable react/jsx-no-undef */ + +import useModalStore from "@stores/useModalStore"; +import Button from "./Button"; +import FeedbackModal from "./modals/FeedbackModal"; + +/* eslint-disable @next/next/no-img-element */ +const Header = () => { + const [setModal] = useModalStore((state) => [state.setModal]); + const handleOnBtnClick = () => setModal(); + return ( +
+
+
+ + +
+
+ + + {/*
+ + +
*/} +
+
+
+ ); +}; + +export default Header; diff --git a/src/components/Showreel.tsx b/src/components/Showreel.tsx new file mode 100644 index 0000000..5fa223f --- /dev/null +++ b/src/components/Showreel.tsx @@ -0,0 +1,54 @@ +import { useState } from "react"; +import LoadingIcon from "./icons/LoadingIcon"; + +const Showreel = () => { + const [isBuffering, setIsBuffering] = useState(true); + + const handleOnPlaying = () => setIsBuffering(false); + const handleOnWaiting = () => setIsBuffering(true); + return ( + <> +
+

+ Интерактивный инструмент +
+ продаж для застройщиков +

+

+ Помогаем девелоперам эффективно демонстрировать свой объект. Продавать + больше и быстрее. +

+
+ +
+
+
+
+ + ); +}; + +export default Showreel; diff --git a/src/components/Stats.tsx b/src/components/Stats.tsx new file mode 100644 index 0000000..55e8c94 --- /dev/null +++ b/src/components/Stats.tsx @@ -0,0 +1,99 @@ +/* eslint-disable @next/next/no-img-element */ +import Heading2 from "./Headings/Heading2"; + +const Stats = () => { + return ( +
+ + Продавайте недвижимость +
+ + проще и{" "} + + быстрее + + {" "} + дороже + +
+ +
+

+ Мы собрали статистику{" "} + за 13 лет работы +
+ с застройщиками,{" "} + + реализовав 31 проект + +

+ +
+ +
+
+ +

+ Graff.estate +

+ +
+
+

На

+

+ 18 + + % + +

+

+ увеличивает конверсию из консультации в бронирование +

+
+ +
+

На

+

+ 12 + + % + +

+

+ увеличивает конверсию из бронирования в продажу +

+
+ +
+

До

+

+ 2 + + раз + +

+

+ сокращает время +
+ реализации проекта +

+
+ +
+

До

+

+ 4 + + раз + +

+

+ сокращает время на подготовку рекламных материалов +

+
+
+
+ ); +}; + +export default Stats; diff --git a/src/components/Stream/Stream.tsx b/src/components/Stream/Stream.tsx new file mode 100644 index 0000000..2e3bf6b --- /dev/null +++ b/src/components/Stream/Stream.tsx @@ -0,0 +1,85 @@ +/* eslint-disable @next/next/no-img-element */ +import Button from "../Button"; +import Heading2 from "../Headings/Heading2"; +import StreamButton from "./StreamButton"; + +const Stream = () => { + return ( +
+
+
+ + Graff.estate stream — +
+ + удаленная +
+ демонстрация +
+ жилого комплекса +
+
+ + + +
+
+
+

+ Высокий уровень графики и полное погружение покупателя в процесс + выбора квартиры +

+

+ Местоположение и устройство значения не имеют. Нужен только + интернет +

+
+
+ +
+ + + +
+
+ +
+ + + +
+ +
+ +
+
+ ); +}; + +export default Stream; diff --git a/src/components/StreamButton.tsx b/src/components/Stream/StreamButton.tsx similarity index 94% rename from src/components/StreamButton.tsx rename to src/components/Stream/StreamButton.tsx index 82794c5..8f7ff0a 100644 --- a/src/components/StreamButton.tsx +++ b/src/components/Stream/StreamButton.tsx @@ -1,7 +1,7 @@ /* eslint-disable @next/next/no-img-element */ -import Button from "./Button"; -import ArrowIcon from "./icons/ArrowIcon"; -import ArrowRightIcon from "./icons/ArrowRightIcon"; +import Button from "../Button"; +import ArrowIcon from "../icons/ArrowIcon"; +import ArrowRightIcon from "../icons/ArrowRightIcon"; interface StreamButton { icon: string; diff --git a/src/components/icons/LoadingIcon.tsx b/src/components/icons/LoadingIcon.tsx new file mode 100644 index 0000000..5aa955c --- /dev/null +++ b/src/components/icons/LoadingIcon.tsx @@ -0,0 +1,28 @@ +import { IIconProps } from "../../types/IconProps"; + +const LoadingIcon = ({ className }: IIconProps) => { + return ( + + + + + ); +}; + +export default LoadingIcon; diff --git a/src/components/modals/FeedbackModal.tsx b/src/components/modals/FeedbackModal.tsx index 8ce5bf9..010909a 100644 --- a/src/components/modals/FeedbackModal.tsx +++ b/src/components/modals/FeedbackModal.tsx @@ -1,4 +1,4 @@ -import ContactsForm from "../ContactsForm"; +import ContactsForm from "../ContactsForm/ContactsForm"; function FeedbackModal() { return ( diff --git a/src/types/IconProps.ts b/src/types/IconProps.ts new file mode 100644 index 0000000..f32b731 --- /dev/null +++ b/src/types/IconProps.ts @@ -0,0 +1,5 @@ +interface IIconProps { + className?: string; +} + +export type { IIconProps };