diff --git a/client/public/images/1135.jpg b/client/public/images/1135.jpg new file mode 100644 index 0000000..f042b35 Binary files /dev/null and b/client/public/images/1135.jpg differ diff --git a/client/public/images/feature.jpg b/client/public/images/feature.jpg new file mode 100644 index 0000000..3c6e8d7 Binary files /dev/null and b/client/public/images/feature.jpg differ diff --git a/client/public/images/shapes/1.svg b/client/public/images/shapes/1.svg new file mode 100644 index 0000000..cd70484 --- /dev/null +++ b/client/public/images/shapes/1.svg @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/public/images/shapes/2.svg b/client/public/images/shapes/2.svg new file mode 100644 index 0000000..be98de0 --- /dev/null +++ b/client/public/images/shapes/2.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/public/images/shapes/3.svg b/client/public/images/shapes/3.svg new file mode 100644 index 0000000..bd27c67 --- /dev/null +++ b/client/public/images/shapes/3.svg @@ -0,0 +1,266 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/public/images/shapes/4.svg b/client/public/images/shapes/4.svg new file mode 100644 index 0000000..06625fd --- /dev/null +++ b/client/public/images/shapes/4.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/App.tsx b/client/src/App.tsx index d0f820b..1e5a2ce 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -12,6 +12,7 @@ import api from "./utils/api"; import { OrbitControls, PerspectiveCamera, Wireframe } from "@react-three/drei"; import ComplexCard from "./components/ComplexCard"; import Map2 from "./components/Map2"; +import FeatureCard from "./components/FeatureCard"; function App() { const parallaxRef = useRef(null); @@ -31,6 +32,31 @@ function App() { const helmetInView = useInView(helmetRef); // const [helmetIsAnim, setHelmetIsAnim] = useState(true); + const featureImagesContainer = useRef(null); + const featureImages = [ + "https://images.unsplash.com/photo-1682595950157-8d1cc0ef388f?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60", + "https://images.unsplash.com/photo-1682402178953-f2cb484d4024?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHw1fHx8ZW58MHx8fHw%3D&auto=format&fit=crop&w=500&q=60", + "https://plus.unsplash.com/premium_photo-1676648534973-dd205cb63d99?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxMnx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60", + "https://images.unsplash.com/photo-1682353213492-8433d437855a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwxM3x8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=60", + ]; + const [selectedFeatureImageIndex, setSelectedFeatureImageIndex] = + useState(0); + + useEffect(() => { + if (featureImagesContainer.current) { + featureImagesContainer.current.insertAdjacentHTML( + "beforeend", + `
` + ); + + if (featureImagesContainer.current.children.length > 1) { + setTimeout(() => { + featureImagesContainer.current?.firstElementChild?.remove(); + }, 1000); + } + } + }, [selectedFeatureImageIndex]); + function handleScroll() { if (parallaxRef.current) { parallaxRef.current.style.transform = `translateY(${ @@ -93,9 +119,9 @@ function App() {
- -
+
-
-

- Эффективность инстумента продаж в цифрах +

+

+ Эффективность инстумента +
+ продаж в цифрах

- Мы собрали статистику за 10 лет работы с застройщиками, - реализовав 21 проект + Мы собрали статистику за 10 лет работы +
с застройщиками, реализовав 21 проект

-
-
-

- 10 -

-

что-то на умном

+
+
+
+
+

+ 10 +

+

что-то на умном

+
+
+

+ 26 +

+

+ что-то на умном +
в две строчки +

+
+
+

+ 32% +

+

+ что-то на умном +
в две строчки +

+
+
+

+ 12% +

+

+ что-то на умном +
в две строчки +

+
+
+
-
-

- 26 -

-

- что-то на умном -
в две строчки -

-
-
-

- 32% -

-

- что-то на умном -
в две строчки -

-
-
-

- 12% -

-

- что-то на умном -
в две строчки -

+
+
-
-
+
Функциональные возможности @@ -202,8 +240,57 @@ function App() { преимущества объекта
-
- +
+ +
+ {/*
*/} + {/* */} +
+ setSelectedFeatureImageIndex(0)} + /> +
+ {/*
*/} +
+
+ setSelectedFeatureImageIndex(1)} + /> + setSelectedFeatureImageIndex(2)} + /> + setSelectedFeatureImageIndex(3)} + /> + setSelectedFeatureImageIndex(2)} + /> + setSelectedFeatureImageIndex(1)} + /> + setSelectedFeatureImageIndex(0)} + /> + setSelectedFeatureImageIndex(3)} + /> +
@@ -254,223 +341,79 @@ function App() {
+
-
-
-
+
+
+
Анализируем
поведение
пользователей
-
- Система внутренней аналитики программы собирает информацию о - поведении пользователя и эффективности работы менеджеров для - создания отчета, содержащего необходимые метрики +
+

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

+

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

-
-
-
-

- Конверсия менеджеров в брони -

-
-
- К.Н. Федоров - - 45% +
+
+
+

Конверсия менеджеров в брони

+
+
+ + К. Н. Федоров + +
+
+
+ 45%
-
- И.Ф. Яковлева - - 30% + +
+ + И. Ф. Яковлева + +
+
+
+ 30%
-
- А.М. Ташева - - 20% -
-
- А.А. Фетисов - - 5% + +
+ + А. М. Ташева + +
+
+
+ 20%
-
-

- Популярные типы квартир, % -

-
- -
-
- - Студии -
-
- - 1-к. квартиры -
-
- - 2-к. квартиры -
-
- - 3-к. квартиры -
-
- - 4-к. квартиры -
-
-
-
-
-

Воронка продаж

-
-
-
-
- - Сеансы - -
-
- 100% -
-
-
-
- - В избранное - -
-
- 93,47% -
-
-
-
- - Брони - -
-
- 45,68% -
-
-
-
- - Продажи - -
-
- 29,13% -
-
-
-
-
-

- Среднее -
- время сеанса, -
мин. -

-

- 12:45 -

-
-
-

- Сформировано -
- коммерческих -
- предложений, шт -

-

- 856 -

-
-
-

- Конверсия -
- из сеанса -
в продажу, % -

-

- 12,44 -

-
-
-

- Продано через -
- Graff.estate, -
- млн.руб. -

-

- 134,5 -

-
-
-
- Полученный отчет позволяет сделать процесс демонстрации жилого - комплекса еще эффективнее -
+
2
+
3
+
+
+
1
+
2
+
3
+
4
+
@@ -516,6 +459,7 @@ function App() {
+
diff --git a/client/src/components/FeatureCard.tsx b/client/src/components/FeatureCard.tsx new file mode 100644 index 0000000..86bc0bf --- /dev/null +++ b/client/src/components/FeatureCard.tsx @@ -0,0 +1,46 @@ +import React from "react"; + +interface IFeatureCard { + text: string; + image?: string; + handleMouseEnter: () => void; +} + +function FeatureCard({ text, image, handleMouseEnter }: IFeatureCard) { + return ( +
+ + + + + + + + + + +

{text}

+ {/* */} +
+ ); +} + +export default FeatureCard; diff --git a/client/src/index.css b/client/src/index.css index 321446f..4ab96a5 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -60,3 +60,16 @@ body { .text-gradient { @apply bg-gradient-to-bl from-[#BC75FF] to-[#798FFF] text-transparent bg-clip-text; } + +.fade-in-image { + animation: fadeIn 0.5s; +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} diff --git a/server/app.js b/server/app.js index 45fab20..34d7523 100644 --- a/server/app.js +++ b/server/app.js @@ -2,8 +2,8 @@ import express from "express"; import cors from "cors"; import ky from "ky"; import mongoose from "mongoose"; -import Mail from "./models/Mail.js"; import nodemailer from "nodemailer"; +import Mail from "./models/Mail.js"; const app = express(); const port = 3003; @@ -70,10 +70,6 @@ app.post("/mail", async (req, res) => { const { fullname, email, company, phone } = req.body; await Mail.create(req.body); - // mx0.graff.tech - - let testAccount = await nodemailer.createTestAccount(); - // create reusable transporter object using the default SMTP transport let transporter = nodemailer.createTransport({ host: "mail.netangels.ru", @@ -96,20 +92,13 @@ app.post("/mail", async (req, res) => { console.log(info); - // console.log("Message sent: %s", info.messageId); - // Message sent: - - // Preview only available when sending through an Ethereal account - // console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info)); - // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou... - res.send({ ok: 1 }); }); app.listen(port, async () => { await mongoose.connect( "mongodb://192.168.1.159:27017/", - { dbName: "test" }, + { dbName: "estate" }, console.log("DB connection...") );