Refactoring

This commit is contained in:
2024-04-03 14:09:48 +05:00
parent 4300cdfe91
commit 1ac07fe51a
27 changed files with 803 additions and 680 deletions
+1 -1
View File
@@ -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[];
+23 -655
View File
@@ -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<string>(
"/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 (
<div>
<div className="min-h-screen 2xl:px-10 xl:px-8 sm:px-6 px-4 overflow-x-clip">
<div className="relative container mx-auto 2xl:max-w-screen-2xl">
<div className="flex justify-between py-6 2xl:mb-28 xl:mb-[88px] sm:mb-12 mb-14">
<div>
<img
src="/images/Logo.svg"
alt=""
className="sm:block hidden max-h-fit"
/>
<img
src="/images/LogoMobile.svg"
alt=""
className="sm:hidden block"
/>
</div>
<div className="flex sm:gap-8 gap-2">
<Button onClick={() => setModal(<FeedbackModal />)}>
<span className="sm:inline hidden">Оставить заявку</span>
<span className="sm:hidden inline">Связаться</span>
</Button>
<Header />
{/* <div className="flex gap-1">
<button className="px-3 border-gradient rounded-full font-gilroy font-medium h-10 flex items-center justify-center w-12">
<span className="absolute">RU</span>
</button>
<button className="px-3 rounded-full font-gilroy font-medium leading-none h-10 flex items-center justify-center w-12">
<span className="absolute">EN</span>
</button>
</div> */}
</div>
</div>
<div className="flex flex-col 2xl:gap-14 gap-6 2xl:mb-[120px] xl:mb-20 sm:mb-12 mb-8">
<h1 className="max-w-[1255px] font-gilroy 2xl:text-8xl sm:text-[64px] text-[40px] leading-none text-gradient font-medium">
Интерактивный инструмент
<br />
продаж{" "}
<span className="text-gradient-none">для застройщиков</span>
</h1>
<p className="xl:text-xl text-base font-gilroy max-w-[650px] font-medium leading-[120%]">
Помогаем девелоперам эффективно демонстрировать свой объект.
Продавать больше и быстрее.
</p>
<div className="absolute top-20 right-0 blur-[10px] -z-10">
<img src="/images/blendings/1.svg" alt="" />
</div>
</div>
</div>
<div className="relative aspect-video w-full 2xl:mb-[200px] sm:mb-[120px] mb-20 overflow-x-clip">
<video
src="/videos/showreel_1080p_4000k_h264.mp4"
muted
autoPlay
loop
playsInline
className="absolute aspect-video w-full"
onPlaying={() => setIsBuffering(false)}
onWaiting={() => setIsBuffering(true)}
/>
<div
className={`absolute aspect-video w-full h-full flex justify-center items-center bg-black bg-opacity-50 transition-opacity ${
isBuffering ? "opacity-100" : "opacity-0"
}`}
>
<div className="flex gap-4 items-center">
<span>
<svg
className="animate-spin h-5 w-5"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</span>
<span className="font-gilroy">Загружаем шоурил...</span>
</div>
</div>
</div>
<Showreel />
<div className="relative container mx-auto 2xl:max-w-screen-2xl">
<div className="flex flex-col 2xl:gap-16 xl:gap-10 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<Heading2>
Продавайте недвижимость
<br />
<span className="text-gradient-none">
проще и{" "}
<span className="relative">
<span style={{ WebkitTextFillColor: "#52587A" }}>
быстрее
</span>
<span className="absolute top-[55%] -left-[2.5%] 2xl:h-1.5 h-1 w-[105%] bg-white"></span>
</span>{" "}
дороже
</span>
</Heading2>
<div className="relative xl:flex items-center gap-4 xl:max-h-[400px]">
<p className="2xl:text-2xl sm:text-xl font-gilroy min-w-fit">
Мы собрали статистику{" "}
<span className="text-gradient font-semibold">за 13 лет</span>{" "}
работы
<br />
с застройщиками,{" "}
<span className="text-gradient font-semibold">
реализовав 31 проект
</span>
</p>
<div className="2xl:ml-6 xl:ml-[14px] relative 2xl:-top-8 xl:-top-4 -z-10">
<img src="/images/Map.png" alt="" />
</div>
</div>
<p className="2xl:text-[64px] xl:text-5xl text-[40px] text-gradient font-gilroy font-medium w-fit leading-none">
Graff.estate
</p>
<div className="grid xl:grid-cols-4 sm:grid-cols-2 grid-cols-1 xl:gap-0 gap-3">
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">На</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
18
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
%
</span>
</p>
<p className="2xl:text-base text-sm">
увеличивает конверсию из консультации в бронирование
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">На</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
12
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
%
</span>
</p>
<p className="2xl:text-base text-sm">
увеличивает конверсию из бронирования в продажу
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">До</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
2
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
раз
</span>
</p>
<p className="2xl:text-base text-sm">
сокращает время
<br />
реализации проекта
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">До</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
4
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
раз
</span>
</p>
<p className="2xl:text-base text-sm">
сокращает время на подготовку рекламных материалов
</p>
</div>
</div>
</div>
<div className="relative sm:grid grid-cols-2 xl:gap-x-8 sm:gap-x-6 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div>
<ExampleCard
title="ЖК «Upside Towers»"
company="Upside Development"
image="/images/examples/5.jpg"
/>
<ExampleCard
title="ЖК «Life Резиденция»"
company="ГК Паритет Девелопмент"
image="/images/examples/1.jpg"
/>
<ExampleCard
title="ЖК «Айвазовский City»"
company="ЭНКО"
image="/images/examples/3.jpg"
/>
</div>
<div className="2xl:mt-[220px] xl:mt-40 sm:mt-[104px]">
<ExampleCard
title="Авторский квартал Машаров"
company="Сибинтел Девелопмент"
image="/images/examples/2.jpg"
/>
<ExampleCard
title="ЖК «Сюжеты»"
company="Fortis Development"
image="/images/examples/4.jpg"
className="xl:mb-[0px] sm:mb-[0px] mb-[0px]"
/>
</div>
<div className="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%] scale-150 -z-10 blur-[44px]">
<img src="/images/blendings/2.svg" alt="" />
</div>
</div>
<motion.div
className="xl:grid flex flex-col grid-cols-2 xl:gap-4 sm:gap-10 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20"
viewport={{ margin: "-10%" }}
onViewportEnter={handleOnViewportFeatureEnter}
>
<div className="flex flex-col gap-20">
<div className="xl:flex flex-col grid sm:grid-cols-2 xl:gap-8 gap-3">
<Heading2>
Функциональные
<br />
<span className="text-gradient-none">возможности</span>
</Heading2>
<p className="xl:w-2/3 xl:text-base text-sm">
Интерактивная презентация увлекает покупателей и предоставляет
актуальную информацию о жилом комплексе, отвечая на все
вопросы и показывая важные особенности и преимущества объекта
</p>
</div>
<div className="pr-6 xl:block hidden">
{videosFeatures.map((video) => (
<FeatureItem
key={video.id}
title={video.title}
desc={video.desc}
video={video.value}
handleHoverStart={(video) => setSelectedVideo(video)}
/>
))}
</div>
</div>
<FeatureVideoViewBox
isViewportEntered={isViewportEntered}
selectedVideo={selectedVideo}
videos={videosFeatures}
/>
<VideoSliderMobile
isViewportEntered={isViewportEntered}
videos={videosFeatures}
/>
</motion.div>
<Stats />
<Examples />
<Features />
<Histories />
<div className="relative 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="grid sm:grid-cols-2 sm:gap-4 gap-6 2xl:mb-16 xl:mb-10 sm:mb-12 mb-8">
<div className="flex flex-col gap-8 justify-between">
<Heading2>
Graff.estate stream 
<br />
<span className="text-gradient-none">
удаленная
<br />
демонстрация
<br />
жилого комплекса
</span>
</Heading2>
<a
href="https://stream.graff.tech"
target="_blank"
className="w-fit sm:inline-block hidden"
>
<Button>Узнать больше</Button>
</a>
</div>
<div className="flex flex-col xl:gap-16 gap-6">
<div className="grid xl:grid-cols-2 xl:gap-4 gap-2">
<p className="2xl:text-base text-sm">
Высокий уровень графики и полное погружение покупателя в
процесс выбора квартиры
</p>
<p className="2xl:text-base text-sm">
Местоположение и устройство значения не имеют. Нужен только
интернет
</p>
</div>
<div className="xl:grid grid-cols-2 gap-4">
<img src="/images/Datamining.jpg" alt="" className="w-full" />
</div>
<a
href="https://stream.graff.tech"
target="_blank"
className="w-fit sm:hidden inline-block"
>
<Button>Узнать больше</Button>
</a>
</div>
</div>
<div className="border-t border-[#3D425C]">
<StreamButton
icon="/icons/Revolution.svg"
title="МФК «Re:volution towers»"
location="Россия, Екатеринбург"
background="/images/stream/nks.jpg"
link="https://stream.graff.tech/?build=nksJukovaDev&location=a1"
/>
<StreamButton
icon="/icons/Residence.svg"
title="ЖК «Life Резиденция»"
location="Россия, Тюмень"
background="/images/stream/liferes.jpg"
link="https://stream.graff.tech/?build=lifeResidence&location=a1"
/>
<StreamButton
icon="/icons/Aivaz.svg"
title="ЖК «Айвазовский City»"
location="Россия, Тюмень"
background="/images/stream/aivaz.jpg"
link="https://stream.graff.tech/?build=IvazowskyDev&location=a1"
/>
</div>
<div className="absolute -top-36 left-0 -z-10 blur-[20px]">
<img src="/images/blendings/3.svg" alt="" />
</div>
</div>
<div className="grid sm:grid-cols-2 xl:gap-4 sm:gap-3 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col justify-between">
<div className="flex flex-col xl:gap-8 sm:gap-6 gap-4">
<Heading2>
Анализируем
<br />
<span className="text-gradient-none">
поведение
<br />
пользователей
</span>
</Heading2>
<p className="xl:w-2/3 2xl:text-base text-sm">
Система внутренней аналитики программы собирает информацию о
поведении пользователя и эффективности работы менеджеров для
создания отчета, содержащего необходимые метрики
</p>
</div>
<div className="sm:block hidden xl:pb-8 pb-6 border-b border-[#3D425C] -mt-0.5">
<p className="xl:w-4/5 2xl:text-xl font-gilroy font-medium 2xl:leading-[120%]">
Полученный отчет позволяет сделать процесс демонстрации
жилого комплекса еще эффективнее
</p>
</div>
</div>
<div
className="w-full 2xl:min-h-[600px] xl:min-h-[500px] min-h-[384px] bg-cover bg-center bg-no-repeat"
style={{ backgroundImage: "url('/images/Analysis.jpg')" }}
></div>
<div className="sm:hidden block xl:pb-8 pb-6 border-b border-[#3D425C] -mt-0.5">
<p className="xl:w-4/5 2xl:text-xl text-base font-gilroy font-medium leading-[120%]">
Полученный отчет позволяет сделать процесс демонстрации
жилого комплекса еще эффективнее
</p>
</div>
</div>
<div className="relative grid sm:grid-cols-2 2xl:gap-4 xl:gap-10 sm:gap-3 gap-4 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col justify-between">
<div className="flex flex-col gap-8">
<Heading2>
Экскурсия
<br />
<span className="text-gradient-none">
в виртуальной
<br />
реальности
</span>
</Heading2>
<Button
className="sm:block hidden"
onClick={() => setModal(<FeedbackModal />)}
>
Записаться в шоу-рум
</Button>
</div>
<div className="xl:block hidden pb-8 border-b border-[#3D425C]">
<p className="font-gilroy 2xl:text-xl 2xl:leading-[120%]">
Клиент полностью погружается в воссозданную реальность,
чувствует удобство и уровень комфорта
</p>
</div>
</div>
<div className="flex flex-col gap-10">
<div className="grid xl:grid-cols-2 xl:gap-4 gap-6">
<p className="2xl:text-base text-sm">
Достаточно надеть шлем виртуальной реальности, чтобы
прогуляться, оценить и ощутить пространство
</p>
<img
src="/images/VR.png"
alt=""
className="sm:px-6 sm:pt-8 sm:pb-5 p-4 pb-2 border-t border-[#3D425C] w-full"
/>
</div>
<video
src="/videos/vr.mp4"
muted
autoPlay
loop
playsInline
className="xl:block hidden"
></video>
</div>
<div className="col-span-full sm:mt-8 mt-4 flex flex-col sm:gap-12 gap-8">
<video
src="/videos/vr.mp4"
muted
autoPlay
loop
playsInline
className="xl:hidden block"
></video>
<div className="xl:hidden flex border-b border-[#3D425C] sm:pb-10 pb-6 flex-col gap-8">
<p className="font-gilroy font-medium leading-[120%] xl:hidden block">
Клиент полностью погружается
<br />
в воссозданную реальность, чувствует
<br />
удобство и уровень комфорта
</p>
<Button
className="sm:hidden inline-block"
onClick={() => setModal(<FeedbackModal />)}
>
Записаться в шоу-рум
</Button>
</div>
</div>
<div className="absolute -top-[50%] left-[16%] blur-[20px] -z-10">
<img src="/images/blendings/4.svg" alt="" />
</div>
</div>
<div className="relative flex flex-col 2xl:gap-16 xl:gap-10 sm:gap-12 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col sm:gap-8 gap-6">
<Heading2>
Оцените эффективность <br className="xl:hidden block" />
интерактивного
<br />
<span className="text-gradient-none">инструмента продаж</span>
</Heading2>
<div className="grid sm:grid-cols-2 xl:gap-4 sm:gap-3 gap-2">
<p className="xl:w-2/3 2xl:text-base text-sm">
Мы изучили отраслевую аналитику на рынке продаж новых квартир
и на основе данных собрали калькулятор эффективности продукта
</p>
<p className="xl:w-2/3 2xl:text-base text-sm">
При использовании проектного финансирования, главное это
время. Быстрее наполняются эскроу-счета меньше процент за
использование заемных денег
</p>
</div>
</div>
<Calc />
<div className="absolute -top-16 right-0 blur-[18px] -z-10">
<img src="/images/blendings/5.svg" alt="" />
</div>
</div>
<Stream />
<AnalyzeUsers />
<ExcursionVR />
<EffeciencyCalculator />
<Winners />
<Reviews />
{/* <Reviews /> */}
<Projects />
<Clients />
<div className="relative overflow-hidden pb-[50px]">
<div className="grid lg:grid-cols-4 grid-cols-1 lg:gap-4 gap-6">
<div className="col-span-1">
<div className="grid lg:grid-cols-1 sm:grid-cols-2 lg:gap-6 gap-4">
<p className="2xl:text-[64px] xl:text-5xl text-[40px] font-gilroy text-gradient font-medium w-fit leading-none">
Свяжитесь
<br />с нами
</p>
<p className="2xl:text-xl lg:text-lg font-gilroy font-semibold leading-tight">
Хотите увеличить конверсию?
<br />
Давайте обсудим детали!
</p>
</div>
</div>
<div className="lg:col-span-3">
<FeedbackForm />
</div>
</div>
<div className="mt-[104px] relative">
<div className="relative grid lg:grid-cols-4 gap-4">
<div className="flex gap-4">
<p className="2xl:text-xl font-gilroy font-semibold">
Горячая линия
</p>
<div className="w-full h-px bg-[#3D425C]"></div>
</div>
<div className="space-y-2 2xl:pr-4 xl:pr-2">
<a
href="mailto:info@graff.tech"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
>
<span>Написать</span>
<MailIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</a>
<a
href="tel:88007700067"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
>
<span>Позвонить</span>
<PhoneIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</a>
</div>
<div className="sm:col-span-2 flex sm:justify-end lg:mt-0 mt-10">
<div className="lg:w-auto sm:w-1/2 w-full flex justify-between 2xl:gap-8 lg:gap-6 gap-4">
<p className="2xl:text-xl font-gilroy font-semibold 2xl:-mt-1.5 -mt-1">
Социальные
<br />
сети
</p>
<div className="flex gap-2 h-fit">
<a
href="https://www.youtube.com/@GRAFFtech"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
>
<YouTubeIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://vk.com/graff.interactive"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
>
<VKIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://t.me/GRAFFinteractive"
target="_blank"
className="border rounded-full border-[#52587A] xl:p-4 p-3 opacity-80 hover:opacity-100 transition-all"
>
<TelegramIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
</div>
</div>
</div>
</div>
</div>
<div className="absolute top-[65%] left-[26%] -z-10 blur-[10px]">
<img src="/images/blendings/7.svg" alt="" />
</div>
</div>
<ContactUs />
</div>
</div>
<div className=" border-t border-[#3D425C] text-sm">
<div className="container mx-auto xl:px-8 max-w-[1600px]">
<div className="grid lg:grid-cols-4">
<div className="sm:col-span-2 lg:order-none order-last py-6 xl:px-0 px-6 flex sm:flex-row flex-col sm:gap-6 gap-4 lg:border-t-0 border-t border-[#3D425C]">
<div>
<img src="/images/Logo.svg" alt="" className="max-h-fit" />
</div>
<div className="flex flex-col sm:gap-1 gap-4">
<p className="flex sm:flex-row flex-col sm:gap-4 gap-1">
<a href="https://graff.tech/privacypolicy" target="_blank">
Политика конфиденциальности
</a>
{/* <a href="https://graff.estate" className="">
graff.estate
</a> */}
</p>
<p className="text-xs text-[#C5C7CE]">
© 2023 GRAFF interactive. Все права защищены.
</p>
</div>
</div>
<div className="col-span-1 lg:border-l sm:border-b-0 border-b border-[#3D425C] xl:px-8 sm:px-6 px-4 py-6 flex flex-col justify-center">
<div className="flex justify-between items-center">
<div className="text-[#EBEBEB] flex flex-col gap-1">
<a href="mailto:info@graff.tech">info@graff.tech</a>
<a href="tel:88007700067">8 800 770 00 67</a>
</div>
<div className="w-12 h-12 border border-[#3D425C] rounded-full flex justify-center items-center">
RU
</div>
</div>
</div>
<div className="col-span-1 sm:border-l border-[#3D425C] xl:pl-8 xl:pr-0 sm:px-6 px-4 py-6 flex flex-col justify-center">
<div className="flex justify-between items-center">
<div className="text-[#EBEBEB] flex flex-col gap-1">
<a href="mailto:waseem@graff.tech">waseem@graff.tech</a>
<a href="tel:+971509388902">+971 50 938 8902</a>
</div>
<div className="w-12 h-12 border border-[#3D425C] rounded-full flex justify-center items-center">
UAE
</div>
</div>
</div>
</div>
</div>
</div>
<Footer />
<ModalContainer />
</div>
+45
View File
@@ -0,0 +1,45 @@
import Heading2 from "./Headings/Heading2";
const AnalyzeUsers = () => {
return (
<div className="grid sm:grid-cols-2 xl:gap-4 sm:gap-3 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col justify-between">
<div className="flex flex-col xl:gap-8 sm:gap-6 gap-4">
<Heading2>
Анализируем
<br />
<span className="text-gradient-none">
поведение
<br />
пользователей
</span>
</Heading2>
<p className="xl:w-2/3 2xl:text-base text-sm">
Система внутренней аналитики программы собирает информацию о
поведении пользователя и эффективности работы менеджеров для
создания отчета, содержащего необходимые метрики
</p>
</div>
<div className="sm:block hidden xl:pb-8 pb-6 border-b border-[#3D425C] -mt-0.5">
<p className="xl:w-4/5 2xl:text-xl font-gilroy font-medium 2xl:leading-[120%]">
Полученный отчет позволяет сделать процесс демонстрации
жилого комплекса еще эффективнее
</p>
</div>
</div>
<div
className="w-full 2xl:min-h-[600px] xl:min-h-[500px] min-h-[384px] bg-cover bg-center bg-no-repeat"
style={{ backgroundImage: "url('/images/Analysis.jpg')" }}
></div>
<div className="sm:hidden block xl:pb-8 pb-6 border-b border-[#3D425C] -mt-0.5">
<p className="xl:w-4/5 2xl:text-xl text-base font-gilroy font-medium leading-[120%]">
Полученный отчет позволяет сделать процесс демонстрации
жилого комплекса еще эффективнее
</p>
</div>
</div>
);
};
export default AnalyzeUsers;
+97
View File
@@ -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 (
<div className="relative overflow-hidden pb-[50px]">
<div className="grid lg:grid-cols-4 grid-cols-1 lg:gap-4 gap-6">
<div className="col-span-1">
<div className="grid lg:grid-cols-1 sm:grid-cols-2 lg:gap-6 gap-4">
<p className="2xl:text-[64px] xl:text-5xl text-[40px] font-gilroy text-gradient font-medium w-fit leading-none">
Свяжитесь
<br />с нами
</p>
<p className="2xl:text-xl lg:text-lg font-gilroy font-semibold leading-tight">
Хотите увеличить конверсию?
<br />
Давайте обсудим детали!
</p>
</div>
</div>
<div className="lg:col-span-3">
<FeedbackForm />
</div>
</div>
<div className="mt-[104px] relative">
<div className="relative grid lg:grid-cols-4 gap-4">
<div className="flex gap-4">
<p className="2xl:text-xl font-gilroy font-semibold">
Горячая линия
</p>
<div className="w-full h-px bg-[#3D425C]"></div>
</div>
<div className="space-y-2 2xl:pr-4 xl:pr-2">
<a
href="mailto:info@graff.tech"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
>
<span>Написать</span>
<MailIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</a>
<a
href="tel:88007700067"
className="2xl:h-16 h-14 px-6 py-4 2xl:text-base text-sm border rounded-full font-medium flex justify-between items-center w-full border-[#52587A] opacity-80 hover:opacity-100 transition-all"
>
<span>Позвонить</span>
<PhoneIcon className="lg:w-8 lg:h-8 w-6 h-6" />
</a>
</div>
<div className="sm:col-span-2 flex sm:justify-end lg:mt-0 mt-10">
<div className="lg:w-auto sm:w-1/2 w-full flex justify-between 2xl:gap-8 lg:gap-6 gap-4">
<p className="2xl:text-xl font-gilroy font-semibold 2xl:-mt-1.5 -mt-1">
Социальные
<br />
сети
</p>
<div className="flex gap-2 h-fit">
<a
href="https://www.youtube.com/@GRAFFtech"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
>
<YouTubeIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://vk.com/graff.interactive"
target="_blank"
className="group border border-[#3D425C] xl:p-4 p-3 rounded-full hover:border-[#52587A] transition-all"
>
<VKIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
<a
href="https://t.me/GRAFFinteractive"
target="_blank"
className="border rounded-full border-[#52587A] xl:p-4 p-3 opacity-80 hover:opacity-100 transition-all"
>
<TelegramIcon className="2xl:w-8 2xl:h-8 w-6 h-6" />
</a>
</div>
</div>
</div>
</div>
</div>
<div className="absolute top-[65%] left-[26%] -z-10 blur-[10px]">
<img src="/images/blendings/7.svg" alt="" />
</div>
</div>
);
};
export default ContactUs;
@@ -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<string>("");
@@ -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;
@@ -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 {
@@ -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 (
<div className="relative flex flex-col 2xl:gap-16 xl:gap-10 sm:gap-12 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col sm:gap-8 gap-6">
<Heading2>
Оцените эффективность <br className="xl:hidden block" />
интерактивного
<br />
<span className="text-gradient-none">инструмента продаж</span>
</Heading2>
<div className="grid sm:grid-cols-2 xl:gap-4 sm:gap-3 gap-2">
<p className="xl:w-2/3 2xl:text-base text-sm">
Мы изучили отраслевую аналитику на рынке продаж новых квартир и на
основе данных собрали калькулятор эффективности продукта
</p>
<p className="xl:w-2/3 2xl:text-base text-sm">
При использовании проектного финансирования, главное это время.
Быстрее наполняются эскроу-счета меньше процент за использование
заемных денег
</p>
</div>
</div>
<Calc />
<div className="absolute -top-16 right-0 blur-[18px] -z-10">
<img src="/images/blendings/5.svg" alt="" />
</div>
</div>
);
};
export default EffeciencyCalculator;
+47
View File
@@ -0,0 +1,47 @@
import ExampleCard from "./ExampleCard";
const Examples = () => {
return (
<div className="relative sm:grid grid-cols-2 xl:gap-x-8 sm:gap-x-6 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div>
<ExampleCard
title="ЖК «Upside Towers»"
company="Upside Development"
image="/images/examples/5.jpg"
/>
<ExampleCard
title="ЖК «Life Резиденция»"
company="ГК Паритет Девелопмент"
image="/images/examples/1.jpg"
/>
<ExampleCard
title="ЖК «Айвазовский City»"
company="ЭНКО"
image="/images/examples/3.jpg"
/>
</div>
<div className="2xl:mt-[220px] xl:mt-40 sm:mt-[104px]">
<ExampleCard
title="Авторский квартал Машаров"
company="Сибинтел Девелопмент"
image="/images/examples/2.jpg"
/>
<ExampleCard
title="ЖК «Сюжеты»"
company="Fortis Development"
image="/images/examples/4.jpg"
className="xl:mb-[0px] sm:mb-[0px] mb-[0px]"
/>
</div>
<div className="absolute top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%] scale-150 -z-10 blur-[44px]">
<img src="/images/blendings/2.svg" alt="" />
</div>
</div>
);
};
export default Examples;
+91
View File
@@ -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(<FeedbackModal />);
return (
<div className="relative grid sm:grid-cols-2 2xl:gap-4 xl:gap-10 sm:gap-3 gap-4 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="flex flex-col justify-between">
<div className="flex flex-col gap-8">
<Heading2>
Экскурсия
<br />
<span className="text-gradient-none">
в виртуальной
<br />
реальности
</span>
</Heading2>
<Button className="sm:block hidden" onClick={handleBtnClick}>
Записаться в шоу-рум
</Button>
</div>
<div className="xl:block hidden pb-8 border-b border-[#3D425C]">
<p className="font-gilroy 2xl:text-xl 2xl:leading-[120%]">
Клиент полностью погружается в воссозданную реальность, чувствует
удобство и уровень комфорта
</p>
</div>
</div>
<div className="flex flex-col gap-10">
<div className="grid xl:grid-cols-2 xl:gap-4 gap-6">
<p className="2xl:text-base text-sm">
Достаточно надеть шлем виртуальной реальности, чтобы прогуляться,
оценить и ощутить пространство
</p>
<img
src="/images/VR.png"
alt=""
className="sm:px-6 sm:pt-8 sm:pb-5 p-4 pb-2 border-t border-[#3D425C] w-full"
/>
</div>
<video
src="/videos/vr.mp4"
muted
autoPlay
loop
playsInline
className="xl:block hidden"
></video>
</div>
<div className="col-span-full sm:mt-8 mt-4 flex flex-col sm:gap-12 gap-8">
<video
src="/videos/vr.mp4"
muted
autoPlay
loop
playsInline
className="xl:hidden block"
></video>
<div className="xl:hidden flex border-b border-[#3D425C] sm:pb-10 pb-6 flex-col gap-8">
<p className="font-gilroy font-medium leading-[120%] xl:hidden block">
Клиент полностью погружается
<br />
в воссозданную реальность, чувствует
<br />
удобство и уровень комфорта
</p>
<Button
className="sm:hidden inline-block"
onClick={() => setModal(<FeedbackModal />)}
>
Записаться в шоу-рум
</Button>
</div>
</div>
<div className="absolute -top-[50%] left-[16%] blur-[20px] -z-10">
<img src="/images/blendings/4.svg" alt="" />
</div>
</div>
);
};
export default ExcursionVR;
@@ -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;
@@ -1,5 +1,5 @@
import { useRef } from "react";
import { Video } from "../types/Video";
import { Video } from "../../types/Video";
interface FeatureVideoViewBoxProps {
selectedVideo: string;
+66
View File
@@ -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<string>(
"/videos/features/virtual_tour.mp4"
);
const [isViewportEntered, setIsViewportEntered] = useState(false);
const handleOnViewportFeatureEnter = () => {
if (isViewportEntered) return;
setIsViewportEntered(true);
};
return (
<motion.div
className="xl:grid flex flex-col grid-cols-2 xl:gap-4 sm:gap-10 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20"
viewport={{ margin: "-10%" }}
onViewportEnter={handleOnViewportFeatureEnter}
>
<div className="flex flex-col gap-20">
<div className="xl:flex flex-col grid sm:grid-cols-2 xl:gap-8 gap-3">
<Heading2>
Функциональные
<br />
<span className="text-gradient-none">возможности</span>
</Heading2>
<p className="xl:w-2/3 xl:text-base text-sm">
Интерактивная презентация увлекает покупателей и предоставляет
актуальную информацию о жилом комплексе, отвечая на все вопросы
и показывая важные особенности и преимущества объекта
</p>
</div>
<div className="pr-6 xl:block hidden">
{videosFeatures.map((video) => (
<FeatureItem
key={video.id}
title={video.title}
desc={video.desc}
video={video.value}
handleHoverStart={(video) => setSelectedVideo(video)}
/>
))}
</div>
</div>
<FeatureVideoViewBox
isViewportEntered={isViewportEntered}
selectedVideo={selectedVideo}
videos={videosFeatures}
/>
<VideoSliderMobile
isViewportEntered={isViewportEntered}
videos={videosFeatures}
/>
</motion.div>
);
};
export default Features;
@@ -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;
+55
View File
@@ -0,0 +1,55 @@
/* eslint-disable @next/next/no-img-element */
const Footer = () => {
return (
<div className=" border-t border-[#3D425C] text-sm">
<div className="container mx-auto xl:px-8 max-w-[1600px]">
<div className="grid lg:grid-cols-4">
<div className="sm:col-span-2 lg:order-none order-last py-6 xl:px-0 px-6 flex sm:flex-row flex-col sm:gap-6 gap-4 lg:border-t-0 border-t border-[#3D425C]">
<div>
<img src="/images/Logo.svg" alt="" className="max-h-fit" />
</div>
<div className="flex flex-col sm:gap-1 gap-4">
<p className="flex sm:flex-row flex-col sm:gap-4 gap-1">
<a href="https://graff.tech/privacypolicy" target="_blank">
Политика конфиденциальности
</a>
{/* <a href="https://graff.estate" className="">
graff.estate
</a> */}
</p>
<p className="text-xs text-[#C5C7CE]">
© 2023 GRAFF interactive. Все права защищены.
</p>
</div>
</div>
<div className="col-span-1 lg:border-l sm:border-b-0 border-b border-[#3D425C] xl:px-8 sm:px-6 px-4 py-6 flex flex-col justify-center">
<div className="flex justify-between items-center">
<div className="text-[#EBEBEB] flex flex-col gap-1">
<a href="mailto:info@graff.tech">info@graff.tech</a>
<a href="tel:88007700067">8 800 770 00 67</a>
</div>
<div className="w-12 h-12 border border-[#3D425C] rounded-full flex justify-center items-center">
RU
</div>
</div>
</div>
<div className="col-span-1 sm:border-l border-[#3D425C] xl:pl-8 xl:pr-0 sm:px-6 px-4 py-6 flex flex-col justify-center">
<div className="flex justify-between items-center">
<div className="text-[#EBEBEB] flex flex-col gap-1">
<a href="mailto:waseem@graff.tech">waseem@graff.tech</a>
<a href="tel:+971509388902">+971 50 938 8902</a>
</div>
<div className="w-12 h-12 border border-[#3D425C] rounded-full flex justify-center items-center">
UAE
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default Footer;
+46
View File
@@ -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(<FeedbackModal />);
return (
<div className="relative container mx-auto 2xl:max-w-screen-2xl">
<div className="flex justify-between py-6 2xl:mb-28 xl:mb-[88px] sm:mb-12 mb-14">
<div>
<img
src="/images/Logo.svg"
alt=""
className="sm:block hidden max-h-fit"
/>
<img
src="/images/LogoMobile.svg"
alt=""
className="sm:hidden block"
/>
</div>
<div className="flex sm:gap-8 gap-2">
<Button onClick={handleOnBtnClick}>
<span className="sm:inline hidden">Оставить заявку</span>
<span className="sm:hidden inline">Связаться</span>
</Button>
{/* <div className="flex gap-1">
<button className="px-3 border-gradient rounded-full font-gilroy font-medium h-10 flex items-center justify-center w-12">
<span className="absolute">RU</span>
</button>
<button className="px-3 rounded-full font-gilroy font-medium leading-none h-10 flex items-center justify-center w-12">
<span className="absolute">EN</span>
</button>
</div> */}
</div>
</div>
</div>
);
};
export default Header;
+54
View File
@@ -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 (
<>
<div className="container mx-auto 2xl:max-w-screen-2xl flex flex-col 2xl:gap-14 gap-6 2xl:mb-[120px] xl:mb-20 sm:mb-12 mb-8">
<h1 className="max-w-[1255px] font-gilroy 2xl:text-8xl sm:text-[64px] text-[40px] leading-none text-gradient font-medium">
Интерактивный инструмент
<br />
продаж <span className="text-gradient-none">для застройщиков</span>
</h1>
<p className="xl:text-xl text-base font-gilroy max-w-[650px] font-medium leading-[120%]">
Помогаем девелоперам эффективно демонстрировать свой объект. Продавать
больше и быстрее.
</p>
<div className="absolute top-20 right-0 blur-[10px] -z-10">
<img src="/images/blendings/1.svg" alt="" />
</div>
</div>
<div className="relative aspect-video w-full 2xl:mb-[200px] sm:mb-[120px] mb-20 overflow-x-clip">
<video
src="/videos/showreel_1080p_4000k_h264.mp4"
muted
autoPlay
loop
playsInline
className="absolute aspect-video w-full"
onPlaying={handleOnPlaying}
onWaiting={handleOnWaiting}
/>
<div
className={`absolute aspect-video w-full h-full flex justify-center items-center bg-black bg-opacity-50 transition-opacity ${
isBuffering ? "opacity-100" : "opacity-0"
}`}
>
<div className="flex gap-4 items-center">
<span>
<LoadingIcon className="animate-spin h-5 w-5" />
</span>
<span className="font-gilroy">Загружаем шоурил...</span>
</div>
</div>
</div>
</>
);
};
export default Showreel;
+99
View File
@@ -0,0 +1,99 @@
/* eslint-disable @next/next/no-img-element */
import Heading2 from "./Headings/Heading2";
const Stats = () => {
return (
<div className="flex flex-col 2xl:gap-16 xl:gap-10 gap-8 2xl:mb-[200px] sm:mb-[120px] mb-20">
<Heading2>
Продавайте недвижимость
<br />
<span className="text-gradient-none">
проще и{" "}
<span className="relative">
<span style={{ WebkitTextFillColor: "#52587A" }}>быстрее</span>
<span className="absolute top-[55%] -left-[2.5%] 2xl:h-1.5 h-1 w-[105%] bg-white"></span>
</span>{" "}
дороже
</span>
</Heading2>
<div className="relative xl:flex items-center gap-4 xl:max-h-[400px]">
<p className="2xl:text-2xl sm:text-xl font-gilroy min-w-fit">
Мы собрали статистику{" "}
<span className="text-gradient font-semibold">за 13 лет</span> работы
<br />
с застройщиками,{" "}
<span className="text-gradient font-semibold">
реализовав 31 проект
</span>
</p>
<div className="2xl:ml-6 xl:ml-[14px] relative 2xl:-top-8 xl:-top-4 -z-10">
<img src="/images/Map.png" alt="" />
</div>
</div>
<p className="2xl:text-[64px] xl:text-5xl text-[40px] text-gradient font-gilroy font-medium w-fit leading-none">
Graff.estate
</p>
<div className="grid xl:grid-cols-4 sm:grid-cols-2 grid-cols-1 xl:gap-0 gap-3">
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">На</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
18
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
%
</span>
</p>
<p className="2xl:text-base text-sm">
увеличивает конверсию из консультации в бронирование
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">На</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
12
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
%
</span>
</p>
<p className="2xl:text-base text-sm">
увеличивает конверсию из бронирования в продажу
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">До</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
2
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
раз
</span>
</p>
<p className="2xl:text-base text-sm">
сокращает время
<br />
реализации проекта
</p>
</div>
<div className="2xl:px-8 px-6 py-4 flex flex-col gap-4 border-l border-[#3D425C]">
<p className="2xl:text-base text-sm">До</p>
<p className="2xl:text-8xl text-[64px] font-gilroy font-medium leading-none">
4
<span className="2xl:text-2xl text-xl ml-1 font-semibold leading-[135%]">
раз
</span>
</p>
<p className="2xl:text-base text-sm">
сокращает время на подготовку рекламных материалов
</p>
</div>
</div>
</div>
);
};
export default Stats;
+85
View File
@@ -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 (
<div className="relative 2xl:mb-[200px] sm:mb-[120px] mb-20">
<div className="grid sm:grid-cols-2 sm:gap-4 gap-6 2xl:mb-16 xl:mb-10 sm:mb-12 mb-8">
<div className="flex flex-col gap-8 justify-between">
<Heading2>
Graff.estate stream 
<br />
<span className="text-gradient-none">
удаленная
<br />
демонстрация
<br />
жилого комплекса
</span>
</Heading2>
<a
href="https://stream.graff.tech"
target="_blank"
className="w-fit sm:inline-block hidden"
>
<Button>Узнать больше</Button>
</a>
</div>
<div className="flex flex-col xl:gap-16 gap-6">
<div className="grid xl:grid-cols-2 xl:gap-4 gap-2">
<p className="2xl:text-base text-sm">
Высокий уровень графики и полное погружение покупателя в процесс
выбора квартиры
</p>
<p className="2xl:text-base text-sm">
Местоположение и устройство значения не имеют. Нужен только
интернет
</p>
</div>
<div className="xl:grid grid-cols-2 gap-4">
<img src="/images/Datamining.jpg" alt="" className="w-full" />
</div>
<a
href="https://stream.graff.tech"
target="_blank"
className="w-fit sm:hidden inline-block"
>
<Button>Узнать больше</Button>
</a>
</div>
</div>
<div className="border-t border-[#3D425C]">
<StreamButton
icon="/icons/Revolution.svg"
title="МФК «Re:volution towers»"
location="Россия, Екатеринбург"
background="/images/stream/nks.jpg"
link="https://stream.graff.tech/?build=nksJukovaDev&location=a1"
/>
<StreamButton
icon="/icons/Residence.svg"
title="ЖК «Life Резиденция»"
location="Россия, Тюмень"
background="/images/stream/liferes.jpg"
link="https://stream.graff.tech/?build=lifeResidence&location=a1"
/>
<StreamButton
icon="/icons/Aivaz.svg"
title="ЖК «Айвазовский City»"
location="Россия, Тюмень"
background="/images/stream/aivaz.jpg"
link="https://stream.graff.tech/?build=IvazowskyDev&location=a1"
/>
</div>
<div className="absolute -top-36 left-0 -z-10 blur-[20px]">
<img src="/images/blendings/3.svg" alt="" />
</div>
</div>
);
};
export default Stream;
@@ -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;
+28
View File
@@ -0,0 +1,28 @@
import { IIconProps } from "../../types/IconProps";
const LoadingIcon = ({ className }: IIconProps) => {
return (
<svg
className={`${className}`}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
);
};
export default LoadingIcon;
+1 -1
View File
@@ -1,4 +1,4 @@
import ContactsForm from "../ContactsForm";
import ContactsForm from "../ContactsForm/ContactsForm";
function FeedbackModal() {
return (
+5
View File
@@ -0,0 +1,5 @@
interface IIconProps {
className?: string;
}
export type { IIconProps };