added fetch card from server, style changes, i18

This commit is contained in:
DmitriyB
2023-03-20 16:45:16 +05:00
parent 85fa8dfe09
commit 21ac6e239c
59 changed files with 1452 additions and 501 deletions
BIN
View File
Binary file not shown.
+490 -20
View File
@@ -8,6 +8,7 @@
"name": "streaming-landing",
"version": "0.1.0",
"dependencies": {
"@reduxjs/toolkit": "^1.9.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
@@ -18,14 +19,21 @@
"@types/swiper": "^6.0.0",
"animejs": "^3.2.1",
"aos": "^2.3.4",
"axios": "^1.3.4",
"framer-motion": "^7.2.0",
"i": "^0.3.7",
"i18next": "^22.4.12",
"i18next-browser-languagedetector": "^7.0.1",
"i18next-http-backend": "^2.2.0",
"js-cookie": "^3.0.1",
"moment": "^2.29.4",
"npm": "^8.18.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.2.0",
"react-minimal-pie-chart": "^8.3.0",
"react-player": "^2.11.0",
"react-redux": "^8.0.5",
"react-router-dom": "^5.2.0",
"react-scripts": "5.0.1",
"swiper": "^8.3.2",
@@ -38,6 +46,7 @@
"@types/animejs": "^3.1.5",
"@types/aos": "^3.0.4",
"@types/body-scroll-lock": "^3.1.0",
"@types/js-cookie": "^3.0.3",
"@types/react-router-dom": "^5.3.3",
"babel-plugin-named-exports-order": "^0.0.2",
"prop-types": "^15.8.1",
@@ -1837,11 +1846,11 @@
}
},
"node_modules/@babel/runtime": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
"integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
"dependencies": {
"regenerator-runtime": "^0.13.4"
"regenerator-runtime": "^0.13.11"
},
"engines": {
"node": ">=6.9.0"
@@ -3154,6 +3163,29 @@
}
}
},
"node_modules/@reduxjs/toolkit": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
"integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
"dependencies": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
},
"peerDependencies": {
"react": "^16.9.0 || ^17.0.0 || ^18",
"react-redux": "^7.2.1 || ^8.0.2"
},
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-redux": {
"optional": true
}
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -3852,6 +3884,15 @@
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
"dev": true
},
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@@ -3895,6 +3936,12 @@
"pretty-format": "^27.0.0"
}
},
"node_modules/@types/js-cookie": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz",
"integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==",
"dev": true
},
"node_modules/@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -4054,6 +4101,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/ws": {
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@@ -4860,6 +4912,29 @@
"node": ">=4"
}
},
"node_modules/axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/axios/node_modules/form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -5822,6 +5897,14 @@
"node": ">=10"
}
},
"node_modules/cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"dependencies": {
"node-fetch": "2.6.7"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -8582,6 +8665,14 @@
"node": ">=12"
}
},
"node_modules/html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"dependencies": {
"void-elements": "3.1.0"
}
},
"node_modules/html-webpack-plugin": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz",
@@ -8724,6 +8815,44 @@
"node": ">=0.4"
}
},
"node_modules/i18next": {
"version": "22.4.12",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.4.12.tgz",
"integrity": "sha512-2lE+vRXxQ3lGLub1CVbwgO0IfkLHmUSDVOAVdPh22CsxttMXi+35n2qgxh2wZIkKl6t/NMzPfgFPRDiFQOmiCg==",
"funding": [
{
"type": "individual",
"url": "https://locize.com"
},
{
"type": "individual",
"url": "https://locize.com/i18next.html"
},
{
"type": "individual",
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
}
],
"dependencies": {
"@babel/runtime": "^7.20.6"
}
},
"node_modules/i18next-browser-languagedetector": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz",
"integrity": "sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g==",
"dependencies": {
"@babel/runtime": "^7.19.4"
}
},
"node_modules/i18next-http-backend": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.0.tgz",
"integrity": "sha512-Z4sM7R6tzdLknSPER9GisEBxKPg5FkI07UrQniuroZmS15PHQrcCPLyuGKj8SS68tf+O2aEDYSUnmy1TZqZSbw==",
"dependencies": {
"cross-fetch": "3.1.5"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -8771,9 +8900,9 @@
}
},
"node_modules/immer": {
"version": "9.0.15",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
"integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==",
"version": "9.0.19",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz",
"integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
@@ -11237,6 +11366,14 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==",
"engines": {
"node": ">=12"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -11868,6 +12005,44 @@
"tslib": "^2.0.3"
}
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@@ -16041,6 +16216,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -16330,6 +16510,27 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"node_modules/react-i18next": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.2.0.tgz",
"integrity": "sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ==",
"dependencies": {
"@babel/runtime": "^7.20.6",
"html-parse-stringify": "^3.0.1"
},
"peerDependencies": {
"i18next": ">= 19.0.0",
"react": ">= 16.8.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -16359,6 +16560,49 @@
"react": ">=16.6.0"
}
},
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-redux/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@@ -16573,6 +16817,22 @@
"node": ">=8"
}
},
"node_modules/redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"dependencies": {
"@babel/runtime": "^7.9.2"
}
},
"node_modules/redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
"peerDependencies": {
"redux": "^4"
}
},
"node_modules/regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -16590,9 +16850,9 @@
}
},
"node_modules/regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/regenerator-transform": {
"version": "0.15.0",
@@ -16715,6 +16975,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
"node_modules/reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"node_modules/resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -18302,6 +18567,14 @@
"react": "^16.0.0"
}
},
"node_modules/use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -18386,6 +18659,14 @@
"node": ">= 0.8"
}
},
"node_modules/void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
@@ -20514,11 +20795,11 @@
}
},
"@babel/runtime": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
"integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
"integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
"requires": {
"regenerator-runtime": "^0.13.4"
"regenerator-runtime": "^0.13.11"
}
},
"@babel/runtime-corejs3": {
@@ -21418,6 +21699,17 @@
"source-map": "^0.7.3"
}
},
"@reduxjs/toolkit": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.3.tgz",
"integrity": "sha512-GU2TNBQVofL09VGmuSioNPQIu6Ml0YLf4EJhgj0AvBadRlCGzUWet8372LjvO4fqKZF2vH1xU0htAa7BrK9pZg==",
"requires": {
"immer": "^9.0.16",
"redux": "^4.2.0",
"redux-thunk": "^2.4.2",
"reselect": "^4.1.7"
}
},
"@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@@ -21923,6 +22215,15 @@
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
"dev": true
},
"@types/hoist-non-react-statics": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz",
"integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==",
"requires": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"@types/html-minifier-terser": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
@@ -21966,6 +22267,12 @@
"pretty-format": "^27.0.0"
}
},
"@types/js-cookie": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.3.tgz",
"integrity": "sha512-Xe7IImK09HP1sv2M/aI+48a20VX+TdRJucfq4vfRVy6nWN8PYPOEnlMRSgxJAgYQIXJVL8dZ4/ilAM7dWNaOww==",
"dev": true
},
"@types/json-schema": {
"version": "7.0.11",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz",
@@ -22124,6 +22431,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz",
"integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg=="
},
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/ws": {
"version": "8.5.3",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.3.tgz",
@@ -22699,6 +23011,28 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.3.tgz",
"integrity": "sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w=="
},
"axios": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz",
"integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
},
"dependencies": {
"form-data": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
"requires": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
}
}
}
},
"axobject-query": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -23432,6 +23766,14 @@
"yaml": "^1.10.0"
}
},
"cross-fetch": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz",
"integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==",
"requires": {
"node-fetch": "2.6.7"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -25425,6 +25767,14 @@
"terser": "^5.10.0"
}
},
"html-parse-stringify": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
"integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
"requires": {
"void-elements": "3.1.0"
}
},
"html-webpack-plugin": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz",
@@ -25521,6 +25871,30 @@
"resolved": "https://registry.npmjs.org/i/-/i-0.3.7.tgz",
"integrity": "sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q=="
},
"i18next": {
"version": "22.4.12",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-22.4.12.tgz",
"integrity": "sha512-2lE+vRXxQ3lGLub1CVbwgO0IfkLHmUSDVOAVdPh22CsxttMXi+35n2qgxh2wZIkKl6t/NMzPfgFPRDiFQOmiCg==",
"requires": {
"@babel/runtime": "^7.20.6"
}
},
"i18next-browser-languagedetector": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz",
"integrity": "sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g==",
"requires": {
"@babel/runtime": "^7.19.4"
}
},
"i18next-http-backend": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.0.tgz",
"integrity": "sha512-Z4sM7R6tzdLknSPER9GisEBxKPg5FkI07UrQniuroZmS15PHQrcCPLyuGKj8SS68tf+O2aEDYSUnmy1TZqZSbw==",
"requires": {
"cross-fetch": "3.1.5"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -25553,9 +25927,9 @@
"integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ=="
},
"immer": {
"version": "9.0.15",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz",
"integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ=="
"version": "9.0.19",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.19.tgz",
"integrity": "sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ=="
},
"import-fresh": {
"version": "3.3.0",
@@ -27323,6 +27697,11 @@
}
}
},
"js-cookie": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz",
"integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -27798,6 +28177,35 @@
"tslib": "^2.0.3"
}
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
"requires": {
"whatwg-url": "^5.0.0"
},
"dependencies": {
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
},
"webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
},
"whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"requires": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
}
}
},
"node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
@@ -30494,6 +30902,11 @@
}
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@@ -30700,6 +31113,15 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"react-i18next": {
"version": "12.2.0",
"resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.2.0.tgz",
"integrity": "sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ==",
"requires": {
"@babel/runtime": "^7.20.6",
"html-parse-stringify": "^3.0.1"
}
},
"react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -30722,6 +31144,26 @@
"react-fast-compare": "^3.0.1"
}
},
"react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"dependencies": {
"react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}
}
},
"react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@@ -30895,6 +31337,19 @@
"strip-indent": "^3.0.0"
}
},
"redux": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
"integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
"requires": {
"@babel/runtime": "^7.9.2"
}
},
"redux-thunk": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
"integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q=="
},
"regenerate": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
@@ -30909,9 +31364,9 @@
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
"version": "0.13.11",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"regenerator-transform": {
"version": "0.15.0",
@@ -31006,6 +31461,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="
},
"reselect": {
"version": "4.1.7",
"resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.7.tgz",
"integrity": "sha512-Zu1xbUt3/OPwsXL46hvOOoQrap2azE7ZQbokq61BQfiXvhewsKDwhMeZjTX9sX0nvw1t/U5Audyn1I9P/m9z0A=="
},
"resolve": {
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
@@ -32155,6 +32615,11 @@
"resolved": "https://registry.npmjs.org/use-screen-size/-/use-screen-size-1.1.0.tgz",
"integrity": "sha512-GmHD1guO2+t5XZ1M8w/H7hlC1CO6IsD3lz1l9o+mKpmZfcm27cHKDw0J5kkj5sy3WT3hZAtno6pVaI3lRzDszA=="
},
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
},
"util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@@ -32221,6 +32686,11 @@
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
},
"void-elements": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
"integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w=="
},
"w3c-hr-time": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz",
+9
View File
@@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.9.3",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
@@ -13,14 +14,21 @@
"@types/swiper": "^6.0.0",
"animejs": "^3.2.1",
"aos": "^2.3.4",
"axios": "^1.3.4",
"framer-motion": "^7.2.0",
"i": "^0.3.7",
"i18next": "^22.4.12",
"i18next-browser-languagedetector": "^7.0.1",
"i18next-http-backend": "^2.2.0",
"js-cookie": "^3.0.1",
"moment": "^2.29.4",
"npm": "^8.18.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^12.2.0",
"react-minimal-pie-chart": "^8.3.0",
"react-player": "^2.11.0",
"react-redux": "^8.0.5",
"react-router-dom": "^5.2.0",
"react-scripts": "5.0.1",
"swiper": "^8.3.2",
@@ -67,6 +75,7 @@
"@types/animejs": "^3.1.5",
"@types/aos": "^3.0.4",
"@types/body-scroll-lock": "^3.1.0",
"@types/js-cookie": "^3.0.3",
"@types/react-router-dom": "^5.3.3",
"babel-plugin-named-exports-order": "^0.0.2",
"prop-types": "^15.8.1",
+80
View File
@@ -0,0 +1,80 @@
{
"main-titleCaption": "Technology for remote demonstration of a residential complex.",
"main-button": "Demoversion",
"slider-title": "",
"slider-mainBlockCaptionColor": "an uncompromising level of graphics and a complete immersion of the customer in the process of choosing an apartment.",
"slider-mainBlockCaption": "We can show your residential complex to any client from any part of the world. Location and device don't matter. All you need is internet connection.",
"slider-subtitle": "Floor plan",
"slider-subtitle1": "Architecture",
"slider-subtitle2": "Infrastructure",
"slider-subtitle3": "Landscaping",
"calendar-title": "easily embeds into an existing sales chain.",
"calendar-mainBlockCaptionColor": "developer's sales team can conduct virtual tours with potential customers",
"calendar-mainBlockCaption": "Customer able to see all the advantages of the residential complex, choose a layout and book an apartment, and the sales manager will be able to remotely help them do it.",
"calendar-mainBlockSubblock": "Our solution can be integrated to the site of the residential complex where the developer has set up advertising.",
"calendarCaption": "Pick a date",
"timepickerCaption": "Pick a time",
"formCaption": "Submit",
"appointmentTrue": "Available",
"appointmentFalse": "Not Available",
"confirm-title": "View planned",
"confirm-caption": "Additional information will be send to the email and phone number",
"buttons-plan": "Сonfirm",
"buttons-next": "Continue",
"placeholders-name": "Name",
"placeholders-phoneNumber": "Phone number",
"placeholders-email": "E-mail",
"multiplayer-title": "for teamwork.",
"multiplayer-mainBlockCaption": "The customer can walk around the residential complex together with their loved ones who connect from different devices. This is a completely new experience in the process of choosing an apartment",
"multiplayer-mainBlockSubblock": "The application easily adapts to any screen size. Our solution looks good on both mobile or large touchscreen in a developer's sales department.",
"multiplayer-button": "Demoversion",
"devices-title": "is available on any device.",
"devices-mainBlockCaption": "The application easily adapts to any screen size. Our solution looks good on both mobile or large touchscreen in a developer's sales department.",
"devices-button": "Demoversion",
"photoComponent-title": "already works in the sales departments of the developer",
"photoComponent-mainBlockCaption": "To organize an interactive presentation of a residential complex, the developer does not need to buy expensive equipment and maintain its performance.",
"photoComponent-mainBlockSubblock": "In the sales office, It is enough to place a touch table with Internet access.",
"player-title": "allows you to transfer an impressive level of graphics to the user's device",
"player-mainBlockCaption": "To work with an interactive presentation, the customer only needs a smartphone and mobile Internet.",
"player-mainBlockSubblock": "Our soultion optimaized to work smoothly even with mobile internet.",
"player-button": "Demoversion",
"analytics-title": "collects data about the users and their behavior.",
"analytics-mainBlockCaption": "The program's internal analytics system collects information about the user's behavior and prepare an analytical report that contains necessary metrics about user's behavior and manager's efficiency",
"cardLarge-title": "Converting managers to bookings",
"cardLarge-row": "Jane Cooper",
"cardLarge-row1": "Guy Hawkins",
"cardLarge-row2": "Robert Fox",
"cardLarge-row3": "Bessie Cooper",
"cardLarge1-title": "Popular types of apartments, %",
"cardLarge1-row": "Studios",
"cardLarge1-row1": "1-r. apartment",
"cardLarge1-row2": "2-r. apartment",
"cardLarge1-row3": "3-r. apartment",
"cardLarge1-row4": "4-r. apartment",
"cardLarge2-title": "Purchase funnel",
"cardLarge2-row": "Sessions",
"cardLarge2-row1": "To favorites",
"cardLarge2-row2": "Bookings",
"cardLarge2-row3": "Sales",
"cardSmall-title": "Average session time, min.",
"cardSmall1-title": "Commercial proposals, pcs.",
"cardSmall2-title": "Conversion from session to sale, %",
"cardSmall3-title": "Sold through Graff.estate, million rubles.",
"analytics-mainBlockSubblock": "Based on the report of our analytics system, you can make the process of demonstrating a residential complex even more efficient.",
"analytics-button": "Demoversion",
"cloudSolution-title": "is a cloud solution.",
"cloudSolution=mainBlockCaption": "Hosting the project on our servers allows you to quickly apply program updates and keep the product in the most efficient state.",
"footer-social": "Social Networks",
"footer-captionCompain": "About",
"footer-captionContact": "Contacts",
"footer-ru-addres": "st. Moskovskaya, 47,",
"footer-ru-city": "Yekaterinburg",
"footer-ru-country": "Russia",
"footer-uae-address": "Dubai",
"footer-uae-country": "UAE",
"card1-caption": "Write us",
"card2-caption": "Call us",
"copyright-caption": "Privacy Policy",
"copyright-caption1": "©Graff Interactive. All rights reserved",
"demo-title": "Available demonstrations"
}
+81
View File
@@ -0,0 +1,81 @@
{
"main-titleCaption": "Технология удаленной демонстрации жилого комплекса.",
"main-button": "Демоверсия",
"slider-title": "",
"slider-mainBlockCaptionColor": "бескомпромиссный уровень графики и полное погружение покупателя в процесс выбора квартиры.",
"slider-mainBlockCaption": "Покажем все преимущества вашего жилого комплекса клиенту из любого конца мира. Местоположение и устройство значения не имеют. Нужен только интернет.",
"slider-subtitle": "План этажа",
"slider-subtitle1": "Архитектура",
"slider-subtitle2": "Инфраструктура",
"slider-subtitle3": "Благоустройство",
"calendar-title": "легко встраивается в существующую цепочку продаж.",
"calendar-mainBlockCaptionColor": "Проведение виртуальных экскурсий сотрудниками офиса продаж.",
"calendar-mainBlockCaption": "Покупателю доступна возможность самостоятельно записаться на просмотр в удобное для него время, а менеджер отдела продаж удаленно поможет выбрать планировку и забронировать квартиру.",
"calendar-mainBlockSubblock": "Процесс записи может быть встроен на сайт жилого комплекса, на который была настроена реклама.",
"calendarCaption": "Выбор даты",
"timepickerCaption": "Выбор времени",
"formCaption": "Оформление",
"appointmentTrue": "Запись есть",
"appointmentFalse": "Записи нет",
"confirm-title": "Просмотр запланирован",
"confirm-caption": "Дополнительная информация будет отправлена на указанный почтовый адрес или номер телефона.",
"buttons-plan": "Запланировать",
"buttons-next": "Продолжить",
"placeholders-name": "Имя",
"placeholders-phoneNumber": "Номер телефона",
"placeholders-email": "E-mail",
"multiplayer-title": "для совместной работы.",
"multiplayer-mainBlockCaption": "Покупатель может вместе с близкими людьми осмотреть жилой комплекс. Это совершенно новый опыт в процессе выбора квартиры.",
"multiplayer-mainBlockSubblock": "Осмотр жилого комплекса доступен в любой момент, без необходимости предварительной записи на просмотр.",
"multiplayer-button": "Демоверсия",
"devices-title": "доступен на любых устройствах.",
"devices-mainBlockCaption": "Приложение легко адаптируется под экран любого размера и одинаково хорошо выглядит на мобильном телефоне или на большом сенсорном экране в отделе продаж застройщика.",
"devices-button": "Демоверсия",
"photoComponent-title": "уже работает в офисах продаж застройщиков.",
"photoComponent-mainBlockCaption": "Для организации интерактивной презентации жилого комплекса застройщику не нужно покупать дорогостоящее оборудование и поддерживать его работоспособность.",
"photoComponent-mainBlockSubblock": "В офисе продаж достаточно разместить сенсорный стол с доступом в интернет.",
"player-title": "позволяет передать на устройство пользователя впечатляющий уровень графики.",
"player-mainBlockCaption": "Для работы с интерактивной презентацией покупателю достаточно смартфона и мобильного интернета.",
"player-mainBlockSubblock": "Решение дополнительно оптимизированно для работы даже с мобильным интернетом.",
"player-button": "Демоверсия",
"analytics-title": "собирает данные о пользователе и его поведении.",
"analytics-mainBlockCaption": "Система внутренней аналитики программы собирает информацию о поведении пользователя и эффективности работы менеджеров для создания отчета, содержащего необходимые метрики.",
"cardLarge-title": "Конверсия менеджеров в брони",
"cardLarge-row": "К.Н. Федоров",
"cardLarge-row1": "И.Ф. Яковлева",
"cardLarge-row2": "А.М. Ташева",
"cardLarge-row3": "А.А. Фетисов",
"cardLarge1-title": "Популярные типы квартир, %",
"cardLarge1-row": "Студии",
"cardLarge1-row1": "1-к. квартиры",
"cardLarge1-row2": "2-к. квартиры",
"cardLarge1-row3": "3-к. квартиры",
"cardLarge1-row4": "4-к. квартиры",
"cardLarge2-title": "Воронка продаж",
"cardLarge2-row": "Сеансы",
"cardLarge2-row1": "В избранное",
"cardLarge2-row2": "Брони",
"cardLarge2-row3": "Продажи",
"cardSmall-title": "Среднее \n время сеанса,\n мин.",
"cardSmall1-title": "Сформировано коммерческих предложений, шт",
"cardSmall2-title": "Конверсия из сеанса в продажу, %",
"cardSmall3-title": "Продано через Graff.estate, млн.руб.",
"analytics-mainBlockSubblock": "Полученный отчет позволяет сделать процесс демонстрации жилого комплекса еще эффективнее.",
"analytics-button": "Демоверсия",
"cloudSolution-title": "это облачное решение.",
"cloudSolution=mainBlockCaption": "Необходимые для работы приложения вычисления проводятся на удаленном сервере. Это позволяет быстро применять обновления программы и поддерживать продукт в максимально эффективном состоянии.",
"footer-social": "Социальные сети",
"footer-captionCompain": "О компании",
"footer-captionContact": "Контакты",
"footer-ru-addres": "ул. Московская, 47,",
"footer-ru-city": "Екатеринбург",
"footer-ru-country": "Россия",
"footer-uae-address": "Дубаи",
"footer-uae-country": "ОАЭ",
"card1-caption": "Написать нам",
"card2-caption": "Позвонить",
"copyright-caption": "Политика конфиденциальности",
"copyright-caption1": "©Graff Interactive. Все права защищены",
"demo-title": "Доступные демонстрации"
}
+49 -41
View File
@@ -3,14 +3,21 @@ import "./App.css"
import { Route, Switch } from "react-router-dom";
import React, { useEffect, useState } from "react";
import { useAppDispatch, useAppSelector } from "./hooks/redux";
import cookies from "js-cookie";
import AOS from "aos";
import "aos/dist/aos.css";
import { Main } from "./components/main/main";
import { Header } from "./components/header/header";
import { Footer } from "./components/footer/footer";
import { Demostration } from "./components/demonstration/demonstartion";
import useQuery from "./hooks/useQuery";
import textRU from "./utils/textRU"
import textEN from "./utils/textEN";
import { languageSlice } from "./store/reducers/languageSlice";
import { fetchCards } from "./store/reducers/ActionCreator";
export type TObjct = {
calendar: boolean;
@@ -28,51 +35,52 @@ export const App: React.FC = () => {
const savedLanguage = localStorage.getItem('savedLang')
const dispatch = useAppDispatch();
const { handleChangeLanguage } = languageSlice.actions;
const { cards, currentCard, error } = useAppSelector((state) => state.cardReducer);
const { currentLang } = useAppSelector((state) => state.languageReducer);
const query = useQuery()
const langQuery = query.get('lang')
const langArray = ['en', 'ru']
const browserLanguage = window.navigator.language
const handleBrowserLanguage = () => {
return langArray.includes(browserLanguage)
}
const handleCookiesLanguage = () => {
const language = cookies.get("i18next")
return language
}
useEffect(() => {
if (savedLanguage !== null) {
setSavedLanguage()
} else {
setInitialLanguage()
if (langArray.includes(langQuery as string)) {
dispatch(handleChangeLanguage(langQuery as string));
return
}
}, []);
function setSavedLanguage() {
if (savedLanguage === 'RU') {
setLanguage('RU')
localStorage.setItem("lang", 'RU')
setText(textRU)
} else if (savedLanguage === 'EN') {
setLanguage('EN')
localStorage.setItem("lang", 'EN')
setText(textEN)
else if (handleCookiesLanguage()) {
const languageCookies = handleCookiesLanguage()
console.log(languageCookies)
dispatch(handleChangeLanguage(languageCookies as string))
return
}
}
let isSupported = handleBrowserLanguage()
dispatch(handleChangeLanguage(isSupported ? browserLanguage : 'en'));
}, [])
function setInitialLanguage() {
if (window.navigator.language === 'ru') {
setLanguage('RU')
localStorage.setItem("lang", 'RU')
setText(textRU)
} else {
setLanguage('EN')
setText(textEN)
useEffect(() => {
if (currentLang) {
dispatch(fetchCards(currentLang))
}
}
}, [currentLang])
function changeLanguage(language: string) {
if (language === 'RU') {
setLanguage(language);
setText(textRU)
localStorage.setItem('savedLang', 'RU');
localStorage.setItem("lang", 'RU')
} else {
setLanguage('EN')
localStorage.setItem("lang", 'EN')
localStorage.setItem("savedLang", 'EN')
setText(textEN)
}
}
AOS.init({
mirror: true,
@@ -81,8 +89,8 @@ export const App: React.FC = () => {
<Switch>
<Route path="/" exact>
<div className='App'>
<Header text={text.footer} language={language} changeLanguage={changeLanguage}></Header>
<Main locale={language} text={text}></Main>
<Header></Header>
<Main cards={cards} locale={language} text={text}></Main>
<Footer language={language} text={text.footer}></Footer>
</div>
</Route>
+5 -5
View File
@@ -37,7 +37,7 @@
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
background: #141414;
background: #1C1D21;
border-radius: 16px;
padding: 32px;
font-style: normal;
@@ -49,7 +49,7 @@
/* Landing/White */
color: #EBEBEB;
color: #F2F2F2;
}
@@ -85,7 +85,7 @@
align-items: flex-start;
gap: 20px;
padding: 24px;
background: #141414;
background: #1C1D21;
border-radius: 16px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -95,7 +95,7 @@
font-weight: 400;
font-size: 18px;
line-height: 140%;
color: #EBEBEB;
color: #F2F2F2;
background-color: transparent;
}
@@ -104,7 +104,7 @@
font-weight: 400;
font-size: 18px;
line-height: 140%;
color: #EBEBEB;
color: #F2F2F2;
}
.graph__row_item_l {
+25 -23
View File
@@ -4,21 +4,23 @@ import "../multiplayer/multiplayer.css";
import { PieChartComp } from "../piechart/piechart";
import { Button } from "../buttonDemo/buttonDemo"
import { Content } from "../content/content";
import { useTranslation } from "react-i18next";
export const Analytics: React.FC<any> = ({ text }) => {
const { cardLarge, cardLarge1, cardLarge2, cardSmall, cardSmall1, cardSmall2, cardSmall3 } = text;
const {t} = useTranslation()
return (
<div className="analytics__container">
<Content text={text}></Content>
<div data-aos="fade-up" data-aos-delay="100" className="graph__container">
<div className="graph__row_1">
<div className="graph__row_item">
<span className="graph__title title_1">{cardLarge.title}</span>
<span className="graph__title title_1">{t('cardLarge-title')}</span>
<div className="graph__bar_row">
<p className="graph__caption">{cardLarge.row}</p>
<p className="graph__caption">{t('cardLarge-row')}</p>
<div className="bar__container">
<div className="graph__bar_width_container">
<div className="graph__bar_1"></div>
@@ -27,7 +29,7 @@ export const Analytics: React.FC<any> = ({ text }) => {
<p className="graph__procentage">45%</p>
</div>
<div className="graph__bar_row">
<p className="graph__caption">{cardLarge.row1}</p>
<p className="graph__caption">{t('cardLarge-row1')}</p>
<div className="bar__container">
<div className="graph__bar_width_container">
<div className="graph__bar_2"></div>
@@ -37,7 +39,7 @@ export const Analytics: React.FC<any> = ({ text }) => {
</div>
<div className="graph__bar_row">
<p className="graph__caption">{cardLarge.row2}</p>
<p className="graph__caption">{t('cardLarge-row2')}</p>
<div className="bar__container">
<div className="graph__bar_width_container">
<div className="graph__bar_3"></div>
@@ -47,7 +49,7 @@ export const Analytics: React.FC<any> = ({ text }) => {
</div>
<div className="graph__bar_row">
<p className="graph__caption">{cardLarge.row3}</p>
<p className="graph__caption">{t('cardLarge-row3')}</p>
<div className="bar__container">
<div className="graph__bar_width_container">
<div className="graph__bar_4"></div>
@@ -58,57 +60,57 @@ export const Analytics: React.FC<any> = ({ text }) => {
</div>
</div>
<div className="graph__row_item">
<span className="graph__title title_2">{cardLarge1.title}</span>
<span className="graph__title title_2">{t('cardLarge1-title')}</span>
<div className="chart__container">
<PieChartComp />
<div className="legend__container">
<div className="legend__row">
<div className="legend__point color"></div>
<p className="legend__caption">{cardLarge1.row}</p>
<p className="legend__caption">{t('cardLarge1-row')}</p>
</div>
<div className="legend__row">
<div className="legend__point color1"></div>
<p className="legend__caption">{cardLarge1.row1}</p>
<p className="legend__caption">{t('cardLarge1-row1')}</p>
</div>
<div className="legend__row">
<div className="legend__point color2"></div>
<p className="legend__caption">{cardLarge1.row2}</p>
<p className="legend__caption">{t('cardLarge1-row2')}</p>
</div>
<div className="legend__row">
<div className="legend__point color3"></div>
<p className="legend__caption">{cardLarge1.row3}</p>
<p className="legend__caption">{t('cardLarge1-row3')}</p>
</div>
<div className="legend__row">
<div className="legend__point color4"></div>
<p className="legend__caption">{cardLarge1.row4}</p>
<p className="legend__caption">{t('cardLarge1-row4')}</p>
</div>
</div>
</div>
</div>
<div className="graph__row_item">
<span className="graph__title">{cardLarge2.title}</span>
<span className="graph__title">{t('cardLarge2-title')}</span>
<div className="sales__container">
<div className="sales__row">
<div className="background__row">
<div className="sales__bar">{cardLarge2.row}</div>
<div className="sales__bar">{t('cardLarge2-row')}</div>
</div>
<div className="sales__procentage"></div>
</div>
<div className="sales__row">
<div className="background__row">
<div className="sales__bar sales_bar_width">{cardLarge2.row1}</div>
<div className="sales__bar sales_bar_width">{t('cardLarge2-row1')}</div>
</div>
<div className="sales__procentage">93,47%</div>
</div>
<div className="sales__row">
<div className="background__row">
<div className="sales__bar sales_bar_width1">{cardLarge2.row2}</div>
<div className="sales__bar sales_bar_width1">{t('cardLarge2-row2')}</div>
</div>
<div className="sales__procentage">45,68%</div>
</div>
<div className="sales__row">
<div className="background__row">
<div className="sales__bar sales_bar_width3">{cardLarge2.row3}</div>
<div className="sales__bar sales_bar_width3">{t('cardLarge2-row3')}</div>
</div>
<div className="sales__procentage">29,13%</div>
</div>
@@ -118,38 +120,38 @@ export const Analytics: React.FC<any> = ({ text }) => {
</div>
<div className="graph__row_2">
<div className=" graph__row_item_s">
<span className="graph__title_s">{cardSmall.title}</span>
<span className="graph__title_s">{t('cardSmall-title')}</span>
<div className="graph__color_elem">
12:45
</div>
</div>
<div className="graph__row_item_s">
<span className="graph__title_s">{cardSmall1.title}</span>
<span className="graph__title_s">{t('cardSmall1-title')}</span>
<div className="graph__color_elem">
856
</div>
</div>
<div className=" graph__row_item_s">
<span className="graph__title_s">{cardSmall2.title}</span>
<span className="graph__title_s">{t('cardSmall2-title')}</span>
<div className="graph__color_elem">
12,44
</div>
</div>
<div className="graph__row_item_s">
<span className="graph__title_s">{cardSmall3.title}</span>
<span className="graph__title_s">{t('cardSmall3-title')}</span>
<div className="graph__color_elem">
134,5
</div>
</div>
<div className=" graph__row_mobile graph__row_item_l">
<div className="graph__text">{text.mainBlockSubblock}</div>
<div className="graph__text">{t(`${text}-mainBlockSubblock`)}</div>
</div>
</div>
</div>
<div className="main-block_subblock">
<div className="graph__text_mobile">{text.mainBlockSubblock}</div>
<Button text={text}></Button>
<div className="graph__text_mobile">{t(`${text}-mainBlockSubblock`)}</div>
<Button></Button>
</div>
</div>
@@ -3,8 +3,11 @@ import "./animationComponent.css"
import "../../styles/styles.css"
import "./mapblock.css"
import { Button } from "../buttonDemo/buttonDemo"
import { useTranslation } from 'react-i18next';
export const AnimationComponent: React.FC<any> = () => {
const { t } = useTranslation()
export const AnimationComponent: React.FC<any> = ({ text }) => {
return (
<div>
<div className="animation-container">
@@ -18,9 +21,9 @@ export const AnimationComponent: React.FC<any> = ({ text }) => {
</div>
<span className="title__caption">
{text.titleCaption}
{t('main-titleCaption')}
</span>
<Button text={text}></Button>
<Button></Button>
</div>
</div>
</div>
+22 -12
View File
@@ -1,16 +1,26 @@
import { Link } from "react-router-dom";
import iconButton from '../../styles/iconButton.svg'
import '../../styles/styles.css'
import { useTranslation } from 'react-i18next';
import { useAppSelector, useAppDispatch } from "../../hooks/redux";
export const Button: React.FC<any> = () => {
const { currentLang } = useAppSelector((state) => state.languageReducer);
const { t } = useTranslation()
return (
<a href={`https://stream.graff.tech/?lang=${currentLang}`} className="link">
<button className="main-block__button">
{t('main-button')}
<div className="main-block__icon_container">
<img alt="icon" src={iconButton} className="main-block__icon"></img>
</div>
</button>
</a>
)
}
export const Button: React.FC<any> = ({text}) => {
return (
<a href="https://stream.graff.tech/" className="link">
<button className="main-block__button">
{text.button}
<div className="main-block__icon_container">
<img alt="icon" src={iconButton} className="main-block__icon"></img>
</div>
</button>
</a>
)
}
+10 -7
View File
@@ -5,8 +5,9 @@ import point0 from "./Ellipse0.svg";
import point1 from "./Ellipse1.svg";
import { TProps } from "../calendarDesktop/calendarDesktop";
import { useSwiper } from 'swiper/react';
import { useTranslation } from "react-i18next";
export const Calendar: React.FC<TProps> = ({ open, setOpen, time, onUpdate, isMobile, locale, text }) => {
export const Calendar: React.FC<TProps> = ({ open, setOpen, time, onUpdate, isMobile, locale }) => {
const swiper = useSwiper();
const [calendar, setCalendar] = useState<any[]>([]);
const [value, setValue] = useState(time);
@@ -25,8 +26,8 @@ export const Calendar: React.FC<TProps> = ({ open, setOpen, time, onUpdate, isMo
useEffect(() => {
setValue(time.locale(locale as string))
}, [locale])
}, [locale])
useEffect(() => {
const day = startDay.clone().subtract("1", "day");
@@ -86,11 +87,13 @@ export const Calendar: React.FC<TProps> = ({ open, setOpen, time, onUpdate, isMo
}
return (<div data-aos="fade-up" className='calendar'>
const { t } = useTranslation()
return (<div data-aos="fade-up" className='calendar'>
<div className={open.calendar ? 'opacity_active' : 'opacity'}>
<div className="calendar__header">
<span className="calendar__caption calendar__caption_calendar">
{text.calendarCaption}
{t('calendarCaption')}
</span>
<div className="line"></div>
</div>
@@ -134,11 +137,11 @@ export const Calendar: React.FC<TProps> = ({ open, setOpen, time, onUpdate, isMo
<div className="appointment__block">
<div>
<img alt="point" className="point" src={point1}></img>
<span className="appointment__caption_active">{text.appointmentTrue}</span>
<span className="appointment__caption_active">{t('appointmentTrue')}</span>
</div>
<div>
<img alt="point" className="point" src={point0}></img>
<span className="appointment__caption" >{text.appointmentFalse}</span>
<span className="appointment__caption" >{t('appointmentFalse')}</span>
</div>
</div>
</div>)
@@ -1,3 +0,0 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 12H1M1 12L8.2 5M1 12L8.2 19" stroke="#EBEBEB" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 211 B

+2 -30
View File
@@ -3,35 +3,7 @@
}
.button__arrow_l {
cursor: pointer;
background-image: url(./Arrow_Left.svg);
background-repeat: no-repeat;
background-position: center;
height: 14px;
width: 22px;
}
.button__arrow_r {
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-ms-transform: matrix(-1, 0, 0, 1, 0, 0);
transform: matrix(-1, 0, 0, 1, 0, 0);
cursor: pointer;
background-image: url(./Arrow_Left.svg);
background-repeat: no-repeat;
background-position: center;
height: 14px;
width: 22px;
}
.button__arrow_r:hover {
background-image: url(../calendar/arrow_active1.png);
}
.button__arrow_l:hover {
background-image: url(../calendar/arrow_active1.png);
}
.button__arrow_back {
cursor: pointer;
@@ -139,11 +111,11 @@
-ms-flex-direction: column;
flex-direction: column;
color: #ebebeb;
color: #F2F2F2;
-webkit-box-sizing: border-box;
box-sizing: border-box;
width: 385px;
background: #141414;
background: #1C1D21;
border-radius: 16px;
padding: 24px 32px;
box-sizing: border-box;
@@ -9,6 +9,7 @@ import "../../styles/styles.css";
import { Confirm } from "../confirm/confirm";
import { Calendar } from "../calendar/calendar";
import { Content } from '../content/content'
import { useTranslation } from "react-i18next";
export type TProps = {
@@ -36,14 +37,13 @@ export const CalendarDesktop: React.FC<TProps> = ({
text,
locale
}) => {
console.log(text, 'here2')
const {t} = useTranslation()
return (
<div className="calendar__container">
<Content text={text}></Content>
<Content isColorCaption={true} text={text}></Content>
<div className="wrapper">
<Calendar
text={text}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
open={open}
@@ -56,7 +56,6 @@ export const CalendarDesktop: React.FC<TProps> = ({
/>
<Timepicker
text={text}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
open={open}
@@ -68,7 +67,6 @@ export const CalendarDesktop: React.FC<TProps> = ({
></Timepicker>
<Form
text={text}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
open={open}
@@ -80,7 +78,6 @@ export const CalendarDesktop: React.FC<TProps> = ({
></Form>
<Confirm
text={text}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
open={open}
@@ -93,7 +90,7 @@ export const CalendarDesktop: React.FC<TProps> = ({
</div>
<div className="main-block__subblock-container">
<div className="main-block_subblock">
{text.mainBlockSubblock}
{t('calendar-mainBlockSubblock')}
</div>
</div>
</div>
@@ -11,6 +11,7 @@ import "swiper/css/pagination";
import "swiper/css/navigation";
import "./calendarMobile.css"
import { Content } from "../content/content";
import { useTranslation } from "react-i18next";
@@ -18,11 +19,12 @@ import { Content } from "../content/content";
export const CalendarMobile: React.FC<TProps> = ({ setDisplayForm, displayForm, open, setOpen, onUpdate, time, onExit, isMobile, text, locale }) => {
const { t } = useTranslation()
return (
<div className="calendar__mobile">
<div className="calendar__container">
<div className="slider">
<Content text={text}></Content>
<Content isColorCaption={true} text={text}></Content>
</div>
<Swiper
rewind={true}
@@ -87,7 +89,7 @@ export const CalendarMobile: React.FC<TProps> = ({ setDisplayForm, displayForm,
</Swiper>
<div className="main-block__subblock-container calendar__padding">
<div className="main-block_subblock">
{text.mainBlockSubblock}
{t('calendar-mainBlockSubblock')}
</div>
</div>
</div>
@@ -5,8 +5,7 @@
.block__container {
overflow: hidden;
background: #141414;
border-radius: 32px;
background: #1C1D21; border-radius: 32px;
padding: 74px 80px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1,9 +1,11 @@
import './cloudSolution.css'
import "../../styles/styles.css";
import serverFrame from './serverFrame.png'
import { useTranslation } from 'react-i18next';
export const CloudSolution: React.FC<any> = ({ text }) => {
const {t} = useTranslation()
return (
<div data-aos="zoom-in" data-aos-duration="500" className="cloud__container">
<div className='block__container'>
@@ -17,11 +19,11 @@ export const CloudSolution: React.FC<any> = ({ text }) => {
Graff.estate stream
</p>
<p className=" main-block__title_gardient_small width cloud__title">
{text.title}
{t('cloudSolution-title')}
</p>
</div>
<p className="main-block__caption cloud__caption">
{text.mainBlockCaption}
{t('cloudSolution=mainBlockCaption')}
</p>
</div>
</div>
+7 -4
View File
@@ -1,13 +1,16 @@
import '../form/form.css'
import { TProps } from "../calendarDesktop/calendarDesktop";
import { useSwiper } from 'swiper/react';
import { useTranslation } from 'react-i18next';
export const Confirm: React.FC<TProps> = ({ open, onExit, setOpen, isMobile, text }) => {
export const Confirm: React.FC<TProps> = ({ open, onExit, setOpen, isMobile }) => {
const swiper = useSwiper();
const {t} = useTranslation()
function exit() {
if (isMobile) {
swiper.slideNext()
@@ -20,14 +23,14 @@ export const Confirm: React.FC<TProps> = ({ open, onExit, setOpen, isMobile, tex
return (<div className={open.confirm ? "confirm" : "confirm__none"}>
<div className="confirm__container">
<h2 className="confirm__title">
{text.confirm.title}
{t("confirm-title")}
</h2>
<p className="confirm__caption">
{text.confirm.caption}
{t("confirm-caption")}
</p>
</div>
<button onClick={exit} className="button__submit">
{text.buttons.next}
{t("buttons-next")}
</button>
</div>
)
+8 -7
View File
@@ -1,20 +1,21 @@
import { useTranslation } from "react-i18next";
import "../../styles/styles.css";
export const Content: React.FC<any> = ({ text, captionSmall }) => {
export const Content: React.FC<any> = ({ text, captionSmall, isColorCaption }) => {
const { t } = useTranslation()
return (
<div data-aos="fade-up"
data-aos-delay="400"
className="main-block__container">
<p className="main-block__title_small">
Graff.estate stream{" "}
<p className="main-block__title_gardient_small">{text.title}</p>
<p className="main-block__title_gardient_small">{t(`${text}-title`)}</p>
</p>
{text.mainBlockCaptionColor ? <p className=" main-block__caption_color">
{text.mainBlockCaptionColor}
</p>
: <></>}
{isColorCaption ? <p className=" main-block__caption_color">
{t(`${text}-mainBlockCaptionColor`)}
</p> : <></>}
<p className={captionSmall ? "main-block__caption main-block__caption_small" : "main-block__caption"}>
{text.mainBlockCaption}
{t(`${text}-mainBlockCaption`)}
</p>
</div>
)
+6 -7
View File
@@ -35,7 +35,7 @@
}
.demos_container {
background: #141414;
background: #1C1D21;
border-radius: 16px;
}
@@ -52,6 +52,7 @@
}
.demo_image {
object-fit: cover;
background: -webkit-gradient(linear, left bottom, left top, from(rgba(0, 0, 0, 0.3)), to(rgba(0, 0, 0, 0.3)));
background: -o-linear-gradient(bottom, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
background: linear-gradient(0deg, rgba(0, 0, 0, 0.3), rgba(0, 0, 0, 0.3));
@@ -88,7 +89,7 @@
/* Landing/White */
color: #EBEBEB;
color: #F2F2F2;
}
.caption {
@@ -102,7 +103,7 @@
/* Landing/White */
color: #EBEBEB;
color: #F2F2F2;
opacity: 0.5;
@@ -120,7 +121,7 @@
/* Landing/White */
color: #EBEBEB;
color: #F2F2F2;
}
.caption2 {
@@ -135,7 +136,7 @@
/* Landing/White */
color: #EBEBEB;
color: #F2F2F2;
opacity: 0.5;
}
@@ -232,8 +233,6 @@
.demo_image {
height: auto;
-o-object-fit: cover;
object-fit: cover;
width: 240px;
}
}
+25 -40
View File
@@ -3,56 +3,41 @@ import "../../styles/styles.css";
import building1 from './building1.png'
import building2 from './building2.png'
import { useAppDispatch, useAppSelector } from "../../hooks/redux";
import iconButton from "./iconButton.svg"
import { useTranslation } from 'react-i18next';
export const Demos: React.FC<any> = ({ text }) => {
const { card, card1 } = text;
console.log(text)
export const Demos: React.FC<any> = ({ cards }) => {
const { currentLang } = useAppSelector((state) => state.languageReducer);
const {t} = useTranslation()
return (<div className=" demo__container_mobile main-block__container width demo__container">
<h3 className='demos__tittle'>
{text.title}
{t('demo-title')}
</h3>
<a href='https://stream.graff.tech/' target='_blank' rel="noreferrer" data-aos="fade-up"
data-aos-delay="100" className='demos_container'>
<div className="main-block__icon_container demo__icon">
<img alt='icon' src={iconButton} className="main-block__icon"></img>
</div>
<div className='demo'>
<img alt='buildingImg' src={building1} className='demo_image'></img>
<div className='demo_info'>
<div className='title__block'>
<h4 className='title__demo'>{card.title}</h4>
<p className='caption'>{card.subTitle}</p>
</div>
<div className='body__block'>
<p className='caption1'>{card.caption}</p>
<p className='caption2'>{card.caption1}</p>
{cards.map((i: any) => (
<a href={`https://stream.graff.tech/?lang=${currentLang}`} target='_blank' rel="noreferrer" data-aos="fade-up"
data-aos-delay="100" className='demos_container'>
<div className="main-block__icon_container demo__icon">
<img alt='icon' src={iconButton} className="main-block__icon"></img>
</div>
<div className='demo'>
<img alt='buildingImg' src={i.preview} className='demo_image'></img>
<div className='demo_info'>
<div className='title__block'>
<h4 className='title__demo'>{i.title}</h4>
<p className='caption'>{i.location}</p>
</div>
<div className='body__block'>
<p className='caption1'>{i.description}</p>
{i.feature_description ? <p className='caption2'>{i.feature_description}</p> : <p></p>}
</div>
</div>
</div>
</div>
</a>
<a href='https://stream.graff.tech/' target='_blank' rel="noreferrer" data-aos="fade-up"
data-aos-delay="150" className='demos_container'>
<div className="main-block__icon_container demo__icon">
<img alt='icon' src={iconButton} className="main-block__icon"></img>
</div>
<div className='demo'>
<img alt='buildingImg' src={building2} className='demo_image'></img>
<div className='demo_info'>
<div className='title__block'>
<h4 className='title__demo'>{card1.title}</h4>
<p className='caption'>{card1.subTitle}</p>
</div>
<div className='body__block'>
<p className='caption1'>{card1.caption}</p>
<p className='caption2'>{card1.caption1}</p>
</div>
</div>
</div>
</a>
</a>
))}
</div>
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 382 KiB

+2 -3
View File
@@ -34,8 +34,7 @@
flex-direction: column;
height: 380px;
padding: 32px;
background: #141414;
border-radius: 16px;
background: #1C1D21; border-radius: 16px;
gap: 20px;
}
@@ -67,7 +66,7 @@
/* Landing/White */
color: #ebebeb;
color: #C5C7CE;
opacity: 0.8;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 639 KiB

After

Width:  |  Height:  |  Size: 669 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 433 KiB

After

Width:  |  Height:  |  Size: 437 KiB

+6 -5
View File
@@ -9,7 +9,7 @@
-webkit-box-sizing: border-box;
box-sizing: border-box;
background-color: transparent;
background: #141414;
background: #1C1D21;
border-radius: 32px 32px 0px 0px;
color: #EBEBEB;
display: -webkit-box;
@@ -30,7 +30,7 @@
display: -webkit-box;
display: -ms-flexbox;
display: flex;
padding: 120px 120px;
padding: 0 120px;
gap: 186px;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
@@ -173,7 +173,7 @@
}
.footer__card_l {
background: #1E1E1E;
background: #2E3038;
border-radius: 16px;
padding: 32px;
margin-bottom: 30px;
@@ -190,6 +190,7 @@
}
.footer__card_2 {
-webkit-box-sizing: border-box;
box-sizing: border-box;
cursor: pointer;
@@ -205,8 +206,8 @@
/* Gray */
color: #E3DDE5;
border: 1px solid #454545;
color: #FFFFFF;
border: 1px solid #73788C;
border-radius: 16px;
}
-1
View File
@@ -22,7 +22,6 @@ export const Footer: React.FC<any> = ({ text, language }) => {
<p className='contacts__title'>{text.social}</p>
<div className='footer__container_social'>
<a href='https://www.facebook.com/GRAFFinteractive' target='_blank' rel="noreferrer" className='footer__social'>Facebook</a>
<a href='https://www.instagram.com/graffinteractive/' target='_blank' rel="noreferrer" className='footer__social'>Instagram</a>
<a href='https://www.youtube.com/channel/UCveYBNLVeGxgsDsfhrVxNoA' target='_blank' rel="noreferrer" className='footer__social'>YouTube</a>
<a href='https://vk.com/graffinteractive' target='_blank' rel="noreferrer" className='footer__social'>VK</a>
</div>
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 17 KiB

+2 -2
View File
@@ -1,6 +1,5 @@
.form__container {
width: 385px;
color: #ebebeb;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
@@ -11,7 +10,8 @@
padding: 24px 32px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
background: #141414;
background: #1C1D21;
color: #F2F2F2;
border-radius: 16px;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
+10 -8
View File
@@ -3,9 +3,10 @@ import "../timepicker/timepicker.css"
import "../../index.css"
import { TProps } from "../calendarDesktop/calendarDesktop";
import { useSwiper } from 'swiper/react';
import { useTranslation } from "react-i18next";
export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDisplayForm, isMobile, text }) => {
export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDisplayForm, isMobile }) => {
const swiper = useSwiper();
@@ -37,7 +38,7 @@ export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDi
form: false,
confirm: true
})
swiper.slideNext()
swiper.slideNext()
} else {
setDisplayForm(false)
setOpen({
@@ -45,11 +46,12 @@ export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDi
timePicker: false,
form: false,
confirm: true
})
})
}
}
const { t } = useTranslation()
return (
@@ -58,7 +60,7 @@ export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDi
<div className="timepicker__header">
<div className="caption__container">
<div onClick={goBack} className="button__arrow_back"></div>
<span className="calendar__caption">{text.formCaption}</span>
<span className="calendar__caption">{t('formCaption')}</span>
</div>
<div className="line line_time"></div>
<div className="date date_time">{!open.form ? '' : time.format("DD MMM, HH:mm")}</div>
@@ -70,26 +72,26 @@ export const Form: React.FC<TProps> = ({ time, open, setOpen, displayForm, setDi
name="tel"
className="form__input"
type="text"
placeholder={text.placeholders.name}
placeholder={t('placeholders-phoneNumber') as string}
></input>
<input
name="email"
className="form__input"
type="number"
placeholder={text.placeholders.phoneNumber}
placeholder={t('placeholders-email') as string}
></input>
<input
name="name"
className="form__input"
type="email"
placeholder={text.placeholders.email}
placeholder={t('placeholders-name') as string}
></input>
</form>
</div>
</div>
</div>
<button onClick={handleConfirm} disabled={!open.form} type="submit" className={open.form ? 'button__submit' : 'button__submit button__submit_disabled'}>
{text.buttons.plan}
{t('buttons-plan')}
</button>
</div>
);
+4
View File
@@ -0,0 +1,4 @@
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 13C0.447716 13 0 12.5523 0 12V1C0 0.447715 0.447715 0 1 0H6.82201C7.28827 0 7.66624 0.377978 7.66624 0.844238V0.844238C7.66624 1.3105 7.28827 1.68848 6.82201 1.68848H2.34491C2.06877 1.68848 1.84491 1.91233 1.84491 2.18848V5.14941C1.84491 5.42556 2.06877 5.64941 2.34491 5.64941H6.42515C6.88966 5.64941 7.26621 6.02597 7.26621 6.49048V6.49048C7.26621 6.95499 6.88966 7.33154 6.42515 7.33154H2.34491C2.06877 7.33154 1.84491 7.5554 1.84491 7.83154V10.8115C1.84491 11.0877 2.06877 11.3115 2.34491 11.3115H6.89365C7.35991 11.3115 7.73789 11.6895 7.73789 12.1558V12.1558C7.73789 12.622 7.35991 13 6.89365 13H1Z" fill="#F2F2F2"/>
<path d="M19.0865 0C19.591 0 20 0.408988 20 0.913501V12C20 12.5523 19.5523 13 19 13H18.8462C18.5082 13 18.193 12.8293 18.0085 12.5461L12.1107 3.49922C12.0972 3.47838 12.074 3.46582 12.0491 3.46582V3.46582C12.0085 3.46582 11.9755 3.49876 11.9755 3.5394V12.0775C11.9755 12.587 11.5625 13 11.0531 13V13C10.5436 13 10.1306 12.587 10.1306 12.0775V1C10.1306 0.447715 10.5783 0 11.1306 0H11.2963C11.6343 0 11.9495 0.170802 12.1341 0.454032L18.0378 9.51347C18.0514 9.53431 18.0746 9.54687 18.0994 9.54687V9.54687C18.1401 9.54687 18.173 9.51394 18.173 9.4733V0.913501C18.173 0.408988 18.582 0 19.0865 0V0Z" fill="#F2F2F2"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+4
View File
@@ -0,0 +1,4 @@
<svg width="20" height="13" viewBox="0 0 20 13" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0.897734 12.7877C0.401929 12.7877 0 12.3858 0 11.89V0.999999C0 0.447714 0.447715 0 1 0H4.24172C5.16366 0 5.92872 0.170669 6.5369 0.512008C7.14894 0.853346 7.60604 1.32581 7.90819 1.92939C8.21034 2.52882 8.36142 3.2219 8.36142 4.00865C8.36142 4.79123 8.20841 5.48015 7.90238 6.07541C7.60023 6.66651 7.14313 7.12648 6.53109 7.45533C5.92291 7.78418 5.15785 7.94861 4.23591 7.94861H1.85311C1.39447 7.94861 1.02266 7.5768 1.02266 7.11816C1.02266 6.65951 1.39447 6.2877 1.85311 6.2877H4.07321C4.65427 6.2877 5.12686 6.19821 5.49099 6.01921C5.859 5.84022 6.12822 5.58005 6.29866 5.23871C6.46911 4.89737 6.55433 4.48735 6.55433 4.00865C6.55433 3.52578 6.46717 3.10743 6.29285 2.7536C6.12241 2.39978 5.85319 2.1292 5.48518 1.94188C5.12105 1.7504 4.64265 1.65466 4.04997 1.65466H2.29547C2.01933 1.65466 1.79547 1.87852 1.79547 2.15466V11.89C1.79547 12.3858 1.39354 12.7877 0.897734 12.7877ZM5.32848 7.01825C5.66354 7.01825 5.97028 7.20621 6.12241 7.50474L8.14113 11.4661C8.44931 12.0708 8.01003 12.7877 7.3313 12.7877C6.9869 12.7877 6.67209 12.5931 6.51818 12.285L4.53132 8.30754C4.23536 7.71508 4.66621 7.01825 5.32848 7.01825Z" fill="#F2F2F2"/>
<path d="M18.1987 0.900639C18.1987 0.403229 18.602 0 19.0994 0C19.5968 0 20 0.40323 20 0.900639V8.41066C20 9.30564 19.8044 10.0986 19.4131 10.7896C19.0219 11.4765 18.4718 12.0176 17.7629 12.4131C17.054 12.8044 16.2231 13 15.2702 13C14.3211 13 13.4922 12.8044 12.7833 12.4131C12.0744 12.0176 11.5243 11.4765 11.1331 10.7896C10.7418 10.0986 10.5462 9.30564 10.5462 8.41066V0.897733C10.5462 0.401929 10.9481 0 11.4439 0C11.9397 0 12.3417 0.401929 12.3417 0.897734V8.25456C12.3417 8.83317 12.4598 9.34726 12.6961 9.79683C12.9363 10.2464 13.2752 10.6002 13.713 10.8583C14.1507 11.1122 14.6698 11.2392 15.2702 11.2392C15.8745 11.2392 16.3955 11.1122 16.8332 10.8583C17.2748 10.6002 17.6119 10.2464 17.8443 9.79683C18.0806 9.34726 18.1987 8.83317 18.1987 8.25456V0.900639Z" fill="#F2F2F2"/>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

+93 -111
View File
@@ -1,32 +1,53 @@
/*
* Prefixed by https://autoprefixer.github.io
* PostCSS: v8.4.14,
* Autoprefixer: v10.4.7
* Browsers: last 4 version
*/
.header-container {
display: -webkit-box;
display: -ms-flexbox;
.header {
box-sizing: border-box;
width: 100%;
display: flex;
padding: 30px 40px;
color: #ffffff;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
position: relative;
}
.header-popup {
position: absolute;
}
.header-button-container {
display: flex;
gap: 8px;
}
.button-lang {
background: transparent;
border: none;
outline: none;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
box-sizing: border-box;
border-radius: 4px;
padding: 10px 14px;
}
.button-lang:hover {
background: #23242A;
}
.button-lang-active {
cursor: pointer;
pointer-events: none;
background: #2E3038;
}
.header__buttons_wrapper {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
gap: 40px;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
@@ -35,73 +56,48 @@
}
.header-logo {
width: 31px;
height: 50px;
width: 104px;
height: 40px;
}
.header-buttons {
margin-right: 96px;
}
.header-button {
font-family: "GilroyWebRegular";
font-style: normal;
font-weight: 400;
font-size: 16px;
line-height: 125%;
background-color: transparent;
border: none;
color: #ffffff;
cursor: pointer;
padding: 0px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
text-decoration: none;
}
.header-lang-button-text:hover {
background: rgba(235, 235, 235, 0.2);
}
.wrapper__button {
margin: 0;
height: 15px;
}
.header-lang-button {
position: absolute;
right: 40px;
top: 40px;
overflow: hidden;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
gap: 10px;
width: 58px;
padding: 5px 12px;
-webkit-box-sizing: border-box;
width: 55px;
padding: 6px 8px 5px 12px;
box-sizing: border-box;
height: 31px;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
height: 29px;
justify-content: space-between;
box-sizing: border-box;
line-height: 13px;
background-color: transparent;
border: 1.2px solid #ebebeb;
border: 2px solid #ebebeb;
border-radius: 12px;
-webkit-transition: height ease-in 0.3s;
-o-transition: height ease-in 0.3s;
transition: height ease-in 0.3s;
font-style: normal;
font-weight: 500;
font-size: 15px;
line-height: 130%;
transition: height ease-in 0.5s;
}
.header-lang-button_disabled {
@@ -109,7 +105,7 @@
}
.header-lang-button_active {
height: 53px;
height: 51px;
}
.header-lang-button_active {
@@ -117,8 +113,8 @@
}
.header-lang-button-text {
width: 100%;
-moz-appearance: none;
appearance: none;
background-color: transparent;
color: #ebebeb;
@@ -126,54 +122,29 @@
text-align: left;
margin: 0;
border: none;
height: 15px;
height: 13px;
-webkit-appearance: none;
font-style: normal;
font-weight: 500;
font-size: 15px;
line-height: 130%;
cursor: pointer;
}
.header-lang-button-picked {
width: 100%;
-moz-appearance: none;
appearance: none;
background-color: transparent;
color: #ebebeb;
padding: 0;
text-align: left;
margin: 0;
border: none;
height: 100%;
-webkit-appearance: none;
font-style: normal;
font-weight: 500;
font-size: 15px;
line-height: 130%;
cursor: pointer;
}
.header-select__icon {
top: 6px;
height: 16px;
height: 13px;
right: 5px;
position: absolute;
}
.select {
background-color: transparent;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-ms-flex-item-align: center;
-ms-grid-row-align: center;
align-self: center;
gap: 11px;
position: relative;
@@ -187,9 +158,10 @@
.option {
/* or 16px */
/* Landing/White */
color: #ebebeb;
color: #EBEBEB;
}
.burger__button {
@@ -197,34 +169,31 @@
cursor: pointer;
background-color: transparent;
display: none;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
gap: 5px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.line__burger {
background-color: #ffffff;
background-color: #FFFFFF;
width: 14px;
height: 1px;
}
@media screen and (min-width: 1600px) {
.header-container {
.header {
padding: 35px 48px;
}
.header-logo {
width: 46px;
height: 74px;
cursor: pointer;
}
.header-button {
font-size: 20px;
}
.header-lang-button_active {
height: auto;
}
.header-buttons {
@@ -232,45 +201,58 @@
}
.header-lang-button {
width: 70px;
padding: 7px 15px;
top: 57px;
width: 60px;
}
}
@media screen and (max-width: 1279px) {
.header-container {
.header {
padding: 30px 12px;
}
.header-lang-button {
top: 40px;
right: 12px;
}
}
@media screen and (max-width: 1024px) {
.header-container {
.header {
padding: 15px 12px;
}
.header-lang-button {
right: 12px;
top: 26px;
top: 25%;
}
}
@media screen and (max-width: 639px) {
.header-container {
.header-logo {
width: 94px;
height: 36px;
}
.header-popup {
position: static;
}
.header {
padding: 8px 10px;
}
.header-buttons {
display: none;
}
.burger__button {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}
}
+27 -94
View File
@@ -1,106 +1,39 @@
import React, { CSSProperties, useState } from "react";
import "./Header.css";
import logo from "./logoIcon.svg";
import chevron from "./chevronIcon.svg";
import "./header.css";
import "../../styles/styles.css";
import iconClose from './closeIcon1.svg'
import { Nav } from "../Navigaton/navigation";
import { useLocation, useHistory } from "react-router-dom";
import ru from './RU.svg'
import en from './EN.svg'
import { useAppSelector, useAppDispatch } from "../../hooks/redux";
import { languageSlice } from "../../store/reducers/languageSlice";
import { useLocation } from "react-router-dom";
export type THeader = {
language: string;
changeLanguage: (language: string) => void;
text?: any;
};
export const Header: React.FC<THeader> =
({ changeLanguage, language, text }) => {
const [open, setOpen] = useState<boolean>(false)
const [menuOpen, setMenuOpen] = useState(false)
const [opacity, setOpacity] = useState(false)
const userLanguage = language === 'RU';
export const Header: React.FC = ({ }) => {
const buttons = [{
icon: ru, value: "ru"
}, { icon: en, value: "en" }]
const location = useLocation();
const location = useLocation()
const history = useHistory()
console.log(location, 'loc')
function handleUpdateLanguage(value: string) {
changeLanguage(value)
setOpen(prev => !prev)
}
function handleOpen() {
setOpen(prev => !prev)
}
function handleOpacity() {
setOpacity(true)
}
const style = {
background: 'rgba(235, 235, 235, 0.2'
};
const iconTransform = {
transform: 'rotate(-90deg)'
} as CSSProperties
const setBackground = opacity && !open as boolean;
function setOpacityAndMenu() {
setMenuOpen(true)
const targetElement = document.querySelector('body') as HTMLElement
targetElement.style.overflow = 'hidden'
}
const { handleChangeLanguage } = languageSlice.actions;
const { currentLang } = useAppSelector((state) => state.languageReducer);
const dispatch = useAppDispatch();
function openMenu() {
setMenuOpen(false)
const targetElement = document.querySelector('body') as HTMLElement
targetElement.style.overflow = 'visible'
}
function goBack() {
if (location.pathname === '/demos') {
history.goBack()
} else {
window.location.reload();
}
}
return (
<div className="header">
<div className="header-container">
<img onClick={goBack} className="header-logo" alt="company-logo" src={logo} />
<div className="header-buttons">
<div className="header__buttons_wrapper">
<a target='_blank' rel="noreferrer" href={userLanguage ? 'https://graff.tech/contacts/' : 'http://en.graff.tech/contactseng' } className="header-button">{text.captionContact}</a>
<a target='_blank' rel="noreferrer" href={userLanguage ? 'https://graff.tech/' : 'http://en.graff.tech/' } className="header-button">{text.captionCompain}</a>
</div>
<div className={open ? "header-lang-button header-lang-button_active" : 'header-lang-button header-lang-button_disabled'} style={setBackground ? style : { background: 'transparent' }}>
<img alt="img" src={chevron} className="header-select__icon" style={open ? iconTransform : {
transform: 'rotate(0deg)'
}}></img>
<div className="wrapper__button">
<button onMouseEnter={handleOpacity} onMouseLeave={() => setOpacity(false)} onClick={handleOpen} className=" header-lang-button-picked">{language}</button>
</div>
{language === 'RU' ? (<button value={'EN'} onClick={(e: any) => handleUpdateLanguage(e.target.value)} className="header-lang-button-text">EN</button>
) : (<button onClick={(e: any) => handleUpdateLanguage(e.target.value)} value={'RU'} className="header-lang-button-text">RU</button>)}
</div>
</div>
{menuOpen ? <img alt="iconClose" src={iconClose} onClick={openMenu} className='nav__close'></img>
:
<button onClick={setOpacityAndMenu} className="burger__button">
<span className="line__burger"></span>
<span className="line__burger"></span>
<span className="line__burger"></span>
</button>}
</div>
<Nav text={text} setOpacity={setOpacity} language={language} menuOpen={menuOpen} setOpen={setMenuOpen} changeLanguage={changeLanguage}></Nav>
return (
<header className={location.pathname === '/' ? 'header' : 'header header-popup'}>
<a className="header-logo" target='_blank' href="https://estate.graff.tech/" style={{ cursor: "pointer" }}><img alt="company-logo" src={logo} />
</a>
<div className="header-button-container">
{buttons.map((item, index) => (<button key={index} onClick={() => dispatch(handleChangeLanguage(item.value))} value={item.value} className={currentLang === item.value ? 'button-lang button-lang-active' : "button-lang"}><img src={item.icon}></img></button>
))}
</div>
);
}
</header>
);
};
+14 -12
View File
@@ -12,6 +12,7 @@ import { Demos } from "../demos/demos";
import { PhotoComponent } from "../photoComponent/photoComponent";
import { CalendarMobile } from "../calendarMobile/calendarMobile";
import moment, { Moment } from "moment";
import useScreenSize from 'use-screen-size'
@@ -28,7 +29,7 @@ export type TText = {
text: object,
}
export const Main: React.FC<any> = ({ text, locale }) => {
export const Main: React.FC<any> = ({ locale, cards }) => {
const { width } = useScreenSize()
const [displayForm, setDisplayForm] = useState(true);
@@ -78,14 +79,15 @@ export const Main: React.FC<any> = ({ text, locale }) => {
})
setDisplayForm(true)
}
return (
<main className="main">
<AnimationComponent text={text.title} />
<SliderComponent text={text.slider} />
<AnimationComponent />
<SliderComponent />
<div className="calendar__mobile">
<CalendarMobile
locale={locale}
text={text.calendar}
text={'calendar'}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
setOpen={navigationHandler}
@@ -99,7 +101,7 @@ export const Main: React.FC<any> = ({ text, locale }) => {
<div className="calendar__desktop">
<CalendarDesktop
locale={locale}
text={text.calendar}
text={'calendar'}
setDisplayForm={setDisplayForm}
displayForm={displayForm}
setOpen={navigationHandler}
@@ -110,13 +112,13 @@ export const Main: React.FC<any> = ({ text, locale }) => {
isMobile={isMobile}
></CalendarDesktop>
</div>
<Multiplayer text={text.multiplayer} />
<Devices text={text.devices} />
<PhotoComponent text={text.photoComponent} />
<Player text={text.player} />
<Analytics text={text.analytics} />
<CloudSolution text={text.cloudSolution} />
<Demos text={text.demos} />
<Multiplayer text={'multiplayer'} />
<Devices text={'devices'} />
<PhotoComponent text={'photoComponent'} />
<Player text={'player'} />
<Analytics text={'analytics'} />
<CloudSolution text={'analytics'} />
<Demos cards={cards} />
</main>
);
};
+1 -1
View File
@@ -6,7 +6,7 @@
*/
.multiplayer__container {
background: #141414;
background: #1C1D21;
border-radius: 32px;
padding: 120px 32px 80px;
margin-bottom: 160px;
+4 -2
View File
@@ -7,16 +7,18 @@ import photo3 from "./Photo3.png";
import { Button } from "../buttonDemo/buttonDemo"
import { Content } from "../content/content";
import { useState } from "react";
import { useTranslation } from "react-i18next";
export const Multiplayer: React.FC<any> = ({text}) => {
const [captionSmall, setCaptionSmall] = useState(true);
const {t} = useTranslation()
return (
<div
data-aos="zoom-in"
data-aos-duration="400"
className="multiplayer__container"
>
<Content captionSmall={captionSmall} text={text}></Content>
<Content isColor={false} captionSmall={captionSmall} text={text}></Content>
<div className="multiplayer__photo-container">
<img alt="device" src={photo1} className="multiplayer__image" />
<img alt="device" src={photo} className="multiplayer__image" />
@@ -25,7 +27,7 @@ export const Multiplayer: React.FC<any> = ({text}) => {
</div>
<div className="main-block__subblock-container">
<div className={captionSmall ? " main-block__caption_small main-block_subblock " : 'main-block_subblock'}>
{text.mainBlockSubblock}
{t(`${text}-mainBlockSubblock`)}
<Button text={text}></Button>
</div>
</div>
+1 -2
View File
@@ -6,8 +6,7 @@
*/
.player__container {
background: #141414;
border-radius: 32px;
background: #1C1D21; border-radius: 32px;
padding: 120px 32px 80px;
margin-bottom: 80px;
}
@@ -9,7 +9,7 @@
width: 100%;
margin: 0 auto;
background: #141414;
background: #1C1D21;
border-radius: 32px;
padding-top: 120px;
padding-bottom: 85px;
@@ -1,9 +1,11 @@
import React from "react";
import "./sliderComponent.css";
import "../../styles/styles.css"
import Swiper from "../swiper/swiper";
import Swiper from "../swiper/swiper"
import { useTranslation } from 'react-i18next';
export const SliderComponent: React.FC<any> = React.memo(({ text }) => {
export const SliderComponent: React.FC<any> = () => {
const { t } = useTranslation()
return (
<div data-aos="zoom-in" data-aos-duration="500" className="slider-container">
<div className="slider">
@@ -15,14 +17,13 @@ export const SliderComponent: React.FC<any> = React.memo(({ text }) => {
<p className="main-block__title_gardient title__gardient_pos">stream</p>
</div>
<p className=" main-block__caption_color main-block__caption_color_slider">
{text.mainBlockCaptionColor}
{t('slider-mainBlockCaptionColor')}
</p>
<p className="main-block__caption_l">{text.mainBlockCaption}</p>
<p className="main-block__caption_l">{t('slider-mainBlockCaption')}</p>
</div>
</div>
</div>
<Swiper
text={text}
slidesPerView={'2'}
centeredSlides={false}
spaceBetween={0}
@@ -34,4 +35,4 @@ export const SliderComponent: React.FC<any> = React.memo(({ text }) => {
></Swiper>
</div>
);
});
}
+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 12H1M1 12L8.2 5M1 12L8.2 19" stroke="#F2F2F2" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 228 B

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 215 B

+24 -1
View File
@@ -10,6 +10,29 @@
width: 536px;
}
.button__arrow_l {
cursor: pointer;
background-image: url(./Arrow_Left.svg);
background-repeat: no-repeat;
background-position: center;
height: 14px;
width: 22px;
}
.button__arrow_r {
-webkit-transform: matrix(-1, 0, 0, 1, 0, 0);
-ms-transform: matrix(-1, 0, 0, 1, 0, 0);
transform: matrix(-1, 0, 0, 1, 0, 0);
cursor: pointer;
background-image: url(./Arrow_Left.svg);
background-repeat: no-repeat;
background-position: center;
height: 14px;
width: 22px;
}
@@ -81,7 +104,7 @@
color: #ebebeb;
display: flex;
color: #ebebeb !important;
color: #F2F2F2 !important;
}
.swiper__caption {
+12 -10
View File
@@ -15,6 +15,7 @@ import "swiper/css";
import "swiper/css/pagination";
import "swiper/css/navigation";
import "../calendar/calendar";
import { useTranslation } from "react-i18next";
type propsTypes = {
slidesPerView: string;
@@ -24,17 +25,18 @@ type propsTypes = {
className: string;
children: React.ReactNode;
rewind: boolean;
text: any;
slideToClickedSlide: boolean,
};
export default function SwiperCentred(props: propsTypes) {
const { t } = useTranslation()
const size = useScreenSize();
const [caption, setCaption] = useState<any>();
useEffect(() => {
setCaption(props.text.subtitle1);
}, [props.text]);
setCaption(t('slider-subtitle1'));
}, [t]);
function updateCaption() {
const slide = document
@@ -82,8 +84,8 @@ export default function SwiperCentred(props: propsTypes) {
<SwiperSlide style={swiperWidth()}>
{({ isActive }) => (
<img
data-caption={props.text.subtitle}
className={isActive ? "image__slider_active" : "image__slider"}
data-caption={t('slider-subtitle')}
className={isActive ? "image__slider_active" : "image__slider"}
src={img1}
alt="slide"
/>
@@ -92,7 +94,7 @@ export default function SwiperCentred(props: propsTypes) {
<SwiperSlide style={swiperWidth()}>
{({ isActive }) => (
<img
data-caption={props.text.subtitle1}
data-caption={t('slider-subtitle1')}
className={isActive ? "image__slider_active" : "image__slider"}
src={img}
alt="slide"
@@ -102,8 +104,8 @@ export default function SwiperCentred(props: propsTypes) {
<SwiperSlide style={swiperWidth()}>
{({ isActive }) => (
<img
data-caption={props.text.subtitle2}
className={isActive ? "image__slider_active" : "image__slider"}
data-caption={t('slider-subtitle2')}
className={isActive ? "image__slider_active" : "image__slider"}
src={img2}
alt="slide"
/>
@@ -112,8 +114,8 @@ export default function SwiperCentred(props: propsTypes) {
<SwiperSlide style={swiperWidth()}>
{({ isActive }) => (
<img
data-caption={props.text.subtitle3}
className={isActive ? "image__slider_active" : "image__slider"}
data-caption={t('slider-subtitle3')}
className={isActive ? "image__slider_active" : "image__slider"}
src={img3}
alt="slide"
/>
+7 -5
View File
@@ -7,6 +7,7 @@ import point0 from "../calendar/Ellipse0.svg";
import point1 from "../calendar/Ellipse1.svg";
import { TProps } from "../calendarDesktop/calendarDesktop";
import { useSwiper } from 'swiper/react';
import { useTranslation } from "react-i18next";
@@ -16,7 +17,6 @@ export const Timepicker: React.FC<TProps> = ({
open,
setOpen,
isMobile,
text
}) => {
@@ -84,16 +84,18 @@ export const Timepicker: React.FC<TProps> = ({
}
}
const { t } = useTranslation()
return (
<div data-aos="fade-up" className={open.timePicker ? " calendar aos-init aos-animate" : "calendar aos-init aos-animate"}>
<div className={open.timePicker ? 'opacity_active' : 'opacity'}>
<div className="timepicker__header">
<div className="caption__container">
<div onClick={() => goBack()} className="button__arrow_back" ></div>
<span className="calendar__caption">{text.timepickerCaption}</span>
<span className="calendar__caption">{t('timepickerCaption')}</span>
</div>
<div className="line line_time"></div>
<div className="date date_time">{!open.calendar ? time.format("DD MMMM") : '' }</div>
<div className="date date_time">{!open.calendar ? time.format("DD MMMM") : ''}</div>
</div>
<div className="form__block">
{timePicker.map((date, i) => (
@@ -114,11 +116,11 @@ export const Timepicker: React.FC<TProps> = ({
<div className="appointment__block appointment__block_time">
<div>
<img alt="point" className="point" src={point1}></img>
<span className="appointment__caption_active">{text.appointmentTrue}</span>
<span className="appointment__caption_active">{t('appointmentTrue')}</span>
</div>
<div>
<img alt="point" className="point" src={point0}></img>
<span>{text.appointmentFalse}</span>
<span>{t('appointmentFalse')}</span>
</div>
</div>
+6
View File
@@ -0,0 +1,6 @@
import { useDispatch, useSelector, TypedUseSelectorHook } from "react-redux";
import { AppDispatch, RootState } from "../store/store";
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
+5
View File
@@ -0,0 +1,5 @@
import { useLocation } from "react-router";
const useQuery = () => new URLSearchParams(useLocation().search);
export default useQuery
+2 -2
View File
@@ -5,7 +5,7 @@
@import url(./components/cloudSolution/cloudSolution.css);
@import url(./components/devices/devices.css);
@import url(./components/form/form.css);
@import url(./components/header/header.css);
@import url(./components/header/Header.css);
@import url(./components/multiplayer/multiplayer.css);
@import url(./components/player/player.css);
@import url(./components/sliderComponent/sliderComponent.css);
@@ -28,7 +28,7 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-overflow-scrolling: touch;
background: #0e0e0e;
background: #151619;
width: 100%;
}
+32 -2
View File
@@ -3,6 +3,34 @@ import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";
import { setupStore } from "./store/store";
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import HttpApi from "i18next-http-backend";
import LanguageDetector from "i18next-browser-languagedetector";
const store = setupStore();
i18next
.use(HttpApi)
.use(LanguageDetector)
.use(initReactI18next)
.init({
supportedLngs: ["en", "ru"],
fallbackLng: "en",
debug: false,
// Options for language detector
detection: {
order: ["cookie", "navigator"],
caches: ["cookie"],
},
// react: { useSuspense: false },
backend: {
loadPath: "/assets/locales/{{lng}}/translation.json",
},
});
const root = ReactDOM.createRoot(
@@ -10,8 +38,10 @@ const root = ReactDOM.createRoot(
);
root.render(
<BrowserRouter basename='/streaming-landing'>
<App />
<BrowserRouter>
<Provider store={store}>
<App />
</Provider>
</BrowserRouter>
);
+11
View File
@@ -0,0 +1,11 @@
export interface ICards {
app_title: string;
title: string;
language: string;
location: string;
feature_description: string;
icon: string;
logo: string;
preview: string;
_id: string;
}
+5
View File
@@ -0,0 +1,5 @@
export interface IData {
link: string;
connection_code: string;
msg: string,
}
BIN
View File
Binary file not shown.
+69
View File
@@ -0,0 +1,69 @@
import { createAsyncThunk } from "@reduxjs/toolkit";
import axios from 'axios';
const instance = axios.create({
baseURL: 'https://a1.coord.graff.tech',
});
instance.defaults.headers.post['Content-Type'] = 'application/json';
export const fetchCards = createAsyncThunk(
"cards/FetchAll",
async (language: string, thunkApi) => {
try {
const { data } = await instance.get('/title/get_for_language/', { params: { start: 0, count: 100, language: language } });
return data;
} catch (e: any) {
const { response } = e
if (!response) {
return thunkApi.rejectWithValue('Произошла ошибка, попробуйте позже');
} else {
return thunkApi.rejectWithValue(response.data.message);
}
}
}
);
export const createSession = createAsyncThunk(
"session/Create",
async (title: string, thunkApi) => {
try {
const { data } = await instance.post('/session/create', { title });
return data;
} catch (e: any) {
const { response } = e
if (!response) {
return thunkApi.rejectWithValue('Произошла ошибка, попробуйте позже');
} else {
return thunkApi.rejectWithValue(response.data.message);
}
}
}
);
export const connectSession = createAsyncThunk(
"session/Connect",
async (code: string, thunkApi) => {
try {
const { data } = await instance.get('/session/connect', { params: { session_id: code } });
return data;
} catch (e: any) {
const { response } = e
if (!response) {
return thunkApi.rejectWithValue('Произошла ошибка, попробуйте позже');
} else {
return thunkApi.rejectWithValue(response.data.message);
}
}
}
);
+45
View File
@@ -0,0 +1,45 @@
import { ICards } from "../../models/ICards";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { fetchCards } from "./ActionCreator";
interface CardState {
cards: ICards[];
isLoading: boolean;
error: any;
currentCard: ICards | null;
}
const initialState: CardState = {
cards: [],
isLoading: false,
error: "",
currentCard: null,
};
export const cardSlice = createSlice({
name: "cards",
initialState,
reducers: {
handleCurrentCard(state, action: PayloadAction<ICards>) {
state.currentCard = action.payload;
},
},
extraReducers: {
[fetchCards.fulfilled.type]: (state, action: PayloadAction<ICards[]>) => {
state.isLoading = false;
state.error = "";
state.cards = action.payload;
},
[fetchCards.pending.type]: (state) => {
state.isLoading = true;
},
[fetchCards.rejected.type]: (state, action: PayloadAction<any>) => {
console.log(action.payload)
state.isLoading = false;
state.error = action.payload;
},
},
});
export default cardSlice.reducer;
+50
View File
@@ -0,0 +1,50 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import HttpApi from "i18next-http-backend";
import cookies from "js-cookie";
import LanguageDetector from "i18next-browser-languagedetector";
i18next
.use(HttpApi)
.use(LanguageDetector)
.use(initReactI18next)
.init({
supportedLngs: ["en", "ru"],
fallbackLng: "en",
debug: false,
// Options for language detector
detection: {
order: ["cookie", "navigator"],
caches: ["cookie"],
},
// react: { useSuspense: false },
backend: {
loadPath: "/assets/locales/{{lng}}/translation.json",
},
});
interface LanguageState {
currentLang: string;
}
const initialState: LanguageState = {
currentLang: '',
};
export const languageSlice = createSlice({
name: "language",
initialState,
reducers: {
handleChangeLanguage(state, action: PayloadAction<string>) {
i18next.changeLanguage(action.payload)
state.currentLang = action.payload
},
},
});
export default languageSlice.reducer;
+76
View File
@@ -0,0 +1,76 @@
import { IData } from "../../models/IData";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { createSession, connectSession } from "./ActionCreator";
export interface sessionState {
isLoading: boolean;
error: any;
url: string;
id: string;
playerCount: any
}
interface ConnectSessionResponseInterface {
websocket_url: string;
}
interface CreateSessionResponseInterface {
session_id: string;
}
const initialState: sessionState = {
isLoading: false,
error: null,
url: "",
id: "",
playerCount: [],
};
export const sessionSlice = createSlice({
name: "data",
initialState,
reducers: {
cleanErrors(state) {
state = initialState
},
setUserCount(state, action) {
console.log(action.payload)
const newArr = new Array(action.payload).fill('user')
state.playerCount = newArr
}
},
extraReducers: {
[createSession.fulfilled.type]: (
state,
action: PayloadAction<CreateSessionResponseInterface>
) => {
state.isLoading = false;
state.id = action.payload.session_id;
},
[createSession.rejected.type]: (state, action: PayloadAction<any>) => {
state.isLoading = false;
state.error = action.payload;
},
[createSession.pending.type]: (state) => {
state.isLoading = true;
},
[connectSession.fulfilled.type]: (
state,
action: PayloadAction<ConnectSessionResponseInterface>
) => {
state.isLoading = false;
const url = action.payload.websocket_url;
state.url = url;
},
[connectSession.rejected.type]: (state, action: PayloadAction<any>) => {
state.isLoading = false;
state.error = action.payload;
},
[connectSession.pending.type]: (state, action) => {
state.isLoading = true;
},
},
});
export default sessionSlice.reducer;
+25
View File
@@ -0,0 +1,25 @@
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import cardReducer from "./reducers/cardSlice";
import sessionReducer from "./reducers/sessionSlice";
import languageReducer from "./reducers/languageSlice";
const rootReducer = combineReducers({
cardReducer,
sessionReducer,
languageReducer,
});
export const setupStore = () => {
return configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ serializableCheck: false }),
});
};
export type RootState = ReturnType<typeof rootReducer>;
export type AppStore = ReturnType<typeof setupStore>;
export type AppDispatch = AppStore["dispatch"];
+6 -6
View File
@@ -38,7 +38,7 @@
font-size: 18px;
line-height: 140%;
margin: 0;
color: #ebebeb;
color: #F2F2F2;
}
.main-block__subblock-container {
@@ -76,7 +76,7 @@
/* Landing/White */
color: #ebebeb;
color: #F2F2F2;
}
.main-block__title {
@@ -84,7 +84,7 @@
font-weight: 400;
font-size: 64px;
line-height: 100%;
color: #ebebeb;
color: #F2F2F2;
margin: 0;
}
@@ -92,7 +92,7 @@
font-style: normal;
font-weight: 400;
line-height: 100%;
color: #ebebeb;
color: #F2F2F2;
margin: 0;
font-size: 40px;
}
@@ -133,7 +133,7 @@
font-size: 18px;
line-height: 140%;
margin: 20px 0 0 0;
color: #ebebeb;
color: #F2F2F2;
}
.main-block__caption_color {
@@ -191,7 +191,7 @@
border: 1px solid #454545;
border-radius: 32px;
background-color: transparent;
color: #ebebeb;
color: #F2F2F2;
cursor: pointer;
}
.main-block__icon {