This commit is contained in:
= 2023-05-28 20:45:14 +03:00
parent 6df47ee610
commit 545dd522e7
17 changed files with 1056 additions and 454 deletions

462
package-lock.json generated
View File

@ -18,17 +18,21 @@
"@types/jest": "^27.5.2",
"@types/node": "^16.18.31",
"@types/react": "^18.2.6",
"@types/react-bootstrap": "^0.32.32",
"@types/react-dom": "^18.2.4",
"@types/react-sidebar": "^3.0.2",
"@yandex/ui": "^3.33.0",
"antd": "^5.5.0",
"axios": "^1.4.0",
"bootstrap": "^5.2.3",
"gl-matrix": "^3.4.3",
"mapbox-gl": "^2.14.1",
"react": "^18.2.0",
"react-bootstrap": "^2.7.4",
"react-dom": "^18.2.0",
"react-map-gl": "^7.0.23",
"react-pro-sidebar": "^1.1.0-alpha.1",
"react-responsive-carousel": "^3.2.23",
"react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"react-sidebar": "^3.0.2",
@ -3442,9 +3446,9 @@
}
},
"node_modules/@popperjs/core": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz",
"integrity": "sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ==",
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
@ -3569,6 +3573,17 @@
"resolved": "https://registry.npmjs.org/@reach/observe-rect/-/observe-rect-1.2.0.tgz",
"integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ=="
},
"node_modules/@react-aria/ssr": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz",
"integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==",
"dependencies": {
"@swc/helpers": "^0.4.14"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
}
},
"node_modules/@react-spring/animated": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.2.tgz",
@ -3644,6 +3659,45 @@
"node": ">=14"
}
},
"node_modules/@restart/hooks": {
"version": "0.4.9",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz",
"integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==",
"dependencies": {
"dequal": "^2.0.2"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@restart/ui": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.5.tgz",
"integrity": "sha512-kDjhH8lk+aVGc+dPb8wEBXRDx4B1WX6/pqyWi22R3Oim6KQokeLGO2g8MYzwd2/UdjsrDt+HyYFpKihLIN7+/A==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"@popperjs/core": "^2.11.6",
"@react-aria/ssr": "^3.5.0",
"@restart/hooks": "^0.4.9",
"@types/warning": "^3.0.0",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"uncontrollable": "^8.0.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
}
},
"node_modules/@restart/ui/node_modules/uncontrollable": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz",
"integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==",
"peerDependencies": {
"react": ">=16.14.0"
}
},
"node_modules/@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -3962,6 +4016,14 @@
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@swc/helpers": {
"version": "0.4.14",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz",
"integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==",
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@testing-library/dom": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz",
@ -4508,6 +4570,14 @@
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-bootstrap": {
"version": "0.32.32",
"resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz",
"integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-dom": {
"version": "18.2.4",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz",
@ -4524,6 +4594,14 @@
"@types/react": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.6",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
"integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -4599,6 +4677,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
},
"node_modules/@types/warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
"integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA=="
},
"node_modules/@types/ws": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
@ -5005,6 +5088,15 @@
"resolved": "https://registry.npmjs.org/@yandex/ui-icons/-/ui-icons-0.0.1-alpha.1.tgz",
"integrity": "sha512-ZQiztkMu+pVRCl3cut4d0tutjzzk5J5K3R8fNKSiX4cQcTTbMe5x0OIXGIb8PCryrIy37MNMWjFNN21Ub5v3hQ=="
},
"node_modules/@yandex/ui/node_modules/@popperjs/core": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz",
"integrity": "sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@yandex/ui/node_modules/react-range": {
"version": "1.8.7",
"resolved": "https://registry.npmjs.org/react-range/-/react-range-1.8.7.tgz",
@ -5971,6 +6063,24 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"node_modules/bootstrap": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.6"
}
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -7094,6 +7204,14 @@
"node": ">= 0.8"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
"engines": {
"node": ">=6"
}
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
@ -7219,6 +7337,15 @@
"utila": "~0.4"
}
},
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@ -9642,6 +9769,14 @@
"node": ">= 0.4"
}
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@ -14691,6 +14826,23 @@
"react-is": "^16.13.1"
}
},
"node_modules/prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"dependencies": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
},
"peerDependencies": {
"react": ">=0.14.0"
}
},
"node_modules/prop-types-extra/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/prop-types/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -15490,6 +15642,35 @@
"node": ">=14"
}
},
"node_modules/react-bootstrap": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.4.tgz",
"integrity": "sha512-EPKPwhfbxsKsNBhJBitJwqul9fvmlYWSft6jWE2EpqhEyjhqIqNihvQo2onE5XtS+QHOavUSNmA+8Lnv5YeAyg==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"@restart/hooks": "^0.4.9",
"@restart/ui": "^1.6.3",
"@types/react-transition-group": "^4.4.5",
"classnames": "^2.3.2",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.8.1",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.5",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"@types/react": ">=16.14.8",
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-debounce-input": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.3.0.tgz",
@ -15631,6 +15812,17 @@
"react": "^18.2.0"
}
},
"node_modules/react-easy-swipe": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz",
"integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==",
"dependencies": {
"prop-types": "^15.5.8"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/react-error-overlay": {
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
@ -15641,6 +15833,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"node_modules/react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"node_modules/react-map-gl": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-7.0.23.tgz",
@ -15668,15 +15865,6 @@
"react-dom": ">=16.8.0"
}
},
"node_modules/react-pro-sidebar/node_modules/@popperjs/core": {
"version": "2.11.7",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/react-refresh": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
@ -15685,6 +15873,16 @@
"node": ">=0.10.0"
}
},
"node_modules/react-responsive-carousel": {
"version": "3.2.23",
"resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz",
"integrity": "sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg==",
"dependencies": {
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
"react-easy-swipe": "^0.0.21"
}
},
"node_modules/react-router": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.2.tgz",
@ -15821,6 +16019,21 @@
}
}
},
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/react-yandex-login": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-yandex-login/-/react-yandex-login-1.0.2.tgz",
@ -17646,6 +17859,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
"dependencies": {
"@babel/runtime": "^7.6.3",
"@types/react": ">=16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
},
"peerDependencies": {
"react": ">=15.0.0"
}
},
"node_modules/unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@ -17868,6 +18095,14 @@
"makeerror": "1.0.12"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
@ -21117,9 +21352,9 @@
}
},
"@popperjs/core": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz",
"integrity": "sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ=="
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="
},
"@rc-component/color-picker": {
"version": "1.0.2",
@ -21201,6 +21436,14 @@
"resolved": "https://registry.npmjs.org/@reach/observe-rect/-/observe-rect-1.2.0.tgz",
"integrity": "sha512-Ba7HmkFgfQxZqqaeIWWkNK0rEhpxVQHIoVyW1YDSkGsGIXzcaW4deC8B0pZrNSSyLTdIk7y+5olKt5+g0GmFIQ=="
},
"@react-aria/ssr": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.6.0.tgz",
"integrity": "sha512-OFiYQdv+Yk7AO7IsQu/fAEPijbeTwrrEYvdNoJ3sblBBedD5j5fBTNWrUPNVlwC4XWWnWTCMaRIVsJujsFiWXg==",
"requires": {
"@swc/helpers": "^0.4.14"
}
},
"@react-spring/animated": {
"version": "9.7.2",
"resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.2.tgz",
@ -21256,6 +21499,38 @@
"resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.2.tgz",
"integrity": "sha512-LzqpSrMK/3JBAVBI9u3NWtOhWNw5AMQfrUFYB0+bDHTSw17z++WJLsPsxAuK+oSddsxk4d7F/JcdDPM1M5YAhA=="
},
"@restart/hooks": {
"version": "0.4.9",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.9.tgz",
"integrity": "sha512-3BekqcwB6Umeya+16XPooARn4qEPW6vNvwYnlofIYe6h9qG1/VeD7UvShCWx11eFz5ELYmwIEshz+MkPX3wjcQ==",
"requires": {
"dequal": "^2.0.2"
}
},
"@restart/ui": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.5.tgz",
"integrity": "sha512-kDjhH8lk+aVGc+dPb8wEBXRDx4B1WX6/pqyWi22R3Oim6KQokeLGO2g8MYzwd2/UdjsrDt+HyYFpKihLIN7+/A==",
"requires": {
"@babel/runtime": "^7.21.0",
"@popperjs/core": "^2.11.6",
"@react-aria/ssr": "^3.5.0",
"@restart/hooks": "^0.4.9",
"@types/warning": "^3.0.0",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"uncontrollable": "^8.0.1",
"warning": "^4.0.3"
},
"dependencies": {
"uncontrollable": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.2.tgz",
"integrity": "sha512-/GDx+K1STGtpgTsj5Dj3J51YaKxZDblbCQHTH1zHLuoBEWodj6MjtRVv3TUijj1JYLRLSFsFzN8NV4M3QV4d9w==",
"requires": {}
}
}
},
"@rollup/plugin-babel": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz",
@ -21450,6 +21725,14 @@
"loader-utils": "^2.0.0"
}
},
"@swc/helpers": {
"version": "0.4.14",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.4.14.tgz",
"integrity": "sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==",
"requires": {
"tslib": "^2.4.0"
}
},
"@testing-library/dom": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.0.tgz",
@ -21911,6 +22194,14 @@
"csstype": "^3.0.2"
}
},
"@types/react-bootstrap": {
"version": "0.32.32",
"resolved": "https://registry.npmjs.org/@types/react-bootstrap/-/react-bootstrap-0.32.32.tgz",
"integrity": "sha512-GM9UtV7v+C2F0rbqgIpMWdCKBMdX3PQURoJQobPO4vDAeFadcExNtKffi13/MjaAks+riJKVGyiMe+6OmDYT2w==",
"requires": {
"@types/react": "*"
}
},
"@types/react-dom": {
"version": "18.2.4",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.4.tgz",
@ -21927,6 +22218,14 @@
"@types/react": "*"
}
},
"@types/react-transition-group": {
"version": "4.4.6",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
"integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
"requires": {
"@types/react": "*"
}
},
"@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -22002,6 +22301,11 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
},
"@types/warning": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.0.tgz",
"integrity": "sha512-t/Tvs5qR47OLOr+4E9ckN8AmP2Tf16gWq+/qA4iUGS/OOyHVO8wv2vjJuX8SNOUTJyWb+2t7wJm6cXILFnOROA=="
},
"@types/ws": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
@ -22293,6 +22597,11 @@
"web-platform-alpha": "0.0.1-alpha.22"
},
"dependencies": {
"@popperjs/core": {
"version": "2.5.4",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.5.4.tgz",
"integrity": "sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ=="
},
"react-range": {
"version": "1.8.7",
"resolved": "https://registry.npmjs.org/react-range/-/react-range-1.8.7.tgz",
@ -23034,6 +23343,12 @@
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"bootstrap": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.3.tgz",
"integrity": "sha512-cEKPM+fwb3cT8NzQZYEu4HilJ3anCrWqh3CHAok1p9jXqMPsPTBhU25fBckEJHJ/p+tTxTFTsFQGM+gaHpi3QQ==",
"requires": {}
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -23828,6 +24143,11 @@
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
},
"dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
"integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="
},
"destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
@ -23929,6 +24249,15 @@
"utila": "~0.4"
}
},
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
@ -25696,6 +26025,14 @@
"side-channel": "^1.0.4"
}
},
"invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"ipaddr.js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
@ -29171,6 +29508,22 @@
}
}
},
"prop-types-extra": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/prop-types-extra/-/prop-types-extra-1.1.1.tgz",
"integrity": "sha512-59+AHNnHYCdiC+vMwY52WmvP5dM3QLeoumYuEyceQDi9aEhtwN9zIQ2ZNo25sMyXnbh32h+P1ezDsUpUH3JAew==",
"requires": {
"react-is": "^16.3.2",
"warning": "^4.0.0"
},
"dependencies": {
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}
}
},
"protocol-buffers-schema": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
@ -29720,6 +30073,25 @@
"whatwg-fetch": "^3.6.2"
}
},
"react-bootstrap": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.7.4.tgz",
"integrity": "sha512-EPKPwhfbxsKsNBhJBitJwqul9fvmlYWSft6jWE2EpqhEyjhqIqNihvQo2onE5XtS+QHOavUSNmA+8Lnv5YeAyg==",
"requires": {
"@babel/runtime": "^7.21.0",
"@restart/hooks": "^0.4.9",
"@restart/ui": "^1.6.3",
"@types/react-transition-group": "^4.4.5",
"classnames": "^2.3.2",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.8.1",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.5",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
}
},
"react-debounce-input": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.3.0.tgz",
@ -29824,6 +30196,14 @@
"scheduler": "^0.23.0"
}
},
"react-easy-swipe": {
"version": "0.0.21",
"resolved": "https://registry.npmjs.org/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz",
"integrity": "sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg==",
"requires": {
"prop-types": "^15.5.8"
}
},
"react-error-overlay": {
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
@ -29834,6 +30214,11 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
"integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
},
"react-lifecycles-compat": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
},
"react-map-gl": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/react-map-gl/-/react-map-gl-7.0.23.tgz",
@ -29851,13 +30236,6 @@
"@emotion/styled": "^11.10.5",
"@popperjs/core": "^2.11.6",
"classnames": "^2.3.2"
},
"dependencies": {
"@popperjs/core": {
"version": "2.11.7",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw=="
}
}
},
"react-refresh": {
@ -29865,6 +30243,16 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A=="
},
"react-responsive-carousel": {
"version": "3.2.23",
"resolved": "https://registry.npmjs.org/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz",
"integrity": "sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg==",
"requires": {
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
"react-easy-swipe": "^0.0.21"
}
},
"react-router": {
"version": "6.11.2",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.11.2.tgz",
@ -29954,6 +30342,17 @@
"p-sleep": "^1.1.0"
}
},
"react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
},
"react-yandex-login": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/react-yandex-login/-/react-yandex-login-1.0.2.tgz",
@ -31313,6 +31712,17 @@
"which-boxed-primitive": "^1.0.2"
}
},
"uncontrollable": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-7.2.1.tgz",
"integrity": "sha512-svtcfoTADIB0nT9nltgjujTi7BzVmwjZClOmskKu/E8FW9BXzg9os8OLr4f8Dlnk0rYWJIWr4wv9eKUXiQvQwQ==",
"requires": {
"@babel/runtime": "^7.6.3",
"@types/react": ">=16.9.11",
"invariant": "^2.2.4",
"react-lifecycles-compat": "^3.0.4"
}
},
"unicode-canonical-property-names-ecmascript": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
@ -31471,6 +31881,14 @@
"makeerror": "1.0.12"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"requires": {
"loose-envify": "^1.0.0"
}
},
"watchpack": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

View File

@ -13,17 +13,21 @@
"@types/jest": "^27.5.2",
"@types/node": "^16.18.31",
"@types/react": "^18.2.6",
"@types/react-bootstrap": "^0.32.32",
"@types/react-dom": "^18.2.4",
"@types/react-sidebar": "^3.0.2",
"@yandex/ui": "^3.33.0",
"antd": "^5.5.0",
"axios": "^1.4.0",
"bootstrap": "^5.2.3",
"gl-matrix": "^3.4.3",
"mapbox-gl": "^2.14.1",
"react": "^18.2.0",
"react-bootstrap": "^2.7.4",
"react-dom": "^18.2.0",
"react-map-gl": "^7.0.23",
"react-pro-sidebar": "^1.1.0-alpha.1",
"react-responsive-carousel": "^3.2.23",
"react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"react-sidebar": "^3.0.2",

BIN
public/pin.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

View File

@ -1,9 +1,16 @@
import axios from "axios";
export const backend = axios.create({
baseURL: 'https://dev2.akarpov.ru/api/',
timeout: 10000,
headers: {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjg3Mjk0NTExLCJpYXQiOjE2ODQ3MDI1MTEsImp0aSI6ImUwNGNjZGViMzA0NzQxYTlhYzJhODRhNzc1YWFkZTIxIiwidXNlcl9pZCI6N30.M-F08v6Wit5Bbm668m84JThyDX5yZhzsh3_GFh3nzXM'}
// export const backend = axios.create({
// baseURL: 'https://dev2.akarpov.ru/api/',
// timeout: 10000,
// headers: {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjg3Mjk0NTExLCJpYXQiOjE2ODQ3MDI1MTEsImp0aSI6ImUwNGNjZGViMzA0NzQxYTlhYzJhODRhNzc1YWFkZTIxIiwidXNlcl9pZCI6N30.M-F08v6Wit5Bbm668m84JThyDX5yZhzsh3_GFh3nzXM'}
// });
export const backend = axios.create({
baseURL: 'https://0e06-92-100-146-65.ngrok-free.app/api/',
timeout: 100000,
headers: {'Authorization': 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjg3NjEwNTg3LCJpYXQiOjE2ODUwMTg1ODcsImp0aSI6IjZhY2E2NDJkYWM0NzQyYmZhNGRjM2UzNjdiZTlhMzZhIiwidXNlcl9pZCI6OH0.JsmCZTvNXuL3VCgntvaDDtnA7u9eBeR6WFfgaosXWZo'}
});

View File

@ -0,0 +1,56 @@
import React, { useState } from "react";
import { backend } from "../../consts";
import { Button } from "../Button";
import './style.css'
export interface EventCardIE{
category: string,
description: string,
lat: number,
lon: number,
oid: string,
title: string
}
enum category{
'attractions' = 'Развлечения',
'museum' = 'Музей',
'movie' = 'Кино',
'concert' = 'Концерт',
'artwork' = 'Арт',
'plays' = 'Игры',
'shop' = 'Магазин',
'gallery' = 'Галерея',
'theme_park' = 'Тематический парк',
'viewpoint' = 'Достопримечательность',
'zoo' = 'Зоопарк'
}
export const EventCard:React.FC<EventCardIE> = (props) =>{
const [liked, setLiked] = useState(false)
const onLiked = ()=>{
backend.get('/onboarding/' + props.oid + '/add_to_favorites/')
setLiked(!liked)
}
return(
<div key={props.oid}>
<div className="hotelCard" >
<div className="hotelCardTools">
<div></div>
<img className="likeHotelBtn" onClick={()=>onLiked()} src={liked? '/icons/liked.svg':'/icons/unliked.svg'}></img>
</div>
<img className="hotelImg" src='/icons/not_found.jpeg'></img>
<h5>{props.title}</h5>
<div className="hotelCardRow">
<div>{props.description}</div>
<div>{category[props.category as keyof typeof category]}</div>
</div>
</div>
</div>
);
}

View File

@ -0,0 +1,93 @@
.hotelCard{
width: 250px;
padding: 0px 15px 15px 15px;
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-between;
background: #F5F5F5;
border-radius: 20px;
height: 350px;
}
h3{
margin: 0px;
}
.likeHotelBtn{
width: 40px;
height: 40px;
cursor: pointer;
}
.likeHotelBtn:hover{
opacity: 0.5;
}
.ratingTile{
width: 40px;
height: 40px;
background: #007470;
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
font-size: 18px;
color:white;
font-weight: 500;
}
.hotelCardTools{
position: relative;
top:15px;
display: flex;
flex-direction: row;
width: 250px;
justify-content: space-between;
}
.hotelCardRow{
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
gap:15px;
font-size: 12px;
}
.hotelBtn{
margin-top: 15px;
}
.openHotelCardBG{
position: fixed;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0,0,0, 0.2);
left: 0px;
top:0px;
width: 100%;
height: 100vh;
z-index: 10000;
}
.openHotelCard{
width: 75%;
height: 75vh;
overflow-y: scroll;
padding: 50px;
background-color: white;
z-index: 10000;
border-radius: 20px;
}
.hotelImg{
margin-top: -65px;
margin-left: -15px;
width: 280px;
height: 240px;
}

View File

@ -15,7 +15,7 @@ export const GenerateCard:React.FC = (props) =>{
<Block className='generatecard-block'>
<div className="generateCardDescr">
<div className="generateCardTitle">
<div className="generateTitleText">Выбери свой фантастический Тур!</div>
<div className="generateTitleText">Выбери свой Тур!</div>
</div>
</div>
<img src='generateTour.png'></img>

View File

@ -1,10 +1,10 @@
.generatecard-block{
width: 400px;
height: 548px;
width: 238px;
height: 323px;
display: flex;
flex-direction: column;
gap:30px;
padding: 25px;
gap:15px;
padding: 20px;
border: solid #F5DFB8 1px;
background-color: #fff;
}
@ -26,6 +26,7 @@
.generateTitleText{
font-size: 24px;
line-height: 22px;
}
.generateCardTitle{

View File

@ -21,7 +21,6 @@ export const Prefernces = () =>{
backend.get('/data/cities').then((response)=>setCities(response.data))
backend.get('/data/regions').then((response)=>setRegions(response.data))
}
})
@ -221,7 +220,7 @@ export const Prefernces = () =>{
},
],
onChange: (e)=>backend.post('/onboarding/event/', {
stars: e.map((value)=>Number(value))
types: e
}).then((response)=>setEvents(response.data.events))
} as ChoiceIconIE

View File

@ -6,12 +6,17 @@ import { MyMap } from "../map";
import Sidebar from "react-sidebar";
import { PlaceCard } from "../TourCard";
import { Collapse, Tabs, TabsProps } from "antd";
import { backend } from "../../consts";
export interface RouteCardIE{
rawProps:any,
city:string,
options: {
date:string,
paths:({
type:string
distance:number,
point_type:string,
point:{
lat:number,
lon:number,
@ -38,7 +43,11 @@ export const RouteCard:React.FC<RouteCardIE> = (props) =>{
})
let points = props.options[Number(selectedDay)].paths.map((path)=>{
return [path.point.lon, path.point.lat]
return {
description:path.point.description,
title: path.point.title,
cords:[path.point.lon, path.point.lat]
}
})
const items: TabsProps['items'] = props.options.map((day, index)=>{
@ -79,8 +88,15 @@ export const RouteCard:React.FC<RouteCardIE> = (props) =>{
}
})
const onLiked = () =>{
// backend.get('route/list').then((e)=>console.log(e.data))
backend.post('route/save', {
points: props.rawProps.path
})
setLiked(!liked)
}
return(
<div>
<div key={props.city + props.options[0].paths[0].point.oid}>
<Sidebar
sidebar={
<div className='sidebarContent'>
@ -99,7 +115,7 @@ export const RouteCard:React.FC<RouteCardIE> = (props) =>{
<Block className='tourcard-block'>
<div className="cardDescr">
<div className="cardTitle">
<div className="titleText">ИМЯ ТУРА</div>
<div className="titleText">{props.city}</div>
<div className="cardInfo">
<div>{props.options.length} дней,</div>
<div>{cntPlaces} мест</div>
@ -113,7 +129,7 @@ export const RouteCard:React.FC<RouteCardIE> = (props) =>{
<div className="yOpenBtnTitle">От 5000 рублей</div>
<div className="yOpenBtnDescr">Просмотреть план тура</div>
</div>
<div className="likeBtn" onClick={()=>setLiked(!liked)}>
<div className="likeBtn" onClick={()=>onLiked()}>
<img src={liked? '/icons/likedHeart.svg':'/icons/heart.svg'}></img>
</div>
</div>

View File

@ -0,0 +1,233 @@
import { AutoComplete, DatePicker, Input, Checkbox, Select, Radio, Space } from 'antd';
import react, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom';
import { backend } from '../../consts';
import { Button } from '../../elements/Button';
import './style.css'
import dayjs from 'dayjs';
import type { RangePickerProps } from 'antd/es/date-picker';
import type { Dayjs } from 'dayjs';
import { propTypes } from 'react-tinder-card';
type RangeValue = [Dayjs | null, Dayjs | null] | null;
export const Search:React.FC<{onSearch?:()=>void}> = (props) =>{
const { RangePicker } = DatePicker;
const [cities, setCities] = useState([])
useEffect(()=>{
if (cities.length == 0){
backend.get('/data/cities').then((response)=>setCities(response.data))
}
})
const [toolsOpened, setToolsOpened] = useState(false)
const [city, setCity] = useState('')
const [datesValue, setDatesValue] = useState([])
const [transport, setTransport] = useState('walk')
const [whatToSee, setWhatToSee] = useState<string[]>([])
const [whereStay, setWhereStay] = useState<string[]>([])
const [whereEat, setWhereEat] = useState<string[]>([])
const [stars, setStars] = useState<number[]>([])
const [withKids, setWithKids] = useState(false)
const [withAnimals, setWithAnimals] = useState(false)
const [dates, setDates] = useState<RangeValue>(null);
const onWhatToSeeChange = (value:string, checked:boolean) =>{
if (checked){
setWhatToSee([...whatToSee, value])
} else {
let newData = whatToSee
newData.splice(whatToSee.indexOf(value), 1)
setWhatToSee(newData)
}
}
const onStarsChange = (value:number, checked:boolean) =>{
if (checked){
setStars([...stars, value])
} else {
let newData = stars
newData.splice(stars.indexOf(value), 1)
setStars(newData)
}
}
const onWhereStay = (value:string, checked:boolean) =>{
if (checked){
setWhereStay([...whereStay, value])
} else {
let newData = whereStay
newData.splice(whereStay.indexOf(value), 1)
setWhereStay(newData)
}
}
const onWhereEat = (value:string, checked:boolean) =>{
if (checked){
setWhereEat([...whereEat, value])
} else {
let newData = whereEat
newData.splice(whereEat.indexOf(value), 1)
setWhereEat(newData)
}
}
let searchParams = {}
if (datesValue.length == 2){
searchParams = {
date_from: new Date((datesValue as any)[0]).toISOString().split('T')[0],
date_to: new Date((datesValue as any)[1]).toISOString().split('T')[0],
city: city,
stars:stars,
what_to_see:whatToSee,
where_stay: whereStay,
where_eat: whereEat,
with_kids: withKids,
with_animals: withAnimals,
movement: transport
}
}
const disabledDate: RangePickerProps['disabledDate'] = (current:any) => {
if (!dates) {
return false;
}
const tooLate = dates[0] && current.diff(dates[0], 'days') >= 5;
const tooEarly = dates[1] && dates[1].diff(current, 'days') >= 5;
return current && current < dayjs().endOf('day') || !!tooEarly || !!tooLate;;
};
const onOpenChange = (open: boolean) => {
if (open) {
setDates([null, null]);
} else {
setDates(null);
}
};
let navigate = useNavigate()
const onNavigate = () => {
navigate('/search/' + JSON.stringify(searchParams))
if (props != undefined){
(props as any).onSearch()
}
}
return (
<div style={{width:'75%'}}>
<div style={{borderRadius: toolsOpened? '20px 20px 0px 0px':'20px'}} className='toolsMainWrapper'>
<div className='rowWrapper' onClick={()=>setToolsOpened(!toolsOpened)}>
<img src='/filter.svg'></img>
<div>Фильтры</div>
</div>
<img src='/react.svg'></img>
<Select
className='antdBorder'
showSearch
placeholder="Выберите направление"
optionFilterProp="children"
onChange={(e)=>setCity(e)}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={cities.map((city:any)=>{
return {
value:city.oid,
label: city.title
}
}
)}
/>
<img src='/react.svg'></img>
<RangePicker
disabledDate={disabledDate}
onCalendarChange={(val) => {
setDates(val);
}}
onOpenChange={onOpenChange}
changeOnBlur
onChange={(e)=>setDatesValue(e as any)}
></RangePicker>
<img src='/react.svg'></img>
<Button className='btn-y' onClick={()=>onNavigate()}>Сгенерировать</Button>
</div>
{
toolsOpened? <div className='searchOpened'>
<div className='questionWrapper'>
<h2>Где остановимся</h2>
<div className='checkboxWrapper'>
<Checkbox onChange={(e)=>onWhereStay('hotel', e.target.checked)}>Отель</Checkbox>
<Checkbox onChange={(e)=>onWhereStay('hostel', e.target.checked)}>Хостел</Checkbox>
<Checkbox onChange={(e)=>onWhereStay('apartment', e.target.checked)}>Апартаменты</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Как перемещаться на месте</h2>
<div className='checkboxWrapper'>
<Radio.Group onChange={(e)=>setTransport(e.target.value)} value={transport}>
<Space direction="vertical">
<Radio value={'walk'}>Пешком</Radio>
<Radio value={'auto'}>Автомобиль</Radio>
<Radio value={'bike'}>Велосипед</Radio>
<Radio value={'scooter'}>Скутер</Radio>
</Space>
</Radio.Group>
</div>
</div>
<div className='questionWrapper'>
<h2>Что посмотреть</h2>
<div className='checkboxWrapper'>
<Checkbox onChange={(e)=>onWhatToSeeChange('museum', e.target.checked)}>Музеи и выставки</Checkbox>
<Checkbox onChange={(e)=>onWhatToSeeChange('attractions', e.target.checked)}>Развлечения</Checkbox>
<Checkbox onChange={(e)=>onWhatToSeeChange('concert', e.target.checked)}>Концерты</Checkbox>
<Checkbox onChange={(e)=>onWhatToSeeChange('movie', e.target.checked)}>Фильмы</Checkbox>
<Checkbox onChange={(e)=>onWhatToSeeChange('theme_park', e.target.checked)}>Тематические парки</Checkbox>
<Checkbox onChange={(e)=>onWhatToSeeChange('viewpoint', e.target.checked)}>Достопримечательности</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где питаться</h2>
<div className='checkboxWrapper'>
<Checkbox onChange={(e)=>onWhereEat('restaurant', e.target.checked)}>Рестораны</Checkbox>
<Checkbox onChange={(e)=>onWhereEat('cafe', e.target.checked)}>Кафе</Checkbox>
<Checkbox onChange={(e)=>onWhereEat('bar', e.target.checked)}>Бары</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Дополнительно</h2>
<div className='checkboxWrapper'>
<Checkbox onChange={(e)=>setWithKids(e.target.checked)}>С детьми</Checkbox>
<Checkbox onChange={(e)=>setWithAnimals(e.target.checked)}>С животными</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox onChange={(e)=>onStarsChange(5, e.target.checked)}>5*</Checkbox>
<Checkbox onChange={(e)=>onStarsChange(4, e.target.checked)}>4*</Checkbox>
<Checkbox onChange={(e)=>onStarsChange(3, e.target.checked)}>3*</Checkbox>
<Checkbox onChange={(e)=>onStarsChange(2, e.target.checked)}>2*</Checkbox>
<Checkbox onChange={(e)=>onStarsChange(1, e.target.checked)}>1*</Checkbox>
</div>
</div>
</div>:null
}
</div>
);
}

View File

View File

@ -20,7 +20,11 @@ export interface TourCardIE{
points: PlaceCardIE[],
imageURL?: string;
id?: string
mapPoints: number[][]
mapPoints: {
description:string,
cords:number[],
title:string
}[]
}
export const PlaceCard: React.FC<PlaceCardIE> = (props) =>{

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react";
import Map, {Source, Layer} from 'react-map-gl';
import Map, {Source, Layer, Marker, Popup} from 'react-map-gl';
import axios from 'axios'
import { Checkbox } from '@yandex/ui/Checkbox/desktop/bundle'
import path from "path";
@ -8,66 +8,44 @@ import { theme } from '@yandex/ui/Theme/presets/default'
configureRootTheme({ theme })
export interface MapIE{
points: number[][]
points: {
cords:number[],
title:string,
description:string
}[]
}
export const MyMap: React.FC<MapIE> = (props) =>{
console.log(props.points)
let pathString = ''
let firstChecked = new Array<Boolean>()
props.points.forEach((point, index) => {
firstChecked.push(true)
pathString = pathString + point[0] + ',' + point[1] + (index == (props.points.length-1)? '':';')
pathString = pathString + point.cords[0] + ',' + point.cords[1] + (index == (props.points.length-1)? '':';')
});
const [route, setRoute] = useState()
const [path, setPath] = useState(pathString)
const [checked, setChecked] = useState(firstChecked)
useEffect(()=>{
if (route == undefined){
axios.get('https://api.mapbox.com/directions/v5/mapbox/driving/'+path+'?alternatives=true&continue_straight=true&geometries=geojson&language=en&overview=simplified&steps=true&access_token=pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q').then(
axios.get('https://api.mapbox.com/directions/v5/mapbox/walking/'+pathString+'?alternatives=true&continue_straight=true&geometries=geojson&language=en&overview=simplified&steps=true&access_token=pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q').then(
(data:any) => setRoute(data.data.routes[0].geometry)
)
}
})
const onCheckChange = (e:any, cords:Array<string>, ind:number) => {
console.log(e)
if (e.target.checked){
if (path == ''){
setPath(cords[0] + '%2C' + cords[1])
}else{
setPath(path + "%3B" + cords[0]+'%2C' + cords[1])
}
axios.get('https://api.mapbox.com/directions/v5/mapbox/walking/'+path+'?alternatives=true&continue_straight=true&geometries=geojson&language=en&overview=simplified&steps=true&access_token=pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q').then(
(data:any) => setRoute(data.data.routes[0].geometry)
)
checked[ind] = true
setChecked(checked)
}else{
setPath(path.replace("%3B" + cords[0]+'%2C' + cords[1], ''))
axios.get('https://api.mapbox.com/directions/v5/mapbox/walking/'+path+'?alternatives=true&continue_straight=true&geometries=geojson&language=en&overview=simplified&steps=true&access_token=pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q').then(
(data:any) => setRoute({
type: 'Feature',
properties: {},
geometry: data.data.routes[0].geometry
} as any)
)
checked[ind] = false
setChecked(checked)
}
};
const geojson = {
type: 'FeatureCollection',
features: props.points.map((point, index)=>{
return {type: 'Feature', geometry: {type: 'Point', coordinates: point}}
return {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: point.cords,
},
properties: {
'title': point.title
}}
}
)
};
@ -92,45 +70,48 @@ export const MyMap: React.FC<MapIE> = (props) =>{
}
const layerStyle = {
id: 'point',
type: 'circle',
paint: {
'circle-radius': 10,
'circle-color': '#007cbf'
type: 'symbol',
iconImage: 'custom-marker',
layout: {
'text-field': ['get', 'title'],
'text-font': [
'Open Sans Semibold',
'Arial Unicode MS Bold'
],
'text-size': 8,
'text-offset': [0, 0],
'text-anchor': 'top'
}
};
console.log(props)
return (
<div>
<div>
{
props.points.map((value, index)=>
<Checkbox
size='m'
view='default'
checked={checked[index]}
onChange={(e:any)=>onCheckChange(e, [value[0].toString(), value[1].toString()],index)}
label={value[0].toString()+", "+value[1].toString()
}></Checkbox>
)
}
</div>
<div style={{width:'100%'}}>
<Map initialViewState={{
longitude: props.points[0][0],
latitude: props.points[0][1],
longitude: props.points[0].cords[0],
latitude: props.points[0].cords[1],
zoom: 14
}}
style={{width: '100%', height: '40vh'}}
mapStyle="mapbox://styles/mapbox/streets-v9"
mapboxAccessToken='pk.eyJ1IjoiZmlyZXNpZWh0IiwiYSI6ImNrdW9kemYzbTB4ZGkycHAxbXN2YnIzaGMifQ.G0fl-qVbecucfOvn8OtU4Q'
>
<Source id="my-data" type="geojson" data={geojson as any}>
<Layer {...layerStyle as any} />
</Source>
<Source id="way-data" type="geojson" data={route as any}>
<Layer {...layerWayStyle as any} />
</Source>
<Source id="my-data" type="geojson" data={geojson as any}>
<Layer {...layerStyle as any} />
</Source>
{
props.points.map((point, index)=>{
return <Marker longitude={point.cords[0]} latitude={point.cords[1]} anchor="bottom" >
<img src="/pin.png" />
</Marker>
})
}
</Map>
</div>

View File

@ -32,12 +32,17 @@ export const GenerateTour = () =>{
let tours = new Array()
toursData.forEach((tour, index) => {
const points = [] as number[][]
let points = new Array()
tour.points.forEach((point, index)=>{
points.push([point.location[1], point.location[0]])
points.push({
cords:[point.location[1], point.location[0]],
title: point.title,
description: point.description
}
)
})
tours.push(
<TourCard {...tour} mapPoints={points} id={index.toString()}></TourCard>
<TourCard {...tour} mapPoints={points as any} id={index.toString()}></TourCard>
)
})

View File

@ -1,4 +1,4 @@
import { AutoComplete, DatePicker, Input, Checkbox, Select } from 'antd';
import { AutoComplete, DatePicker, Input, Checkbox, Select, Radio, Space, Spin } from 'antd';
import react, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom';
import { backend } from '../../consts';
@ -10,47 +10,24 @@ import { TourCard, TourCardIE } from '../../elements/TourCard';
import './style.css'
import dayjs from 'dayjs';
import type { RangePickerProps } from 'antd/es/date-picker';
import { Search } from '../../elements/Search';
import { AttractionCard } from '../../elements/AttractionCard';
import { EventCard, EventCardIE } from '../../elements/EventCard';
export const Main: react.FC = () => {
const { RangePicker } = DatePicker;
const [cities, setCities] = useState([])
const [events, setEvents] = useState([])
const [favorites, setFavorites] = useState([])
useEffect(()=>{
if (cities.length == 0){
backend.get('/data/cities').then((response)=>setCities(response.data))
if (favorites.length == 0){
backend.get('user/favorite').then((e)=>setFavorites(e.data))
}
})
if (events.length == 0){
backend.get('recommendations/recommendations/').then((e)=>setEvents(e.data as any));
}
})
const TourPropsCard = {
name: 'Я покажу тебе Москву',
days: 8,
id:'23343',
mapPoints: [[-71.0703,42.3419],[-71.0688, 42.3393],[-71.0728, 42.3348]],
imageURL: 'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aW1hZ2V8ZW58MHx8MHx8fDA%3D&w=1000&q=80',
points: [
{
title:'Парк Горького',
description: 'Место',
icon:'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aW1hZ2V8ZW58MHx8MHx8fDA%3D&w=1000&q=80',
location:[1,2],
},
{
title:'Отель Москва',
description: 'Отель',
icon:'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aW1hZ2V8ZW58MHx8MHx8fDA%3D&w=1000&q=80',
location:[1,2]
},
{
title:'Ресторан Сказка',
description: 'Ресторан',
icon:'https://images.unsplash.com/photo-1575936123452-b67c3203c357?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxzZWFyY2h8Mnx8aW1hZ2V8ZW58MHx8MHx8fDA%3D&w=1000&q=80',
location:[1,2]
}
]
} as TourCardIE
const favoriteCardProps = {
imageURL:'restourant.png',
@ -59,168 +36,54 @@ export const Main: react.FC = () => {
} as FavoriteCardIE
const [toolsOpened, setToolsOpened] = useState(false)
const [city, setCity] = useState('')
const [dates, setDates] = useState([])
let searchParams = {}
if (dates.length == 2){
searchParams = {
date_from: new Date((dates as any)[0]).toISOString().split('T')[0],
date_to: new Date((dates as any)[1]).toISOString().split('T')[0],
city: city
}
}
const disabledDate: RangePickerProps['disabledDate'] = (current:any) => {
// Can not select days before today and today
return current && current < dayjs().endOf('day');
};
let navigate = useNavigate()
return (
<div className='mainWrapper'>
<RusPassHeader></RusPassHeader>
<div className='headMainWrapper'>
<img className='backgroundIMG' src='background.png'></img>
<div style={{width:'75%'}}>
<div style={{borderRadius: toolsOpened? '20px 20px 0px 0px':'20px'}} className='toolsMainWrapper'>
<div className='rowWrapper' onClick={()=>setToolsOpened(!toolsOpened)}>
<img src='filter.svg'></img>
<div>Фильтры</div>
</div>
<img src='react.svg'></img>
<Select
className='antdBorder'
showSearch
placeholder="Выберите направление"
optionFilterProp="children"
onChange={(e)=>setCity(e)}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={cities.map((city:any)=>{
return {
value:city.oid,
label: city.title
}
}
)}
/>
<img src='react.svg'></img>
<RangePicker
disabledDate={disabledDate}
onChange={(e)=>setDates(e as any)}
></RangePicker>
<img src='react.svg'></img>
<Button className='btn-y' onClick={()=>navigate('search/' + JSON.stringify(searchParams))}>Сгенерировать</Button>
</div>
{
toolsOpened? <div className='searchOpened'>
<div className='questionWrapper'>
<h2>Как добраться</h2>
<div className='checkboxWrapper'>
<Checkbox>Самолет</Checkbox>
<Checkbox>ЖД</Checkbox>
<Checkbox>Автобус</Checkbox>
<Checkbox>Смешанный</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где остановимся</h2>
<div className='checkboxWrapper'>
<Checkbox>Отель</Checkbox>
<Checkbox>Хостел</Checkbox>
<Checkbox>Апартаменты</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Как перемещаться на месте</h2>
<div className='checkboxWrapper'>
<Checkbox>Машина</Checkbox>
<Checkbox>Общественный транспорт</Checkbox>
<Checkbox>Пешком</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Что посмотреть</h2>
<div className='checkboxWrapper'>
<Checkbox>Музеи и выставки</Checkbox>
<Checkbox>Мероприятия и места</Checkbox>
<Checkbox>Обзорные экскурсии</Checkbox>
<Checkbox>Культурное наследие</Checkbox>
<Checkbox>Парки и прогулки</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где питаться</h2>
<div className='checkboxWrapper'>
<Checkbox>Рестораны</Checkbox>
<Checkbox>Кафе</Checkbox>
<Checkbox>Бары</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Дополнительно</h2>
<div className='checkboxWrapper'>
<Checkbox>С детьми</Checkbox>
<Checkbox>С животными</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
</div>:null
}
</div>
<Search onSearch={()=>null}></Search>
</div>
<div className='mainCard'>
<h2>Рекомендации</h2>
<div className='cardWrapper'>
<GenerateCard></GenerateCard>
<TourCard {...TourPropsCard}></TourCard>
<TourCard {...TourPropsCard}></TourCard>
<TourCard {...TourPropsCard}></TourCard>
<TourCard {...TourPropsCard}></TourCard>
<TourCard {...TourPropsCard}></TourCard>
{
events.length == 0? <Spin/>
:
events.map((category:any)=>{
category = category.events.map((event:any)=>{
return <EventCard category={category.category} {...event}></EventCard>
})
return category
})
}
</div>
</div>
<div className='mainCard'>
<h2>Избранное</h2>
<div className='fav-wrapper'>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
<FavoriteCard {...favoriteCardProps}></FavoriteCard>
{
favorites.length == 0? <Spin/>
:
favorites.map((favorite:any, index)=>{
if (index < 10){
return <EventCard category='attraction'
description={favorite.description}
lat={1}
lon={2}
oid={favorite.oid}
title={favorite.title} ></EventCard>
}
else{
return null
}
})
}
</div>
<div>
<Button className=''>Посмотреть все</Button>

View File

@ -1,194 +1,116 @@
import React, { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { useParams } from "react-router-dom";
import { backend } from "../../consts";
import data from './struct.json';
import { RouteCard } from "../../elements/RouteCard";
import { RouteCard, RouteCardIE } from "../../elements/RouteCard";
import { RusPassHeader } from "../../elements/Header";
import { AutoComplete, DatePicker, Input, Checkbox, Select } from 'antd';
import { RangePickerProps } from "antd/es/date-picker";
import dayjs from 'dayjs';
import { Button } from "../../elements/Button";
import './style.css'
const { RangePicker } = DatePicker;
import { Search } from "../../elements/Search";
import { Spin } from "antd";
import { EventCard } from "../../elements/EventCard";
export const SearchPage:React.FC = () =>{
let { prefs } = useParams();
const [cities, setCities] = useState([])
let props = data.map((day)=>{
let paths = day.paths
for (let i=0; i<paths.length; i++){
if (paths[i].type != 'point'){
paths.splice(i,1)
i--
}
}
return {
date:day.date,
paths: paths
}
})
const [data, setData] = useState([])
const [events, setEvents] = useState([])
useEffect(()=>{
if (cities.length == 0){
backend.get('/data/cities').then((response)=>setCities(response.data))
backend.post('/route/build',JSON.parse(prefs as string)).then((r)=>setData(r.data as any))
backend.post('/recommendations/build_events/',JSON.parse(prefs as string)).then((r)=>setEvents(r.data as any))
}
// backend.post('/route/build', props).then((response)=>console.log(response.data))
})
console.log(events)
const [city, setCity] = useState('')
const [dates, setDates] = useState([])
let searchParams = {}
let newData;
if (dates.length == 2){
searchParams = {
date_from: new Date((dates as any)[0]).toISOString().split('T')[0],
date_to: new Date((dates as any)[1]).toISOString().split('T')[0],
city: city
}
if (data.length != 0){
newData = data.map((tour:any)=>{
let newPath = tour.path.map((path:any)=>{
let newPaths = path.paths
for (let i = 0; i < newPaths.length; i++) {
if (newPaths[i].type == 'transition') {
newPaths.splice(i, 1);
i--;
}
}
return {
date:path.date,
paths: newPaths
}
})
return {
city: tour.city,
path: newPath
}
})
}
const disabledDate: RangePickerProps['disabledDate'] = (current:any) => {
// Can not select days before today and today
return current && current < dayjs().endOf('day');
};
let navigate = useNavigate()
const [toolsOpened, setToolsOpened] = useState(false)
const onSearch = () =>{
setData([])
}
const contentStyle: React.CSSProperties = {
height: '160px',
color: '#fff',
lineHeight: '160px',
textAlign: 'center',
background: '#364d79',
};
return(
<div className="mainWrapper">
<RusPassHeader></RusPassHeader>
<h1>Посмотрите, что мы нашли по вашему запросу</h1>
<div>
<div style={{borderRadius: toolsOpened? '20px 20px 0px 0px':'20px'}} className='toolsMainWrapper'>
<div className='rowWrapper' onClick={()=>setToolsOpened(!toolsOpened)}>
<img src='/filter.svg'></img>
<div>Фильтры</div>
</div>
<img src='/react.svg'></img>
<Select
className='antdBorder'
showSearch
placeholder="Выберите направление"
optionFilterProp="children"
onChange={(e)=>setCity(e)}
filterOption={(input, option) =>
(option?.label ?? '').toLowerCase().includes(input.toLowerCase())
}
options={cities.map((city:any)=>{
return {
value:city.oid,
label: city.title
}
}
)}
/>
<Search onSearch={()=>onSearch()}></Search>
{
data.length == 0 || newData == undefined?
<img src='/react.svg'></img>
<RangePicker
disabledDate={disabledDate}
onChange={(e)=>setDates(e as any)}
></RangePicker>
<img src='/react.svg'></img>
<Button className='btn-y' onClick={()=>navigate('search/' + JSON.stringify(searchParams))}>Сгенерировать</Button>
</div>
{
toolsOpened? <div className='searchOpened'>
<div className='questionWrapper'>
<h2>Как добраться</h2>
<div className='checkboxWrapper'>
<Checkbox>Самолет</Checkbox>
<Checkbox>ЖД</Checkbox>
<Checkbox>Автобус</Checkbox>
<Checkbox>Смешанный</Checkbox>
</div>
</div>
<Spin />:
<div className='mainCard'>
<h2>Рекомендованные Туры</h2>
<div className='questionWrapper'>
<h2>Где остановимся</h2>
<div className='checkboxWrapper'>
<Checkbox>Отель</Checkbox>
<Checkbox>Хостел</Checkbox>
<Checkbox>Апартаменты</Checkbox>
</div>
</div>
<div className='cardWrapper'>
{
newData.map((tour:any, index:number)=>
<RouteCard city={tour.city} rawProps={data[index]} options={tour.path}></RouteCard>
)
}
<div className='questionWrapper'>
<h2>Как перемещаться на месте</h2>
<div className='checkboxWrapper'>
<Checkbox>Машина</Checkbox>
<Checkbox>Общественный транспорт</Checkbox>
<Checkbox>Пешком</Checkbox>
</div>
</div>
</div>
</div>
}
<div className='questionWrapper'>
<h2>Что посмотреть</h2>
<div className='checkboxWrapper'>
<Checkbox>Музеи и выставки</Checkbox>
<Checkbox>Мероприятия и места</Checkbox>
<Checkbox>Обзорные экскурсии</Checkbox>
<Checkbox>Культурное наследие</Checkbox>
<Checkbox>Парки и прогулки</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Где питаться</h2>
<div className='checkboxWrapper'>
<Checkbox>Рестораны</Checkbox>
<Checkbox>Кафе</Checkbox>
<Checkbox>Бары</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Дополнительно</h2>
<div className='checkboxWrapper'>
<Checkbox>С детьми</Checkbox>
<Checkbox>С животными</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
<div className='questionWrapper'>
<h2>Рейтинг</h2>
<div className='checkboxWrapper'>
<Checkbox>5*</Checkbox>
<Checkbox>4*</Checkbox>
<Checkbox>3*</Checkbox>
<Checkbox>2*</Checkbox>
<Checkbox>1*</Checkbox>
</div>
</div>
</div>:null
}
</div>
{
events.length == 0? <Spin/>
:
<div className='mainCard'>
<div className='cardWrapper'>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
<RouteCard options={props as any}></RouteCard>
</div>
<h2>Рекомендованные меропрития</h2>
<div className='cardWrapper'>{
events.map((event:any)=>{
return <EventCard category={'viewpoint'} {...event}></EventCard>
})
}
</div>
</div>
}
<a href='/'>Документация</a>