diff --git a/client/src/components/FeatureSlider.tsx b/client/src/components/FeatureSlider.tsx
index 08f3687..6848c67 100644
--- a/client/src/components/FeatureSlider.tsx
+++ b/client/src/components/FeatureSlider.tsx
@@ -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("");
- const featureSliderRef = useRef(null);
- const featureSliderItemRef = useRef(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",
- ``
- );
-
- if (featureSliderItemRef.current.children.length > 1) {
- setTimeout(() => {
- featureSliderItemRef.current?.firstElementChild?.remove();
- }, 1000);
- }
- }
- }, [selectedItem]);
-
return (
-
-
- setSelectedItem("/videos/features/virtual_tour.webm")}
- />
- setSelectedItem("/videos/features/nks_infra.webm")}
- />
-
-
-
- setSelectedItem("/videos/features/uralsky.webm")}
- />
- setSelectedItem("/videos/features/parametric.webm")}
- />
-
-
- setSelectedItem("/videos/features/render.webm")}
- />
- setSelectedItem("/videos/features/wish.webm")}
- />
-
-
- setSelectedItem("/videos/features/integra_crm.webm")}
- />
-
-
- setSelectedItem("/videos/features/send.webm")}
- />
-
+
+
+
+
+
+
+
+
+
);
}
diff --git a/client/src/components/FeatureSliderItem.tsx b/client/src/components/FeatureSliderItem.tsx
index 3b05de2..9d4c98f 100644
--- a/client/src/components/FeatureSliderItem.tsx
+++ b/client/src/components/FeatureSliderItem.tsx
@@ -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
(null);
+ const [isTouchScreen, setIsTouchScreen] = useState(false);
+
+ function handleMouseEnter() {
+ videoRef.current?.play();
+ }
+
+ function handleMouseLeave() {
+ videoRef.current?.pause();
+ }
+
+ useEffect(() => {
+ if (navigator.maxTouchPoints > 1) {
+ setIsTouchScreen(true);
+ }
+ }, []);
+
return (
-
-
+
+
+
+ {isTouchScreen && (
+
+ )}
-
);
diff --git a/client/src/components/FeatureSliderItemOld.tsx b/client/src/components/FeatureSliderItemOld.tsx
new file mode 100644
index 0000000..3b05de2
--- /dev/null
+++ b/client/src/components/FeatureSliderItemOld.tsx
@@ -0,0 +1,40 @@
+import React from "react";
+
+interface IFeatureSliderItem {
+ title: string;
+ text: string;
+ handleHover: () => void;
+}
+
+function FeatureSliderItem({ title, text, handleHover }: IFeatureSliderItem) {
+ return (
+
+ );
+}
+
+export default FeatureSliderItem;
diff --git a/client/src/components/FeatureSliderOld.tsx b/client/src/components/FeatureSliderOld.tsx
new file mode 100644
index 0000000..2acf108
--- /dev/null
+++ b/client/src/components/FeatureSliderOld.tsx
@@ -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
("");
+ const featureSliderRef = useRef(null);
+ const featureSliderItemRef = useRef(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",
+ ``
+ );
+
+ if (featureSliderItemRef.current.children.length > 1) {
+ setTimeout(() => {
+ featureSliderItemRef.current?.firstElementChild?.remove();
+ }, 1000);
+ }
+ }
+ }, [selectedItem]);
+
+ return (
+
+
+ setSelectedItem("/videos/features/virtual_tour.mp4")}
+ />
+ setSelectedItem("/videos/features/nks_infra.mp4")}
+ />
+
+
+
+ setSelectedItem("/videos/features/uralsky.mp4")}
+ />
+ setSelectedItem("/videos/features/parametric.mp4")}
+ />
+
+
+ setSelectedItem("/videos/features/render.mp4")}
+ />
+ setSelectedItem("/videos/features/wish.mp4")}
+ />
+
+
+ setSelectedItem("/videos/features/integra_crm.mp4")}
+ />
+
+
+ setSelectedItem("/videos/features/send.mp4")}
+ />
+
+
+ );
+}
+
+export default FeatureSlider;
diff --git a/client/src/components/FeedbackForm.tsx b/client/src/components/FeedbackForm.tsx
new file mode 100644
index 0000000..d1e63be
--- /dev/null
+++ b/client/src/components/FeedbackForm.tsx
@@ -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("");
+ const [email, setEmail] = useState("");
+ const [company, setCompany] = useState("");
+ const [phone, setPhone] = useState("");
+
+ async function handleSubmitSendMail(e: FormEvent) {
+ e.preventDefault();
+
+ await api.post("mail", {
+ json: {
+ fullname,
+ email,
+ company,
+ phone,
+ },
+ });
+
+ setFullname("");
+ setEmail("");
+ setCompany("");
+ setPhone("");
+
+ setModalComponent();
+ }
+
+ return (
+
+
+
+
+ Свяжитесь с нами
+
+
+
+
+
+
+ );
+}
+
+export default FeedbackForm;
diff --git a/client/src/components/FeedbackFormSuccess.tsx b/client/src/components/FeedbackFormSuccess.tsx
new file mode 100644
index 0000000..3dd0258
--- /dev/null
+++ b/client/src/components/FeedbackFormSuccess.tsx
@@ -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("");
+ const [email, setEmail] = useState("");
+ const [company, setCompany] = useState("");
+ const [phone, setPhone] = useState("");
+
+ const [modalComponent, setModalComponent] = useModalStore((state) => [
+ state.component,
+ state.setComponent,
+ ]);
+
+ return (
+
+
+
+
+
+
+ Заявка отправлена
+
+
+
+
+ Спасибо за подачу заявки!
+
+
+ Мы ценим ваш интерес к нашей компании и уже начинаем работу по
+ заявке.
+
+
+ Мы свяжемся с вами в ближайшее время для уточнения деталей и
+ ответим на все ваши вопросы.
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default FeedbackForm;
diff --git a/client/src/components/Map2.tsx b/client/src/components/Map2.tsx
index 4067bd7..2822606 100644
--- a/client/src/components/Map2.tsx
+++ b/client/src/components/Map2.tsx
@@ -915,8 +915,8 @@ function Map2() {
y2="982.338"
gradientUnits="userSpaceOnUse"
>
-
-
+
+
diff --git a/client/src/components/Slider/Slider.tsx b/client/src/components/Slider/Slider.tsx
index eb5540a..3310a36 100644
--- a/client/src/components/Slider/Slider.tsx
+++ b/client/src/components/Slider/Slider.tsx
@@ -32,64 +32,18 @@ function Slider() {
className="h-full"
>
-
+
-
+
-
+
+
+
+
- {/*
-
-
{realIndex + 1}
-
-
8
-
-
-
*/}
);
}
diff --git a/client/src/index.css b/client/src/index.css
index 5133838..9ce40c9 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -118,8 +118,8 @@ input:checked + div svg {
}
.swiper-pagination-bullet {
- width: 16px;
- height: 16px;
+ width: 12px;
+ height: 12px;
}
.swiper-pagination-bullet-active {
diff --git a/client/yarn.lock b/client/yarn.lock
index c3526db..f9c4a96 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -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"
diff --git a/server/app.js b/server/app.js
index 34d7523..27cb567 100644
--- a/server/app.js
+++ b/server/app.js
@@ -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: `
+
Имя Фамилия: ${fullname}
+
Телефон: ${phone}
+
Компания: ${company}
+
`, // html body
});
console.log(info);