diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..88197dc --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "baseUrl": "src", + + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "strictNullChecks": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] + } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index c236fb6..4bdbc1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,13 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "animejs": "^3.2.1", + "framer-motion": "^10.8.5", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-minimal-pie-chart": "^8.4.0", "react-scripts": "5.0.1", + "swiper": "^9.1.1", "web-vitals": "^2.1.4" } }, @@ -2130,6 +2134,21 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", @@ -4251,6 +4270,11 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "node_modules/@types/svg-path-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/svg-path-parser/-/svg-path-parser-1.1.3.tgz", + "integrity": "sha512-F1Y6lQIto5b2sKCseVUsFfY5J+8PIhhX4jrDVxpth4m7hwM2OdySh3iTLeR35lEhl/K4ZMEF+GDAwTl7yJcO5Q==" + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.5", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", @@ -4827,6 +4851,11 @@ "ajv": "^6.9.1" } }, + "node_modules/animejs": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz", + "integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==" + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -8329,6 +8358,29 @@ "url": "https://www.patreon.com/infusion" } }, + "node_modules/framer-motion": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.8.5.tgz", + "integrity": "sha512-qwvUAIwCc6fEZhg7ST+/z+f7Vt882jJvLiWZUHNdq2oZ/Y7gM6mLlpKi9xQg+pLu6DQVypikcKQ+MKnoFoXAJg==", + "dependencies": { + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -14342,6 +14394,18 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-minimal-pie-chart": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/react-minimal-pie-chart/-/react-minimal-pie-chart-8.4.0.tgz", + "integrity": "sha512-A0wG+6mRjboyMxMDrzQNWp+2+GSn2ai4ERzRFHLp/OCC45PwIR1DpDVjwedawO+5AtFpzBRQKSFm3ZUxrqIEzA==", + "dependencies": { + "@types/svg-path-parser": "^1.1.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18", + "react-dom": "^16.8.0 || ^17.0.0 || ^18" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -15293,6 +15357,11 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "node_modules/ssr-window": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz", + "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==" + }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -15683,6 +15752,27 @@ "boolbase": "~1.0.0" } }, + "node_modules/swiper": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-9.1.1.tgz", + "integrity": "sha512-D1zArOwI6XCXCYBULPA4jTxpqp5SQtvntjinbXNZwXzj6P3KS51zSWuMarCLXq5oRISay4nX+TuShpxz8qhtbw==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/swiperjs" + }, + { + "type": "open_collective", + "url": "http://opencollective.com/swiper" + } + ], + "dependencies": { + "ssr-window": "^4.0.2" + }, + "engines": { + "node": ">= 4.7.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -18597,6 +18687,21 @@ "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "requires": {} }, + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "@eslint-community/eslint-utils": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", @@ -20179,6 +20284,11 @@ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.1.tgz", "integrity": "sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==" }, + "@types/svg-path-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@types/svg-path-parser/-/svg-path-parser-1.1.3.tgz", + "integrity": "sha512-F1Y6lQIto5b2sKCseVUsFfY5J+8PIhhX4jrDVxpth4m7hwM2OdySh3iTLeR35lEhl/K4ZMEF+GDAwTl7yJcO5Q==" + }, "@types/testing-library__jest-dom": { "version": "5.14.5", "resolved": "https://registry.npmjs.org/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.5.tgz", @@ -20603,6 +20713,11 @@ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "requires": {} }, + "animejs": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/animejs/-/animejs-3.2.1.tgz", + "integrity": "sha512-sWno3ugFryK5nhiDm/2BKeFCpZv7vzerWUcUPyAZLDhMek3+S/p418ldZJbJXo5ZUOpfm2kP2XRO4NJcULMy9A==" + }, "ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -23163,6 +23278,15 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" }, + "framer-motion": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.8.5.tgz", + "integrity": "sha512-qwvUAIwCc6fEZhg7ST+/z+f7Vt882jJvLiWZUHNdq2oZ/Y7gM6mLlpKi9xQg+pLu6DQVypikcKQ+MKnoFoXAJg==", + "requires": { + "@emotion/is-prop-valid": "^0.8.2", + "tslib": "^2.4.0" + } + }, "fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -27312,6 +27436,14 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-minimal-pie-chart": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/react-minimal-pie-chart/-/react-minimal-pie-chart-8.4.0.tgz", + "integrity": "sha512-A0wG+6mRjboyMxMDrzQNWp+2+GSn2ai4ERzRFHLp/OCC45PwIR1DpDVjwedawO+5AtFpzBRQKSFm3ZUxrqIEzA==", + "requires": { + "@types/svg-path-parser": "^1.1.3" + } + }, "react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -28011,6 +28143,11 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" }, + "ssr-window": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz", + "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==" + }, "stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", @@ -28307,6 +28444,14 @@ } } }, + "swiper": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/swiper/-/swiper-9.1.1.tgz", + "integrity": "sha512-D1zArOwI6XCXCYBULPA4jTxpqp5SQtvntjinbXNZwXzj6P3KS51zSWuMarCLXq5oRISay4nX+TuShpxz8qhtbw==", + "requires": { + "ssr-window": "^4.0.2" + } + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index f448f12..8cb424a 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,13 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", + "animejs": "^3.2.1", + "framer-motion": "^10.8.5", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-minimal-pie-chart": "^8.4.0", "react-scripts": "5.0.1", + "swiper": "^9.1.1", "web-vitals": "^2.1.4" }, "scripts": { diff --git a/src/App.js b/src/App.js index 3784575..9f187f4 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,26 @@ import logo from './logo.svg'; import './App.css'; +import { Header } from 'components/Header/Header'; +import { Title } from 'components/Title/Title'; +import { CounterComponent } from 'components/CounterComponent/CounterComponent'; +import { SwiperComponent } from 'components/SwiperComponent/SwiperComponent'; +import { VirtualTour } from 'components/VirtualTour/VirtualTour'; +import { Analytics } from 'components/Analytics/Analytics'; +import { MapComponent } from 'components/MapComponent/MapComponent'; function App() { return ( -
-
- logo -

- Edit src/App.js and save to reload. -

- - Learn React - -
-
+ <> +
+ +
+ + + + + +
+ ); } diff --git a/src/components/Analytics/Analytics.css b/src/components/Analytics/Analytics.css new file mode 100644 index 0000000..b05c432 --- /dev/null +++ b/src/components/Analytics/Analytics.css @@ -0,0 +1,701 @@ +.analytics__container { + margin-bottom: 160px; + font-family: "GilroyWebRegular"; +} + +.analytics-text-container { + display: flex; + flex-direction: column; + gap: 32px; + width: 496px; +} + +.analytics-section { + align-items: center; + gap: 64px; + display: flex; + flex-direction: column; +} + +.mobile { + display: none; +} + +.graph__container { + display: -ms-grid; + display: grid; + -ms-grid-rows: 1fr 26px auto; + grid-template-rows: 1fr auto; + gap: 26px; + margin-bottom: 80px; +} + +.graph__row_1 { + -webkit-box-sizing: border-box; + box-sizing: border-box; + display: -ms-grid; + display: grid; + -ms-grid-columns: 1fr 30px 1fr 30px 1fr; + grid-template-columns: 1fr 1fr 1fr; + gap: 30px; +} + +.graph__row_item { + height: 280px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 16px; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + background: #1C1D21; + border-radius: 8px; + padding: 32px; + font-style: normal; + font-weight: 500; + font-size: 20px; + line-height: 120%; + /* identical to box height, or 24px */ + + + /* Landing/White */ + + color: #F2F2F2; +} + + + + +.graph__row_2 { + display: -ms-grid; + display: grid; + -ms-grid-columns: 175px 30px 175px 30px 175px 30px 175px 30px 380px; + grid-template-columns: 175px 175px 175px 175px 380px; + gap: 30px; +} + + + +.graph__row_item_s { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + font-weight: 600; + font-size: 14px; + line-height: 120%; + padding: 24px; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + gap: 20px; + padding: 24px; + background: #1C1D21; + border-radius: 8px; + -webkit-box-sizing: border-box; + box-sizing: border-box; +} + +.graph__text { + font-weight: 400; + font-size: 18px; + line-height: 140%; + color: #C5C7CE; + background-color: transparent; +} + +.graph__text_mobile { + display: none; + font-weight: 400; + font-size: 18px; + line-height: 140%; + color: #F2F2F2; +} + +.graph__row_item_l { + background-color: transparent; +} + +.graph__color_elem { + font-weight: 400; + font-size: 48px; + line-height: 100%; + /* identical to box height, or 48px */ + + + /* Landing/Pink */ + + color: #D375FF; +} + +.graph__bar_row { + display: -ms-grid; + display: grid; + -ms-grid-columns: auto 16px 2fr 16px auto; + grid-template-columns: auto 2fr auto; + gap: 16px; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.graph__title { + margin-bottom: 8px; +} + +.graph__bar_row:last-of-type { + margin-bottom: 0; + +} + +.graph__caption { + width: 98px; + margin: 0; + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 140%; +} + +.graph__bar_width_container { + width: 169px; +} + +.graph__bar_1 { + width: 100%; + background: linear-gradient(180deg, #BC75FF 0%, #798FFF 100%); + border-radius: 2px; + height: 24px; +} + +.graph__procentage { + font-size: 12px; + font-weight: 500; + line-height: 130%; + margin: 0; + text-align: center; + width: 25px; + text-align: left; +} + +.graph__bar_2 { + margin-right: 41px; + background: -o-linear-gradient(33.25deg, #D375FF 19.74%, #798FFF 82.32%); + background: linear-gradient(56.75deg, #D375FF 19.74%, #798FFF 82.32%); + border-radius: 2px; + height: 24px; + width: 80%; + +} + +.graph__bar_3 { + + background: -o-linear-gradient(33.25deg, #D375FF 19.74%, #798FFF 82.32%); + + background: linear-gradient(56.75deg, #D375FF 19.74%, #798FFF 82.32%); + border-radius: 2px; + height: 24px; + width: 60%; + + + +} + +.graph__bar_4 { + background: -o-linear-gradient(33.25deg, #D375FF 19.74%, #798FFF 82.32%); + background: linear-gradient(56.75deg, #D375FF 19.74%, #798FFF 82.32%); + border-radius: 2px; + height: 24px; + width: 15%; + + +} + +.bar__container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; +} + +.chart__container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + gap: 49px; +} + +.legend__container { + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 140%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 6px; + height: auto; +} + +.legend__point { + width: 12px; + height: 12px; + border-radius: 50%; +} + +.legend__row { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + gap: 18px; +} + +.legend__caption { + margin: 0; + white-space: nowrap; +} + +.color { + background: #7A31C3; +} + +.color1 { + background: #798FFF; +} + +.color2 { + background: #D375FF; +} + +.color3 { + background: #8742F8; + ; +} + +.color4 { + background: #FB57F4; + ; +} + +.sales__container { + -webkit-box-align: start; + -ms-flex-align: start; + align-items: flex-start; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + gap: 15px; + font-style: normal; +} + +.background__row { + background: -o-linear-gradient(33.25deg, rgba(211, 117, 255, 0.1) 19.74%, rgba(121, 143, 255, 0.1) 82.32%), rgba(124, 142, 255, 0.1); + background: linear-gradient(56.75deg, rgba(211, 117, 255, 0.1) 19.74%, rgba(121, 143, 255, 0.1) 82.32%), rgba(124, 142, 255, 0.1); + border-radius: 2px; + width: 262px; + height: 30px; +} + +.sales__bar { + width: 100%; + + padding-top: 3px; + padding-bottom: 5px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-size: 14px; + line-height: 140%; + /* identical to box height, or 17px */ + + text-align: center; + border-radius: 2px; + height: 30px; + text-align: center; + background: linear-gradient(180deg, #BC75FF 0%, #798FFF 100%); +} + +.sales__row { + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + gap: 16px; + width: 100%; +} + + +.sales_bar_width { + width: 90%; +} + +.sales_bar_width1 { + width: 45%; +} + +.sales_bar_width3 { + width: 30%; +} + +.background__row { + width: 262px; + + -webkit-box-pack: center; + + -ms-flex-pack: center; + + justify-content: center; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + +} + +.sales__procentage { + font-weight: 500; + font-size: 12px; + line-height: 130%; + +} + +.graph__title_s { + font-family: "Inter"; + width: fit-content; + color: #F2F2F2; + height: 51px; +} + + +@media (max-width: 1300px) { + + .background__row { + width: 216px; + } + + .graph__bar_width_container { + width: 123px; + } + + + .graph__row_2 { + -ms-grid-columns: 151px 15px 151px 15px 151px 15px 151px 15px 318px; + grid-template-columns: 151px 151px 151px 151px 318px; + gap: 15px; + } + + + .graph__row_1 { + -ms-grid-columns: 318px 15px 318px 15px 318px; + grid-template-columns: 318px 318px 318px; + gap: 15px; + } + + .graph__row_item { + height: 266px; + padding: 24px; + } + + + .chart__container { + gap: 19px; + } + + .graph__row_item_l { + margin-left: 15px; + } + + + + .analytics__container { + margin-bottom: 40px; + } + + +} + +@media (max-width: 1024px) { + + + .chart__container { + gap: 54px; + } + + .bar__container { + width: 100%; + } + + .background__row { + width: 100%; + + } + + .sales__procentage { + width: 37px; + } + + .desktop { + display: none; + } + + .mobile { + display: block; + } + + + + .graph__row_1 { + grid-template-columns: repeat(auto-fit, minmax(405px, 1fr)); + width: 100%; + } + + .graph__row_mobile { + display: none; + } + + .graph__row_2 { + grid-template-columns: repeat(auto-fit, minmax(175px, 1fr)); + } + + .graph__row_item { + height: 240px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + + .graph__row_item_s { + -webkit-box-sizing: border-box; + box-sizing: border-box; + height: 100%; + gap: 28px; + } + + .analytics__container { + padding: 120px 20px 80px; + -webkit-box-sizing: border-box; + box-sizing: border-box; + + } + + .graph__text { + display: none; + } + + + .graph__bar_width_container { + width: 100%; + } + + .graph__text_mobile { + display: block; + font-style: normal; + font-weight: 400; + font-size: 2.8vw; + line-height: 140%; + } +} + +@media (max-width: 890px) { + .graph__container { + display: -ms-grid; + display: grid; + -ms-grid-columns: 1fr 20px auto; + grid-template-columns: 1fr auto; + gap: 20px; + row-gap: 0; + } + +} + +@media (max-width: 690px) { + + + .graph__container { + display: block; + } + + .graph__row_2 { + margin-top: 10px; + } + + + .analytics__container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + } + + .sales__procentage { + width: 37px; + + } + + + .chart__container { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + gap: 35px; + } + + .bar__container { + width: 100%; + } + + + .graph__bar_width_container { + width: 100%; + } + + .graph__row_1 { + gap: 10px; + } + + .sales__row { + -webkit-box-pack: start; + -ms-flex-pack: start; + justify-content: flex-start; + } + + .background__row { + width: 100%; + + } + + .desktop { + display: none; + } + + .mobile { + display: block; + } + + .analytics__container { + padding: 40px 10px 80px; + } + + .graph__row_1 { + width: 100%; + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: vertical; + -webkit-box-direction: normal; + -ms-flex-direction: column; + flex-direction: column; + + } + + .graph__row_item { + height: auto; + width: 100%; + padding: 20px; + } + + + .graph__row_2 { + display: -ms-grid; + display: grid; + -ms-grid-columns: 1fr 10px 1fr; + grid-template-columns: 1fr 1fr; + gap: 10px; + } + + .graph__text { + display: none; + } + + + + + + .graph__row_mobile { + display: none; + } + + + + .legend__caption { + font-family: "Inter"; + font-weight: 400; + font-size: 14px; + line-height: 140%; + } + + + + .graph__row_item_s { + padding: 16px; + gap: 14px; + font-size: 14px; + } + + .graph__color_elem { + font-size: 47px; + } + + .analytics__container { + margin-bottom: 0; + } + + .graph__text_mobile { + font-size: 4.5vw; + } + + .graph__container { + margin-bottom: 40px; + } + +} \ No newline at end of file diff --git a/src/components/Analytics/Analytics.js b/src/components/Analytics/Analytics.js new file mode 100644 index 0000000..aabb286 --- /dev/null +++ b/src/components/Analytics/Analytics.js @@ -0,0 +1,150 @@ +import './Analytics.css' +import { PieChartComp } from 'components/Piechart/Piechart' + +export const Analytics = () => { + return ( +
+
+

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

+

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

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

К.Н. Федоров

+
+
+
+
+
+

45%

+
+
+

И.Ф. Яковлева

+
+
+
+
+
+

30%

+ +
+
+

А.М. Ташева

+
+
+
+
+
+

28%

+ +
+
+

А.А. Фетисов

+
+
+
+
+
+

5%

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

Студии

+
+
+
+

1-к. квартиры

+
+
+
+

2-к. квартиры

+
+
+
+

3-к. квартиры

+
+
+
+

4-к. квартиры

+
+
+
+
+
+ Воронка продаж +
+
+
+
Сеансы
+
+
+
+
+
+
В избранное
+
+
93,47%
+
+
+
+
Брони
+
+
45,68%
+
+
+
+
Продажи
+
+
29,13%
+
+ +
+
+
+
+
+ Среднее время сеанса, мин. +
+ 12:45 +
+
+
+ Сформировано коммерческих предложений, шт +
+ 856 +
+
+
+ Конверсия из сеанса в продажу, % +
+ 12,44 +
+
+
+ Продано через Graff.estate, млн.руб. +
+ 134,5 +
+
+
+
Полученный отчет позволяет сделать процесс демонстрации жилого комплекса еще эффективнее.
+
+
+
+
+ +
) +} \ No newline at end of file diff --git a/src/components/Counter/Counter.css b/src/components/Counter/Counter.css new file mode 100644 index 0000000..b600aa4 --- /dev/null +++ b/src/components/Counter/Counter.css @@ -0,0 +1,28 @@ +.count-container { + user-select: none; + box-sizing: border-box; + border-top: 2px solid #23242A; + padding-top: 32px; + padding-bottom: 22px; + margin-bottom: 118px; + +} + +.count { + margin: 0; + font-style: normal; + font-weight: 400; + font-size: 96px; + line-height: 100%; + /* identical to box height, or 96px */ + + + /* B-P */ + + background: linear-gradient(180deg, #BC75FF 0%, #798FFF 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; + +} \ No newline at end of file diff --git a/src/components/Counter/Counter.js b/src/components/Counter/Counter.js new file mode 100644 index 0000000..d7b2ce5 --- /dev/null +++ b/src/components/Counter/Counter.js @@ -0,0 +1,36 @@ +import './Counter.css' +import { animate, useInView } from "framer-motion"; +import React, { useEffect, useRef } from "react"; + + + +export const Counter = ({ from, to, text, precentage }) => { + const nodeRef = useRef(); + const isInView = useInView(nodeRef) + + + useEffect(() => { + + const node = nodeRef.current; + + const controls = animate(from, to, { + duration: 1, + onUpdate(value) { + if (precentage) { + node.textContent = value.toFixed(0) + '%' + } else { + node.textContent = value.toFixed(0) + } + } + }); + + return () => controls.stop(); + }, [isInView]); + + return ( +
+

; + {text} +

+ ) +} diff --git a/src/components/CounterComponent/CounterComponent.css b/src/components/CounterComponent/CounterComponent.css new file mode 100644 index 0000000..a5a4e67 --- /dev/null +++ b/src/components/CounterComponent/CounterComponent.css @@ -0,0 +1,12 @@ + + +.counter-row { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + gap: 32px; +} + + +.section-counter { + margin-bottom: 200px; +} \ No newline at end of file diff --git a/src/components/CounterComponent/CounterComponent.js b/src/components/CounterComponent/CounterComponent.js new file mode 100644 index 0000000..3e83cbd --- /dev/null +++ b/src/components/CounterComponent/CounterComponent.js @@ -0,0 +1,23 @@ +import './CounterComponent.css' +import { Counter } from "components/Counter/Counter" +import {zero, counters, precentage} from 'utils/utils' + +export const CounterComponent = () => { + + + return (
+
+

Эффективность инстумента

продаж в цифрах

+

Мы собрали статистику за 10 лет работы

+ с застройщиками, реализовав 21 проект.

+
+
+ {counters.map((i) => ( + + ))} +
+ +
) +} \ No newline at end of file diff --git a/src/components/Header/Header.css b/src/components/Header/Header.css new file mode 100644 index 0000000..7954900 --- /dev/null +++ b/src/components/Header/Header.css @@ -0,0 +1,16 @@ + + +.header-button-container { + + display: flex; + flex-direction: row; + gap: 40px; +} + + +.header-lang-container { + + display: flex; + flex-direction: row; + gap: 8px; +} \ No newline at end of file diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js new file mode 100644 index 0000000..b85217f --- /dev/null +++ b/src/components/Header/Header.js @@ -0,0 +1,29 @@ +import './Header.css' +import ru from 'images/icons/RU.svg' +import en from 'images/icons/EN.svg' +import logo from 'images/logoIcon.svg' +import send from 'images/icons/Send.svg' + + +export const Header = () => { + const buttons = [ + { value: 'ru', icon: ru }, { value: 'ru', icon: en } + ] + return ( +
+ company-logo + +
+ +
+ {buttons.map((item, index) => ( + ))} +
+
+
+ ) + +} \ No newline at end of file diff --git a/src/components/Map/Map.css b/src/components/Map/Map.css new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Map/Map.js b/src/components/Map/Map.js new file mode 100644 index 0000000..7bf2548 --- /dev/null +++ b/src/components/Map/Map.js @@ -0,0 +1,2321 @@ +import React, { useEffect, useRef, useState } from "react"; +import anime from 'animejs'; +import { wait } from "@testing-library/user-event/dist/utils"; + + +export const MapAnimation = React.memo(() => { + const lineClasses = ['.first', '.second', '.third', '.fourth', '.fifth', '.sixth', '.seventh']; + // const [showLines, setShowLines] = useState({ + // '.first': { + // isShow: true, + // opacity: 1 + // }, + // '.second': { + // isShow: true, + // opacity: 1 + // }, + // '.third': { + // isShow: true, + // opacity: 1 + // }, + // '.fourth': { + // isShow: true, + // opacity: 1 + // }, + // '.fifth': { + // isShow: true, + // opacity: 1 + // }, + // '.sixth': { + // isShow: true, + // opacity: 1 + // }, + // '.seventh': { + // isShow: true, + // opacity: 1 + // }, + // ".eighth": { + // isShow: true, + // opacity: 1 + // } + // }); + const showLines = useRef({ + '.first': true, + '.second': true, + '.third': true, + '.fourth': true, + '.fifth': true, + '.sixth': true, + '.seventh': true, +}); + const currentShowCaption = useRef(); + const [showCaptionData, setShowCaptionData] = useState({ + ".fifth-caption": { + opacity:0, + widthFill: '40px' + }, + ".second-caption": { + opacity:0, + widthFill: '40px' + }, + ".third-caption": { + opacity:0, + widthFill: '40px' + }, + ".fourth-caption": { + opacity:0, + widthFill: '40px' + }, + ".seventh-caption": { + opacity:0, + widthFill: '40px' + }, + ".sixth-caption": { + opacity:0, + widthFill: '40px' + }, + ".first-caption": { + opacity:0, + widthFill: '40px' + }, + '.eighth-caption': { + opacity:0, + widthFill: '40px' + } + }) + + function animation(currentTarget) { + let a = anime({ + // targets: currentTarget || ['path', "rect"], + targets: currentTarget || ['.eighth', '.first', '.second', '.third', '.fourth', '.fifth', '.sixth', '.seventh'], + // loop: true, + strokeDashoffset: [anime.setDashoffset, 0], + easing: "cubicBezier(.5, .05, .1, .3)", + duration: 600, + //@ts-ignore + delay: function(el, i) { + return i * 20; + }, + update: function(anim) { + if(currentTarget) { + // showLines.current[currentTarget].opacity = a.progress; + // setShowLines({...showLines, [currentTarget]: {opacity: a.progress, isShow: showLines[currentTarget].isShow}}) + } + }, + complete: function(anim) { + // setShowLines({...showLines, [currentTarget]: {opacity: 1, isShow: showLines[currentTarget].isShow}}) + } + }); + } + + function removeAnimation(currentTarget) { + let a = anime({ + // targets: "svg path", + targets: currentTarget || "svg path", + strokeDashoffset: [anime.setDashoffset, 0], + easing: "cubicBezier(.5, .05, .1, .3)", + duration: 600, + direction: 'reverse', + //@ts-ignore + delay: function(el, i) { + return i * 20; + }, + update: function(anim) { + + }, + begin: function(anim) { + // setShowLines({...showLines, [currentTarget]: {...showLines[currentTarget], opacity: 0}}) + }, + + }); + + } + + function drawCaption(target) { + // if(currentShowCaption.current) { + // removeCaption(currentShowCaption.current); + // currentShowCaption.current = target; + // } else { + currentShowCaption.current = target; + // } + + let a = anime({ + // width: '121', + opacity: 1, + targets: target, + strokeDashoffset: [anime.setDashoffset, 0], + easing: "cubicBezier(.5, .05, .1, .3)", + duration: 500, + complete: function(anim) { + // removeCaption(currentShowCaption.current); + }, + update: function(anim) { + // setShowCaptionData({...showCaptionData, ".third-caption": {opacity: a.progress, widthFill: a.progress + 'px'}}) + // setFuckingWidth(a.progress) + } + }); + } + + function removeCaption(target) { + let a = anime({ + // width: 40, + //сейчас анимация удаления подсказки работает как просто смена opacity, иначе если делать именно анимацией рисования удаление, есть множество багов + opacity: 0, + targets: target || ['.first-caption', '.second-caption', '.third-caption', '.fourth-caption', '.fifth-caption', '.sixth-caption', '.seventh-caption'], + // strokeDashoffset: [anime.setDashoffset, 0], + easing: "cubicBezier(.5, .05, .1, .3)", + duration: 500, + // direction: 'reverse', + update: function(anim) { + // setShowCaptionData({...showCaptionData, ".third-caption": {opacity: a.progress, widthFill: '0px'}}) + + }, + complete: function(anim) { + + }, + }); + } + + useEffect(() => { + async function start() { + let lastNmber = 0; + while(true) { + let randNumber = 0 + while(randNumber === lastNmber) { + randNumber = Math.floor(Math.random() * lineClasses.length); + } + lastNmber = randNumber; + showLines.current[lineClasses[randNumber]] = !showLines.current[lineClasses[randNumber]]; + if(showLines.current[lineClasses[randNumber]]) { + animation(lineClasses[randNumber]) + } else { + removeAnimation(lineClasses[randNumber]) + } + // setShowLines({...showLines, [lineClasses[randNumber]]: { + // ...showLines[lineClasses[randNumber]], + // isShow: !showLines[lineClasses[randNumber]].isShow + // }}) + await wait(Math.random() * (3200 - 800) + 800); + } + } + animation() + setTimeout(() => { + start(); + }, 3000); + }, []) + + + + return
+ + + + {/* голубые точки и розовая точка выделены в группы для визуального отображения, ищутся по классам blue-ellipse и pink-ellipse */} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + drawCaption('.third-caption')} + onMouseOut={() => removeCaption('.third-caption')} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + drawCaption('.seventh-caption')} + onMouseOut={() => removeCaption('.seventh-caption')} + > + + + + + + + + + + + + + + + + + + + + + drawCaption('.first-caption')} + onMouseOut={() => removeCaption('.first-caption')} + > + + + + + + + + + + + + + + + drawCaption('.sixth-caption')} + onMouseOut={() => removeCaption('.sixth-caption')} + > + + + + + + + + + + + + + + + drawCaption('.eighth-caption')} + onMouseOut={() => removeCaption('.eighth-caption')} + > + + + + + + + + + + + + + + + + + + + + + drawCaption('.second-caption')} + onMouseOut={() => removeCaption('.second-caption')} + > + + + + + + + + + + + + + + + + + + + + + drawCaption('.fifth-caption')} + onMouseOut={() => removeCaption('.fifth-caption')} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + drawCaption('.fourth-caption')} + onMouseOut={() => removeCaption('.fourth-caption')} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+}) \ No newline at end of file diff --git a/src/components/MapComponent/MapComponent.css b/src/components/MapComponent/MapComponent.css new file mode 100644 index 0000000..4137f9d --- /dev/null +++ b/src/components/MapComponent/MapComponent.css @@ -0,0 +1,20 @@ +.section-map { + display: flex; + flex-direction: row; + position: relative; +} + +.map-container { + left: 40%; + position: absolute; + z-index: -1; + top: -100%; + +} + +.map-text-container { + width: 40%; + display: flex; + flex-direction: column; + gap: 32px; +} \ No newline at end of file diff --git a/src/components/MapComponent/MapComponent.js b/src/components/MapComponent/MapComponent.js new file mode 100644 index 0000000..57caeb8 --- /dev/null +++ b/src/components/MapComponent/MapComponent.js @@ -0,0 +1,13 @@ +import './MapComponent.css' +import { MapAnimation } from 'components/Map/Map' +export const MapComponent = () => { + return
+
+

Инструмент продаж поможет вам продавать удаленно

+

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

+

Покажите все преимущества вашего жилого комплекса клиенту из любого конца мира. Местоположение и устройство значения не имеют. Нужен только интернет.

+
+
+
+
+} \ No newline at end of file diff --git a/src/components/Piechart/Piechart.js b/src/components/Piechart/Piechart.js new file mode 100644 index 0000000..d1ce41e --- /dev/null +++ b/src/components/Piechart/Piechart.js @@ -0,0 +1,43 @@ +import { PieChart } from 'react-minimal-pie-chart'; +import './chart.css' +import "../../styles/styles.css"; + + + + +export const PieChartComp = () => { + const dataMock = [ + { title: 'One', value: 36.27, color: '#7A31C4' }, + { title: 'Two', value: 6.22, color: '#FB57F4' }, + { title: 'Three', value: 9.95, color: '#8742F8' }, + { title: 'Four', value: 17.93, color: '#D375FF' }, + { title: 'Five', value: 29.64, color: '#798FFF' }, + + ]; + + + const defaultLabelStyle = { + fontSize: '9px', + fontWeight: '500', + lineHeight: '140%', + fontFamily: 'Inter', + fill: '#EBEBEB', + }; + + + + + + return ( +
+ `${Math.round(dataEntry.percentage)} %`} + data={dataMock} + labelStyle={ + defaultLabelStyle + } + labelPosition={65} + /> +
+ ) +} \ No newline at end of file diff --git a/src/components/Piechart/chart.css b/src/components/Piechart/chart.css new file mode 100644 index 0000000..ad59546 --- /dev/null +++ b/src/components/Piechart/chart.css @@ -0,0 +1,54 @@ +/* +* Prefixed by https://autoprefixer.github.io +* PostCSS: v8.4.14, +* Autoprefixer: v10.4.7 +* Browsers: last 4 version +*/ + +.chart { + font-family: 'Gilroy'; + font-style: normal; + font-weight: 500; + font-size: 12px; + line-height: 140%; + /* or 17px */ + + -webkit-font-feature-settings: 'tnum' on, 'lnum' on; + + font-feature-settings: 'tnum' on, 'lnum' on; + + /* Landing/White */ + width: 144px; + color: #EBEBEB; +} + + + +@media screen and (max-width: 1279px) { + .chart { + width: 128px; + } + +} + +@media screen and (max-width: 1023px) { + .chart { + width: 144px; + } + +} + + +@media screen and (max-width: 690px) { + .chart { + width: 40%; + } +} + + +@media screen and (max-width: 450px) { + .chart { + width: 100%; + } + +} \ No newline at end of file diff --git a/src/components/SwiperComponent/SwiperComponent.css b/src/components/SwiperComponent/SwiperComponent.css new file mode 100644 index 0000000..6548ea5 --- /dev/null +++ b/src/components/SwiperComponent/SwiperComponent.css @@ -0,0 +1,55 @@ +.slider-container { + border-top: 2px solid #23242A; + border-bottom: 2px solid #23242A; + padding-top: 48px; + padding-bottom: 48px; + box-sizing: border-box; +} + +.section-swiper { + margin-bottom: 200px; +} + +.slide-container { + position: relative; + box-sizing: border-box; + margin: 0; + display: flex; + flex-direction: row; + user-select: none; + gap: 16px; + margin-bottom: 16px; +} + +.swiper-slide { + width: 76% +} + +.slide-text-col { + display: flex; + flex-direction: column; + gap: 16px; +} + +.pagination { + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 130%; + /* identical to box height, or 16px */ + /* Inactive */ + color: #C5C7CE; + +} + +.slider-control-container { + align-items: center; + display: flex; + flex-direction: row; +} + +.slider-button-container { + display: flex; + flex-direction: row; + gap: 8px; +} \ No newline at end of file diff --git a/src/components/SwiperComponent/SwiperComponent.js b/src/components/SwiperComponent/SwiperComponent.js new file mode 100644 index 0000000..7aeef3d --- /dev/null +++ b/src/components/SwiperComponent/SwiperComponent.js @@ -0,0 +1,70 @@ +import 'swiper/css'; +import 'swiper/css/navigation'; +import 'swiper/css/pagination'; +import 'swiper/css/scrollbar'; +import './SwiperComponent.css' +import left from 'images/icons/Arrow_Left.svg' +import right from 'images/icons/Arrow_Right.svg' + + +import { Navigation, Pagination } from 'swiper'; +import { Swiper, SwiperSlide } from 'swiper/react'; +import { swiperArray } from 'utils/utils'; + + +export const SwiperComponent = () => { + + return ( +
+
+

Функциональные

возможности.

+

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

+
+ +
+ + {swiperArray.map((i) => ( + +
+
+

{i.title}

+

{i.pargraph}

+
+ {i.title} +
+
+ ))} +
+
+
+
+ + +
+
+ +
+
+
+ + + ) +} \ No newline at end of file diff --git a/src/components/Title/Title.css b/src/components/Title/Title.css new file mode 100644 index 0000000..35e8f1f --- /dev/null +++ b/src/components/Title/Title.css @@ -0,0 +1,38 @@ +.section-title { + padding-top: calc(112px + 36px); + box-sizing: border-box; + margin-bottom: 200px; + +} + +.caption-container { + width: 448px; +} + +.video-container { + display: block; + position: relative; + overflow: hidden; + +} + +video { + object-fit: cover; + top: 0; + left: 0; + width: 100%; + max-height: 760px; +} + + +.title-container { + top: calc(112px + 50px); + position: sticky; + justify-content: center; + display: flex; + flex-direction: column; + gap: 56px; + width: 1200px; + height: 60vh; + margin: 0 auto; +} \ No newline at end of file diff --git a/src/components/Title/Title.js b/src/components/Title/Title.js new file mode 100644 index 0000000..fae4f54 --- /dev/null +++ b/src/components/Title/Title.js @@ -0,0 +1,16 @@ +import './Title.css' +import video from './video.mp4' + +export const Title = () => { + return (
+
+

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

+
+

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

+
+
+
+ +
+
) +} \ No newline at end of file diff --git a/src/components/Title/video.mp4 b/src/components/Title/video.mp4 new file mode 100644 index 0000000..562c244 Binary files /dev/null and b/src/components/Title/video.mp4 differ diff --git a/src/components/VirtualTour/VirtualTour.css b/src/components/VirtualTour/VirtualTour.css new file mode 100644 index 0000000..95a08ab --- /dev/null +++ b/src/components/VirtualTour/VirtualTour.css @@ -0,0 +1,27 @@ +.virtual-section { + margin-bottom: 400px; +} + +.virtual-container { + display: grid; + gap: 32px; + grid-template-columns: 1fr 1fr; +} + +.virtual-image-container { + position: relative; +} + +.virtual-image { + position: absolute; + top: -80%; + left: -50%; + z-index: -1; + +} + +.virtual-text-container { + display: flex; + flex-direction: column; + gap: 32px; +} \ No newline at end of file diff --git a/src/components/VirtualTour/VirtualTour.js b/src/components/VirtualTour/VirtualTour.js new file mode 100644 index 0000000..462f3e0 --- /dev/null +++ b/src/components/VirtualTour/VirtualTour.js @@ -0,0 +1,21 @@ +import './VirtualTour.css' +import glasses from 'images/Photo.png' + +export const VirtualTour = () => { + return (
+
+
+ +
+
+

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

+

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

+ +
+
+ +
) +} \ No newline at end of file diff --git a/src/images/FilterSearch.png b/src/images/FilterSearch.png new file mode 100644 index 0000000..e0c3a39 Binary files /dev/null and b/src/images/FilterSearch.png differ diff --git a/src/images/Form.png b/src/images/Form.png new file mode 100644 index 0000000..b3206bb Binary files /dev/null and b/src/images/Form.png differ diff --git a/src/images/Infrastructure.png b/src/images/Infrastructure.png new file mode 100644 index 0000000..9ae87e6 Binary files /dev/null and b/src/images/Infrastructure.png differ diff --git a/src/images/Interior.png b/src/images/Interior.png new file mode 100644 index 0000000..cf7b5c5 Binary files /dev/null and b/src/images/Interior.png differ diff --git a/src/images/Photo.png b/src/images/Photo.png new file mode 100644 index 0000000..6924396 Binary files /dev/null and b/src/images/Photo.png differ diff --git a/src/images/Render.png b/src/images/Render.png new file mode 100644 index 0000000..2f5bdd2 Binary files /dev/null and b/src/images/Render.png differ diff --git a/src/images/Wishlist.png b/src/images/Wishlist.png new file mode 100644 index 0000000..e0c3a39 Binary files /dev/null and b/src/images/Wishlist.png differ diff --git a/src/images/icons/Arrow_Left.svg b/src/images/icons/Arrow_Left.svg new file mode 100644 index 0000000..cb58dd5 --- /dev/null +++ b/src/images/icons/Arrow_Left.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/Arrow_Right.svg b/src/images/icons/Arrow_Right.svg new file mode 100644 index 0000000..a89c5d3 --- /dev/null +++ b/src/images/icons/Arrow_Right.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/icons/EN.svg b/src/images/icons/EN.svg new file mode 100644 index 0000000..e9e4b79 --- /dev/null +++ b/src/images/icons/EN.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/icons/RU.svg b/src/images/icons/RU.svg new file mode 100644 index 0000000..eee0b13 --- /dev/null +++ b/src/images/icons/RU.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/images/icons/Send.svg b/src/images/icons/Send.svg new file mode 100644 index 0000000..501cbe4 --- /dev/null +++ b/src/images/icons/Send.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/images/logoIcon.svg b/src/images/logoIcon.svg new file mode 100644 index 0000000..21b0f36 --- /dev/null +++ b/src/images/logoIcon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/index.css b/src/index.css index ec2585e..83b6f84 100644 --- a/src/index.css +++ b/src/index.css @@ -1,13 +1,17 @@ +@import url(./styles/styles.css); + body { - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', - 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + margin: 0 auto; + min-height: 100vh; + overflow-x: hidden; + font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Helvetica Neue', sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + background: #151619; } code { - font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 'Inter', monospace; -} +} \ No newline at end of file diff --git a/src/styles/fonts/Gilroy_Bold.woff b/src/styles/fonts/Gilroy_Bold.woff new file mode 100644 index 0000000..c5bbebb Binary files /dev/null and b/src/styles/fonts/Gilroy_Bold.woff differ diff --git a/src/styles/fonts/Gilroy_Bold.woff2 b/src/styles/fonts/Gilroy_Bold.woff2 new file mode 100644 index 0000000..bb8d73a Binary files /dev/null and b/src/styles/fonts/Gilroy_Bold.woff2 differ diff --git a/src/styles/fonts/Gilroy_Light.woff b/src/styles/fonts/Gilroy_Light.woff new file mode 100644 index 0000000..3c8aca8 Binary files /dev/null and b/src/styles/fonts/Gilroy_Light.woff differ diff --git a/src/styles/fonts/Gilroy_Light.woff2 b/src/styles/fonts/Gilroy_Light.woff2 new file mode 100644 index 0000000..bac74f7 Binary files /dev/null and b/src/styles/fonts/Gilroy_Light.woff2 differ diff --git a/src/styles/fonts/Gilroy_Medium.woff b/src/styles/fonts/Gilroy_Medium.woff new file mode 100644 index 0000000..af869f6 Binary files /dev/null and b/src/styles/fonts/Gilroy_Medium.woff differ diff --git a/src/styles/fonts/Gilroy_Medium.woff2 b/src/styles/fonts/Gilroy_Medium.woff2 new file mode 100644 index 0000000..dfaa5b6 Binary files /dev/null and b/src/styles/fonts/Gilroy_Medium.woff2 differ diff --git a/src/styles/fonts/Gilroy_Regular.woff b/src/styles/fonts/Gilroy_Regular.woff new file mode 100644 index 0000000..d7ddc7e Binary files /dev/null and b/src/styles/fonts/Gilroy_Regular.woff differ diff --git a/src/styles/fonts/Gilroy_Regular.woff2 b/src/styles/fonts/Gilroy_Regular.woff2 new file mode 100644 index 0000000..57b277d Binary files /dev/null and b/src/styles/fonts/Gilroy_Regular.woff2 differ diff --git a/src/styles/fonts/Gilroy_SemiBold.woff b/src/styles/fonts/Gilroy_SemiBold.woff new file mode 100644 index 0000000..acdf98e Binary files /dev/null and b/src/styles/fonts/Gilroy_SemiBold.woff differ diff --git a/src/styles/fonts/Gilroy_SemiBold.woff2 b/src/styles/fonts/Gilroy_SemiBold.woff2 new file mode 100644 index 0000000..9a1b0dc Binary files /dev/null and b/src/styles/fonts/Gilroy_SemiBold.woff2 differ diff --git a/src/styles/fonts/fonts.css b/src/styles/fonts/fonts.css new file mode 100644 index 0000000..2e582f9 --- /dev/null +++ b/src/styles/fonts/fonts.css @@ -0,0 +1,54 @@ +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-regular.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-regular.woff') format('woff'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-300.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-300.woff') format('woff'); + font-weight: 300; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-500.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-500.woff') format('woff'); + font-weight: 500; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-600.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-600.woff') format('woff'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'Inter'; + src: + url('./inter-v12-latin_cyrillic-700.woff2') format('woff2'), + url('./inter-v12-latin_cyrillic-700.woff') format('woff'); + font-weight: 700; + font-style: normal; +} + + +@font-face { + font-family: 'GilroyWebRegular'; + src: url('./Gilroy_Regular.woff'), + url('./Gilroy_Regular.woff2'); + font-weight: 400; + font-style: normal; + +} \ No newline at end of file diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-300.woff b/src/styles/fonts/inter-v12-latin_cyrillic-300.woff new file mode 100644 index 0000000..dfbdbc5 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-300.woff differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-300.woff2 b/src/styles/fonts/inter-v12-latin_cyrillic-300.woff2 new file mode 100644 index 0000000..c34a22e Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-300.woff2 differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-500.woff b/src/styles/fonts/inter-v12-latin_cyrillic-500.woff new file mode 100644 index 0000000..c66dbc7 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-500.woff differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-500.woff2 b/src/styles/fonts/inter-v12-latin_cyrillic-500.woff2 new file mode 100644 index 0000000..7538425 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-500.woff2 differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-600.woff b/src/styles/fonts/inter-v12-latin_cyrillic-600.woff new file mode 100644 index 0000000..d14fffe Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-600.woff differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-600.woff2 b/src/styles/fonts/inter-v12-latin_cyrillic-600.woff2 new file mode 100644 index 0000000..3f47285 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-600.woff2 differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-700.woff b/src/styles/fonts/inter-v12-latin_cyrillic-700.woff new file mode 100644 index 0000000..f72a471 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-700.woff differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-700.woff2 b/src/styles/fonts/inter-v12-latin_cyrillic-700.woff2 new file mode 100644 index 0000000..60f0094 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-700.woff2 differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff b/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff new file mode 100644 index 0000000..87685eb Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff differ diff --git a/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff2 b/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff2 new file mode 100644 index 0000000..daf5b02 Binary files /dev/null and b/src/styles/fonts/inter-v12-latin_cyrillic-regular.woff2 differ diff --git a/src/styles/styles.css b/src/styles/styles.css new file mode 100644 index 0000000..cae0b3b --- /dev/null +++ b/src/styles/styles.css @@ -0,0 +1,151 @@ + @import url(./fonts/fonts.css); + + /* global styles for headings, buttons, and so */ + + .title { + pointer-events: none; + user-select: none; + font-family: 'GilroyWebRegular'; + -webkit-text-fill-color: transparent; + -webkit-background-clip: text; + background-color: initial; + background-image: linear-gradient(180deg, #bc75ff, #798fff); + background-repeat: repeat; + font-weight: 400; + font-style: normal; + line-height: 100%; + margin: 0; + } + + main { + box-sizing: border-box; + margin: 0 auto; + max-width: 1200px; + } + + h1 { + font-size: 72px; + background: linear-gradient(180deg, #798FFF -41.07%, #D375FF 100%); + } + + h2 { + font-size: 36px; + + } + + h3 { + font-size: 24px; + + } + + .caption { + margin: 0; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 140%; + /* or 22px */ + + + /* White */ + + color: #F2F2F2; + } + + .caption-small { + font-size: 18px; + } + + button { + font-family: 'Inter'; + border: none; + cursor: pointer; + outline: none; + } + + .button-primary { + transition: background 0.2s ease-in-out; + + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 8px 16px 8px 8px; + gap: 4px; + width: fit-content; + height: fit-content; + background: linear-gradient(180deg, #BC75FF 0%, #798FFF 100%); + border-radius: 20px; + color: #F2F2F2; + font-style: normal; + font-weight: 400; + font-size: 16px; + line-height: 150%; + } + + .button-primary:hover { + transition: background 0.2s ease-in-out; + background: linear-gradient(180deg, #798FFF -41.07%, #D375FF 100%); + } + + .button-second { + transition: background 0.2s ease-in-out; + + padding: 8px; + background: #23242A; + border-radius: 20px; + width: 40px; + height: 40px; + } + + .button-second:hover { + transition: background 0.2s ease-in-out; + background: #2E3038; + + } + + header { + display: flex; + box-sizing: border-box; + align-items: center; + height: 112px; + position: fixed; + z-index: 11; + width: 100%; + padding: 35px 48px; + left: 0; + top: 0; + background: #151619; + justify-content: space-between; + } + + .paragraph { + margin: 0; + font-family: 'Inter'; + font-style: normal; + font-weight: 400; + font-size: 18px; + line-height: 140%; + /* or 25px */ + /* Inactive */ + color: #C5C7CE; + + } + + .paragraph-small { + font-size: 16px; + + } + + .subparagraph { + font-size: 16px; + color: #C5C7CE; + + } + + .text-row-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 32px; + margin-bottom: 118px; +} \ No newline at end of file diff --git a/src/utils/texts.js b/src/utils/texts.js new file mode 100644 index 0000000..7862ddc --- /dev/null +++ b/src/utils/texts.js @@ -0,0 +1,29 @@ +export const crmText = { + title: 'Интеграция с CRM - системой.', + paragraph: 'Приложение передает информацию о клиенте в CRM-систему застройщика и получает актуальную информацию по ценам и статусам квартир.' +} + +export const infrastractureText = { + title: 'Вся инфрастуктурана одном экране.', + paragraph: 'Возможность оценить инфраструктуру района покажет важные для клиента точки интереса и время, за которое он сможет до них дойти.' +} + +export const filterSearchText = { + title: 'Параметрический поиск квартир.', + paragraph: 'Фильтр позволит отметить конкретные преимущества, определить количество комнат, желаемый этаж, цену, и получить выборку подходящих вариантов' +} + +export const interiorText = { + title: 'Конфигуратор интерьера.', + paragraph: 'Клиент может свободно выбирать мебель и дизайн с помощью конфигуратора интерьера. Возможно выбрать стиль всей квартиры или изменить отдельные детали.' +} + +export const wishlistText = { + title: 'Формирование вишлиста.', + paragraph: 'Клиент может добавить варианты квартир в избранное, сравнить их между собой по основным параметрам и выбрать свою будущую квартиру.' +} + +export const renderText = { + title: 'Любой рендер за несколько секунд.', + paragraph: 'Когда для рекламы вам понадобится любой объект с любого ракурса, просто сделайте фотографию внутри презентации.' +} \ No newline at end of file diff --git a/src/utils/utils.js b/src/utils/utils.js new file mode 100644 index 0000000..3ef4fd9 --- /dev/null +++ b/src/utils/utils.js @@ -0,0 +1,26 @@ +import { crmText, filterSearchText, infrastractureText, interiorText, renderText, wishlistText } from './texts' +import form from 'images/Form.png' +import filter from 'images/FilterSearch.png' +import infrastracture from 'images/Infrastructure.png' +import interior from 'images/Interior.png' +import render from 'images/Render.png' +import wishlist from 'images/Wishlist.png' + + +export {crmText, infrastractureText, filterSearchText, interiorText, wishlistText, renderText} from './texts' +export const zero = 0 + +export const precentage = '%' + +export const counters = [{ from: zero, to: 10, text: 'plain text', precentage: false }, { from: zero, to: 26, text: 'plain text', precentage: false }, { from: zero, to: 32, text: 'plain text', precentage: precentage }, { from: zero, to: 12, text: 'plain text', precentage: precentage }] + + +export const swiperArray = [ + {title: crmText.title, pargraph: crmText.paragraph, img: form}, + {title: infrastractureText.title, pargraph: infrastractureText.paragraph, img: infrastracture}, + {title: filterSearchText.title, pargraph: filterSearchText.paragraph, img: filter}, + {title: interiorText.title, pargraph: interiorText.paragraph, img: interior}, + {title: wishlistText.title, pargraph: wishlistText.paragraph, img: wishlist}, + {title: renderText.title, pargraph: renderText.paragraph, img: render}, + +] \ No newline at end of file