diff --git a/.gitignore b/.gitignore index e36333d..3d42112 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,6 @@ yarn-error.log* # Optional eslint cache .eslintcache + +# não commitar url de environment +src/constants/environment.ts diff --git a/mock/db.json b/mock/db.json new file mode 100644 index 0000000..6b1251a --- /dev/null +++ b/mock/db.json @@ -0,0 +1,12 @@ +{ + "cadastro-van": [ + { + "id": 1, + "placa": "DBE2356", + "marca": "Fiat", + "modelo": "Ducatto", + "numPassageiros": 14, + "alugado": false + } + ] +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 73ca025..5ffb4a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,8 @@ "@capacitor/haptics": "1.1.4", "@capacitor/keyboard": "1.2.2", "@capacitor/status-bar": "1.0.8", + "@hookform/error-message": "^2.0.0", + "@ionic-selectable/core": "^5.0.0-alpha.13", "@ionic/react": "^6.0.0", "@ionic/react-router": "^6.0.0", "@testing-library/jest-dom": "^5.11.9", @@ -26,10 +28,16 @@ "@types/react-router-dom": "^5.1.7", "axios": "^0.26.1", "ionicons": "^5.4.0", + "lodash.isequal": "^4.5.0", + "pigeon-maps": "^0.21.0", + "pullstate": "^1.24.0", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-google-places-autocomplete": "^3.3.4", + "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", + "reselect": "^4.1.5", "typescript": "^4.1.3", "web-vitals": "^0.2.4", "workbox-background-sync": "^5.1.4", @@ -43,11 +51,13 @@ "workbox-range-requests": "^5.1.4", "workbox-routing": "^5.1.4", "workbox-strategies": "^5.1.4", - "workbox-streams": "^5.1.4" + "workbox-streams": "^5.1.4", + "yup": "^0.32.11" }, "devDependencies": { "@capacitor/cli": "3.4.3", "@types/axios": "^0.14.0", + "@types/lodash.isequal": "^4.5.6", "react-scripts": "5.0.1" } }, @@ -55,7 +65,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.0" }, @@ -78,7 +87,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -87,7 +95,6 @@ "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", - "dev": true, "dependencies": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -117,7 +124,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -184,7 +190,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, "dependencies": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -198,7 +203,6 @@ "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -232,7 +236,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, "dependencies": { "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", @@ -250,7 +253,6 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, "bin": { "semver": "bin/semver.js" } @@ -324,7 +326,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -348,7 +349,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -361,7 +361,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -385,7 +384,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -397,7 +395,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -428,7 +425,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -467,7 +463,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, "dependencies": { "@babel/types": "^7.17.0" }, @@ -491,7 +486,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "dependencies": { "@babel/types": "^7.16.7" }, @@ -511,7 +505,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -535,7 +528,6 @@ "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", - "dev": true, "dependencies": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", @@ -626,7 +618,6 @@ "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", - "dev": true, "bin": { "parser": "bin/babel-parser.js" }, @@ -1067,7 +1058,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", - "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.16.7" }, @@ -2020,7 +2010,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -2034,7 +2023,6 @@ "version": "7.17.3", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.3", @@ -2055,7 +2043,6 @@ "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -2304,6 +2291,141 @@ "postcss": "^8.3" } }, + "node_modules/@emotion/babel-plugin": { + "version": "11.9.2", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz", + "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==", + "dependencies": { + "@babel/helper-module-imports": "^7.12.13", + "@babel/plugin-syntax-jsx": "^7.12.13", + "@babel/runtime": "^7.13.10", + "@emotion/hash": "^0.8.0", + "@emotion/memoize": "^0.7.5", + "@emotion/serialize": "^1.0.2", + "babel-plugin-macros": "^2.6.1", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.0.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "dependencies": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@emotion/babel-plugin/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.9.3.tgz", + "integrity": "sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg==", + "dependencies": { + "@emotion/memoize": "^0.7.4", + "@emotion/sheet": "^1.1.1", + "@emotion/utils": "^1.0.0", + "@emotion/weak-memoize": "^0.2.5", + "stylis": "4.0.13" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "node_modules/@emotion/memoize": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", + "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" + }, + "node_modules/@emotion/react": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.3.tgz", + "integrity": "sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@emotion/babel-plugin": "^11.7.1", + "@emotion/cache": "^11.9.3", + "@emotion/serialize": "^1.0.4", + "@emotion/utils": "^1.1.0", + "@emotion/weak-memoize": "^0.2.5", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.4.tgz", + "integrity": "sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg==", + "dependencies": { + "@emotion/hash": "^0.8.0", + "@emotion/memoize": "^0.7.4", + "@emotion/unitless": "^0.7.5", + "@emotion/utils": "^1.0.0", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.1.tgz", + "integrity": "sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "node_modules/@emotion/utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ==" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" + }, "node_modules/@eslint/eslintrc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", @@ -2369,6 +2491,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.14.3.tgz", + "integrity": "sha512-6iIb+qpGgQpgIHmIFO44WhE1rDUxPVHuezNFL30wRJnkvhwFm94tD291UvNg9L05hLDSoL16jd0lbqqmdy4C5g==", + "dependencies": { + "fast-deep-equal": "^3.1.3" + } + }, + "node_modules/@hookform/error-message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.0.tgz", + "integrity": "sha512-Y90nHzjgL2MP7GFy75kscdvxrCTjtyxGmOLLxX14nd08OXRIh9lMH/y9Kpdo0p1IPowJBiZMHyueg7p+yrqynQ==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-hook-form": "^7.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -2389,6 +2529,14 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "node_modules/@ionic-selectable/core": { + "version": "5.0.0-alpha.13", + "resolved": "https://registry.npmjs.org/@ionic-selectable/core/-/core-5.0.0-alpha.13.tgz", + "integrity": "sha512-AdwGuPSD3Qy6uyo0jJp05JZMQr5KS1r/ojDEsyvBNjl1agxWJn7cQC0nagF29CPzaCQjwUh8qYa+FKsyCll2jA==", + "peerDependencies": { + "@ionic/core": "5.x" + } + }, "node_modules/@ionic/cli-framework-output": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.3.tgz", @@ -2404,35 +2552,16 @@ } }, "node_modules/@ionic/core": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.0.13.tgz", - "integrity": "sha512-FY3+q3cIcyadQ6CWi/l/B57DlUO+MHOFCNl/4RjxCBqdwpgx1N4H2lLYGUk/V6j6AVjFNxef63hHr8z7xfTqVg==", + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.4.tgz", + "integrity": "sha512-Ngz9yVT6fIiGdSxxBer8uJxP4w6PasvohYpLxhtMgYiWnyIu0vZra2ui3HrYukCzUo5/SbNPiUr1l7cj1E+7qw==", + "peer": true, "dependencies": { - "@stencil/core": "^2.14.2", - "ionicons": "^6.0.0", + "@stencil/core": "^2.4.0", + "ionicons": "^5.5.3", "tslib": "^2.1.0" } }, - "node_modules/@ionic/core/node_modules/ionicons": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-6.0.1.tgz", - "integrity": "sha512-xQekOJsxH82O7oB+3F60zeRggCdND9pJ/k0E6IJDVUGGlCj5mlyFqNgxUimytKgstPGv3S+3EmCxjefvtGgWUg==", - "dependencies": { - "@stencil/core": "~2.12.0" - } - }, - "node_modules/@ionic/core/node_modules/ionicons/node_modules/@stencil/core": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz", - "integrity": "sha512-u24TZ+FEvjnZt5ZgIkLjLpUNsO6Ml3mUZqwmqk81w6RWWz75hgB5p4RFI5rvuErFeh2xvMIGo+pNdG24XUBz1A==", - "bin": { - "stencil": "bin/stencil" - }, - "engines": { - "node": ">=12.10.0", - "npm": ">=6.0.0" - } - }, "node_modules/@ionic/react": { "version": "6.0.13", "resolved": "https://registry.npmjs.org/@ionic/react/-/react-6.0.13.tgz", @@ -2462,6 +2591,28 @@ "react-router-dom": "^5.0.1" } }, + "node_modules/@ionic/react/node_modules/@ionic/core": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.7.tgz", + "integrity": "sha512-CUbH7xtKcPejHTyMvvUJZq4GIyLbL2YflzFH+mad1PoLN4TLwFTTKTDB1oeFNqwnTzaByeBvhEWSayxCbLgvjQ==", + "dependencies": { + "@stencil/core": "^2.14.2", + "ionicons": "^6.0.0", + "tslib": "^2.1.0" + } + }, + "node_modules/@ionic/react/node_modules/@ionic/core/node_modules/@stencil/core": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.15.2.tgz", + "integrity": "sha512-D6dv2KAXlWt9mjC28q0s6anghQgXRn0k93suOf+4pqsv1Uq19zNJXpYL68N5GxMSiNZyMPTU4Tt2NCbut7DVGg==", + "bin": { + "stencil": "bin/stencil" + }, + "engines": { + "node": ">=12.10.0", + "npm": ">=6.0.0" + } + }, "node_modules/@ionic/react/node_modules/@stencil/core": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz", @@ -2935,7 +3086,6 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true, "engines": { "node": ">=6.0.0" } @@ -2943,14 +3093,12 @@ "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -3157,6 +3305,7 @@ "version": "2.14.2", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz", "integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==", + "peer": true, "bin": { "stencil": "bin/stencil" }, @@ -3709,6 +3858,11 @@ "@types/range-parser": "*" } }, + "node_modules/@types/google.maps": { + "version": "3.49.2", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.49.2.tgz", + "integrity": "sha512-ZO1qWciukqED9qcUNW7OaPXWnTlT+tO3WcYkmudZyQW2BqD7TlMFRrdqSCoqfwKhERCwBA5A/YZt/g5A3BqgLQ==" + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -3817,6 +3971,20 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "node_modules/@types/lodash.isequal": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", + "integrity": "sha512-Ww4UGSe3DmtvLLJm2F16hDwEQSv7U0Rr8SujLUA2wHI2D2dm8kPu6Et+/y303LfjTIwSBKXB/YTUcAKpem/XEg==", + "dev": true, + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -3831,8 +3999,7 @@ "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "node_modules/@types/prettier": { "version": "2.4.4", @@ -5296,7 +5463,6 @@ "version": "4.20.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5389,7 +5555,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -5441,7 +5606,6 @@ "version": "1.0.30001320", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -5884,7 +6048,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "dependencies": { "safe-buffer": "~5.1.1" } @@ -6413,7 +6576,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -6710,6 +6872,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.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", @@ -6841,8 +7012,7 @@ "node_modules/electron-to-chromium": { "version": "1.4.96", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz", - "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==", - "dev": true + "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==" }, "node_modules/elementtree": { "version": "0.1.7", @@ -6933,7 +7103,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "dependencies": { "is-arrayish": "^0.2.1" } @@ -7017,7 +7186,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, "engines": { "node": ">=6" } @@ -7032,7 +7200,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -7890,8 +8057,7 @@ "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.2.11", @@ -8084,6 +8250,11 @@ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -8335,8 +8506,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -8348,7 +8518,6 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, "engines": { "node": ">=6.9.0" } @@ -8499,7 +8668,6 @@ "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, "engines": { "node": ">=4" } @@ -8561,7 +8729,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -8943,7 +9110,6 @@ "version": "9.0.12", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -8953,7 +9119,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -8969,7 +9134,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -9099,8 +9263,7 @@ "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "node_modules/is-bigint": { "version": "1.0.4", @@ -9158,7 +9321,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -10441,7 +10603,6 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, "bin": { "jsesc": "bin/jsesc" }, @@ -10458,8 +10619,7 @@ "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "node_modules/json-schema": { "version": "0.4.0", @@ -10483,7 +10643,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -10601,8 +10760,7 @@ "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/loader-runner": { "version": "4.2.0", @@ -10647,12 +10805,22 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -10786,6 +10954,11 @@ "node": ">= 4.0.0" } }, + "node_modules/memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -11028,8 +11201,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "6.2.3", @@ -11050,6 +11222,11 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "node_modules/nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", @@ -11136,8 +11313,7 @@ "node_modules/node-releases": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -11512,7 +11688,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "dependencies": { "callsites": "^3.0.0" }, @@ -11524,7 +11699,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -11593,8 +11767,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-to-regexp": { "version": "1.8.0", @@ -11608,7 +11781,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, "engines": { "node": ">=8" } @@ -11628,8 +11800,7 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -11643,6 +11814,14 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pigeon-maps": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/pigeon-maps/-/pigeon-maps-0.21.0.tgz", + "integrity": "sha512-p3GaGday5nmufHVGZW/36LnSXfYVh6qfzYisqcC87nqFr0eXIKkqQcDuPP9g4F1OXL1JeJe4x6JEnAE9HB+zWQ==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -13041,6 +13220,11 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -13069,6 +13253,18 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "node_modules/pullstate": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.24.0.tgz", + "integrity": "sha512-uKXQjGnZUNb3wg7STF3HvCDbGtYg7tju42QjVtaefMik6JpbadnmKgI8DgZL02SvtTNlFPosMQkAwuI/a9D8dg==", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "immer": "^9.0.12" + }, + "peerDependencies": { + "react": "^16.12.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -13287,6 +13483,47 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "dev": true }, + "node_modules/react-google-places-autocomplete": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/react-google-places-autocomplete/-/react-google-places-autocomplete-3.3.4.tgz", + "integrity": "sha512-IeoBxUvwFYZ8gEXC7K9e9Az3QUO7A3fbc/ED0Px63dvY4fRtipdXbGK1nBCr7qJRpZbArOk2LMUgAi21lvjPOQ==", + "dependencies": { + "@googlemaps/js-api-loader": "^1.12.3", + "@types/google.maps": "^3.46.1", + "react-select": "^4.3.1", + "use-debounce": "^3.4.3" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/react-hook-form": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", + "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/react-input-autosize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz", + "integrity": "sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==", + "dependencies": { + "prop-types": "^15.5.8" + }, + "peerDependencies": { + "react": "^16.3.0 || ^17.0.0" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -13416,6 +13653,39 @@ } } }, + "node_modules/react-select": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-4.3.1.tgz", + "integrity": "sha512-HBBd0dYwkF5aZk1zP81Wx5UsLIIT2lSvAY2JiJo199LjoLHoivjn9//KsmvQMEFGNhe58xyuOITjfxKCcGc62Q==", + "dependencies": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.1.1", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.0", + "react-input-autosize": "^3.0.0", + "react-transition-group": "^4.3.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0", + "react-dom": "^16.8.0 || ^17.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "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/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -13634,11 +13904,15 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "node_modules/reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "node_modules/resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, "dependencies": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", @@ -13850,8 +14124,7 @@ "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/safer-buffer": { "version": "2.1.2", @@ -14584,6 +14857,11 @@ "postcss": "^8.2.15" } }, + "node_modules/stylis": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", + "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14612,7 +14890,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -15051,7 +15328,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, "engines": { "node": ">=4" } @@ -15077,6 +15353,11 @@ "node": ">=0.6" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "node_modules/tough-cookie": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", @@ -15372,6 +15653,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-debounce": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-3.4.3.tgz", + "integrity": "sha512-nxy+opOxDccWfhMl36J5BSCTpvcj89iaQk2OZWLAtBJQj7ISCtx1gh+rFbdjGfMl6vtCZf6gke/kYvrkVfHMoA==", + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -16569,7 +16858,6 @@ "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, "engines": { "node": ">= 6" } @@ -16622,6 +16910,23 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -16629,7 +16934,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz", "integrity": "sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==", - "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.0" } @@ -16645,14 +16949,12 @@ "@babel/compat-data": { "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.7.tgz", - "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==", - "dev": true + "integrity": "sha512-p8pdE6j0a29TNGebNm7NzYZWB3xVZJBZ7XGs42uAKzQo8VQ3F0By/cQCtUEABwIqw5zo6WA4NbmxsfzADzMKnQ==" }, "@babel/core": { "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.17.8.tgz", "integrity": "sha512-OdQDV/7cRBtJHLSOBqqbYNkOcydOgnX59TZx4puf41fzcVtN3e/4yqY8lMQsK+5X2lJtAdmA+6OHqsj1hBJ4IQ==", - "dev": true, "requires": { "@ampproject/remapping": "^2.1.0", "@babel/code-frame": "^7.16.7", @@ -16674,8 +16976,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -16724,7 +17025,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.17.7.tgz", "integrity": "sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==", - "dev": true, "requires": { "@babel/types": "^7.17.0", "jsesc": "^2.5.1", @@ -16734,8 +17034,7 @@ "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" } } }, @@ -16762,7 +17061,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.17.7.tgz", "integrity": "sha512-UFzlz2jjd8kroj0hmCFV5zr+tQPi1dpC2cRsDV/3IEW8bJfCPrPpmcSN6ZS8RqIq4LXcmpipCQFPddyFA5Yc7w==", - "dev": true, "requires": { "@babel/compat-data": "^7.17.7", "@babel/helper-validator-option": "^7.16.7", @@ -16773,8 +17071,7 @@ "semver": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" } } }, @@ -16831,7 +17128,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz", "integrity": "sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -16849,7 +17145,6 @@ "version": "7.17.9", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz", "integrity": "sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/types": "^7.17.0" @@ -16859,7 +17154,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz", "integrity": "sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -16877,7 +17171,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz", "integrity": "sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -16886,7 +17179,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.7.tgz", "integrity": "sha512-VmZD99F3gNTYB7fJRDTi+u6l/zxY0BE6OIxPSU7a50s6ZUQkHwSDmV92FfM+oCG0pZRVojGYhkR8I0OGeCVREw==", - "dev": true, "requires": { "@babel/helper-environment-visitor": "^7.16.7", "@babel/helper-module-imports": "^7.16.7", @@ -16910,8 +17202,7 @@ "@babel/helper-plugin-utils": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz", - "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==", - "dev": true + "integrity": "sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==" }, "@babel/helper-remap-async-to-generator": { "version": "7.16.8", @@ -16941,7 +17232,6 @@ "version": "7.17.7", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.17.7.tgz", "integrity": "sha512-txyMCGroZ96i+Pxr3Je3lzEJjqwaRC9buMUgtomcrLe5Nd0+fk1h0LLA+ixUF5OW7AhHuQ7Es1WcQJZmZsz2XA==", - "dev": true, "requires": { "@babel/types": "^7.17.0" } @@ -16959,7 +17249,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz", "integrity": "sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==", - "dev": true, "requires": { "@babel/types": "^7.16.7" } @@ -16972,8 +17261,7 @@ "@babel/helper-validator-option": { "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz", - "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==", - "dev": true + "integrity": "sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==" }, "@babel/helper-wrap-function": { "version": "7.16.8", @@ -16991,7 +17279,6 @@ "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.8.tgz", "integrity": "sha512-QcL86FGxpfSJwGtAvv4iG93UL6bmqBdmoVY0CMCU2g+oD2ezQse3PT5Pa+jiD6LJndBQi0EDlpzOWNlLuhz5gw==", - "dev": true, "requires": { "@babel/template": "^7.16.7", "@babel/traverse": "^7.17.3", @@ -17062,8 +17349,7 @@ "@babel/parser": { "version": "7.17.8", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.17.8.tgz", - "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==", - "dev": true + "integrity": "sha512-BoHhDJrJXqcg+ZL16Xv39H9n+AqJ4pcDrQBGZN+wHxIysrLZ3/ECwCBUch/1zUNhnsXULcONU3Ei5Hmkfk6kiQ==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.16.7", @@ -17351,7 +17637,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz", "integrity": "sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==", - "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.16.7" } @@ -17993,7 +18278,6 @@ "version": "7.16.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz", "integrity": "sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/parser": "^7.16.7", @@ -18004,7 +18288,6 @@ "version": "7.17.3", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz", "integrity": "sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==", - "dev": true, "requires": { "@babel/code-frame": "^7.16.7", "@babel/generator": "^7.17.3", @@ -18022,7 +18305,6 @@ "version": "7.17.0", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz", "integrity": "sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==", - "dev": true, "requires": { "@babel/helper-validator-identifier": "^7.16.7", "to-fast-properties": "^2.0.0" @@ -18195,6 +18477,122 @@ "postcss-value-parser": "^4.2.0" } }, + "@emotion/babel-plugin": { + "version": "11.9.2", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz", + "integrity": "sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==", + "requires": { + "@babel/helper-module-imports": "^7.12.13", + "@babel/plugin-syntax-jsx": "^7.12.13", + "@babel/runtime": "^7.13.10", + "@emotion/hash": "^0.8.0", + "@emotion/memoize": "^0.7.5", + "@emotion/serialize": "^1.0.2", + "babel-plugin-macros": "^2.6.1", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.0.13" + }, + "dependencies": { + "babel-plugin-macros": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-2.8.0.tgz", + "integrity": "sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==", + "requires": { + "@babel/runtime": "^7.7.2", + "cosmiconfig": "^6.0.0", + "resolve": "^1.12.0" + } + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==" + } + } + }, + "@emotion/cache": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.9.3.tgz", + "integrity": "sha512-0dgkI/JKlCXa+lEXviaMtGBL0ynpx4osh7rjOXE71q9bIF8G+XhJgvi+wDu0B0IdCVx37BffiwXlN9I3UuzFvg==", + "requires": { + "@emotion/memoize": "^0.7.4", + "@emotion/sheet": "^1.1.1", + "@emotion/utils": "^1.0.0", + "@emotion/weak-memoize": "^0.2.5", + "stylis": "4.0.13" + } + }, + "@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "@emotion/memoize": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", + "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" + }, + "@emotion/react": { + "version": "11.9.3", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.9.3.tgz", + "integrity": "sha512-g9Q1GcTOlzOEjqwuLF/Zd9LC+4FljjPjDfxSM7KmEakm+hsHXk+bYZ2q+/hTJzr0OUNkujo72pXLQvXj6H+GJQ==", + "requires": { + "@babel/runtime": "^7.13.10", + "@emotion/babel-plugin": "^11.7.1", + "@emotion/cache": "^11.9.3", + "@emotion/serialize": "^1.0.4", + "@emotion/utils": "^1.1.0", + "@emotion/weak-memoize": "^0.2.5", + "hoist-non-react-statics": "^3.3.1" + } + }, + "@emotion/serialize": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.0.4.tgz", + "integrity": "sha512-1JHamSpH8PIfFwAMryO2bNka+y8+KA5yga5Ocf2d7ZEiJjb7xlLW7aknBGZqJLajuLOvJ+72vN+IBSwPlXD1Pg==", + "requires": { + "@emotion/hash": "^0.8.0", + "@emotion/memoize": "^0.7.4", + "@emotion/unitless": "^0.7.5", + "@emotion/utils": "^1.0.0", + "csstype": "^3.0.2" + } + }, + "@emotion/sheet": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.1.1.tgz", + "integrity": "sha512-J3YPccVRMiTZxYAY0IOq3kd+hUP8idY8Kz6B/Cyo+JuXq52Ek+zbPbSQUrVQp95aJ+lsAW7DPL1P2Z+U1jGkKA==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, + "@emotion/utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.1.0.tgz", + "integrity": "sha512-iRLa/Y4Rs5H/f2nimczYmS5kFJEbpiVvgN3XVfZ022IYhuNA1IRSHEizcof88LtCTXtl9S2Cxt32KgaXEu72JQ==" + }, + "@emotion/weak-memoize": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz", + "integrity": "sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==" + }, "@eslint/eslintrc": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", @@ -18244,6 +18642,20 @@ } } }, + "@googlemaps/js-api-loader": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.14.3.tgz", + "integrity": "sha512-6iIb+qpGgQpgIHmIFO44WhE1rDUxPVHuezNFL30wRJnkvhwFm94tD291UvNg9L05hLDSoL16jd0lbqqmdy4C5g==", + "requires": { + "fast-deep-equal": "^3.1.3" + } + }, + "@hookform/error-message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.0.tgz", + "integrity": "sha512-Y90nHzjgL2MP7GFy75kscdvxrCTjtyxGmOLLxX14nd08OXRIh9lMH/y9Kpdo0p1IPowJBiZMHyueg7p+yrqynQ==", + "requires": {} + }, "@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -18261,6 +18673,12 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, + "@ionic-selectable/core": { + "version": "5.0.0-alpha.13", + "resolved": "https://registry.npmjs.org/@ionic-selectable/core/-/core-5.0.0-alpha.13.tgz", + "integrity": "sha512-AdwGuPSD3Qy6uyo0jJp05JZMQr5KS1r/ojDEsyvBNjl1agxWJn7cQC0nagF29CPzaCQjwUh8qYa+FKsyCll2jA==", + "requires": {} + }, "@ionic/cli-framework-output": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/@ionic/cli-framework-output/-/cli-framework-output-2.2.3.tgz", @@ -18273,30 +18691,14 @@ } }, "@ionic/core": { - "version": "6.0.13", - "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.0.13.tgz", - "integrity": "sha512-FY3+q3cIcyadQ6CWi/l/B57DlUO+MHOFCNl/4RjxCBqdwpgx1N4H2lLYGUk/V6j6AVjFNxef63hHr8z7xfTqVg==", + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.9.4.tgz", + "integrity": "sha512-Ngz9yVT6fIiGdSxxBer8uJxP4w6PasvohYpLxhtMgYiWnyIu0vZra2ui3HrYukCzUo5/SbNPiUr1l7cj1E+7qw==", + "peer": true, "requires": { - "@stencil/core": "^2.14.2", - "ionicons": "^6.0.0", + "@stencil/core": "^2.4.0", + "ionicons": "^5.5.3", "tslib": "^2.1.0" - }, - "dependencies": { - "ionicons": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ionicons/-/ionicons-6.0.1.tgz", - "integrity": "sha512-xQekOJsxH82O7oB+3F60zeRggCdND9pJ/k0E6IJDVUGGlCj5mlyFqNgxUimytKgstPGv3S+3EmCxjefvtGgWUg==", - "requires": { - "@stencil/core": "~2.12.0" - }, - "dependencies": { - "@stencil/core": { - "version": "2.12.1", - "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz", - "integrity": "sha512-u24TZ+FEvjnZt5ZgIkLjLpUNsO6Ml3mUZqwmqk81w6RWWz75hgB5p4RFI5rvuErFeh2xvMIGo+pNdG24XUBz1A==" - } - } - } } }, "@ionic/react": { @@ -18309,6 +18711,23 @@ "tslib": "*" }, "dependencies": { + "@ionic/core": { + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.7.tgz", + "integrity": "sha512-CUbH7xtKcPejHTyMvvUJZq4GIyLbL2YflzFH+mad1PoLN4TLwFTTKTDB1oeFNqwnTzaByeBvhEWSayxCbLgvjQ==", + "requires": { + "@stencil/core": "^2.14.2", + "ionicons": "^6.0.0", + "tslib": "^2.1.0" + }, + "dependencies": { + "@stencil/core": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.15.2.tgz", + "integrity": "sha512-D6dv2KAXlWt9mjC28q0s6anghQgXRn0k93suOf+4pqsv1Uq19zNJXpYL68N5GxMSiNZyMPTU4Tt2NCbut7DVGg==" + } + } + }, "@stencil/core": { "version": "2.12.1", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz", @@ -18692,20 +19111,17 @@ "@jridgewell/resolve-uri": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz", - "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==", - "dev": true + "integrity": "sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==" }, "@jridgewell/sourcemap-codec": { "version": "1.4.11", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz", - "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==", - "dev": true + "integrity": "sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==" }, "@jridgewell/trace-mapping": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz", "integrity": "sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==", - "dev": true, "requires": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -18842,7 +19258,8 @@ "@stencil/core": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz", - "integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==" + "integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==", + "peer": true }, "@surma/rollup-plugin-off-main-thread": { "version": "2.2.3", @@ -19250,6 +19667,11 @@ "@types/range-parser": "*" } }, + "@types/google.maps": { + "version": "3.49.2", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.49.2.tgz", + "integrity": "sha512-ZO1qWciukqED9qcUNW7OaPXWnTlT+tO3WcYkmudZyQW2BqD7TlMFRrdqSCoqfwKhERCwBA5A/YZt/g5A3BqgLQ==" + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -19354,6 +19776,20 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/lodash": { + "version": "4.14.182", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.182.tgz", + "integrity": "sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==" + }, + "@types/lodash.isequal": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/@types/lodash.isequal/-/lodash.isequal-4.5.6.tgz", + "integrity": "sha512-Ww4UGSe3DmtvLLJm2F16hDwEQSv7U0Rr8SujLUA2wHI2D2dm8kPu6Et+/y303LfjTIwSBKXB/YTUcAKpem/XEg==", + "dev": true, + "requires": { + "@types/lodash": "*" + } + }, "@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -19368,8 +19804,7 @@ "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", - "dev": true + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" }, "@types/prettier": { "version": "2.4.4", @@ -20508,7 +20943,6 @@ "version": "4.20.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.20.2.tgz", "integrity": "sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==", - "dev": true, "requires": { "caniuse-lite": "^1.0.30001317", "electron-to-chromium": "^1.4.84", @@ -20569,8 +21003,7 @@ "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camel-case": { "version": "4.1.2", @@ -20609,8 +21042,7 @@ "caniuse-lite": { "version": "1.0.30001320", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001320.tgz", - "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==", - "dev": true + "integrity": "sha512-MWPzG54AGdo3nWx7zHZTefseM5Y1ccM7hlQKHRqJkPozUaw3hNbBTMmLn16GG2FUzjR13Cr3NPfhIieX5PzXDA==" }, "case-sensitive-paths-webpack-plugin": { "version": "2.4.0", @@ -20947,7 +21379,6 @@ "version": "1.8.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dev": true, "requires": { "safe-buffer": "~5.1.1" } @@ -21325,7 +21756,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "requires": { "ms": "2.1.2" } @@ -21561,6 +21991,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.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", @@ -21661,8 +22100,7 @@ "electron-to-chromium": { "version": "1.4.96", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.96.tgz", - "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==", - "dev": true + "integrity": "sha512-DPNjvNGPabv6FcyjzLAN4C0psN/GgD9rSGvMTuv81SeXG/EX3mCz0wiw9N1tUEnfQXYCJi3H8M0oFPRziZh7rw==" }, "elementtree": { "version": "0.1.7", @@ -21731,7 +22169,6 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, "requires": { "is-arrayish": "^0.2.1" } @@ -21802,8 +22239,7 @@ "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" }, "escape-html": { "version": "1.0.3", @@ -21814,8 +22250,7 @@ "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "2.0.0", @@ -22458,8 +22893,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.11", @@ -22619,6 +23053,11 @@ "pkg-dir": "^4.1.0" } }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==" + }, "find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", @@ -22786,8 +23225,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -22798,8 +23236,7 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" }, "get-caller-file": { "version": "2.0.5", @@ -22909,8 +23346,7 @@ "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, "globby": { "version": "11.1.0", @@ -22957,7 +23393,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -23249,14 +23684,12 @@ "immer": { "version": "9.0.12", "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.12.tgz", - "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==", - "dev": true + "integrity": "sha512-lk7UNmSbAukB5B6dh9fnh5D0bJTOFKxVg2cyJWTYrWRfhLrLMBquONcUs3aFq507hNoIZEDDh8lb8UtOizSMhA==" }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -23265,8 +23698,7 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" } } }, @@ -23363,8 +23795,7 @@ "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" }, "is-bigint": { "version": "1.0.4", @@ -23404,7 +23835,6 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -24370,8 +24800,7 @@ "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" }, "json-parse-better-errors": { "version": "1.0.2", @@ -24382,8 +24811,7 @@ "json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, "json-schema": { "version": "0.4.0", @@ -24406,8 +24834,7 @@ "json5": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", - "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", - "dev": true + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" }, "jsonfile": { "version": "6.1.0", @@ -24493,8 +24920,7 @@ "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "loader-runner": { "version": "4.2.0", @@ -24527,12 +24953,22 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -24644,6 +25080,11 @@ "fs-monkey": "1.0.3" } }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -24821,8 +25262,7 @@ "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multicast-dns": { "version": "6.2.3", @@ -24840,6 +25280,11 @@ "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", "dev": true }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "nanoid": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz", @@ -24908,8 +25353,7 @@ "node-releases": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz", - "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==", - "dev": true + "integrity": "sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==" }, "normalize-path": { "version": "3.0.0", @@ -25173,7 +25617,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, "requires": { "callsites": "^3.0.0" } @@ -25182,7 +25625,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -25233,8 +25675,7 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-to-regexp": { "version": "1.8.0", @@ -25247,8 +25688,7 @@ "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pend": { "version": "1.2.0", @@ -25265,8 +25705,7 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", @@ -25274,6 +25713,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pigeon-maps": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/pigeon-maps/-/pigeon-maps-0.21.0.tgz", + "integrity": "sha512-p3GaGday5nmufHVGZW/36LnSXfYVh6qfzYisqcC87nqFr0eXIKkqQcDuPP9g4F1OXL1JeJe4x6JEnAE9HB+zWQ==", + "requires": {} + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -26195,6 +26640,11 @@ } } }, + "property-expr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", + "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -26219,6 +26669,15 @@ "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", "dev": true }, + "pullstate": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/pullstate/-/pullstate-1.24.0.tgz", + "integrity": "sha512-uKXQjGnZUNb3wg7STF3HvCDbGtYg7tju42QjVtaefMik6JpbadnmKgI8DgZL02SvtTNlFPosMQkAwuI/a9D8dg==", + "requires": { + "fast-deep-equal": "^3.1.3", + "immer": "^9.0.12" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -26381,6 +26840,31 @@ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==", "dev": true }, + "react-google-places-autocomplete": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/react-google-places-autocomplete/-/react-google-places-autocomplete-3.3.4.tgz", + "integrity": "sha512-IeoBxUvwFYZ8gEXC7K9e9Az3QUO7A3fbc/ED0Px63dvY4fRtipdXbGK1nBCr7qJRpZbArOk2LMUgAi21lvjPOQ==", + "requires": { + "@googlemaps/js-api-loader": "^1.12.3", + "@types/google.maps": "^3.46.1", + "react-select": "^4.3.1", + "use-debounce": "^3.4.3" + } + }, + "react-hook-form": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", + "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "requires": {} + }, + "react-input-autosize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz", + "integrity": "sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==", + "requires": { + "prop-types": "^15.5.8" + } + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -26486,6 +26970,31 @@ "workbox-webpack-plugin": "^6.4.1" } }, + "react-select": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/react-select/-/react-select-4.3.1.tgz", + "integrity": "sha512-HBBd0dYwkF5aZk1zP81Wx5UsLIIT2lSvAY2JiJo199LjoLHoivjn9//KsmvQMEFGNhe58xyuOITjfxKCcGc62Q==", + "requires": { + "@babel/runtime": "^7.12.0", + "@emotion/cache": "^11.4.0", + "@emotion/react": "^11.1.1", + "memoize-one": "^5.0.0", + "prop-types": "^15.6.0", + "react-input-autosize": "^3.0.0", + "react-transition-group": "^4.3.0" + } + }, + "react-transition-group": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", + "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "requires": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + } + }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -26660,11 +27169,15 @@ "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", "dev": true }, + "reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "resolve": { "version": "1.22.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", - "dev": true, "requires": { "is-core-module": "^2.8.1", "path-parse": "^1.0.7", @@ -26804,8 +27317,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "safer-buffer": { "version": "2.1.2", @@ -27376,6 +27888,11 @@ "postcss-selector-parser": "^6.0.4" } }, + "stylis": { + "version": "4.0.13", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", + "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -27397,8 +27914,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "svg-parser": { "version": "2.0.4", @@ -27735,8 +28251,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, "to-regex-range": { "version": "5.0.1", @@ -27753,6 +28268,11 @@ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", "dev": true }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "tough-cookie": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", @@ -27977,6 +28497,12 @@ "punycode": "^2.1.0" } }, + "use-debounce": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-3.4.3.tgz", + "integrity": "sha512-nxy+opOxDccWfhMl36J5BSCTpvcj89iaQk2OZWLAtBJQj7ISCtx1gh+rFbdjGfMl6vtCZf6gke/kYvrkVfHMoA==", + "requires": {} + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -28973,8 +29499,7 @@ "yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" }, "yargs": { "version": "16.2.0", @@ -29012,6 +29537,20 @@ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true + }, + "yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } } }, "@typescript-eslint/experimental-utils": { diff --git a/package.json b/package.json index 6962e41..5ad18b1 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "@capacitor/haptics": "1.1.4", "@capacitor/keyboard": "1.2.2", "@capacitor/status-bar": "1.0.8", + "@hookform/error-message": "^2.0.0", + "@ionic-selectable/core": "^5.0.0-alpha.13", "@ionic/react": "^6.0.0", "@ionic/react-router": "^6.0.0", "@testing-library/jest-dom": "^5.11.9", @@ -21,10 +23,16 @@ "@types/react-router-dom": "^5.1.7", "axios": "^0.26.1", "ionicons": "^5.4.0", + "pigeon-maps": "^0.21.0", + "pullstate": "^1.24.0", + "lodash.isequal": "^4.5.0", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-google-places-autocomplete": "^3.3.4", + "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", + "reselect": "^4.1.5", "typescript": "^4.1.3", "web-vitals": "^0.2.4", "workbox-background-sync": "^5.1.4", @@ -38,10 +46,12 @@ "workbox-range-requests": "^5.1.4", "workbox-routing": "^5.1.4", "workbox-strategies": "^5.1.4", - "workbox-streams": "^5.1.4" + "workbox-streams": "^5.1.4", + "yup": "^0.32.11" }, "scripts": { "start": "react-scripts start", + "start:mock": "json-server --port 8080 --watch ./mock/db.json", "build": "react-scripts build", "test": "react-scripts test --transformIgnorePatterns 'node_modules/(?!(@ionic/react|@ionic/react-router|@ionic/core|@stencil/core|ionicons)/)'", "eject": "react-scripts eject" @@ -67,6 +77,7 @@ "devDependencies": { "@capacitor/cli": "3.4.3", "@types/axios": "^0.14.0", + "@types/lodash.isequal": "^4.5.6", "react-scripts": "5.0.1" }, "description": "An Ionic project" diff --git a/public/index.html b/public/index.html index 25b753b..bf3e8a9 100644 --- a/public/index.html +++ b/public/index.html @@ -1,8 +1,8 @@ - + - Ionic App + Vanmos App diff --git a/src/App.tsx b/src/App.tsx index be70932..722f158 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,15 +1,29 @@ import { Redirect, Route } from 'react-router-dom'; import { IonApp, + IonIcon, + IonLabel, IonRouterOutlet, + IonTabBar, + IonTabButton, + IonTabs, setupIonicReact } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; -import Cadastro from './pages/Cadastro'; -import MainPages from './pages/MainPages'; // importação das páginas -import Login from './pages/login/Login'; +import Cadastro from './pages/Cadastro/Cadastro'; +import Login from './pages/Login'; +import Home from './pages/Home'; +import Perfil from './pages/Perfil'; +import PerfilEditar from './pages/PerfilEditar'; +import CadastroVan from './pages/CadastroVan'; +import CadastroCompletar from './pages/CadastroCompletar/CadastroCompletar'; +import CompletarDocumento from './pages/CadastroCompletar/CompletarDocumento'; +import CompletarTelefone from './pages/CadastroCompletar/CompletarTelefone'; +import Transportes from './pages/Transportes/Transportes'; +import BuscarPassageiro from './pages/BuscarPassageiro/BuscarPassageiro'; +import BuscarTransporte from './pages/BuscarTransporte/BuscarTransporte'; /* Core CSS required for Ionic components to work properly */ import '@ionic/react/css/core.css'; @@ -30,23 +44,91 @@ import '@ionic/react/css/display.css'; /* Theme variables */ import './theme/variables.css'; +// import Tabs from './components/Tabs'; +import { search, home, person } from 'ionicons/icons'; +import { useState, useContext } from 'react'; +import React from 'react'; +import MinhasVans from './pages/MinhasVans'; + setupIonicReact(); -const App: React.FC = () => ( +const routes = ( +<> + + + + + + + + + + + + + + + + + + + + + + +) + +interface IUserManager { + setIsLoggedIn: Function; +} + +const user: IUserManager = { + setIsLoggedIn: () => {} +}; + +export const UserContext = React.createContext(user); + +const IonicApp: React.FC = () => { + + const [isLoggedIn, setIsLoggedIn] = useState(false); + const user = useContext(UserContext); + + user.setIsLoggedIn = setIsLoggedIn; + + return( - - - - - - - - - - - + {isLoggedIn ? ( + + {routes} + + + + + Buscar + + + + Home + + + + Perfil + + + + ) : ({routes})} + -); + ) +} + +const App: React.FC = () => { + return ( + + + + ); +}; export default App; diff --git a/src/LocalStorage.ts b/src/LocalStorage.ts new file mode 100644 index 0000000..3596bbc --- /dev/null +++ b/src/LocalStorage.ts @@ -0,0 +1,24 @@ +const tokenId = 'token'; +const productDetails = '@productDetails'; + +const LocalStorage = { + getToken: (): string => { + const tokenId = localStorage.getItem('tokenId') + + if (!tokenId) { + return '' + } + + return tokenId + }, + + setToken: (token: string) => { + localStorage.setItem('tokenId', token) + }, + + clearToken: () => { + localStorage.removeItem('tokenId') + } +} + +export default LocalStorage \ No newline at end of file diff --git a/src/components/Action.tsx b/src/components/Action.tsx index 2509d60..8384042 100644 --- a/src/components/Action.tsx +++ b/src/components/Action.tsx @@ -10,10 +10,8 @@ export const Action = (props: ComponentProps) => ( -

- { props.message } - { props.text } → -

+ { props.message } + { props.text } →
); \ No newline at end of file diff --git a/src/components/Tabs.tsx b/src/components/Tabs.tsx new file mode 100644 index 0000000..ceed0f0 --- /dev/null +++ b/src/components/Tabs.tsx @@ -0,0 +1,45 @@ +import React from 'react'; +import { IonTabs, IonTabBar, IonTabButton, IonIcon, IonLabel } from '@ionic/react'; + +import { logInOutline, logInSharp, personOutline, personSharp } from 'ionicons/icons'; + +interface AppTab { + label: string; + iosIcon: string; + mdIcon: string; + // badge: string; +} + +const appPages: AppTab[] = [ + { + label: 'Login', + iosIcon: logInOutline, + mdIcon: logInSharp, + // badge: '', + }, + { + label: 'Cadastro', + iosIcon: personOutline, + mdIcon: personSharp, + // badge: '', + } +] + +const Tabs: React.FC = () => { + return ( + + + {appPages.map((appPage, index) => { + + + + {appPage.label} + + + + })} + + ); +} + +export default Tabs \ No newline at end of file diff --git a/src/components/UserSearchInfos/UserSearchInfos.css b/src/components/UserSearchInfos/UserSearchInfos.css new file mode 100644 index 0000000..184578d --- /dev/null +++ b/src/components/UserSearchInfos/UserSearchInfos.css @@ -0,0 +1,60 @@ +.overlayContainer { + + display: flex; + flex-direction: column; + /* // align-items: center; + // align-content: center; */ + + padding: 1rem; + + width: 12rem; + height: fit-content; + background-color: white; + + border-radius: 5px; + + box-shadow: rgba(149, 157, 165, 0.2) 0px 8px 24px; +} + +.overlayContainer ion-card-subtitle { + + font-size: 0.7rem; + color: black; +} + +.overlayContainer ion-note { + + font-size: 0.6rem; + margin-bottom: 0.5rem; +} + +.overlayContainer ion-badge { + + margin-bottom: 1.5rem; +} + +.overlayContainer p { + color: black; + padding: 0; + margin: 0; + margin-bottom: 0.3rem; + font-size: 0.6rem; + display: flex; + flex-direction: row; + align-items: center; + align-content: center; +} + +.overlayContainer:after { + + content:''; + position: absolute; + top: 100%; + left: 70%; + margin-left: -50px; + width: 0; + height: 0; + border-top: solid 10px white; + border-left: solid 10px transparent; + border-right: solid 10px transparent; +} \ No newline at end of file diff --git a/src/components/UserSearchInfos/UserSearchInfos.tsx b/src/components/UserSearchInfos/UserSearchInfos.tsx new file mode 100644 index 0000000..f9fae2e --- /dev/null +++ b/src/components/UserSearchInfos/UserSearchInfos.tsx @@ -0,0 +1,65 @@ +import { + IonBadge, + IonButton, + IonCardSubtitle, + IonCol, + IonIcon, + IonNote, + IonRow, +} from "@ionic/react"; +import { + arrowForward, + call, + callOutline, + navigateOutline, +} from "ionicons/icons"; +import "./UserSearchInfos.css"; + +export const UserSearchInfos = (record: any) => { + console.log(record.record); + return ( +
+ {record.record.user.name} + {/* { record.record.addressFrom } */} + + {record.record.user.star_rating + ? `${record.record.user.star_rating} estrelas` + : "Sem avaliações"} + + +

+ +  {record.record.address_to} +

+ + {record.record.user.phone_number && ( +

+ +  {record.record.user.phone_number} +

+ )} + + + + + Ver mais informações → + + + + + + + + + + + +
+ ); +}; diff --git a/src/config/api.config.ts b/src/config/api.config.ts index c30fbd8..172c67e 100644 --- a/src/config/api.config.ts +++ b/src/config/api.config.ts @@ -1,7 +1,7 @@ import environment from "../environments/environment"; -function getBaseUrl() { - const { hostname } = window.location; +const getBaseUrl = (): string => { + // const { hostname } = window.location; const { url } = environment; let apiUrl = null; diff --git a/src/constants/routes/carsRoutes.ts b/src/constants/routes/carsRoutes.ts new file mode 100644 index 0000000..9c6f85d --- /dev/null +++ b/src/constants/routes/carsRoutes.ts @@ -0,0 +1,8 @@ +const carsRoutesDefault = '/cars'; +const carsRoutes = { + list: { + url: `${carsRoutesDefault}/list` + } +} + +export default carsRoutes; \ No newline at end of file diff --git a/src/constants/routes/sessionRoutes.ts b/src/constants/routes/sessionRoutes.ts new file mode 100644 index 0000000..11717b1 --- /dev/null +++ b/src/constants/routes/sessionRoutes.ts @@ -0,0 +1,11 @@ +const sessionRoutesDefault = '/sessions'; +const sessionRoutes = { + create: { + url: `${sessionRoutesDefault}/` + }, + refresh: { + url: `${sessionRoutesDefault}/refresh` + } +} + +export default sessionRoutes; \ No newline at end of file diff --git a/src/constants/routes/usersRoutes.ts b/src/constants/routes/usersRoutes.ts new file mode 100644 index 0000000..eeceedc --- /dev/null +++ b/src/constants/routes/usersRoutes.ts @@ -0,0 +1,27 @@ +const usersRoutesDefault = '/users'; +const usersRoutes = { + create: { + url: `${usersRoutesDefault}` + }, + get: { + url: `${usersRoutesDefault}` + }, + update: { + url: `${usersRoutesDefault}/edit` + }, + checkIfUserIsDriver: { + url: `${usersRoutesDefault}/isDriver` + }, + getSocialInfo: { + url: `${usersRoutesDefault}/social` + }, + // TODO, depois corrigir + getUsersSearching: { + url: `/search/inraio` + }, + createUserSearch: { + url: `${usersRoutesDefault}/search` + }, +} + +export default usersRoutes; \ No newline at end of file diff --git a/src/constants/routes/vansLocatorsRoutes.ts b/src/constants/routes/vansLocatorsRoutes.ts new file mode 100644 index 0000000..1f57945 --- /dev/null +++ b/src/constants/routes/vansLocatorsRoutes.ts @@ -0,0 +1,17 @@ +const vansRoutesDefault = '/vans/locator'; +const vansRoutes = { + list: { + url: `${vansRoutesDefault}/list` + }, + getById: { + url: `${vansRoutesDefault}/` + }, + create: { + url: `${vansRoutesDefault}/` + }, + update: { + url: `${vansRoutesDefault}/edit` + } +} + +export default vansRoutes; \ No newline at end of file diff --git a/src/constants/routes/vansRoutes.ts b/src/constants/routes/vansRoutes.ts new file mode 100644 index 0000000..7bfcd2d --- /dev/null +++ b/src/constants/routes/vansRoutes.ts @@ -0,0 +1,20 @@ +const vansRoutesDefault = '/vans'; +const vansRoutes = { + list: { + url: `${vansRoutesDefault}/list` + }, + getByPlate: { + url: `${vansRoutesDefault}/plate` + }, + getByUserId: { + url: `${vansRoutesDefault}/user` + }, + create: { + url: `${vansRoutesDefault}/` + }, + update: { + url: `${vansRoutesDefault}/` + } +} + +export default vansRoutes; \ No newline at end of file diff --git a/src/models/van.model.ts b/src/models/van.model.ts new file mode 100644 index 0000000..ae90e2b --- /dev/null +++ b/src/models/van.model.ts @@ -0,0 +1,8 @@ +export type Van = { + id: number; + carPlate: string; + carBrand: string; + carModel: string; + maxPassengers: number; + isRent: string; +}; diff --git a/src/pages/BuscarPassageiro/BuscarPassageiro.css b/src/pages/BuscarPassageiro/BuscarPassageiro.css new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/BuscarPassageiro/BuscarPassageiro.tsx b/src/pages/BuscarPassageiro/BuscarPassageiro.tsx new file mode 100644 index 0000000..b03819d --- /dev/null +++ b/src/pages/BuscarPassageiro/BuscarPassageiro.tsx @@ -0,0 +1,127 @@ +import { IonContent, IonPage, IonFab, IonFabButton, IonIcon } from '@ionic/react'; +import { search } from 'ionicons/icons'; +import './BuscarPassageiro.css'; + +import { Map, Marker, Overlay } from "pigeon-maps"; +import { maptiler } from 'pigeon-maps/providers'; +import { useEffect, useState } from 'react'; + +import RecordsStore from '../../store/RecordsStore'; +import { fetchRecords } from '../../store/Selectors'; +import { getUsersSearching } from '../../services/api/users'; +import { UserSearchInfos } from '../../components/UserSearchInfos/UserSearchInfos'; + +const maptilerProvider = maptiler('d5JQJPLLuap8TkJJlTdJ', 'streets'); + +const BuscarPassageiro: React.FC = () => { + + // UNCOMMENT THESE TO USE CURRENT LOCATION. + + // const [ currentPoint, setCurrentPoint ] = useState(false); + + // useEffect(() => { + + // const getCurrentLocation = async () => { + + // const fetchedLocation = await getLocation(); + // setCurrentPoint(fetchedLocation.currentLocation); + // } + + // getCurrentLocation(); + // }, []); + + // useIonViewWillEnter(() => { + + // getUsersSearching(currentPoint); + // }); + + const [ currentPoint, setCurrentPoint ] = useState({ latitude: -22.907829, longitude: -47.062943 }); + + const records = RecordsStore.useState(fetchRecords); + const center = { latitude: -22.907829, longitude: -47.062943 }; + + const [ results, setResults ] = useState([]); + const [ zoom, setZoom ] = useState(14); + + const [ moveMode, setMoveMode ] = useState(false); + + // useEffect(() => { + + // const getData = async () => { + + // await getUsersSearching(currentPoint); + // } + + // getData(); + // }, [ currentPoint ]); + + useEffect(() => { + + setResults(records); + }, [ records ]); + + const hideMarkers = () => { + console.log('entrou') + const tempRecords = JSON.parse(JSON.stringify(results)); + tempRecords.forEach((tempRecord:any) => tempRecord.showInfo = false); + console.log(tempRecords) + setResults(tempRecords); + } + + const handleMap = (e:any) => { + setCurrentPoint({ latitude: e.center[0], longitude: e.center[1] }); + } + + const searchResults = async () => { + await getUsersSearching(currentPoint); + } + + const showMarkerInfo = (e:any, index:any) => { + + const tempRecords = JSON.parse(JSON.stringify(results)); + + // Hide all current marker infos + !tempRecords[index].showInfo && tempRecords.forEach((tempRecord:any) => tempRecord.showInfo = false); + tempRecords[index].showInfo = !tempRecords[index].showInfo; + + console.log(tempRecords) + setResults(tempRecords); + } + + return ( + + + {/* { results && + <> */} + handleMap(e)} defaultCenter={ [center.latitude, center.longitude] } defaultZoom={ zoom } provider={ maptilerProvider } touchEvents={ true }> + + {results && results.map((record:{latitude_from:any, longitude_from:any}, index) => { + return showMarkerInfo(e, index) } key={ index } color="#3578e5" width={ 50 } anchor={ [ parseFloat(record.latitude_from), parseFloat(record.longitude_from) ] } /> + })} + + { results.map((record:any, index) => { + + if (record.showInfo) { + + return ( + + + + ) + } + })} + + + + + + + + {/* */} + {/* } */} + + + ); +}; + +export default BuscarPassageiro; \ No newline at end of file diff --git a/src/pages/BuscarTransporte/BuscarTransporte.css b/src/pages/BuscarTransporte/BuscarTransporte.css new file mode 100644 index 0000000..7c5f206 --- /dev/null +++ b/src/pages/BuscarTransporte/BuscarTransporte.css @@ -0,0 +1,57 @@ +.inputs-from-to{ + display: flex; + align-items: center; +} + +.button-search{ + display: flex; + justify-content: center; +} + +.latest-searches{ + margin: 1rem; +} + +.div_from_to{ + max-width: 70%; + margin-inline: 1rem; +} + +.icon-align-vcenter{ + align-self: center; +} + +.icon-forward{ + margin-left: auto; + margin-right: 0; +} + +.header-search-modal{ + background-color: var(--ion-toolbar-background); + display: flex; + justify-content: center; + align-items: center; + border-radius: 1rem; + margin: 0.5rem; +} + +.icon-return-modal{ + font-size: 1.5rem; +} + +.modal-search-results{ + display: flex; + align-items: center; + margin: 1rem; + padding-bottom: 1rem; + border-bottom: 1px solid var(--ion-toolbar-border-color); +} + +.icon-results-modal{ + font-size: 2rem; +} + +.input-autocomplete{ + margin: 0.5rem 0 0.5rem 0.5rem; + width: 100%; +} \ No newline at end of file diff --git a/src/pages/BuscarTransporte/BuscarTransporte.tsx b/src/pages/BuscarTransporte/BuscarTransporte.tsx new file mode 100644 index 0000000..645d45c --- /dev/null +++ b/src/pages/BuscarTransporte/BuscarTransporte.tsx @@ -0,0 +1,242 @@ +import { + IonContent, + IonPage, + IonIcon, + IonCard, + IonInput, + IonRow, + IonCardContent, + IonButton, + IonSearchbar, + IonModal, + IonProgressBar, +} from "@ionic/react"; +import { + arrowBack, + arrowForwardOutline, + chevronForwardOutline, + locateOutline, + locationOutline, + timeOutline, +} from "ionicons/icons"; +import "./BuscarTransporte.css"; + +import { useEffect, useState } from "react"; +import { autoCompleteAddress } from "../../services/utils"; +import { useHistory } from "react-router"; + +import GooglePlacesAutocomplete, { + geocodeByAddress, + getLatLng, +} from "react-google-places-autocomplete"; + +const BuscarTransporte: React.FC = () => { + const history = useHistory(); + const [addressFrom, setAddressFrom] = useState(""); + const [coordinatesFrom, setCoordinatesFrom] = useState(""); + const [addressTo, setAddressTo] = useState(""); + const [coordinatesTo, setCoordinatesTo] = useState(""); + const [showModalEnd, setShowModalEnd] = useState(false); + const [addressResults, setAddressResults] = useState([]); + const [inputActive, setInputActive] = useState(""); + + // const optionsAddress = async (inputValue: any) => { + // let results = await autoCompleteAddress(inputValue) + // .then((res) => { + // return res.map((item: any) => { + // return { + // value: + // item.geometry.coordinates[0] + "," + item.geometry.coordinates[1], + // label: item.properties.formatted, + // }; + // }); + // }) + // .catch((err) => { + // console.log("Erro ao buscar endereço:", err); + // }); + // setAddressResults(results); + // }; + + // function setInputActiveOpenModal(input: string) { + // setInputActive(input); + // setShowModalEnd(true); + // } + + // function setAddress(div: any) { + // if (inputActive === "from") { + // setAddressFrom(div.target.attributes[2].value); + // setCoordinatesFrom(div.target.attributes[1].value); + // } else { + // setAddressTo(div.target.attributes[2].value); + // setCoordinatesTo(div.target.attributes[1].value); + // } + // setShowModalEnd(false); + // } + + useEffect(() => { + if (addressFrom.label && addressFrom.label.length > 0) { + geocodeByAddress(addressFrom.label) + .then((results) => getLatLng(results[0])) + .then(({ lat, lng }) => setCoordinatesFrom({ lat, lng })); + } + }, [addressFrom]); + + useEffect(() => { + if (addressTo.label && addressTo.label.length > 0) { + geocodeByAddress(addressTo.label) + .then((results) => getLatLng(results[0])) + .then(({ lat, lng }) => setCoordinatesTo({ lat, lng })); + } + }, [addressTo]); + + function buscaTransporte(){ + if (coordinatesFrom && coordinatesTo && addressFrom && addressTo) { + history.push({ + pathname: "/transportes", + state: { + coordinatesFrom, + coordinatesTo, + addressFrom, + addressTo, + }, + }); + } + } + + return ( + + + + +
+ + {/* setInputActiveOpenModal("from")} + value={addressFrom} + placeholder="R. José Paulino, 1234 - Centro, Campinas - SP, 13013-001" + /> */} + +
+
+ + {/* setInputActiveOpenModal("to")} + value={addressTo} + placeholder="PUC Campinas" + /> */} + +
+
+ buscaTransporte()} + > + Buscar + +
+
+
+ + +
+ Rua Tal Tal, 154, São Paulo - SP + + USP +
+ Há 1 hora +
+ +
+ + +
+ Taquaral + + PUC-Campinas +
+ Há 2 hora +
+ +
+ {/* + +
+ setShowModalEnd(false)} + /> + optionsAddress(e.detail.value)} + placeholder="R. José Paulino, 1234 - Centro, Campinas - SP, 13013-001" + className="search-modal" + /> +
+ {addressResults.length > 0 ? ( + addressResults.map((item: any) => { + return ( +
setAddress(e)} + > + {item.label} + +
+ ); + }) + ) : ( + <> + +
+ + )} +
+
*/} +
+
+ ); +}; + +export default BuscarTransporte; diff --git a/src/pages/Cadastro.css b/src/pages/Cadastro/Cadastro.css similarity index 100% rename from src/pages/Cadastro.css rename to src/pages/Cadastro/Cadastro.css diff --git a/src/pages/Cadastro.tsx b/src/pages/Cadastro/Cadastro.tsx similarity index 68% rename from src/pages/Cadastro.tsx rename to src/pages/Cadastro/Cadastro.tsx index b76dd9f..35913d6 100644 --- a/src/pages/Cadastro.tsx +++ b/src/pages/Cadastro/Cadastro.tsx @@ -1,17 +1,23 @@ import { IonToast, IonProgressBar, IonItem, IonLabel, IonInput, IonBackButton, IonButton, IonButtons, IonCardTitle, IonCol, IonContent, IonGrid, IonHeader, IonPage, IonRow, IonToolbar } from '@ionic/react'; import { arrowBack, logoFacebook, mail } from 'ionicons/icons'; -import { Action } from '../components/Action'; -import { useEffect, useState } from 'react'; +import { Action } from '../../components/Action'; +import { useContext, useEffect, useState } from 'react'; import { useHistory, useParams } from 'react-router'; import './Cadastro.css'; -import ModalExample from '../components/Email'; -import * as UsersService from '../services/users' +import ModalExample from '../../components/Email'; +import * as UsersService from '../../services/api/users' +import LocalStorage from '../../LocalStorage'; +import { UserContext } from '../../App'; +import { Color } from '@ionic/react/node_modules/@ionic/core'; const Cadastro: React.FC = () => { const history = useHistory(); + + const user = useContext(UserContext); const [showToast, setShowToast] = useState(false); - const [messageToast, setMessageToast ] = useState(''); + const [messageToast, setMessageToast] = useState(''); + const [toastColor, setToastColor] = useState("primary"); const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); @@ -53,7 +59,7 @@ const Cadastro: React.FC = () => { clearResult(); if(!emailValidate()) { - lResult.error = 'O EMAIL é inválido!'; + lResult.error = 'E-mail inválido!'; lResult.success = false; return lResult; } else if(password.length < 7 || password.length > 12) { //TODO: validar de acordo com a documentação @@ -66,44 +72,56 @@ const Cadastro: React.FC = () => { }; const handleSubmit = async () => { - - if(name != '' && email != '' && birthDate != '' && password != '' && confirmPassword != '') { - if(password === confirmPassword){ - const signUpForm = { - name: firstName +' '+ lastName, - email: email, - birth_date: birthDate, - password: password - } - - let result = fieldValidate(); - if((await result).success) { - - let retorno = await UsersService.create(signUpForm); - console.log(retorno); - if(retorno.token) { - // let signIn = await Api.signIn(email, passwordField); - // if(signIn.token) { - // await AsyncStorage.setItem('token', signIn.token); - // await AsyncStorage.setItem('cpf', retorno.cpf); - history.push('home'); - - } else { - setMessageToast(retorno.message); - setShowToast(true); - } - } else{ - setMessageToast(lResult.error); - setShowToast(true); - } - } else { - setMessageToast('As senhas devem ser iguais!'); - setShowToast(true); - } - } else { - setMessageToast('Nenhum campo pode ser nulo!'); + if(name === '' || email === '' || birthDate === '' || password === '' || confirmPassword === '') { + setToastColor("warning") + setMessageToast('Nenhum campo pode estar vazio!'); setShowToast(true); + return } + + if(password !== confirmPassword) { + setToastColor("warning") + setMessageToast('As senhas devem ser iguais!'); + setShowToast(true); + return + } + + const signUpForm = { + name: firstName, + lastname: lastName, + email: email, + birth_date: birthDate, + password: password + } + + let result = fieldValidate(); + if(!(await result).success) { + setToastColor("warning") + setMessageToast(lResult.error); + setShowToast(true); + return + } + + let retorno = await UsersService.create(signUpForm); + + if(!retorno.token) { + setToastColor('danger') + setMessageToast(retorno.message); + setShowToast(true); + return + } + + LocalStorage.setToken(retorno.token.token); + + user.setIsLoggedIn(true); + + history.push({ pathname: '/home', state: { + redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: "Usuário cadastrado com sucesso!", + } + }}) }; const { name } = useParams<{ name: string; }>(); @@ -113,26 +131,18 @@ const Cadastro: React.FC = () => { - + - - {/* Como você deseja se cadastrar? */} - Cadastro - + + {/* Como você deseja se cadastrar? */} + Cadastro + - {/* - - Continuar com Facebook - - - - Continuar com e-mail - */}
@@ -151,7 +161,7 @@ const Cadastro: React.FC = () => { Sobrenome setLastName(e.target.value)} + onIonChange={(e: any) => setLastName(e.target.value)} > @@ -162,7 +172,7 @@ const Cadastro: React.FC = () => { setEmail(e.target.value)} + onIonChange={(e: any) => setEmail(e.target.value)} > @@ -171,7 +181,7 @@ const Cadastro: React.FC = () => { Data de nascimento setBirthDate(e.target.value)} + onIonChange={(e: any) => setBirthDate(e.target.value)} > @@ -181,7 +191,7 @@ const Cadastro: React.FC = () => { setPassword(e.target.value)} + onIonChange={(e: any) => setPassword(e.target.value)} > @@ -189,7 +199,7 @@ const Cadastro: React.FC = () => { setConfirmPassword(e.target.value)} + onIonChange={(e: any) => setConfirmPassword(e.target.value)} > @@ -202,9 +212,9 @@ const Cadastro: React.FC = () => { {/*
*/} + setShowToast(false)} message={messageToast} diff --git a/src/pages/CadastroCompletar/CadastroCompletar.tsx b/src/pages/CadastroCompletar/CadastroCompletar.tsx new file mode 100644 index 0000000..de2c677 --- /dev/null +++ b/src/pages/CadastroCompletar/CadastroCompletar.tsx @@ -0,0 +1,142 @@ +import { +IonBackButton, +IonButtons, +IonCard, +IonCardContent, +IonContent, +IonHeader, +IonIcon, +IonItem, +IonLabel, +IonPage, +IonTitle, +IonToast, +IonToolbar +} from "@ionic/react"; +import React, { useEffect, useReducer, useState } from "react"; + +import '../Perfil.css' +import { useHistory, useLocation } from "react-router"; +import { callOutline, documentTextOutline } from "ionicons/icons"; + +import '../Cadastro/Cadastro.css' +import { Color } from "@ionic/react/node_modules/@ionic/core"; + +interface cardItem { + icon: string; + label: string; + description: string; + url: string; + required: boolean; +} + +interface userData { + name: string; + lastname: string; + email: string; + phone_number: string; + birth_date: string; + bio: string; + document_type: string; + document: string; +} + +interface LocationState { + userData: userData; + + redirectData?: { + showToastMessage: boolean; + toastColor: Color; + toastMessage: string; + } +} + +let items: cardItem[] = [ + { + icon: documentTextOutline, + label: 'Documento', + description: 'Cadastre seu documento para que seu perfil possa ser verificado', + url: '/perfil/completar/documento', + required: false + }, + { + icon: callOutline, + label: 'Informações de contato', + description: 'Cadastre seu número de telefone celular que para possam contatar você', + url: '/perfil/completar/telefone', + required: false + } +] + +const CadastroCompletar: React.FC = () => { + const history = useHistory(); + const location = useLocation(); + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + const handleCardClick = (item: cardItem) => { + if (!item.required) return + + history.push({ pathname: item.url, state: { userData: location.state.userData } }); + } + + useEffect(() => { + if (!location.state || !location.state.userData) { + history.push({ pathname: '/perfil' }) + } + + if (location.state && location.state.redirectData) { + const redirectData = location.state.redirectData + + if (redirectData.showToastMessage) { + setToastColor(redirectData.toastColor) + setToastMessage(redirectData.toastMessage) + setShowToast(true) + } + } + + if (!location.state.userData.document) items[0].required = true + if (!location.state.userData.phone_number) items[1].required = true + }, []); + + return ( + + + + Completar cadastro + + + + + + + + { items.map((item, index) => { + return ( + { handleCardClick(item) }}> + + + {item.label} + + + {item.description} + + ) + })} + + setShowToast(false)} + message={toastMessage} + duration={2500} + /> + + + ); +}; + +export default CadastroCompletar; diff --git a/src/pages/CadastroCompletar/CompletarDocumento.tsx b/src/pages/CadastroCompletar/CompletarDocumento.tsx new file mode 100644 index 0000000..5fc9a8c --- /dev/null +++ b/src/pages/CadastroCompletar/CompletarDocumento.tsx @@ -0,0 +1,219 @@ +import { + IonBackButton, + IonButtons, + IonContent, + IonFab, + IonFabButton, + IonHeader, + IonIcon, + IonList, + IonPage, + IonSelect, + IonSelectOption, + IonTitle, + IonToast, + IonToolbar +} from "@ionic/react"; +import React, { useEffect, useState } from "react"; +import { IonGrid, IonRow, IonCol } from "@ionic/react"; +import { useHistory, useLocation } from "react-router-dom"; +import { + IonItem, + IonLabel, + IonInput, +} from "@ionic/react"; + +import { saveOutline } from "ionicons/icons"; + +import * as usersRoutes from '../../services/api/users'; + +import validateCpf from '../../services/validateCpf' + +interface documentTypesInterface { + label: string; + name: string; +} + +interface userData { + name: string; + lastname: string; + email: string; + phone_number: string; + birth_date: string; + bio: string; + document_type: string; + document: string; +} + +interface LocationState { + userData: userData; +} + +const CompletarDocumento: React.FC = () => { + const location = useLocation(); + + const [hasChangedSinceInitialState, setHasChangedSinceInitialState] = useState(false); + + const [documentTypes, setDocumentTypes] = useState([]); + + const [document, setDocument] = useState(''); + const [documentType, setDocumentType] = useState(''); + + const [documentMaxLength, setDocumentMaxLength] = useState(0); + + const [showToast, setShowToast] = useState(false); + const [messageToast, setMessageToast] = useState(''); + + const history = useHistory(); + + const validateform = () => { + if (isNaN((Number)(document))) { + setMessageToast('Documento pode conter apenas números!') + setShowToast(true) + return false + } + + if (documentType === 'cpf' && !validateCpf(document)) { + setMessageToast('CPF inválido!') + setShowToast(true) + return false + } + + return true + } + + const handleUpdateUserDocuments = async () => { + if (!validateform()) { + return + } + + usersRoutes.update({ document_type: documentType, document: document }).then(response => { + if (response.status === 'error') { + setMessageToast(response.message); + setShowToast(true); + + return + } + + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: response.message, + } + }}) + }).catch((err) => { + setMessageToast(err); + setShowToast(true); + }) + }; + + const handleChangeDocumentType = (document_type: string) => { + switch(document_type) { + case 'cpf': + setDocumentType('cpf') // workaround para o problema de setState para valores vindos de um evento sendo triggerado por um ion-select + setDocumentMaxLength(11) + break; + case 'cnh': + setDocumentType('cnh') // workaround para o problema de setState para valores vindos de um evento sendo triggerado por um ion-select + setDocumentMaxLength(11) + break; + case 'rg': + setDocumentType('rg') // workaround para o problema de setState para valores vindos de um evento sendo triggerado por um ion-select + setDocumentMaxLength(9) + break; + } + } + + useEffect(() => { + if (!location.state.userData) { + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "warning", + toastMessage: "Houve um erro. Por favor, tente novamente.", + }, userData: location.state.userData + }}) + } + + setDocumentTypes([ + { + name: 'cpf', + label: 'CPF', + }, + { + name: 'rg', + label: 'RG', + }, + { + name: 'cnh', + label: 'CNH', + }, + ]) + }, []) + + return ( + + + + Completar cadastro + + + + + + + + + + Completar cadastro + + + + + + + + + Tipo de documento + { handleChangeDocumentType(e.detail.value) } }> + { documentTypes ? documentTypes.map((document, index) => { + return ({document.label}) + }) : <> } + + + + Documento + { setDocument(e.target.value); setHasChangedSinceInitialState(true) }} + > + + + + + + + + + + + + + setShowToast(false)} + message={messageToast} + duration={2500} + /> + + + ); +}; + +export default CompletarDocumento; + \ No newline at end of file diff --git a/src/pages/CadastroCompletar/CompletarTelefone.tsx b/src/pages/CadastroCompletar/CompletarTelefone.tsx new file mode 100644 index 0000000..f739146 --- /dev/null +++ b/src/pages/CadastroCompletar/CompletarTelefone.tsx @@ -0,0 +1,169 @@ +import { + IonBackButton, + IonButtons, + IonContent, + IonFab, + IonFabButton, + IonHeader, + IonIcon, + IonList, + IonPage, + IonTitle, + IonToast, + IonToolbar +} from "@ionic/react"; +import React, { useState, useEffect } from "react"; +import { IonGrid, IonRow, IonCol } from "@ionic/react"; +import { useHistory, useLocation } from "react-router-dom"; +import { + IonItem, + IonLabel, + IonInput, +} from "@ionic/react"; + +import { saveOutline } from "ionicons/icons"; + +import * as usersRoutes from '../../services/api/users'; +import { Color } from "@ionic/react/node_modules/@ionic/core"; + +interface documentTypesInterface { + label: string; + name: string; +} + +interface userData { + name: string; + lastname: string; + email: string; + phone_number: string; + birth_date: string; + bio: string; + document_type: string; + document: string; +} + +interface LocationState { + userData: userData; +} + +const CompletarTelefone: React.FC = () => { + const location = useLocation(); + + const [hasChangedSinceInitialState, setHasChangedSinceInitialState] = useState(false); + + const [phone, setPhone] = useState(''); + + const [showToast, setShowToast] = useState(false); + const [messageToast, setMessageToast] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + const history = useHistory(); + + const validateform = () => { + if (isNaN((Number)(phone))) { + setMessageToast('O telefone pode conter apenas números!') + setShowToast(true) + return false + } + + return true + } + + const handleUpdateUserDocuments = async () => { + if (!validateform()) { + return + } + + usersRoutes.update({ phone_number: phone }).then(response => { + if (response.status === 'error') { + setToastColor("warning") + setMessageToast(response.message); + setShowToast(true); + + return + } + + const userDataObj = location.state.userData + + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: response.message, + }, + }}) + }).catch((err) => { + setMessageToast(err); + setShowToast(true); + }) + }; + + useEffect(() => { + if (!location.state.userData) { + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "warning", + toastMessage: "Houve um erro. Por favor, tente novamente.", + } + }}) + } + }, []) + + return ( + + + + Completar cadastro + + + + + + + + + + Completar cadastro + + + + + + + + + Telefone + { setPhone(e.target.value); setHasChangedSinceInitialState(true) }} + > + + + + + + + + + + + + + setShowToast(false)} + message={messageToast} + duration={2500} + /> + + + ); +}; + +export default CompletarTelefone; + \ No newline at end of file diff --git a/src/pages/CadastroVan.css b/src/pages/CadastroVan.css new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/CadastroVan.tsx b/src/pages/CadastroVan.tsx new file mode 100644 index 0000000..7091ce7 --- /dev/null +++ b/src/pages/CadastroVan.tsx @@ -0,0 +1,355 @@ +import { + IonToast, + IonItem, + IonLabel, + IonInput, + IonBackButton, + IonButton, + IonButtons, + IonContent, + IonHeader, + IonPage, + IonToolbar, + IonTitle, + IonList, + IonCheckbox, + IonListHeader, + IonSelect, + IonSelectOption, +} from "@ionic/react"; + +import React, { useEffect, useReducer, useState } from "react"; +import { useHistory } from "react-router-dom"; + +// import * as yup from 'yup'; + +import carsService from '../services/functions/carsService' + +import * as vansRoutes from '../services/api/vans'; + +import "./CadastroVan.css"; +import { Color } from "@ionic/react/node_modules/@ionic/core"; + +const CadastroVan: React.FC = () => { + const history = useHistory(); + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(""); + const [toastColor, setToastColor] = useState("primary"); + + const [carModels, setCarModels] = useState([{ + id_model: '', + name: '' + }]); + + const [inputValues, setInputValues] = useReducer( + (state: any, newState: any) => ({ ...state, ...newState }), + { + carPlate: '', + carBrand: '', + carModel: '', + seats_number: 1, + isRented: false, + locator_name: '', + locator_address: '', + locator_complement: '', + locator_city: '', + locator_state: '', + } + ); + + const clearRentalData = () => { + setInputValues({ + carRentalName: '', + complement: '', + city: '', + state: '', + }) + }; + + const validateForm = (): boolean => { + const vanForm = { + carPlate: inputValues.carPlate, + carBrand: inputValues.carBrand, + carModel: inputValues.carModel, + seats_number: inputValues.seats_number, + isRented: inputValues.isRented, + }; + + if ( + !vanForm.carPlate || + vanForm.carPlate.length !== 7 || + !vanForm.carPlate.match(/([A-z0-9]){7}/g) + ) { + setToastMessage("Placa do veículo inválida!"); + setShowToast(true); + return false; + } + + if (!vanForm.carBrand) { + setToastMessage("Marca do veículo é obrigatório"); + setShowToast(true); + return false; + } + + if (!vanForm.carModel) { + setToastMessage("Modelo do veículo é obrigatório"); + setShowToast(true); + return false; + } + + if (!vanForm.seats_number || !parseInt(`${vanForm.seats_number}`)) { + setToastMessage("Número de passageiros inválido"); + setShowToast(true); + return false; + } + + if ((Number)(vanForm.seats_number) < 1) { + setToastMessage("Número de passageiros deve ser positivo!"); + setShowToast(true); + return false; + } + + if (vanForm.isRented) { + return validateRentalForm(); + } else { + clearRentalData(); + } + + return true; + }; + + const validateRentalForm = (): boolean => { + const locatorForm = { + locator_name: inputValues.locator_name, + locator_address: inputValues.locator_address, + locator_complement: inputValues.locator_complement, + locator_city: inputValues.locator_city, + locator_state: inputValues.locator_state, + } + + if (!locatorForm.locator_name) { + setToastMessage("Nome do Locador é obrigatório"); + setShowToast(true); + return false; + } + + if ( + !locatorForm.locator_city || + !locatorForm.locator_city.match(/([A-zà-úÀ-Ú])/g) + ) { + setToastMessage("Cidade inválida"); + setShowToast(true); + return false; + } + + if ( + !locatorForm.locator_state || + !locatorForm.locator_state.match(/([A-zà-úÀ-Ú])/g) + ) { + setToastMessage("Estado inválido"); + setShowToast(true); + return false; + } + + return true; + }; + + const handleSubmit = async () => { + if (!validateForm()) { + return + } + + // cria registro da van + await vansRoutes.create({ + plate: inputValues.carPlate, + brand: inputValues.carBrand, + model: inputValues.carModel, + seats_number: inputValues.seats_number, + locator_name: inputValues.locator_name, + locator_address: inputValues.locator_address, + locator_complement: inputValues.locator_complement, + locator_city: inputValues.locator_city, + locator_state: inputValues.locator_state + }).then(response => { + if (response.status === 'error') { + setToastMessage(response.message); + setShowToast(true); + + return + } + + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: response.message, + }, + }}) + }).catch((err) => { + setToastColor("danger") + setToastMessage(err); + setShowToast(true); + }) + }; + + useEffect(() => { + let isMounted = true + + const getCarsModels = async () => { + const carModelsRes = await carsService.getAllCarModels() + + if (carModelsRes.error) { + setToastColor("danger") + setToastMessage(carModelsRes.error.errorMessage); + setShowToast(true); + return + } + + if (carModelsRes.data) { + if (isMounted) { + setCarModels(carModelsRes.data) + } + } + } + + getCarsModels() + + return () => { isMounted = false } + }, []) + + return ( + + + + Cadastro de veículo + + + + + + + + + + Informações do veículo + + + Placa + setInputValues({ carPlate: e.target.value })} + /> + + + {/* TODO, problema de setState para valores vindos de um evento sendo triggerado por um ion-select */} + + Marca + { setInputValues({ carBrand: e.detail.value }) }}> + { carModels ? carModels.map((carModel, index) => { + return ({carModel.name}) + }) : <> } + + + + + Modelo + setInputValues({ carModel: e.target.value })} + /> + + + + + Número de assentos + + setInputValues({ seats_number: e.target.value })} + /> + + + + + + Informações do locador + + + + O veículo é alugado? + setInputValues({ isRented: e.detail.checked })} /> + + + {inputValues.isRented && ( +
+ + + setInputValues({ locator_name: e.target.value })} + /> + + setInputValues({ locator_address: e.target.value })} + /> + setInputValues({ locator_complement: e.target.value })} + /> + setInputValues({ locator_city: e.target.value })} + /> + setInputValues({ locator_state: e.target.value })} + /> + +
+ )} + +
+ + Salvar + +
+
+ + setShowToast(false)} + message={toastMessage} + duration={2500} + /> +
+
+ ); +}; + +export default CadastroVan; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 2169533..1306fd4 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,56 +1,74 @@ -import { IonItem, IonLabel, IonInput, IonButton, IonCardTitle, IonCol, IonContent, IonGrid, IonPage, IonRow } from '@ionic/react'; -import { Action } from '../components/Action'; +import { IonContent, IonPage, IonToast } from '@ionic/react'; +import { Color } from '@ionic/react/node_modules/@ionic/core'; +import { useContext, useEffect, useState } from 'react'; +import { useLocation } from 'react-router'; + +import { UserContext } from '../App'; + +import * as sessionRoutes from '../services/api/session'; + +interface LocationState { + redirectData?: { + showToastMessage: boolean; + toastColor: Color; + toastMessage: string; + } +} const Home: React.FC = () => { + const location = useLocation(); + + const user = useContext(UserContext); + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + useEffect(() => { + if (location.state && location.state.redirectData) { + const redirectData = location.state.redirectData + + if (redirectData.showToastMessage) { + setToastColor(redirectData.toastColor) + setToastMessage(redirectData.toastMessage) + setShowToast(true) + } + } + + const refreshUserToken = async () => { + await sessionRoutes.refresh().then(response => { + if (response.status === 'error') { + // setMessageToast(response.message); + // setShowToast(true); + + return + } + + user.setIsLoggedIn(true); + }).catch(error => { + // if (!error.response) return + + // se o backend retornou uma mensagem de erro customizada + // if (error.response.data.message) { + console.dir('Houve um erro: ', { error }) + alert('Houve um erro') + }) + } + + refreshUserToken() + }, []) + return ( - - - - - Como você deseja se cadastrar? - - - - -
- - Nome - - - - Sobrenome - - -
- - - E-mail - - - - - Data de nascimento - - - - - Senha - - - - Confirme a senha - - - - Cadastrar-se -
-
- - Ao se cadastrar, você aceita nossos Termos e Condições e nossa Política de Privacidade. - - -
+ + setShowToast(false)} + message={toastMessage} + duration={2500} + />
); diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 0000000..da97644 --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,174 @@ +import { + IonContent, + IonHeader, + IonPage, + IonTitle, + IonToolbar +} from "@ionic/react"; +import React, { useContext, useState } from "react"; +import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react"; +import { useHistory } from "react-router-dom"; +import { + IonItem, + IonLabel, + IonInput, + IonButton, +} from "@ionic/react"; + +import * as sessionRoutes from '../services/api/session'; +import LocalStorage from '../LocalStorage'; +import { Action } from "../components/Action"; +import { UserContext } from "../App"; + +const Page: React.FC = () => { + const [showToast, setShowToast] = useState(false); + const [messageToast, setMessageToast ] = useState(''); + + const history = useHistory(); + const [email, setEmail] = useState(''); + const [password, setPassword] = useState(''); + + const user = useContext(UserContext); + + function validateEmail(email: string) { + const re = + // eslint-disable-next-line no-control-regex + /^((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))$/; + return re.test(String(email).toLowerCase()); + } + + const validateForm = () => { + if (!email) { + setMessageToast("Por favor, informe o e-mail"); + setShowToast(true); + return false; + } + + if (!validateEmail(email)) { + setMessageToast("E-mail inválido"); + setShowToast(true); + return false; + } + + if (!password) { + setMessageToast("Por favor, digite a sua senha"); + setShowToast(true); + return false; + } + + if(password.length < 7 || password.length > 12) { + setMessageToast("A senha deve conter entre 7 e 12 dígitos"); + setShowToast(true); + return false; + } + + return true; + } + + const handleLogin = async () => { + if (!validateForm()) { + return + } + + const singinForm = { + login: email, + password: password, + }; + + await sessionRoutes.create(singinForm).then(response => { + if (response.status === 'error') { + setMessageToast(response.message); + setShowToast(true); + + return + } + + const { token } = response.token + + LocalStorage.setToken(token); + + user.setIsLoggedIn(true); + + history.push({ pathname: '/home', state: { redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: "Usuário autenticado com sucesso!", + }}}) + }).catch(error => { + // if (!error.response) return + + // se o backend retornou uma mensagem de erro customizada + // if (error.response.data.message) { + console.dir('Houve um erro: ', { error }) + alert('Houve um erro') + }) + }; + + return ( + + + + Login + + + + + + + Login + + + + + + + + Email + setEmail(e.detail.value!)} + > + + + + + + + + Senha + setPassword(e.detail.value!)} + > + + + + + + + + Login + +

+ +

+
+
+
+ + setShowToast(false)} + message={messageToast} + duration={2500} + /> +
+
+ ); +}; + +export default Page; diff --git a/src/pages/MainPages.tsx b/src/pages/MainPages.tsx deleted file mode 100644 index 3803212..0000000 --- a/src/pages/MainPages.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useState, useRef } from 'react'; -import { - IonTabs, - IonTabBar, - IonTabButton, - IonLabel, - IonPage, - IonIcon, - IonRouterOutlet -} from '@ionic/react'; -import { Redirect, Route } from 'react-router-dom'; -import { IonReactRouter } from '@ionic/react-router'; -import { search, home, person } from 'ionicons/icons'; - -import Home from './Home'; - -export const MainPages: React.FC = () => { - - return ( - - - - - - } /> - - - - - - Buscar - - - - Home - - - - Perfil - - - - ) -} - -export default MainPages; \ No newline at end of file diff --git a/src/pages/MinhasVans.tsx b/src/pages/MinhasVans.tsx new file mode 100644 index 0000000..904478c --- /dev/null +++ b/src/pages/MinhasVans.tsx @@ -0,0 +1,118 @@ +import { IonBackButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonHeader, IonIcon, IonItem, IonLabel, IonPage, IonTitle, IonToast, IonToolbar } from '@ionic/react'; +import { Color } from '@ionic/react/node_modules/@ionic/core'; +import { carOutline } from 'ionicons/icons'; +import { useContext, useEffect, useState } from 'react'; +import { useHistory, useLocation } from 'react-router'; + +import { UserContext } from '../App'; + +import * as vansRoutes from '../services/api/vans'; + +import sessionsService from '../services/functions/sessionsService' + +interface VanInfo { + plate: string; + brand: string; + model: string; + seats_number: string; + document_status: boolean, + locator_name: string; + locator_address: string; + locator_complement: string; + locator_city: string; + locator_state: string; +} + +const MinhasVans: React.FC = () => { + const history = useHistory(); + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + const [userVans, setUserVans] = useState(); + + const redirectUserToLogin = () => { + history.push({ pathname: '/login' }); + } + + useEffect(() => { + const getUserVans = async () => { + let userId = '' + + const refreshSessionRes = await sessionsService.refreshSession() + + if (refreshSessionRes.error) { + redirectUserToLogin() + return + } + + if (refreshSessionRes.userId) { + userId = refreshSessionRes.userId + } + + vansRoutes.getByUserId(userId).then(response => { + if (response.status === 'error') { + setToastColor("danger") + setToastMessage(response.message); + setShowToast(true); + + return + } + + setUserVans(response.data) + }).catch((err) => { + setToastColor("danger") + setToastMessage(err); + setShowToast(true); + }) + } + + getUserVans() + }, []) + + return ( + + + + Minhas vans + + + + + + + + { userVans ? userVans.map((van, index) => { + return ( + + + {van.plate} + {van.brand} - {van.model} + + { van.locator_name ? + <> + {van.seats_number} assentos - Locador: {van.locator_name} + : + <> + {van.seats_number} assentos - Não é alugado + + } + + ) + }) : <>} + + setShowToast(false)} + message={toastMessage} + duration={2500} + /> + + + ); +}; + +export default MinhasVans; diff --git a/src/pages/Perfil.css b/src/pages/Perfil.css new file mode 100644 index 0000000..1efc84d --- /dev/null +++ b/src/pages/Perfil.css @@ -0,0 +1,16 @@ +#avatar { + border-radius: 50%; + width: 100px; + height: 100px; + display: block; + margin-left: auto; + margin-right: auto; +} + +#profile-status { + text-align: center; +} + +IonIcon { + color: blue; +} \ No newline at end of file diff --git a/src/pages/Perfil.tsx b/src/pages/Perfil.tsx new file mode 100644 index 0000000..3661c11 --- /dev/null +++ b/src/pages/Perfil.tsx @@ -0,0 +1,328 @@ +import { + IonBackButton, + IonBadge, + IonButtons, + IonCard, + IonCardContent, + IonCardHeader, + IonCardTitle, + IonChip, + IonContent, + IonHeader, + IonIcon, + IonItem, + IonLabel, + IonList, + IonListHeader, + IonPage, + IonTitle, + IonToast, + IonToolbar, +} from "@ionic/react"; +import { useHistory, useLocation } from "react-router-dom"; +import React, { useState, useEffect, useReducer, useContext } from "react"; +import { callOutline, cardOutline, carOutline, createOutline, exitOutline, logoFacebook, logoWhatsapp, personOutline, shieldCheckmarkOutline, starOutline } from "ionicons/icons"; + +import './Perfil.css' +import LocalStorage from "../LocalStorage"; + +import sessionsService from '../services/functions/sessionsService' +import usersService from '../services/functions/usersService' +import { UserContext } from "../App"; +import { Color } from "@ionic/react/node_modules/@ionic/core"; + +interface ScanNewProps { + match: { + params: { + id: string; + } + } +} + +interface LocationState { + redirectData?: { + showToastMessage: boolean; + toastColor: Color; + toastMessage: string; + } +} + +const Perfil: React.FC = (props) => { + const user = useContext(UserContext); + + const history = useHistory(); + const location = useLocation(); + + const [isVisitor, setIsVisitor] = useState(true) + const [isDriver, setIsDriver] = useState(false) + + const [incompleteProfile, setIncompleteProfile] = useState(false) + const [incompleteProfileCounter, setIncompleteProfileCounter] = useState(0) + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + const [inputValues, setInputValues] = useReducer( + (state: any, newState: any) => ({ ...state, ...newState }), + { + id: '', + name: '', + lastname: '', + email: '', + phone_number: '', + birth_date: '', + bio: '', + document_type: '', + document: '', + } + ); + + const redirectUserToLogin = () => { + history.push({ pathname: '/login' }); + setToastMessage("Por favor, autentique-se!"); + setShowToast(true); + } + + const logoff = () => { + LocalStorage.clearToken() + user.setIsLoggedIn(false); + history.push({ pathname: '/login' }); + } + + useEffect(() => { + if (location.state && location.state.redirectData) { + const redirectData = location.state.redirectData + + if (redirectData.showToastMessage) { + setToastColor(redirectData.toastColor) + setToastMessage(redirectData.toastMessage) + setShowToast(true) + } + } + + const loadUserData = async () => { + let userId = '' + + // verify if user is authenticated + if (props.match.params.id) { + userId = props.match.params.id + } else { + const refreshSessionRes = await sessionsService.refreshSession() + + if (refreshSessionRes.error) { + redirectUserToLogin() + return + } + + if (refreshSessionRes.userId) { + userId = refreshSessionRes.userId + } + } + + // get user info by ID + const getByIdRes = await usersService.getById(userId) + + if (getByIdRes.error) { + if (isVisitor && props.match.params.id) { + setToastMessage('Usuário não existe!') + setShowToast(true) + history.push({ pathname: '/home' }) + } else { + setToastMessage(getByIdRes.error.errorMessage) + setShowToast(true) + } + + return + } + + // check if user is driver (if they have vans) + const userIsDriverRes = await usersService.checkIfUserIsDriver(userId) + + // if (userIsDriverRes.error) { + // setToastColor('warning') + // setToastMessage(userIsDriverRes.error.errorMessage) + // setShowToast(true) + // return + // } + + if (!userIsDriverRes.error && userIsDriverRes.result !== undefined) { + setIsDriver(userIsDriverRes.result) + } + + if (getByIdRes.userData) { + const userData = getByIdRes.userData + + if (isMounted) { + setInputValues({ + 'id': userId, + 'name': userData.name, + 'lastname': userData.lastname, + 'email': userData.email, + 'phone_number': userData.phone_number, + 'birth_date': userData.birth_date, + 'bio': userData.bio, + 'document_type': userData.document_type, + 'document': userData.document + }); + + if (!props.match.params.id) { + setIsVisitor(false) + } + + if (!userData.document || !userData.phone_number) { + setIncompleteProfile(true) + + let counter = 0 + + if (!userData.document) counter++ + if (!userData.phone_number) counter++ + + setIncompleteProfileCounter(counter) + } + } + } + } + + let isMounted = true; + + const userToken = LocalStorage.getToken() + + if (!userToken) { + redirectUserToLogin() + } + + loadUserData() + + return () => { isMounted = false }; + }, []); + + return ( + + + + Seu perfil + + + + + + + + + + Seu perfil + + + + + + avatar + {/* avatar */} + + {inputValues.name} {inputValues.lastname} + + +
+ { isDriver ? + <> + + + Motorista + + : <> + } + + + Passageiro + +
+
+
+ + + + Biografia + + + {inputValues.bio ? inputValues.bio : 'Sem biografia.' } + + + + + + Informações de contato + + + { !inputValues.phone_number ? + <>Sem informações de contato. + : <> + { + inputValues.phone_number ? + <> + + + {inputValues.phone_number} + + : <> + } + + } + + + + { !isVisitor ? + + Configurações + history.push({ pathname: '/perfil/editar', state: { userData: inputValues } })}> + + Editar perfil + + + { incompleteProfile ? + <> + history.push({ pathname: '/perfil/completar', state: { userData: inputValues } })}> + + Completar cadastro + {incompleteProfileCounter} + + + : <> } + + history.push({ pathname: '/cadastro-van'})}> + + Cadastrar Van + + history.push({ pathname: '/minhas-vans'})}> + + Minhas Vans + + + + Pagamentos + + + + Avaliações + + + + Sair da conta + + : <> + } + + setShowToast(false)} + message={toastMessage} + duration={2500} + /> +
+
+ ); +}; + +export default Perfil; diff --git a/src/pages/PerfilEditar.tsx b/src/pages/PerfilEditar.tsx new file mode 100644 index 0000000..d3fa677 --- /dev/null +++ b/src/pages/PerfilEditar.tsx @@ -0,0 +1,200 @@ +import { + IonBackButton, + IonButtons, + IonContent, + IonFab, + IonFabButton, + IonGrid, + IonHeader, + IonIcon, + IonInput, + IonItem, + IonLabel, + IonPage, + IonTextarea, + IonTitle, + IonToast, + IonToolbar +} from "@ionic/react"; +import React, { useEffect, useReducer, useState } from "react"; +import { IonRow, IonCol } from "@ionic/react"; + +import './Perfil.css' +import { useHistory, useLocation } from "react-router"; +import { saveOutline } from "ionicons/icons"; + +import isEqual from 'lodash.isequal'; + +import * as usersRoutes from '../services/api/users'; + +import './Cadastro/Cadastro.css' +import { Color } from "@ionic/react/node_modules/@ionic/core"; + +interface userData { + name: string; + lastname: string; + email: string; + birth_date: string; + bio: string; +} + +interface LocationState { + userData: userData +} + +const PerfilEditar: React.FC = () => { + const history = useHistory(); + const location = useLocation(); + + const [showToast, setShowToast] = useState(false); + const [messageToast, setMessageToast] = useState(''); + const [toastColor, setToastColor] = useState("primary"); + + const [userData, setUserData] = useState({ + name: '', + lastname: '', + email: '', + birth_date: '', + bio: '', + }); + + const [inputValues, setInputValues] = useReducer( + (state: any, newState: any) => ({ ...state, ...newState }), + { + name: '', + lastname: '', + email: '', + birth_date: '', + bio: '', + } + ); + + useEffect(() => { + if (!location.state) { + history.push({ pathname: '/perfil' }) + } + + let userData = location.state.userData + + setUserData(location.state.userData) + setInputValues({ + 'name': userData.name, + 'lastname': userData.lastname, + 'email': userData.email, + 'birth_date': userData.birth_date, + 'bio': userData.bio + }); + }, [userData]); + + const handleUpdateUserData = () => { + usersRoutes.update(inputValues).then(response => { + if (response.status === 'error') { + setToastColor("danger") + setMessageToast(response.message); + setShowToast(true); + + return + } + + history.push({ pathname: '/perfil', state: { + redirectData: { + showToastMessage: true, + toastColor: "success", + toastMessage: response.message, + }, + }}) + }).catch((err) => { + setToastColor("danger") + setMessageToast(err); + setShowToast(true); + }) + } + + const hasChangedSinceInitialState = () => { + return isEqual(userData, inputValues) + } + + return ( + + + + Editar perfil + + + + + + + + + + +
+ + Nome + setInputValues({'name': e.detail.value!})} + > + + + + Sobrenome + setInputValues({'lastname': e.detail.value!})} + > + +
+ + + Email + setInputValues({'email': e.detail.value!})} + > + + + + Data de nascimento + setInputValues({'birth_date': e.detail.value!})} + > + + + + + Biografia + setInputValues({'bio': e.detail.value!})} + > + +
+
+
+ + + + + + + + setShowToast(false)} + message={messageToast} + duration={2500} + /> +
+
+ ); +}; + +export default PerfilEditar; diff --git a/src/pages/Transportes/Transportes.css b/src/pages/Transportes/Transportes.css new file mode 100644 index 0000000..966beea --- /dev/null +++ b/src/pages/Transportes/Transportes.css @@ -0,0 +1,78 @@ +.header-page{ + background-color: var(--ion-item-background); + border-bottom: 1px solid var(--ion-color-step-150, #dadada); + height: 3.5rem; + display: flex; + padding: 0.5rem; +} + +.icon-return{ + font-size: 1.5rem; +} + +.span-info-back{ + background-color: var(--ion-color-step-150, #dadada); + border-radius: 0.5rem; + padding: 0.5rem; + display: flex; + width: 100%; +} + +.address-from-to{ + /* display: block; */ + margin-top: -0.2rem; + font-size: 0.8rem; + white-space: nowrap; + overflow: hidden; + max-width: 100%; +} + +/* .address-from-to span{ + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 1rem!important; +} */ + +.address-from-to ion-icon{ + margin-inline: 0.2rem; +} + +.address-from-to small{ + display: block; +} + +.header-tabs{ + background-color: var(--ion-color-step-150,#dadada); + height: 5.5rem; + padding: 0.5rem; +} + +.header-tabs h5{ + margin: 0; +} + +.header-tabs .card-transporte{ + margin: 0; +} + +.content-filter-modal{ + margin: 0.5rem; +} + +.header-filter-modal{ + display: flex; + justify-content: space-between; + align-items: center; +} + +.button-criar-alerta{ + display: flex; + justify-content: center; + align-items: center; + margin: 1rem 0 5.5rem 0; +} + +.msg-not-found{ + margin: 1.5rem; +} \ No newline at end of file diff --git a/src/pages/Transportes/Transportes.tsx b/src/pages/Transportes/Transportes.tsx new file mode 100644 index 0000000..f99a602 --- /dev/null +++ b/src/pages/Transportes/Transportes.tsx @@ -0,0 +1,222 @@ +import { + IonContent, + IonPage, + IonFab, + IonFabButton, + IonIcon, + IonCard, + IonInput, + IonRow, + IonCol, + IonCardContent, + IonButton, + IonHeader, + IonToolbar, + IonButtons, + IonBackButton, + IonTabs, + IonTabBar, + IonTabButton, + IonLabel, + IonBadge, + IonRouterOutlet, + IonSlides, + IonSlide, + IonModal, + IonList, + IonRadioGroup, + IonListHeader, + IonItem, + IonRadio, + IonCheckbox, + IonFooter, + IonToast, +} from "@ionic/react"; +import { + arrowBack, + arrowBackOutline, + arrowForwardOutline, + chevronBackOutline, + chevronForwardOutline, + closeOutline, + locateOutline, + locationOutline, + timeOutline, +} from "ionicons/icons"; +import { useEffect, useState } from "react"; +import { useHistory, useLocation } from "react-router"; +import { getTransportes } from "../../services/transportes"; +import { createUserSearch } from "../../services/api/users"; +import "./Transportes.css"; + +interface InfoBusca { + addressFrom: any; + addressTo: any; + coordinatesFrom: any; + coordinatesTo: any; +} + +const Transportes: React.FC = () => { + const history = useHistory(); + const location = useLocation(); + const props = location.state as InfoBusca; + const [transportes, setTransportes] = useState([]); + const [showModalFilters, setShowModalFilters] = useState(false); + const [showToast, setShowToast] = useState(false); + const [messageToast, setMessageToast ] = useState(''); + const [toastColor, setToastColor] = useState('success'); + + useEffect(() => { + if (props) { + buscaTransportes(); + } + }, [props]); + + async function buscaTransportes() { + let data = (await getTransportes(props)) as any; + setTransportes(data); + } + + function criaAlerta(){ + createUserSearch(props.coordinatesFrom.lat, props.coordinatesFrom.lng, props.addressTo.label).then(() => { + setMessageToast('Alerta criado com sucesso!'); + setShowToast(true); + }).catch((err:any) => { + setMessageToast('Não foi possível criar o alerta!'); + setToastColor('danger'); + setShowToast(true); + }) + } + + return ( + + +
+ {/* + + */} + + +
+ {props.addressFrom.label} + + {props.addressTo.label} + Hoje +
+
+
+
+ + {transportes && transportes.length > 0? ( +
+ + +
Mais barata
+ + Seu João + +
+ +
Melhor avaliação
+ + Seu Zé + +
+
+
+ ) + : + (

Não foi encontrado nenhum transporte que atenda essa rota.

)} + {transportes && + transportes.map((record: any, index: any) => { + return ( + + +

Motorista: {record.motorista}

+
Avaliação: {record.avaliacao}
+
Valor: {record.valor}
+
Lugares disponíveis: {record.lugares}
+
+
+ ); + })} + +
+ criaAlerta()}>Criar Alerta +
+ + setShowModalFilters(true)} + vertical="bottom" + horizontal="center" + slot="fixed" + > + Filtros + + + +
+ setShowModalFilters(false)} + /> +

+ Limpar +

+
+
+ +
+

Filtrar

+

Ordernar por

+ + + Menor preço + + + + + Avaliação + + + + + Lugares disponíveis + + + +

Preferências

+ + Vaga avulsa + + + + Ar condicionado + + +
+
+ + setShowModalFilters(false)} + > + Aplicar Filtros + + +
+ setShowToast(false)} + message={messageToast} + duration={2500} + /> +
+
+ ); +}; + +export default Transportes; diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx deleted file mode 100644 index ee3adcd..0000000 --- a/src/pages/login/Login.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import { - IonContent, - IonHeader, - IonPage, - IonTitle, - IonToolbar, - IonButtons, -} from "@ionic/react"; -import React, { useState } from "react"; -import axios from "axios"; -import { IonGrid, IonRow, IonCol } from "@ionic/react"; -import { personCircle } from "ionicons/icons"; -import { useHistory } from "react-router-dom"; -import { - IonItem, - IonLabel, - IonInput, - IonButton, - IonIcon, - IonAlert, -} from "@ionic/react"; - -function validateEmail(email: string) { - const re = - /^((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\]))$/; - return re.test(String(email).toLowerCase()); -} - -const Page: React.FC = () => { - const history = useHistory(); - const [email, setEmail] = useState("matheusalb3213@gmail.com"); - const [password, setPassword] = useState("1234"); - const [isError, setIsError] = useState(false); - const [message, setMessage] = useState(""); - - const handleLogin = () => { - // validação de inputs - if (!email) { - setMessage("Por favor, informe um e-mail válido"); - setIsError(true); - return; - } - - if (validateEmail(email) === false) { - setMessage("E-mail inválido"); - setIsError(true); - return; - } - - if (!password || password.length < 6) { - setMessage("Por favor, digite a sua senha"); - setIsError(true); - return; - } - - const loginData = { - email: email, - password: password, - }; - - const api = axios.create({ - baseURL: `https://625dc16c4c36c7535779792c.mockapi.io/api/v1`, - }); - - api - // .post("/login", loginData) - .get("/users/2") - .then((res) => { - // login bem-sucedido - history.push("/dashboard/" + email); - }) - .catch((error) => { - setMessage("Falha na autenticação! Por favor, crie uma conta"); - setIsError(true); - }); - }; - - return ( - - - - Login - - - - - - - - - - - - - Login - - - - - - - setIsError(false)} - cssClass="my-custom-class" - header={"Error!"} - message={message} - buttons={["Dismiss"]} - /> - - - - - - - Email - setEmail(e.detail.value!)} - > - - - - - - - - Senha - setPassword(e.detail.value!)} - > - - - - - - -

- Clicando no botão de "LOGIN", você concorda com a nossa{" "} - política de termos e serviços -

- - Login - -

- Ainda não possui uma conta? Cadastre-se aqui! -

-
-
-
-
-
- ); -}; - -export default Page; diff --git a/src/services/api-client.service.ts b/src/services/api-client.service.ts new file mode 100644 index 0000000..970a8f3 --- /dev/null +++ b/src/services/api-client.service.ts @@ -0,0 +1,18 @@ +import axios from "axios"; + +export class ApiClient{ + private static api = axios.create({ + baseURL: "http://localhost:8080" + }); + + public static async doPost (url: string, body: any): Promise { + return await this.api + .post(url, body) + .then(res => { + console.log(res.data); + }) + .catch(error => { + console.log(error); + }); + }; +} \ No newline at end of file diff --git a/src/services/api.ts b/src/services/api/api.ts similarity index 71% rename from src/services/api.ts rename to src/services/api/api.ts index 909f183..70062b2 100644 --- a/src/services/api.ts +++ b/src/services/api/api.ts @@ -1,5 +1,5 @@ import axios from 'axios'; -import apiConfig from '../config/api.config'; +import apiConfig from '../../config/api.config'; const instance = axios.create({ baseURL: apiConfig.getBaseUrl(), diff --git a/src/services/api/cars.ts b/src/services/api/cars.ts new file mode 100644 index 0000000..b81cc93 --- /dev/null +++ b/src/services/api/cars.ts @@ -0,0 +1,25 @@ +import instance from './api'; + +import carsRoutes from '../../constants/routes/carsRoutes'; +import { AxiosRequestHeaders } from 'axios'; +import LocalStorage from '../../LocalStorage'; + +let token: string; +let header: AxiosRequestHeaders; + +function updateHeader() { + token = LocalStorage.getToken(); + + header = { + "Accept": 'application/json', + "Content-Type": 'application/json', + "Authorization": 'Bearer ' + token + } +} +export async function list() { + updateHeader(); + + const response = await instance.get(carsRoutes.list.url, { headers: header }); + + return response.data; +} \ No newline at end of file diff --git a/src/services/api/session.ts b/src/services/api/session.ts new file mode 100644 index 0000000..ba8118a --- /dev/null +++ b/src/services/api/session.ts @@ -0,0 +1,33 @@ +import instance from './api'; +import sessionRoutes from '../../constants/routes/sessionRoutes'; +import LocalStorage from '../../LocalStorage'; +import { AxiosRequestHeaders } from 'axios'; + +let token: string | null; +let header: AxiosRequestHeaders; + +interface createData { + login: string, + password: string, +} + +function updateHeader() { + token = LocalStorage.getToken(); + header = { + "Accept": 'application/json', + "Content-Type": 'application/json', + "Authorization": 'Bearer ' + token + } +} + +export async function create(data: createData) { + const response = await instance.post(sessionRoutes.create.url, data); + return response.data; +} + +export async function refresh() { + updateHeader(); + + let response = await instance.post(sessionRoutes.refresh.url, { token }, { headers: header }); + return response.data; +} \ No newline at end of file diff --git a/src/services/api/users.ts b/src/services/api/users.ts new file mode 100644 index 0000000..20c1246 --- /dev/null +++ b/src/services/api/users.ts @@ -0,0 +1,109 @@ +import instance from './api'; +// import LocalStorage from '../LocalStorage'; + +import userRoutes from '../../constants/routes/usersRoutes'; +import { AxiosRequestHeaders } from 'axios'; +import LocalStorage from '../../LocalStorage'; +import { setStore } from '../../store/RecordsStore'; + +let token: string; +let header: AxiosRequestHeaders; + +function updateHeader() { + token = LocalStorage.getToken(); + + header = { + "Accept": 'application/json', + "Content-Type": 'application/json', + "Authorization": 'Bearer ' + token + } +} + +export interface CadastroResponse { + message?: string; + + token?: { + token: string; + }; + + error?: string; +} + +export interface CadastroRequest { + name: string; + lastname: string; + email: string; + birth_date: string; + password: string; +} + +export interface UpdateUserRequest { + name?: string; + email?: string; + bio?: string; + document_type?: string; + document?: string; + phone_number?: string; +} + +// export async function get(cpf) { +// updateHeader(); + +// const response = await instance.get(userRoutes.get.url + `/${cpf}`, { headers: header }); +// return response.data; +// } + +export async function create(CadastroRequest: any) { + updateHeader(); + + const response = await instance.post(userRoutes.create.url, CadastroRequest); + return response.data; +} + +export async function getById(userId: string) { + updateHeader(); + + const response = await instance.get(userRoutes.get.url + `/${userId}`, { headers: header }); + return response.data; +} + +export async function update(userData: UpdateUserRequest) { + updateHeader(); + + const response = await instance.patch(userRoutes.update.url, userData, { headers: header }); + return response.data; +} + +export async function checkIfUserIsDriver(id_user: string) { + updateHeader(); + + const response = await instance.get(userRoutes.checkIfUserIsDriver.url + `/${id_user}`, { headers: header }); + return response.data; +} + +// TODO, continuar +export async function getSocialInfo(userId: string) { + updateHeader(); + + const response = await instance.get(userRoutes.getSocialInfo.url + `/${userId}`, { headers: header }); + return response.data; +} + +export async function getUsersSearching(currentPoint: any) { + // Replace lat/long with values from get current location. + // Allow choosing of radius? + // Offset could = amount loaded in an infinite scroll? + var latitude = currentPoint.latitude, longitude = currentPoint.longitude, radius = 3000, offset = 0; + // const response = await fetch(`http://localhost:4000/get-records?latitude=${ latitude }&longitude=${ longitude }&radius=${ radius }&offset=${ offset }`); + const response = await instance.post(`${userRoutes.getUsersSearching.url}`, currentPoint) + // const data = await response.json(); + console.log(response.data) + setStore(response.data); +} + +export async function createUserSearch(latitude_from: any, longitude_from: any, addres_to: any) { + const response = await instance.post(`${userRoutes.createUserSearch.url}`, { latitude_from, longitude_from, addres_to }); + + console.log(response) + setStore(response); +} \ No newline at end of file diff --git a/src/services/api/vans.ts b/src/services/api/vans.ts new file mode 100644 index 0000000..f4b5fd3 --- /dev/null +++ b/src/services/api/vans.ts @@ -0,0 +1,73 @@ +import instance from "./api"; + +import vansRoutes from "../../constants/routes/vansRoutes"; +import { AxiosRequestHeaders } from "axios"; +import LocalStorage from "../../LocalStorage"; + +let token: string; +let header: AxiosRequestHeaders; + +function updateHeader() { + token = LocalStorage.getToken(); + + header = { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }; +} + +export async function getByPlate(vanId: string) { + updateHeader(); + + const response = await instance.get(vansRoutes.getByPlate.url + `/${vanId}`, { + headers: header, + }); + + return response.data; +} + +export async function getByUserId(userId: string) { + updateHeader(); + + const response = await instance.get(vansRoutes.getByUserId.url + `/${userId}`, { + headers: header, + }); + + return response.data; +} + +interface CreateVanBody { + plate: string; + brand: string; + model: string; + seats_number: string; + locator_name: string; + locator_address: string; + locator_complement: string; + locator_city: string; + locator_state: string; +} + +export async function create(CreateVanBody: CreateVanBody) { + updateHeader(); + + const response = await instance.post(vansRoutes.create.url, CreateVanBody, { headers: header }); + return response.data; +} + +interface UpdateVanBody { + brand?: string; + model?: string; + seats_number?: string; +} + +export async function update(vanData: UpdateVanBody) { + updateHeader(); + + const response = await instance.patch(vansRoutes.update.url, vanData, { + headers: header, + }); + + return response.data; +} diff --git a/src/services/functions/carsService.ts b/src/services/functions/carsService.ts new file mode 100644 index 0000000..e46855e --- /dev/null +++ b/src/services/functions/carsService.ts @@ -0,0 +1,51 @@ +import * as carsRoutes from "../api/cars"; + +interface getAllCarModelsReturn { + data?: { + id_model: string; + name: string; + }[]; + + error?: { + errorMessage: string; + } +} + +interface getAllCarModelsRes { + status?: string; + + message: string + + data?: { + id_model: string; + name: string; + }[]; + + +} + +const getAllCarModels = async (): Promise => { + try { + let res: getAllCarModelsRes = await carsRoutes.list(); + + if (res.status === "error") { + return { + error: { + errorMessage: res.message, + }, + }; + } + + return { + data: res.data, + }; + } catch (err) { + return { + error: { + errorMessage: "Por favor, autentique-se.", + }, + }; + } +}; + +export default { getAllCarModels }; diff --git a/src/services/functions/sessionsService.ts b/src/services/functions/sessionsService.ts new file mode 100644 index 0000000..5685c19 --- /dev/null +++ b/src/services/functions/sessionsService.ts @@ -0,0 +1,46 @@ +import * as sessionRoutes from "../api/session"; + +interface refreshSessionReturn { + userId?: string; + error?: boolean; + errorMessage?: string; +} + +interface refreshSessionResponse { + status?: string; + message?: string; + userId?: string; +} + +const refreshSession = async (): Promise => { + try { + let res: refreshSessionResponse = await sessionRoutes.refresh() + + if (res.status === "error") { + return { + error: true, + errorMessage: res.message, + }; + } + + return { + userId: res.userId, + }; + } catch(err) { + return { + error: true, + errorMessage: "Por favor, autentique-se.", + }; + } + // catch (err: any) { + // if (err.response) { + // // The client was given an error response (5xx, 4xx) + // } else if (err.request) { + // // The client never received a response, and the request was never left + // } else { + // // Anything else + // } +// } +}; + +export default { refreshSession } \ No newline at end of file diff --git a/src/services/functions/usersService.ts b/src/services/functions/usersService.ts new file mode 100644 index 0000000..87b4f40 --- /dev/null +++ b/src/services/functions/usersService.ts @@ -0,0 +1,135 @@ +import * as usersRoutes from "../api/users"; + +interface getByIdReturn { + userData?: { + name: string; + lastname: string; + email: string; + phone_number: string; + birth_date: string; + bio: string; + document_type: string; + document: string; + }, + error?: { + errorMessage: string; + } +} + +interface getByIdRes { + status: string; + message: string; + userId?: string; + data: { + name: string; + lastname: string; + email: string; + phone_number: string; + birth_date: string; + bio: string; + document_type: string; + document: string; + }, +} + +const getById = async (userId: string): Promise => { + try { + let res: getByIdRes = await usersRoutes.getById(userId) + + if (res.status === "error") { + return { + error: { + errorMessage: res.message, + } + }; + } + + return { + userData: res.data, + }; + } catch(err) { + return { + error: { + errorMessage: "Por favor, autentique-se.", + } + }; + } +}; + +interface getByIdReturn { + data?: { + phone: '', + whatsapp: '', + facebook: '', + telegram: '', + }, + error?: { + errorMessage: string; + } +} + +const getUserSocialInfo = async (userId: string): Promise => { + try { + let res: getByIdRes = await usersRoutes.getSocialInfo(userId) + + if (res.status === "error") { + return { + error: { + errorMessage: res.message, + } + }; + } + + return { + userData: res.data, + }; + } catch(err) { + return { + error: { + errorMessage: "Por favor, autentique-se.", + } + }; + } +}; + +interface checkIfUserIsDriverReturn { + result?: boolean; + error?: { + errorMessage: string; + } +} + +interface checkIfUserIsDriverResponse { + status: string; + message: string; + result?: boolean; + error?: { + errorMessage: string; + } +} + +const checkIfUserIsDriver = async (id_user: string): Promise => { + try { + let res: checkIfUserIsDriverResponse = await usersRoutes.checkIfUserIsDriver(id_user) + + if (res.status === "error") { + return { + error: { + errorMessage: res.message, + } + }; + } + + return { + result: res.result, + }; + } catch(err) { + return { + error: { + errorMessage: "Por favor, autentique-se.", + } + }; + } +}; + +export default { getById, getUserSocialInfo, checkIfUserIsDriver } \ No newline at end of file diff --git a/src/services/transportes.ts b/src/services/transportes.ts new file mode 100644 index 0000000..7b5eddf --- /dev/null +++ b/src/services/transportes.ts @@ -0,0 +1,34 @@ +import instance from "../services/api/api"; +import { setStore } from "../store/RecordsStore"; +// import LocalStorage from '../LocalStorage'; + +// let token:string; +let header: string; + +function updateHeader() { + // token = LocalStorage.getToken(); + header = `{ + "Accept": 'application/json', + "Content-Type": 'application/json', + "Authorization": 'Bearer ' + token + }`; +} + +interface CoordinatesRequest { + coordinatesFrom:{ + lat: number, + lng: number + }, + coordinatesTo:{ + lat: number, + lng: number + } +} + +export async function getTransportes(request: CoordinatesRequest) { + updateHeader(); + + console.log(request) + const response = await instance.post("http://localhost:3333/transportes/", request); + return response.data as []; +} diff --git a/src/services/users.ts b/src/services/users.ts deleted file mode 100644 index 73440e1..0000000 --- a/src/services/users.ts +++ /dev/null @@ -1,45 +0,0 @@ -import instance from '../services/api'; -// import LocalStorage from '../LocalStorage'; - -let token:string; -let header:string; - -function updateHeader() { -// token = LocalStorage.getToken(); - header = `{ - "Accept": 'application/json', - "Content-Type": 'application/json', - "Authorization": 'Bearer ' + token - }` -} - -export interface CadastroResponse { - message?: string; - - token?: { - token: string; - }; - - error?: string; -} - -export interface CadastroRequest { - name: string; - email: string; - birth_date: string; - password: string; -} - -// export async function get(cpf) { -// updateHeader(); - -// const response = await instance.get(userRoutes.get.url + `/${cpf}`, { headers: header }); -// return response.data; -// } - -export async function create(CadastroRequest: any) { - updateHeader(); - - const response = await instance.post("http://localhost:3333/users/", CadastroRequest); - return response.data; -} \ No newline at end of file diff --git a/src/services/utils.ts b/src/services/utils.ts new file mode 100644 index 0000000..8827557 --- /dev/null +++ b/src/services/utils.ts @@ -0,0 +1,7 @@ +import instance from '../services/api/api'; + +export async function autoCompleteAddress(address:string) { + + const response = await instance.get(`https://api.geoapify.com/v1/geocode/autocomplete?text=${address}&apiKey=ee574aacff6f440a84378bbbf7e2f20d`); + return response.data.features; +} \ No newline at end of file diff --git a/src/services/validateCpf.ts b/src/services/validateCpf.ts new file mode 100644 index 0000000..d713b68 --- /dev/null +++ b/src/services/validateCpf.ts @@ -0,0 +1,25 @@ +export default function validateCpf(cpf: string): Boolean { + let soma = 0, resto; + + if (cpf === "00000000000") return false; + + for (let i = 1; i <= 9; i++) + soma = soma + parseInt(cpf.substring(i - 1, i)) * (11 - i); + + resto = (soma * 10) % 11; + + if (resto === 10 || resto === 11) resto = 0; + if (resto !== parseInt(cpf.substring(9, 10))) return false; + + soma = 0; + for (let i = 1; i <= 10; i++) + soma = soma + parseInt(cpf.substring(i - 1, i)) * (12 - i); + + resto = (soma * 10) % 11; + + if (resto === 10 || resto === 11) resto = 0; + + if (resto !== parseInt(cpf.substring(10, 11))) return false; + + return true; +}; \ No newline at end of file diff --git a/src/store/RecordsStore.js b/src/store/RecordsStore.js new file mode 100644 index 0000000..76a9ae9 --- /dev/null +++ b/src/store/RecordsStore.js @@ -0,0 +1,14 @@ +import { Store } from 'pullstate'; + +const RecordsStore = new Store({ + + records: [], + center : [] +}); + +export default RecordsStore; + +export const setStore = records => { + RecordsStore.update(state => { state.records = records.allRecords }); + RecordsStore.update(state => { state.center = records.center }); +} \ No newline at end of file diff --git a/src/store/Selectors.js b/src/store/Selectors.js new file mode 100644 index 0000000..c83e9f6 --- /dev/null +++ b/src/store/Selectors.js @@ -0,0 +1,15 @@ +import { createSelector } from 'reselect'; + +const getState = state => state; + +// General getters +export const fetchRecords = createSelector(getState, state => state.records); + +// More specific getters +export const fetchRecord = recordId => createSelector(getState, state => { + + return state.records.filter(record => record.id === recordId)[0]; +}); +// export const getPoll = pollId => createSelector(getState, state => state.polls.filter(poll => poll.id === parseInt(pollId))[0]); +// export const getChat = contactId => createSelector(getState, state => state.chats.filter(c => parseInt(c.contact_id) === parseInt(contactId))[0].chats); +// export const getContact = contactId => createSelector(getState, state => state.contacts.filter(c => parseInt(c.id) === parseInt(contactId))[0]);