upd
@@ -2,9 +2,9 @@
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React + TS</title>
|
||||
<title>Интерактивные решения для застройщиков</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
"react-rangeslider": "^2.2.0",
|
||||
"react-responsive-carousel": "^3.2.23",
|
||||
"react-scroll": "^1.8.9",
|
||||
"react-yandex-metrika": "^2.6.0",
|
||||
"swiper": "^9.2.0",
|
||||
"three": "^0.151.3",
|
||||
"zustand": "^4.3.8"
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.0126 63.5512C49.4365 63.5512 63.5613 49.3248 63.5613 31.7756C63.5613 29.6263 63.3495 27.5269 62.9456 25.4974H43.8858V38.0965H50.0359C47.4423 45.5818 40.3713 50.952 32.055 50.952C21.5398 50.952 13.0155 42.3664 13.0155 31.7756C13.0155 21.1848 21.5398 12.5992 32.055 12.5992V0H32.0126C14.5887 0 0.463867 14.2264 0.463867 31.7756C0.463867 49.3248 14.5887 63.5512 32.0126 63.5512Z" fill="#798FFF"/>
|
||||
<path d="M30.4261 0.0385644C16.871 2.15049 6.49536 13.931 6.49536 28.1472C6.49536 43.8574 19.1662 56.593 34.7964 56.593C50.4267 56.593 63.0975 43.8574 63.0975 28.1472C63.0975 27.2411 63.0553 26.3449 62.9729 25.4605H43.8765V38.0414H50.0305C47.4352 45.5158 40.3599 50.8783 32.0385 50.8783C21.5167 50.8783 12.9872 42.3051 12.9872 31.7296C12.9872 21.729 20.6146 13.519 30.3412 12.6559C30.9004 12.6063 31.4665 12.581 32.0385 12.581V0H31.996C31.4696 0 30.9462 0.0129614 30.4261 0.0385644Z" fill="#D375FF"/>
|
||||
<path opacity="0.3" d="M28.3436 12.9886C29.5316 12.7616 30.7581 12.6428 32.0126 12.6428V0H31.9695C29.4296 0 26.9587 0.293941 24.5894 0.849496L28.3436 12.9886Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M11.709 7.1846L9.74292 35.7185L12.5531 33.0414C12.5364 32.7123 12.528 32.381 12.528 32.0477C12.528 21.4743 21.0239 12.8891 31.5487 12.7721L18.9275 2.7832C16.3203 3.9294 13.8956 5.41515 11.709 7.1846Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M0.465096 32.136L14.8417 39.8933C13.7036 37.4501 13.0683 34.7263 13.0683 31.8544C13.0683 28.9786 13.7054 26.2513 14.8464 23.8056L10.4426 8.81348C4.29975 14.5819 0.463867 22.771 0.463867 31.8544C0.463867 31.9484 0.464277 32.0422 0.465096 32.136Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M0.463867 30.8628L19.5379 59.4596L40.3637 59.8405L32.2394 50.8874C32.1539 50.8885 32.0683 50.8891 31.9826 50.8891C21.486 50.8891 12.9769 42.3811 12.9769 31.8859C12.9769 31.4592 12.991 31.0359 13.0187 30.6162L0.472692 30.6162C0.469436 30.6983 0.466494 30.7805 0.463867 30.8628Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M14.3097 57.985L26.4453 50.0062C18.5941 47.5782 12.9044 40.4127 12.9044 31.951C12.9044 30.8637 12.9983 29.7979 13.1787 28.7607L5.10352 48.7573C7.48783 52.4173 10.628 55.5629 14.3097 57.985Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M42.2195 61.8851C38.982 62.9654 35.513 63.5511 31.9052 63.5511C25.2415 63.5511 19.0515 61.5529 13.9185 58.1315L26.0686 50.0986C27.9232 50.6792 29.8987 50.9925 31.9484 50.9925C32.024 50.9925 32.0995 50.9921 32.1749 50.9912L42.2195 61.8851Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M38.9719 62.7762C36.6999 63.2834 34.3362 63.5511 31.9093 63.5511C30.8578 63.5511 29.8181 63.5008 28.7927 63.4026L25.9812 50.0986C26.3608 50.2208 26.7455 50.3317 27.135 50.4308L38.9719 62.7762Z" fill="black" fill-opacity="0.4"/>
|
||||
<path opacity="0.3" d="M44.0754 30.6163L63.0975 26.1207C63.0625 25.9177 63.0258 25.7154 62.9872 25.5137H44.0754V30.6163Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M48.0297 38.0384L63.0974 25.5346C63.096 25.5276 63.0947 25.5206 63.0933 25.5137L44.5393 38.0384H48.0297Z" fill="black" fill-opacity="0.4"/>
|
||||
<path opacity="0.3" d="M56.8738 25.5137L43.1475 61.2322C48.5545 59.1664 53.2472 55.6523 56.7525 51.1636L58.9218 25.5137H56.8738Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M62.9575 25.5137L43.1475 61.2322C55.0796 56.7129 63.5613 45.1896 63.5613 31.6876C63.5613 29.5748 63.3536 27.5104 62.9575 25.5137Z" fill="black" fill-opacity="0.4"/>
|
||||
<path d="M50.5846 0H63.0975V12.5247H50.5846V0Z" fill="#798FFF"/>
|
||||
<path d="M63.0975 12.5247H50.5846L44.0754 19.019H56.1248L63.0975 12.5247Z" fill="#798FFF"/>
|
||||
<path d="M50.5846 12.5247V0L44.0754 6.95816V19.019L50.5846 12.5247Z" fill="#798FFF"/>
|
||||
<path opacity="0.3" d="M63.0975 10.7935V12.5408L56.2041 19.0187H54.7463V10.6689L63.0975 10.7935Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M44.0754 19.0188V6.76921L52.8114 6.03027L55.6742 6.78702L44.0754 19.0188Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M49.6405 1.3916L44.0754 7.12313V19.0189H51.4987L49.6405 1.3916Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M44.4055 6.47622L44.0754 6.83173V19.0189L51.0638 12.294L54.3349 12.1655L61.7056 13.4079L61.0047 12.3583L52.1683 2.7832L44.4055 6.47622Z" fill="#D375FF"/>
|
||||
<path opacity="0.3" d="M51.0346 0H50.5742L48.7148 1.98114L50.9086 3.24714L51.0346 0Z" fill="black" fill-opacity="0.6"/>
|
||||
<path opacity="0.3" d="M60.7778 14.9295L56.4373 19.0187H55.6743L56.3559 10.8435L59.7322 10.2051L60.7778 14.9295Z" fill="black" fill-opacity="0.6"/>
|
||||
<path d="M50.5708 12.5247H63.0975V0H50.5708V12.5247Z" fill="url(#paint0_linear_1658_21330)"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_1658_21330" x1="57.6988" y1="0" x2="57.6988" y2="12.5247" gradientUnits="userSpaceOnUse">
|
||||
<stop stopColor="#D375FF"/>
|
||||
<stop offset="1" stopColor="#798FFF"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 97 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,69 +1,32 @@
|
||||
import "./App.css";
|
||||
// import { Canvas } from "@react-three/fiber";
|
||||
import { FormEvent, useEffect, useRef, useState } from "react";
|
||||
import { FormEvent, useRef, useState } from "react";
|
||||
import PieChart from "./components/PieChart/PieChart";
|
||||
// import { Model } from "./components/VRHemlet";
|
||||
import Calc from "./components/Calc";
|
||||
import { motion } from "framer-motion";
|
||||
import InputMask from "react-input-mask";
|
||||
import api from "./utils/api";
|
||||
import FeatureCard from "./components/FeatureCard";
|
||||
import ComplexCard from "./components/ComplexCard";
|
||||
import Title from "./components/Title";
|
||||
import FeatureCardMobile from "./components/FeatureCardMobile";
|
||||
import Modal from "./components/Modal";
|
||||
import Slider from "./components/Slider/Slider";
|
||||
import FeatureSlider from "./components/FeatureSlider";
|
||||
import useModalStore from "./store/modal";
|
||||
import FeedbackForm from "./components/FeedbackForm";
|
||||
import { YMInitializer } from "react-yandex-metrika";
|
||||
import Map from "./components/Map";
|
||||
|
||||
function App() {
|
||||
const parallaxRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [fullname, setFullname] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [company, setCompany] = useState<string>("");
|
||||
const [phone, setPhone] = useState<string>("");
|
||||
|
||||
// const [mapPosition, setMapPosition] = useState<string>("29% 100%");
|
||||
// const [mapCity, setMapCity] = useState<string>("Тюмень");
|
||||
|
||||
const [isShowComplexCards, setIsShowComplexCards] = useState<boolean>(false);
|
||||
|
||||
// const helmetRef = useRef(null);
|
||||
// const helmetInView = useInView(helmetRef);
|
||||
// const [helmetIsAnim, setHelmetIsAnim] = useState<boolean>(true);
|
||||
|
||||
// const featureImagesContainer = useRef<HTMLDivElement>(null);
|
||||
// const featureImages = [
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Uralsky.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// "/videos/Integra_CRM.mp4",
|
||||
// ];
|
||||
// const [selectedFeatureImageIndex, setSelectedFeatureImageIndex] =
|
||||
// useState<number>(0);
|
||||
|
||||
// useEffect(() => {
|
||||
// if (featureImagesContainer.current) {
|
||||
// featureImagesContainer.current.insertAdjacentHTML(
|
||||
// "beforeend",
|
||||
// `<div>
|
||||
// <video muted autoplay data-index="${selectedFeatureImageIndex}" class="absolute top-0 left-0 w-full h-full fade-in flex justify-center">
|
||||
// <source src="${featureImages[selectedFeatureImageIndex]}">
|
||||
// </video>
|
||||
// </div>`
|
||||
// );
|
||||
|
||||
// if (featureImagesContainer.current.children.length > 1) {
|
||||
// setTimeout(() => {
|
||||
// featureImagesContainer.current?.firstElementChild?.remove();
|
||||
// }, 1000);
|
||||
// }
|
||||
// }
|
||||
// }, [selectedFeatureImageIndex]);
|
||||
const [modalComponent, setModalComponent] = useModalStore((state) => [
|
||||
state.component,
|
||||
state.setComponent,
|
||||
]);
|
||||
|
||||
async function handleSubmitSendMail(e: FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
@@ -89,17 +52,24 @@ function App() {
|
||||
<div className="bg-[#131317] text-white">
|
||||
<div
|
||||
ref={parallaxRef}
|
||||
className="relative lg:container mx-auto p-4 xl:max-w-screen-2xl overflow-hidden"
|
||||
className="relative lg:container mx-auto px-4 lg:py-8 py-4 xl:max-w-screen-2xl overflow-hidden"
|
||||
>
|
||||
<div className="2xl:space-y-44 xl:space-y-40 sm:space-y-36 space-y-20 2xl:mb-44 xl:mb-40 sm:mb-36 mb-20">
|
||||
<div className="absolute top-0 right-0 sm:translate-x-0 sm:translate-y-0 translate-x-[40%] translate-y-[40%]">
|
||||
<img src="/images/shapes/1.svg" alt="" />
|
||||
</div>
|
||||
|
||||
<div className="relative 2xl:space-y-44 xl:space-y-40 sm:space-y-36 space-y-20 2xl:mb-44 xl:mb-40 sm:mb-36 mb-20">
|
||||
<div className="flex justify-between">
|
||||
<div className="">
|
||||
<a href="/">
|
||||
<img src="/images/logo.png" alt="" />
|
||||
<img src="/logo.svg" alt="" />
|
||||
</a>
|
||||
</div>
|
||||
<div className="flex sm:space-x-8 space-x-2">
|
||||
<button className="px-4 py-2 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity">
|
||||
<div className="sm:space-x-8 space-x-2">
|
||||
<button
|
||||
onClick={() => setModalComponent(<FeedbackForm />)}
|
||||
className="px-4 py-2 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity"
|
||||
>
|
||||
<span className="sm:block hidden">Связаться с нами</span>
|
||||
<span className="sm:hidden block">Связаться</span>
|
||||
</button>
|
||||
@@ -116,21 +86,20 @@ function App() {
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="absolute top-0 right-0 sm:translate-x-0 sm:translate-y-0 translate-x-[40%] translate-y-[40%]">
|
||||
<img src="/images/shapes/1.svg" alt="" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative xl:space-y-48 lg:space-y-40 sm:space-y-28 space-y-20 overflow-hidden">
|
||||
<video
|
||||
autoPlay={true}
|
||||
muted={true}
|
||||
loop={true}
|
||||
playsInline={true}
|
||||
className="aspect-video w-full rounded-2xl"
|
||||
>
|
||||
<source src="/videos/showreel.webm" type="video/mp4" />
|
||||
</video>
|
||||
<div className="px-4">
|
||||
<video
|
||||
autoPlay={true}
|
||||
muted={true}
|
||||
loop={true}
|
||||
playsInline={true}
|
||||
className="aspect-video w-full 2xl:rounded-2xl xl:rounded-xl lg:rounded-lg rounded"
|
||||
>
|
||||
<source src="/videos/showreel.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
<div className="lg:container mx-auto p-4 xl:max-w-screen-2xl">
|
||||
<div className="space-y-32">
|
||||
<div className="space-y-8">
|
||||
@@ -147,6 +116,35 @@ function App() {
|
||||
<div className="grid lg:grid-cols-2 grid-cols-1 gap-8">
|
||||
<div className="space-y-20">
|
||||
<div className="grid sm:grid-cols-2 gap-6">
|
||||
<div className="border-t-2 pt-8 border-[#454554]">
|
||||
<p className="sm:text-lg">На</p>
|
||||
<div className="space-x-2 pt-4">
|
||||
<span className="text-gradient font-gilroy 2xl:text-8xl sm:text-8xl text-6xl ">
|
||||
18%
|
||||
</span>
|
||||
</div>
|
||||
<p className="sm:text-lg">
|
||||
увеличивает конверсию
|
||||
<br />
|
||||
из консультации в бронирование
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t-2 pt-8 border-[#454554]">
|
||||
<p className="sm:text-lg">На</p>
|
||||
<div className="space-x-2 pt-4">
|
||||
<span className="text-gradient font-gilroy 2xl:text-8xl sm:text-8xl text-6xl ">
|
||||
12%
|
||||
</span>
|
||||
{/* <span className="text-gradient text-2xl font-bold">раз</span> */}
|
||||
</div>
|
||||
<p className="sm:text-lg">
|
||||
увеличивает конверсию
|
||||
<br />
|
||||
из бронирования в продажу
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t-2 pt-8 border-[#454554]">
|
||||
<p className="sm:text-lg">До</p>
|
||||
<div className="space-x-2 pt-4">
|
||||
@@ -170,53 +168,28 @@ function App() {
|
||||
<span className="text-gradient font-gilroy 2xl:text-8xl sm:text-8xl text-6xl ">
|
||||
26
|
||||
</span>
|
||||
{/* <span className="text-gradient text-2xl font-bold">раз</span> */}
|
||||
</div>
|
||||
<p className="sm:text-lg">
|
||||
что-то на умном
|
||||
<br />в две строчки
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t-2 pt-8 border-[#454554]">
|
||||
<p className="sm:text-lg">На</p>
|
||||
<div className="space-x-2 pt-4">
|
||||
<span className="text-gradient font-gilroy 2xl:text-8xl sm:text-8xl text-6xl ">
|
||||
18%
|
||||
</span>
|
||||
{/* <span className="text-gradient text-2xl font-bold">раз</span> */}
|
||||
</div>
|
||||
<p className="sm:text-lg">
|
||||
увеличивает конверсию
|
||||
<br />
|
||||
из консультации в бронирование
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="border-t-2 pt-8 border-[#454554]">
|
||||
<p className="sm:text-lg">На</p>
|
||||
<div className="space-x-2 pt-4">
|
||||
<span className="text-gradient font-gilroy 2xl:text-8xl sm:text-8xl text-6xl ">
|
||||
12%
|
||||
</span>
|
||||
{/* <span className="text-gradient text-2xl font-bold">раз</span> */}
|
||||
</div>
|
||||
<p className="sm:text-lg">
|
||||
увеличивает конверсию
|
||||
<br />
|
||||
из бронирования в продажу
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button className="lg:block hidden self-start 2xl:text-xl px-8 py-3 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity sm:w-auto w-full">
|
||||
<button
|
||||
onClick={() => setModalComponent(<FeedbackForm />)}
|
||||
className="lg:block hidden self-start 2xl:text-xl px-8 py-3 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity sm:w-auto w-full"
|
||||
>
|
||||
Заказать решение
|
||||
</button>
|
||||
</div>
|
||||
<div className="h-full min-h-[520px] rounded overflow-hidden">
|
||||
<Slider />
|
||||
</div>
|
||||
<button className="lg:hidden block sm:w-fit self-start 2xl:text-xl px-8 py-3 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity">
|
||||
<button
|
||||
onClick={() => setModalComponent(<FeedbackForm />)}
|
||||
className="lg:hidden block sm:w-fit self-start 2xl:text-xl px-8 py-3 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity"
|
||||
>
|
||||
Заказать решение
|
||||
</button>
|
||||
</div>
|
||||
@@ -239,95 +212,46 @@ function App() {
|
||||
|
||||
<FeatureSlider />
|
||||
|
||||
{/* <div className="relative lg:grid hidden lg:grid-cols-2 ">
|
||||
<FeatureCard
|
||||
title="Виртуальный тур по жилому комплексу"
|
||||
text="Клиент лично оценит угол инсоляции, малые архитектурные формы и ландшафт, перемещаясь по комплексу с помощью тапа."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(0)}
|
||||
/>
|
||||
<div className="overflow-hidden row-span-2 h-full border border-[#454554] backdrop-blur-lg bg-[rgba(46, 46, 56, 0.1)] ">
|
||||
<div
|
||||
ref={featureImagesContainer}
|
||||
className="w-full h-full"
|
||||
></div>
|
||||
</div>
|
||||
<FeatureCard
|
||||
title="Вся инфрастуктура на одном экране"
|
||||
text="Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(1)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Конфигуратор интерьера"
|
||||
text="Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(2)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Параметрический поиск квартир"
|
||||
text="Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(3)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Интеграция с CRM - системой"
|
||||
text="Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(4)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Любой рендер за несколько секунд"
|
||||
text="Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(5)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Формирование вишлиста"
|
||||
text="Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(6)}
|
||||
/>
|
||||
<FeatureCard
|
||||
title="Отправка коммерческого предложения"
|
||||
text="Коммерческое предложение с выбранными квартирами может быть отправлено клиенту на почту или распечатано и отдано лично в руки."
|
||||
handleMouseEnter={() => setSelectedFeatureImageIndex(7)}
|
||||
/>
|
||||
</div> */}
|
||||
|
||||
<div className="relative lg:hidden block">
|
||||
<FeatureCardMobile
|
||||
title="Виртуальный тур по жилому комплексу"
|
||||
text="Клиент лично оценит угол инсоляции, малые архитектурные формы и ландшафт, перемещаясь по комплексу с помощью тапа."
|
||||
image="/images/cards/1.jpg"
|
||||
src="/videos/features/virtual_tour.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Вся инфрастуктура на одном экране"
|
||||
text="Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти."
|
||||
image="/images/cards/2.jpg"
|
||||
src="/videos/features/nks_infra.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Конфигуратор интерьера"
|
||||
text="Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали."
|
||||
image="/images/cards/3.jpg"
|
||||
src="/videos/features/uralsky.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Параметрический поиск квартир"
|
||||
text="Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов."
|
||||
image="/images/cards/4.jpg"
|
||||
src="/videos/features/parametric.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Интеграция с CRM - системой"
|
||||
text="Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир."
|
||||
image="/images/cards/5.jpg"
|
||||
src="/videos/features/integra_crm.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Любой рендер за несколько секунд"
|
||||
text="Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации."
|
||||
image="/images/cards/6.jpg"
|
||||
src="/videos/features/render.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Формирование вишлиста"
|
||||
text="Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру."
|
||||
image="/images/cards/7.jpg"
|
||||
src="/videos/features/wish.mp4"
|
||||
/>
|
||||
<FeatureCardMobile
|
||||
title="Отправка коммерческого предложения"
|
||||
text="Коммерческое предложение с выбранными квартирами может быть отправлено клиенту на почту или распечатано и отдано лично в руки."
|
||||
image="/images/cards/8.jpg"
|
||||
src="/videos/features/send.mp4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -347,7 +271,10 @@ function App() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<button className="2xl:text-xl px-8 py-4 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity sm:w-auto w-full">
|
||||
<button
|
||||
onClick={() => setModalComponent(<FeedbackForm />)}
|
||||
className="2xl:text-xl px-8 py-4 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity sm:w-auto w-full"
|
||||
>
|
||||
Записаться в шоу-рум
|
||||
</button>
|
||||
</div>
|
||||
@@ -628,7 +555,7 @@ function App() {
|
||||
</div>
|
||||
|
||||
<div className="grid lg:grid-cols-2 lg:gap-4 items-center">
|
||||
<div className="space-y-16">
|
||||
<div className="relative z-10 space-y-16">
|
||||
<div className="space-y-14">
|
||||
<Title>
|
||||
Покажите все преимущества вашего жилого комплекса клиенту{" "}
|
||||
@@ -649,7 +576,11 @@ function App() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-8">
|
||||
<button className="text-xl border border-[#BC75FF] px-6 py-3 pr-3 flex items-center space-x-2 rounded-full cursor-pointer">
|
||||
<a
|
||||
href="https://stream.graff.tech"
|
||||
target="_blank"
|
||||
className="w-fit text-xl border border-[#BC75FF] px-6 py-3 pr-3 flex items-center space-x-2 rounded-full cursor-pointer"
|
||||
>
|
||||
<span>Узнать больше</span>
|
||||
<svg
|
||||
width="24"
|
||||
@@ -666,13 +597,15 @@ function App() {
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:absolute z-10 xl:top-2 lg:top-[335px] right-4 2xl:w-full lg:w-[52%] w-full flex lg:justify-end">
|
||||
<Map />
|
||||
|
||||
{/* <div className="lg:absolute xl:top-2 lg:top-[335px] right-4 2xl:w-full lg:w-[52%] w-full flex lg:justify-end">
|
||||
<img src="/images/devices.png" alt="" className="" />
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -704,10 +637,16 @@ function App() {
|
||||
<Title>Реализованные проекты</Title>
|
||||
<div className="2xl:space-y-10 xl:space-y-8 space-y-6 flex flex-col">
|
||||
<div className="grid lg:grid-cols-2 xl:gap-8 gap-4">
|
||||
<ComplexCard
|
||||
{/* <ComplexCard
|
||||
image="/images/cards/1.jpg"
|
||||
name="ЖК «Life Резиденция»"
|
||||
location="Россия, Тюмень."
|
||||
/> */}
|
||||
<ComplexCard
|
||||
image="/images/cards/5.jpg"
|
||||
name="ЖК «Айвазовский»"
|
||||
location="Россия, Тюмень."
|
||||
src="/videos/Ivazowsky.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/2.jpg"
|
||||
@@ -715,26 +654,26 @@ function App() {
|
||||
location="Россия, Екатеринбург."
|
||||
src="/videos/RE_Volution_Towers.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/3.jpg"
|
||||
name="Iskan Abu Dhabi"
|
||||
location="ОАЭ, Абу-Даби."
|
||||
src="/videos/Iskan_Abu_Dhabi.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/4.jpg"
|
||||
name="ЖК «Авторский квартал Машаров»"
|
||||
location="Россия, Тюмень."
|
||||
src="/videos/Masharov.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/8.jpg"
|
||||
name="ЖК «Уральский»"
|
||||
location="Россия, Екатеринбург."
|
||||
src="/videos/Uralsky.mp4"
|
||||
/>
|
||||
|
||||
{isShowComplexCards && (
|
||||
<>
|
||||
<ComplexCard
|
||||
image="/images/cards/5.jpg"
|
||||
name="ЖК «Айвазовский»"
|
||||
location="Россия, Тюмень."
|
||||
src="/videos/Ivazowsky.mp4"
|
||||
image="/images/cards/3.jpg"
|
||||
name="Iskan Abu Dhabi"
|
||||
location="ОАЭ, Абу-Даби."
|
||||
src="/videos/Iskan_Abu_Dhabi.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/6.jpg"
|
||||
@@ -748,12 +687,7 @@ function App() {
|
||||
location="Россия, Екатеринбург."
|
||||
src="/videos/4you.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
image="/images/cards/8.jpg"
|
||||
name="ЖК «Уральский»"
|
||||
location="Россия, Екатеринбург."
|
||||
src="/videos/Uralsky.mp4"
|
||||
/>
|
||||
|
||||
<ComplexCard
|
||||
image="/images/cards/9.jpg"
|
||||
name="ЖК «Новая Атмосфера»"
|
||||
@@ -772,16 +706,16 @@ function App() {
|
||||
location="Россия, Екатеринбург."
|
||||
src="/videos/Dom_na_Opal.mp4"
|
||||
/>
|
||||
<ComplexCard
|
||||
{/* <ComplexCard
|
||||
image="/images/cards/12.jpg"
|
||||
name="ЖК «Свой Круг»"
|
||||
location="Россия, Екатеринбург."
|
||||
/>
|
||||
<ComplexCard
|
||||
/> */}
|
||||
{/* <ComplexCard
|
||||
image="/images/cards/13.jpg"
|
||||
name="ЖК «Александровский»"
|
||||
location="Россия, Нижний Тагил."
|
||||
/>
|
||||
/> */}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
@@ -966,10 +900,12 @@ function App() {
|
||||
<div className="space-y-8">
|
||||
<div className="space-y-2">
|
||||
<p className="2xl:text-xl sm:text-lg text-[#ABABBA]">
|
||||
Адрес
|
||||
Сайт
|
||||
</p>
|
||||
<p className="2xl:text-3xl sm:text-2xl text-xl">
|
||||
ул. Московская, 47, Екатеринбург
|
||||
<a href="https://graff.tech" target="_blank">
|
||||
graff.tech
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
@@ -995,11 +931,12 @@ function App() {
|
||||
</div>
|
||||
<div className="h-0.5 bg-[#454554]"></div>
|
||||
<div className="flex sm:flex-row flex-col flex-wrap sm:items-center gap-4 items-start justify-between text-[#C5C7CE] 2xl:text-xl">
|
||||
<a href="/">
|
||||
<img src="/images/logo.png" alt="" />
|
||||
</a>
|
||||
<a href="#privacy">Политика конфиденциальности</a>
|
||||
<a href="#site">graff.tech</a>
|
||||
<div className="flex items-center space-x-8">
|
||||
<img src="/logo-footer.svg" alt="" />
|
||||
<a href="https://graff.tech/privacypolicy" target="_blank">
|
||||
Политика конфиденциальности
|
||||
</a>
|
||||
</div>
|
||||
<p>© 2023 GRAFF interactive. Все права защищены</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1009,6 +946,8 @@ function App() {
|
||||
</div>
|
||||
|
||||
<Modal />
|
||||
|
||||
<YMInitializer accounts={[93606080]} options={{ webvisor: true }} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,22 +1,42 @@
|
||||
import { useInView } from "framer-motion";
|
||||
import React, { useRef } from "react";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
|
||||
interface IFeatureCard2 {
|
||||
title: string;
|
||||
text: string;
|
||||
image: string;
|
||||
src: string;
|
||||
}
|
||||
|
||||
function FeatureCardMobile2({ title, text, image }: IFeatureCard2) {
|
||||
const fetureCard = useRef(null);
|
||||
|
||||
function FeatureCardMobile2({ title, text, src }: IFeatureCard2) {
|
||||
const fetureCard = useRef<HTMLDivElement>(null);
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const inView = useInView(fetureCard, { margin: "-50%" });
|
||||
|
||||
return (
|
||||
<div ref={fetureCard} className="relative border border-[#23232A] bg-[#2E2E381A]">
|
||||
useEffect(() => {
|
||||
if (videoRef.current) {
|
||||
if (inView) {
|
||||
videoRef.current.play();
|
||||
} else {
|
||||
videoRef.current.pause();
|
||||
}
|
||||
}
|
||||
}, [inView]);
|
||||
|
||||
<div className="">
|
||||
<img src={image} alt="" className="aspect-video w-full" />
|
||||
return (
|
||||
<div
|
||||
ref={fetureCard}
|
||||
className="relative border border-[#23232A] bg-[#2E2E381A] overflow-hidden backdrop-blur-lg"
|
||||
>
|
||||
<div className="relative z-10 aspect-video">
|
||||
<video
|
||||
ref={videoRef}
|
||||
muted={true}
|
||||
autoPlay={true}
|
||||
playsInline={true}
|
||||
className=""
|
||||
>
|
||||
<source src={src} type="video/mp4" />
|
||||
</video>
|
||||
</div>
|
||||
<div className="relative px-4 py-6 sm:space-y-4 space-y-2">
|
||||
<p className="font-gilroy uppercase 2xl:text-2xl sm:text-xl tracking-wider">
|
||||
|
||||
@@ -1,94 +1,65 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import React from "react";
|
||||
import FeatureSliderItem from "./FeatureSliderItem";
|
||||
import { useInView } from "framer-motion";
|
||||
|
||||
function FeatureSlider() {
|
||||
const [selectedItem, setSelectedItem] = useState<string>("");
|
||||
const featureSliderRef = useRef(null);
|
||||
const featureSliderItemRef = useRef<HTMLDivElement>(null);
|
||||
const featureSliderInView = useInView(featureSliderRef);
|
||||
|
||||
useEffect(() => {
|
||||
if (featureSliderInView) {
|
||||
setSelectedItem("/videos/features/virtual_tour.webm");
|
||||
} else {
|
||||
setSelectedItem("");
|
||||
}
|
||||
}, [featureSliderInView]);
|
||||
|
||||
useEffect(() => {
|
||||
if (featureSliderItemRef.current) {
|
||||
featureSliderItemRef.current.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`<video muted autoplay loop playsinline class="absolute fade-in">
|
||||
<source src="${selectedItem}" />
|
||||
</video>`
|
||||
);
|
||||
|
||||
if (featureSliderItemRef.current.children.length > 1) {
|
||||
setTimeout(() => {
|
||||
featureSliderItemRef.current?.firstElementChild?.remove();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}, [selectedItem]);
|
||||
|
||||
return (
|
||||
<div ref={featureSliderRef} className="grid grid-cols-2">
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Виртуальный тур по жилому комплексу"
|
||||
text="Клиент лично оценит угол инсоляции, малые архитектурные формы и ландшафт, перемещаясь по комплексу с помощью тапа."
|
||||
handleHover={() => setSelectedItem("/videos/features/virtual_tour.webm")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Вся инфрастуктура на одном экране"
|
||||
text="Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти."
|
||||
handleHover={() => setSelectedItem("/videos/features/nks_infra.webm")}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
ref={featureSliderItemRef}
|
||||
className="relative aspect-video border border-[#454554] bg-black"
|
||||
></div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Конфигуратор интерьера"
|
||||
text="Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали."
|
||||
handleHover={() => setSelectedItem("/videos/features/uralsky.webm")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Параметрический поиск квартир"
|
||||
text="Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов."
|
||||
handleHover={() => setSelectedItem("/videos/features/parametric.webm")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Любой рендер за несколько секунд"
|
||||
text="Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации."
|
||||
handleHover={() => setSelectedItem("/videos/features/render.webm")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Формирование вишлиста"
|
||||
text="Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру."
|
||||
handleHover={() => setSelectedItem("/videos/features/wish.webm")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Интеграция с CRM - системой"
|
||||
text="Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир."
|
||||
handleHover={() => setSelectedItem("/videos/features/integra_crm.webm")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Отправка коммерческого предложения"
|
||||
text="Коммерческое предложение с выбранными квартирами может быть отправлено клиенту на почту или распечатано и отдано лично в руки."
|
||||
handleHover={() => setSelectedItem("/videos/features/send.webm")}
|
||||
/>
|
||||
</div>
|
||||
<div className="lg:grid grid-cols-2 hidden">
|
||||
<FeatureSliderItem
|
||||
title={"Виртуальный тур по жилому комплексу"}
|
||||
text={
|
||||
"Клиент лично оценит угол инсоляции, малые архитектурные формы и ландшафт, перемещаясь по комплексу с помощью тапа."
|
||||
}
|
||||
video={"/videos/features/virtual_tour.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Вся инфрастуктура на одном экране"}
|
||||
text={
|
||||
"Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти."
|
||||
}
|
||||
video={"/videos/features/nks_infra.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Конфигуратор интерьера"}
|
||||
text={
|
||||
"Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали."
|
||||
}
|
||||
video={"/videos/features/uralsky.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Параметрический поиск квартир"}
|
||||
text={
|
||||
"Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов."
|
||||
}
|
||||
video={"/videos/features/parametric.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Любой рендер за несколько секунд"}
|
||||
text={
|
||||
"Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации."
|
||||
}
|
||||
video={"/videos/features/render.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Формирование вишлиста"}
|
||||
text={
|
||||
"Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру."
|
||||
}
|
||||
video={"/videos/features/wish.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Интеграция с CRM - системой"}
|
||||
text={
|
||||
"Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир."
|
||||
}
|
||||
video={"/videos/features/integra_crm.mp4"}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title={"Отправка коммерческого предложения"}
|
||||
text={
|
||||
"Коммерческое предложение с выбранными квартирами может быть отправлено клиенту на почту или распечатано и отдано лично в руки."
|
||||
}
|
||||
video={"/videos/features/send.mp4"}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,68 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
|
||||
interface IFeatureSliderItem {
|
||||
title: string;
|
||||
text: string;
|
||||
handleHover: () => void;
|
||||
video: string;
|
||||
}
|
||||
|
||||
function FeatureSliderItem({ title, text, handleHover }: IFeatureSliderItem) {
|
||||
function FeatureSliderItem({ title, text, video }: IFeatureSliderItem) {
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const [isTouchScreen, setIsTouchScreen] = useState<boolean>(false);
|
||||
|
||||
function handleMouseEnter() {
|
||||
videoRef.current?.play();
|
||||
}
|
||||
|
||||
function handleMouseLeave() {
|
||||
videoRef.current?.pause();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (navigator.maxTouchPoints > 1) {
|
||||
setIsTouchScreen(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="relative group border border-[#454554] h-1/2 bg-[#2E2E381A] hover:bg-[#2E2E3880] transition-colors duration-300 overflow-hidden backdrop-blur-lg"
|
||||
onMouseEnter={handleHover}
|
||||
className="relative group aspect-video border border-[#454554] backdrop-blur-lg overflow-hidden"
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<div className="absolute top-0 xl:p-6 p-3.5 group-hover:opacity-0 transition-all duration-300">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.60278 21.9944L22 2M22 2L21.8896 22M22 2H2"
|
||||
stroke="#D9D9D9"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
<video
|
||||
ref={videoRef}
|
||||
className="absolute top-0 left-0 w-full"
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
>
|
||||
<source src={video} />
|
||||
</video>
|
||||
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-gradient-to-b from-[#13131700] to-[#131317] flex justify-center items-center">
|
||||
{isTouchScreen && (
|
||||
<svg
|
||||
className="group-hover:scale-125 transition-all group-hover:opacity-0"
|
||||
width="64"
|
||||
height="64"
|
||||
viewBox="0 0 64 64"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M54.285 30.971C55.0618 31.4371 55.0618 32.5629 54.285 33.029L17.8174 54.9096C17.0176 55.3895 16 54.8133 16 53.8806L16 10.1194C16 9.18667 17.0176 8.61054 17.8174 9.09044L54.285 30.971Z"
|
||||
fill="#F2F2F2"
|
||||
/>
|
||||
</svg>
|
||||
)}
|
||||
</div>
|
||||
<div className="absolute top-[64%] xl:p-6 p-3.5 space-y-4 group-hover:top-0 transition-all duration-300">
|
||||
<div className="font-gilroy font-medium uppercase 2xl:text-2xl xl:text-xl tracking-wider">
|
||||
|
||||
<div className="p-6 absolute 2xl:top-[83%] 2xl:group-hover:top-[59%] xl:top-[82%] xl:group-hover:top-[53%] top-[78%] group-hover:top-[45%] transition-all duration-300 space-y-4">
|
||||
<p className="font-gilroy font-medium uppercase 2xl:text-2xl xl:text-xl tracking-wider">
|
||||
{title}
|
||||
</div>
|
||||
<div className="2xl:text-xl xl:text-lg">{text}</div>
|
||||
</p>
|
||||
<p className="2xl:text-xl xl:text-lg">{text}</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import React from "react";
|
||||
|
||||
interface IFeatureSliderItem {
|
||||
title: string;
|
||||
text: string;
|
||||
handleHover: () => void;
|
||||
}
|
||||
|
||||
function FeatureSliderItem({ title, text, handleHover }: IFeatureSliderItem) {
|
||||
return (
|
||||
<div
|
||||
className="relative group border border-[#454554] h-1/2 bg-[#2E2E381A] hover:bg-[#2E2E3880] transition-colors duration-300 overflow-hidden backdrop-blur-lg"
|
||||
onMouseEnter={handleHover}
|
||||
>
|
||||
<div className="absolute top-0 xl:p-6 p-3.5 group-hover:opacity-0 transition-all duration-300">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.60278 21.9944L22 2M22 2L21.8896 22M22 2H2"
|
||||
stroke="#D9D9D9"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="absolute top-[64%] xl:p-6 p-3.5 space-y-4 group-hover:top-0 transition-all duration-300">
|
||||
<div className="font-gilroy font-medium uppercase 2xl:text-2xl xl:text-xl tracking-wider">
|
||||
{title}
|
||||
</div>
|
||||
<div className="2xl:text-xl xl:text-lg">{text}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FeatureSliderItem;
|
||||
@@ -0,0 +1,96 @@
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import FeatureSliderItem from "./FeatureSliderItemOld";
|
||||
import { useInView } from "framer-motion";
|
||||
|
||||
function FeatureSlider() {
|
||||
const [selectedItem, setSelectedItem] = useState<string>("");
|
||||
const featureSliderRef = useRef(null);
|
||||
const featureSliderItemRef = useRef<HTMLDivElement>(null);
|
||||
const featureSliderInView = useInView(featureSliderRef);
|
||||
|
||||
useEffect(() => {
|
||||
if (featureSliderInView) {
|
||||
setSelectedItem("/videos/features/virtual_tour.mp4");
|
||||
} else {
|
||||
setSelectedItem("");
|
||||
}
|
||||
}, [featureSliderInView]);
|
||||
|
||||
useEffect(() => {
|
||||
if (featureSliderItemRef.current) {
|
||||
featureSliderItemRef.current.insertAdjacentHTML(
|
||||
"beforeend",
|
||||
`<video muted autoplay loop playsinline class="absolute fade-in">
|
||||
<source src="${selectedItem}" type="video/mp4" />
|
||||
</video>`
|
||||
);
|
||||
|
||||
if (featureSliderItemRef.current.children.length > 1) {
|
||||
setTimeout(() => {
|
||||
featureSliderItemRef.current?.firstElementChild?.remove();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
}, [selectedItem]);
|
||||
|
||||
return (
|
||||
<div ref={featureSliderRef} className="lg:grid grid-cols-2 hidden">
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Виртуальный тур по жилому комплексу"
|
||||
text="Клиент лично оценит угол инсоляции, малые архитектурные формы и ландшафт, перемещаясь по комплексу с помощью тапа."
|
||||
handleHover={() => setSelectedItem("/videos/features/virtual_tour.mp4")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Вся инфрастуктура на одном экране"
|
||||
text="Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти."
|
||||
handleHover={() => setSelectedItem("/videos/features/nks_infra.mp4")}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
ref={featureSliderItemRef}
|
||||
className="relative aspect-video border border-[#454554] bg-black"
|
||||
></div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Конфигуратор интерьера"
|
||||
text="Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали."
|
||||
handleHover={() => setSelectedItem("/videos/features/uralsky.mp4")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Параметрический поиск квартир"
|
||||
text="Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов."
|
||||
handleHover={() => setSelectedItem("/videos/features/parametric.mp4")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Любой рендер за несколько секунд"
|
||||
text="Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации."
|
||||
handleHover={() => setSelectedItem("/videos/features/render.mp4")}
|
||||
/>
|
||||
<FeatureSliderItem
|
||||
title="Формирование вишлиста"
|
||||
text="Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру."
|
||||
handleHover={() => setSelectedItem("/videos/features/wish.mp4")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Интеграция с CRM - системой"
|
||||
text="Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир."
|
||||
handleHover={() => setSelectedItem("/videos/features/integra_crm.mp4")}
|
||||
/>
|
||||
</div>
|
||||
<div className="aspect-video">
|
||||
<FeatureSliderItem
|
||||
title="Отправка коммерческого предложения"
|
||||
text="Коммерческое предложение с выбранными квартирами может быть отправлено клиенту на почту или распечатано и отдано лично в руки."
|
||||
handleHover={() => setSelectedItem("/videos/features/send.mp4")}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FeatureSlider;
|
||||
@@ -0,0 +1,168 @@
|
||||
import { FormEvent, useState } from "react";
|
||||
import api from "../utils/api";
|
||||
import InputMask from "react-input-mask";
|
||||
import useModalStore from "../store/modal";
|
||||
import FeedbackFormSuccess from "./FeedbackFormSuccess";
|
||||
|
||||
function FeedbackForm() {
|
||||
const [modalComponent, setModalComponent] = useModalStore((state) => [
|
||||
state.component,
|
||||
state.setComponent,
|
||||
]);
|
||||
const [fullname, setFullname] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [company, setCompany] = useState<string>("");
|
||||
const [phone, setPhone] = useState<string>("");
|
||||
|
||||
async function handleSubmitSendMail(e: FormEvent<HTMLFormElement>) {
|
||||
e.preventDefault();
|
||||
|
||||
await api.post("mail", {
|
||||
json: {
|
||||
fullname,
|
||||
email,
|
||||
company,
|
||||
phone,
|
||||
},
|
||||
});
|
||||
|
||||
setFullname("");
|
||||
setEmail("");
|
||||
setCompany("");
|
||||
setPhone("");
|
||||
|
||||
setModalComponent(<FeedbackFormSuccess />);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed top-0 left-0 w-full h-full overflow-y-auto">
|
||||
<div className="lg:p-8 sm:p-6 p-4 w-full min-h-full relative flex flex-col justify-center items-center">
|
||||
<div className="space-y-8 bg-[#23232A] 2xl:p-16 xl:p-12 lg:p-8 p-4 rounded-xl 2xl:w-[1472px] xl:w-[1248px] lg:w-[968px]">
|
||||
<p className="font-gilroy 2xl:text-7xl xl:text-6xl sm:text-5xl text-4xl text-gradient w-fit">
|
||||
Свяжитесь с нами
|
||||
</p>
|
||||
|
||||
<form
|
||||
className="grid lg:grid-cols-2 2xl:gap-8 xl:gap-6 gap-4"
|
||||
onSubmit={handleSubmitSendMail}
|
||||
>
|
||||
<div className="2xl:space-y-8 xl:space-y-6 space-y-4">
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor=""
|
||||
className="text-[#D9D9D9] block 2xl:text-xl sm:text-lg text-sm"
|
||||
>
|
||||
Имя Фамилия*
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
type="text"
|
||||
className="lg:text-xl lg:py-4 px-3 py-2 bg-[#454554] outline-none border border-transparent rounded-lg focus:border-[#BC75FF] transition-colors w-full"
|
||||
value={fullname}
|
||||
onChange={(e) => setFullname(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor=""
|
||||
className="text-[#D9D9D9] block 2xl:text-xl sm:text-lg text-sm"
|
||||
>
|
||||
Компания
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="lg:text-xl lg:py-4 px-3 py-2 bg-[#454554] outline-none border border-transparent rounded-lg focus:border-[#BC75FF] transition-colors w-full"
|
||||
value={company}
|
||||
onChange={(e) => setCompany(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="2xl:space-y-8 xl:space-y-6 space-y-4">
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor=""
|
||||
className="text-[#D9D9D9] block 2xl:text-xl sm:text-lg text-sm"
|
||||
>
|
||||
Email*
|
||||
</label>
|
||||
<input
|
||||
required
|
||||
type="email"
|
||||
className="lg:text-xl lg:py-4 px-3 py-2 bg-[#454554] outline-none border border-transparent rounded-lg focus:border-[#BC75FF] transition-colors w-full"
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label
|
||||
htmlFor=""
|
||||
className="text-[#D9D9D9] block 2xl:text-xl sm:text-lg text-sm"
|
||||
>
|
||||
Номер телефона
|
||||
</label>
|
||||
<InputMask
|
||||
maskChar={null}
|
||||
mask={"+7 (999) 999-99-99"}
|
||||
type="text"
|
||||
className="lg:text-xl lg:py-4 px-3 py-2 bg-[#454554] outline-none border border-transparent rounded-lg focus:border-[#BC75FF] transition-colors w-full"
|
||||
value={phone}
|
||||
onChange={(e) => setPhone(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-8">
|
||||
<div className="space-x-4">
|
||||
<div className="2xl:text-xl sm:text-base text-sm flex items-center space-x-4">
|
||||
<div>
|
||||
<input
|
||||
required
|
||||
type="checkbox"
|
||||
defaultChecked={true}
|
||||
className="absolute opacity-0 h-10 w-10 cursor-pointer"
|
||||
/>
|
||||
<div className="bg-[#454554] rounded-lg h-10 w-10 p-1">
|
||||
<svg
|
||||
width="32"
|
||||
height="32"
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="hidden"
|
||||
>
|
||||
<path
|
||||
d="M6.6665 14.6667L13.3332 21.3334L25.3332 10.6667"
|
||||
stroke="#F2F2F2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<span className="text-[#ABABBA] text-opacity-50">
|
||||
Я согласен с
|
||||
</span>{" "}
|
||||
<a href="#" className="text-white">
|
||||
политикой конфиденциальности
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
className="2xl:text-xl w-full lg:py-4 px-8 py-3 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] rounded-full opacity-95 hover:opacity-100 transition-opacity"
|
||||
>
|
||||
Отправить заявку
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FeedbackForm;
|
||||
@@ -0,0 +1,55 @@
|
||||
import { FormEvent, useState } from "react";
|
||||
import api from "../utils/api";
|
||||
import InputMask from "react-input-mask";
|
||||
import useModalStore from "../store/modal";
|
||||
|
||||
function FeedbackForm() {
|
||||
const [fullname, setFullname] = useState<string>("");
|
||||
const [email, setEmail] = useState<string>("");
|
||||
const [company, setCompany] = useState<string>("");
|
||||
const [phone, setPhone] = useState<string>("");
|
||||
|
||||
const [modalComponent, setModalComponent] = useModalStore((state) => [
|
||||
state.component,
|
||||
state.setComponent,
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className="fixed top-0 left-0 w-full h-full overflow-y-auto">
|
||||
<div className="lg:p-8 sm:p-6 p-4 w-full min-h-full relative flex flex-col justify-center items-center">
|
||||
<div className="space-y-8 bg-[#23232A] 2xl:p-24 xl:p-20 lg:p-16 sm:p-14 p-8 rounded-xl 2xl:w-[1472px] xl:w-[1248px] lg:w-[968px]">
|
||||
<div className="2xl:space-y-44 xl:space-y-40 lg:space-y-36 sm:space-y-36 space-y-8">
|
||||
<div className="2xl:space-y-14 space-y-10 xl:w-2/3 lg:w-3/4">
|
||||
<p className="font-gilroy 2xl:text-7xl xl:text-6xl sm:text-5xl text-4xl text-gradient w-fit">
|
||||
Заявка отправлена
|
||||
</p>
|
||||
|
||||
<div className="2xl:space-y-8 space-y-6 xl:space-y-6">
|
||||
<p className="font-gilroy 2xl:text-4xl sm:text-3xl text-2xl">
|
||||
Спасибо за подачу заявки!
|
||||
</p>
|
||||
<p className="2xl:text-2xl sm:text-xl text-lg">
|
||||
Мы ценим ваш интерес к нашей компании и уже начинаем работу по
|
||||
заявке.
|
||||
</p>
|
||||
<p className="2xl:text-2xl sm:text-xl text-lg">
|
||||
Мы свяжемся с вами в ближайшее время для уточнения деталей и
|
||||
ответим на все ваши вопросы.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={() => setModalComponent(null)}
|
||||
className="2xl:text-3xl sm:text-2xl text-lg px-8 py-4 bg-gradient-to-tr from-[#BC75FF] to-[#798FFF] text-white rounded-full opacity-95 hover:opacity-100 transition-opacity lg:w-1/2 w-full"
|
||||
>
|
||||
Продолжить
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default FeedbackForm;
|
||||
@@ -915,8 +915,8 @@ function Map2() {
|
||||
y2="982.338"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#BC75FF" />
|
||||
<stop offset="1" stop-color="#798FFF" />
|
||||
<stop stopColor="#BC75FF" />
|
||||
<stop offset="1" stopColor="#798FFF" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
||||
@@ -32,64 +32,18 @@ function Slider() {
|
||||
className="h-full"
|
||||
>
|
||||
<SwiperSlide>
|
||||
<Slide image={"/images/cards/1.jpg"} />
|
||||
<Slide image={"/images/slider/1.jpg"} />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide>
|
||||
<Slide image={"/images/cards/2.jpg"} />
|
||||
<Slide image={"/images/slider/2.jpg"} />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide>
|
||||
<Slide image={"/images/cards/3.jpg"} />
|
||||
<Slide image={"/images/slider/3.jpg"} />
|
||||
</SwiperSlide>
|
||||
<SwiperSlide>
|
||||
<Slide image={"/images/slider/4.jpg"} />
|
||||
</SwiperSlide>
|
||||
</Swiper>
|
||||
{/* <div className="flex justify-between">
|
||||
<div className="flex items-center space-x-1 text-[#C5C7CE]">
|
||||
<span>{realIndex + 1}</span>
|
||||
<div className="h-[1px] w-12 bg-[#C5C7CE]"></div>
|
||||
<span>8</span>
|
||||
</div>
|
||||
<div className="space-x-2">
|
||||
<button
|
||||
ref={prevRef}
|
||||
className="p-2 bg-[#23242A] enabled:hover:bg-[#2E3038] transition-colors rounded-full"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 12L18 12M6 12L12.3636 6M6 12L12.3636 18"
|
||||
stroke="#F2F2F2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
ref={nextRef}
|
||||
className="p-2 bg-[#23242A] enabled:hover:bg-[#2E3038] transition-colors rounded-full"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M18 12L6 12M18 12L11.6364 18M18 12L11.6364 6"
|
||||
stroke="#F2F2F2"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,8 +118,8 @@ input:checked + div svg {
|
||||
}
|
||||
|
||||
.swiper-pagination-bullet {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
|
||||
.swiper-pagination-bullet-active {
|
||||
|
||||
@@ -1163,6 +1163,11 @@ react-use-measure@^2.1.1:
|
||||
dependencies:
|
||||
debounce "^1.2.1"
|
||||
|
||||
react-yandex-metrika@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/react-yandex-metrika/-/react-yandex-metrika-2.6.0.tgz#9c935c8c7ea5505e34391b9b3e86deb6d50053c9"
|
||||
integrity sha512-8K4wExsNZtY3DTxh1G8a+zWH9Pg8fw23MJcoJ4I/562qrHRnh7L5nteq3lnNL58dnNQbuuHIRoGgMjIo+r1GjA==
|
||||
|
||||
react@^18.2.0:
|
||||
version "18.2.0"
|
||||
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
||||
|
||||
@@ -85,9 +85,17 @@ app.post("/mail", async (req, res) => {
|
||||
let info = await transporter.sendMail({
|
||||
from: `${email}`, // sender address
|
||||
to: "info@graff.tech", // list of receivers
|
||||
subject: fullname, // Subject line
|
||||
text: `${company} ${phone}`, // plain text body
|
||||
html: `${company} ${phone}`, // html body
|
||||
subject: 'Заявка с сайта estate.graff.tech', // Subject line
|
||||
text: `
|
||||
Имя Фамилия: ${fullname}
|
||||
Телефон: ${phone}
|
||||
Компания: ${company}
|
||||
`, // plain text body
|
||||
html: `<div>
|
||||
<p>Имя Фамилия: ${fullname}</p>
|
||||
<p>Телефон: ${phone}</p>
|
||||
<p>Компания: ${company}</p>
|
||||
</div>`, // html body
|
||||
});
|
||||
|
||||
console.log(info);
|
||||
|
||||