Merge branch 'master' of https://github.com/CloudAlb/tcc-vamos-frontend into feature/buscar-transporte
This commit is contained in:
12
mock/db.json
Normal file
12
mock/db.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"cadastro-van": [
|
||||
{
|
||||
"id": 1,
|
||||
"placa": "DBE2356",
|
||||
"marca": "Fiat",
|
||||
"modelo": "Ducatto",
|
||||
"numPassageiros": 14,
|
||||
"alugado": false
|
||||
}
|
||||
]
|
||||
}
|
||||
231
package-lock.json
generated
231
package-lock.json
generated
@@ -14,6 +14,7 @@
|
||||
"@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",
|
||||
@@ -29,6 +30,7 @@
|
||||
"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-hook-form": "^7.30.0",
|
||||
@@ -48,11 +50,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"
|
||||
}
|
||||
},
|
||||
@@ -2404,6 +2408,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",
|
||||
@@ -2419,35 +2431,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",
|
||||
@@ -2477,6 +2470,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",
|
||||
@@ -3172,6 +3187,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"
|
||||
},
|
||||
@@ -3832,6 +3848,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",
|
||||
@@ -10660,12 +10690,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",
|
||||
@@ -11063,6 +11103,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",
|
||||
@@ -13062,6 +13107,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",
|
||||
@@ -15130,6 +15180,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",
|
||||
@@ -16675,6 +16730,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": {
|
||||
@@ -18320,6 +18392,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",
|
||||
@@ -18332,30 +18410,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": {
|
||||
@@ -18368,6 +18430,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",
|
||||
@@ -18901,7 +18980,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",
|
||||
@@ -19413,6 +19493,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",
|
||||
@@ -24584,12 +24678,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",
|
||||
@@ -24897,6 +25001,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",
|
||||
@@ -26258,6 +26367,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",
|
||||
@@ -27836,6 +27950,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",
|
||||
@@ -29095,6 +29214,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": {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"@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",
|
||||
@@ -24,6 +25,7 @@
|
||||
"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",
|
||||
@@ -44,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"
|
||||
@@ -73,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"
|
||||
|
||||
104
src/App.tsx
104
src/App.tsx
@@ -1,15 +1,26 @@
|
||||
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/Cadastro';
|
||||
import MainPages from './pages/MainPages';
|
||||
|
||||
// importação das páginas
|
||||
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';
|
||||
|
||||
/* Core CSS required for Ionic components to work properly */
|
||||
import '@ionic/react/css/core.css';
|
||||
@@ -33,27 +44,86 @@ import BuscarPassageiro from './pages/BuscarPassageiro/BuscarPassageiro';
|
||||
import Transportes from './pages/Transportes/Transportes';
|
||||
import BuscarTransporte from './pages/BuscarTransporte/BuscarTransporte';
|
||||
// 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 = (
|
||||
<>
|
||||
<Route exact path="/cadastro" component={Cadastro}></Route>
|
||||
<Route exact path="/login" component={Login}></Route>
|
||||
|
||||
<Route exact path="/home" component={Home}></Route>
|
||||
|
||||
<Route exact path="/perfil" component={Perfil}></Route>
|
||||
<Route exact path="/perfil/editar" component={PerfilEditar}></Route>
|
||||
<Route exact path="/perfil/completar" component={CadastroCompletar}></Route>
|
||||
<Route exact path="/perfil/completar/documento" component={CompletarDocumento}></Route>
|
||||
<Route exact path="/perfil/completar/telefone" component={CompletarTelefone}></Route>
|
||||
|
||||
<Route exact path="/usuario/:id" component={Perfil}></Route>
|
||||
|
||||
<Route exact path="/cadastro-van" component={CadastroVan}></Route>
|
||||
<Route exact path="/minhas-vans" component={MinhasVans}></Route>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/login" />
|
||||
</Route>
|
||||
</>)
|
||||
|
||||
interface IUserManager {
|
||||
setIsLoggedIn: Function;
|
||||
}
|
||||
|
||||
const user: IUserManager = {
|
||||
setIsLoggedIn: () => {}
|
||||
};
|
||||
|
||||
export const UserContext = React.createContext<IUserManager>(user);
|
||||
|
||||
const IonicApp: React.FC = () => {
|
||||
|
||||
const [isLoggedIn, setIsLoggedIn] = useState(false);
|
||||
const user = useContext(UserContext);
|
||||
|
||||
user.setIsLoggedIn = setIsLoggedIn;
|
||||
|
||||
return(
|
||||
<IonApp>
|
||||
<IonReactRouter>
|
||||
{isLoggedIn ? (
|
||||
<IonTabs>
|
||||
<IonRouterOutlet>{routes}</IonRouterOutlet>
|
||||
|
||||
<IonRouterOutlet>
|
||||
<Route exact path="/mainpages" component={MainPages}></Route>
|
||||
<Route exact path="/cadastro" component={Cadastro}></Route>
|
||||
<Route exact path="/login" component={Login}></Route>
|
||||
<Route exact path="/buscar-passageiro" component={BuscarPassageiro}></Route>
|
||||
{/* <Route exact path="/buscar-transporte" component={BuscarTransporte}></Route> */}
|
||||
<Route exact path="/transportes" component={Transportes}></Route>
|
||||
<Route exact path="/">
|
||||
<Redirect to="/mainpages" />
|
||||
</Route>
|
||||
</IonRouterOutlet>
|
||||
|
||||
</IonReactRouter>
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="buscar" href="/buscar">
|
||||
<IonIcon icon={search} />
|
||||
<IonLabel>Buscar</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="home" href="/home">
|
||||
<IonIcon icon={home} />
|
||||
<IonLabel>Home</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="perfil" href="/perfil">
|
||||
<IonIcon icon={person} />
|
||||
<IonLabel>Perfil</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
) : (<IonRouterOutlet>{routes}</IonRouterOutlet>)}
|
||||
</IonReactRouter>
|
||||
</IonApp>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
const App: React.FC = () => {
|
||||
return (
|
||||
<UserContext.Provider value={user}>
|
||||
<IonicApp />
|
||||
</UserContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
@@ -2,16 +2,22 @@ const tokenId = 'token';
|
||||
const productDetails = '@productDetails';
|
||||
|
||||
const LocalStorage = {
|
||||
getToken: (): string | null => {
|
||||
return localStorage.getItem(tokenId)
|
||||
getToken: (): string => {
|
||||
const tokenId = localStorage.getItem('tokenId')
|
||||
|
||||
if (!tokenId) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return tokenId
|
||||
},
|
||||
|
||||
setToken: (token: string) => {
|
||||
localStorage.setItem(tokenId, token)
|
||||
localStorage.setItem('tokenId', token)
|
||||
},
|
||||
|
||||
clearToken: () => {
|
||||
localStorage.setItem(tokenId, '');
|
||||
localStorage.removeItem('tokenId')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,8 @@ export const Action = (props: ComponentProps) => (
|
||||
|
||||
<IonRow className="ion-text-center ion-justify-content-center">
|
||||
<IonCol size="12">
|
||||
<p>
|
||||
{ props.message }
|
||||
<IonRouterLink className="custom-link" routerLink={ props.link }> { props.text } →</IonRouterLink>
|
||||
</p>
|
||||
{ props.message }
|
||||
<IonRouterLink className="custom-link" routerLink={ props.link }> { props.text } →</IonRouterLink>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
);
|
||||
8
src/constants/routes/carsRoutes.ts
Normal file
8
src/constants/routes/carsRoutes.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
const carsRoutesDefault = '/cars';
|
||||
const carsRoutes = {
|
||||
list: {
|
||||
url: `${carsRoutesDefault}/list`
|
||||
}
|
||||
}
|
||||
|
||||
export default carsRoutes;
|
||||
20
src/constants/routes/usersRoutes.ts
Normal file
20
src/constants/routes/usersRoutes.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
const usersRoutesDefault = '/users';
|
||||
const usersRoutes = {
|
||||
create: {
|
||||
url: `${usersRoutesDefault}`
|
||||
},
|
||||
get: {
|
||||
url: `${usersRoutesDefault}`
|
||||
},
|
||||
update: {
|
||||
url: `${usersRoutesDefault}/edit`
|
||||
},
|
||||
checkIfUserIsDriver: {
|
||||
url: `${usersRoutesDefault}/isDriver`
|
||||
},
|
||||
getSocialInfo: {
|
||||
url: `${usersRoutesDefault}/social`
|
||||
}
|
||||
}
|
||||
|
||||
export default usersRoutes;
|
||||
17
src/constants/routes/vansLocatorsRoutes.ts
Normal file
17
src/constants/routes/vansLocatorsRoutes.ts
Normal file
@@ -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;
|
||||
20
src/constants/routes/vansRoutes.ts
Normal file
20
src/constants/routes/vansRoutes.ts
Normal file
@@ -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;
|
||||
8
src/models/van.model.ts
Normal file
8
src/models/van.model.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export type Van = {
|
||||
id: number;
|
||||
carPlate: string;
|
||||
carBrand: string;
|
||||
carModel: string;
|
||||
maxPassengers: number;
|
||||
isRent: string;
|
||||
};
|
||||
@@ -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 { 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 * 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<Color>("primary");
|
||||
|
||||
const [email, setEmail] = useState<string>('');
|
||||
const [password, setPassword] = useState<string>('');
|
||||
@@ -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 = () => {
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton text={''} icon={arrowBack} defaultHref='mainpages' />
|
||||
<IonBackButton text={''} icon={arrowBack} defaultHref='login' />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonGrid className="ion-padding">
|
||||
<IonRow>
|
||||
<IonCol size="12">
|
||||
{/* <IonCardTitle>Como você deseja se cadastrar?</IonCardTitle> */}
|
||||
<IonCardTitle>Cadastro</IonCardTitle>
|
||||
</IonCol>
|
||||
<IonCol size="12">
|
||||
{/* <IonCardTitle>Como você deseja se cadastrar?</IonCardTitle> */}
|
||||
<IonCardTitle>Cadastro</IonCardTitle>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
{/* <IonItem>
|
||||
<IonIcon icon={logoFacebook} />
|
||||
Continuar com Facebook
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonIcon icon={mail} />
|
||||
Continuar com e-mail
|
||||
</IonItem> */}
|
||||
<IonRow>
|
||||
<IonCol size="12">
|
||||
<div id='nome-sobrenome'>
|
||||
@@ -151,7 +161,7 @@ const Cadastro: React.FC = () => {
|
||||
<IonLabel position='floating'>Sobrenome</IonLabel>
|
||||
<IonInput
|
||||
clearInput
|
||||
onIonInput={(e: any) => setLastName(e.target.value)}
|
||||
onIonChange={(e: any) => setLastName(e.target.value)}
|
||||
>
|
||||
</IonInput>
|
||||
</IonItem>
|
||||
@@ -162,7 +172,7 @@ const Cadastro: React.FC = () => {
|
||||
<IonInput
|
||||
clearInput
|
||||
type='email'
|
||||
onIonInput={(e: any) => setEmail(e.target.value)}
|
||||
onIonChange={(e: any) => setEmail(e.target.value)}
|
||||
>
|
||||
</IonInput>
|
||||
</IonItem>
|
||||
@@ -171,7 +181,7 @@ const Cadastro: React.FC = () => {
|
||||
<IonLabel position='stacked'>Data de nascimento</IonLabel>
|
||||
<IonInput
|
||||
type='date'
|
||||
onIonInput={(e: any) => setBirthDate(e.target.value)}
|
||||
onIonChange={(e: any) => setBirthDate(e.target.value)}
|
||||
>
|
||||
</IonInput>
|
||||
</IonItem>
|
||||
@@ -181,7 +191,7 @@ const Cadastro: React.FC = () => {
|
||||
<IonInput
|
||||
clearInput
|
||||
type='password'
|
||||
onIonInput={(e: any) => setPassword(e.target.value)}
|
||||
onIonChange={(e: any) => setPassword(e.target.value)}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
@@ -189,7 +199,7 @@ const Cadastro: React.FC = () => {
|
||||
<IonInput
|
||||
clearInput
|
||||
type='password'
|
||||
onIonInput={(e: any) => setConfirmPassword(e.target.value)}
|
||||
onIonChange={(e: any) => setConfirmPassword(e.target.value)}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
|
||||
@@ -202,9 +212,9 @@ const Cadastro: React.FC = () => {
|
||||
<Action message="Já tem conta?" text="Login" link="/login" />
|
||||
</IonGrid>
|
||||
{/* <IonProgressBar type="indeterminate"></IonProgressBar><br /> */}
|
||||
|
||||
<IonToast
|
||||
// cssClass={"toast-notification"}
|
||||
color='danger'
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={messageToast}
|
||||
|
||||
142
src/pages/CadastroCompletar/CadastroCompletar.tsx
Normal file
142
src/pages/CadastroCompletar/CadastroCompletar.tsx
Normal file
@@ -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<LocationState>();
|
||||
|
||||
const [showToast, setShowToast] = useState(false);
|
||||
const [toastMessage, setToastMessage] = useState('');
|
||||
const [toastColor, setToastColor] = useState<Color>("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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Completar cadastro</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/perfil" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
{ items.map((item, index) => {
|
||||
return (
|
||||
<IonCard button={item.required} key={index} onClick={() => { handleCardClick(item) }}>
|
||||
<IonItem>
|
||||
<IonIcon icon={item.icon} slot="start" />
|
||||
<IonLabel>{item.label}</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonCardContent>{item.description}</IonCardContent>
|
||||
</IonCard>
|
||||
)
|
||||
})}
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={toastMessage}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default CadastroCompletar;
|
||||
219
src/pages/CadastroCompletar/CompletarDocumento.tsx
Normal file
219
src/pages/CadastroCompletar/CompletarDocumento.tsx
Normal file
@@ -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<LocationState>();
|
||||
|
||||
const [hasChangedSinceInitialState, setHasChangedSinceInitialState] = useState(false);
|
||||
|
||||
const [documentTypes, setDocumentTypes] = useState<documentTypesInterface[]>([]);
|
||||
|
||||
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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Completar cadastro</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/perfil/completar" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Completar cadastro</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonGrid>
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<IonList lines="full" class="ion-no-margin">
|
||||
<IonItem>
|
||||
<IonLabel position="floating"> Tipo de documento</IonLabel>
|
||||
<IonSelect id="document_type" onIonChange={(e: any) => { handleChangeDocumentType(e.detail.value) } }>
|
||||
{ documentTypes ? documentTypes.map((document, index) => {
|
||||
return (<IonSelectOption key={index} value={document.name}>{document.label}</IonSelectOption>)
|
||||
}) : <></> }
|
||||
</IonSelect>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position="floating"> Documento</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={document}
|
||||
maxlength={documentMaxLength}
|
||||
onIonChange={(e: any) => { setDocument(e.target.value); setHasChangedSinceInitialState(true) }}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
|
||||
<IonFab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<IonFabButton disabled={!hasChangedSinceInitialState} onClick={handleUpdateUserDocuments}>
|
||||
<IonIcon icon={saveOutline} />
|
||||
</IonFabButton>
|
||||
</IonFab>
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color='danger'
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={messageToast}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompletarDocumento;
|
||||
|
||||
169
src/pages/CadastroCompletar/CompletarTelefone.tsx
Normal file
169
src/pages/CadastroCompletar/CompletarTelefone.tsx
Normal file
@@ -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<LocationState>();
|
||||
|
||||
const [hasChangedSinceInitialState, setHasChangedSinceInitialState] = useState(false);
|
||||
|
||||
const [phone, setPhone] = useState('');
|
||||
|
||||
const [showToast, setShowToast] = useState(false);
|
||||
const [messageToast, setMessageToast] = useState('');
|
||||
const [toastColor, setToastColor] = useState<Color>("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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Completar cadastro</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/perfil/completar" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Completar cadastro</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonGrid>
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<IonList lines="full" class="ion-no-margin">
|
||||
<IonItem>
|
||||
<IonLabel position="floating"> Telefone</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={phone}
|
||||
maxlength={11}
|
||||
onIonChange={(e: any) => { setPhone(e.target.value); setHasChangedSinceInitialState(true) }}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
|
||||
<IonFab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<IonFabButton disabled={!hasChangedSinceInitialState} onClick={handleUpdateUserDocuments}>
|
||||
<IonIcon icon={saveOutline} />
|
||||
</IonFabButton>
|
||||
</IonFab>
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={messageToast}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompletarTelefone;
|
||||
|
||||
0
src/pages/CadastroVan.css
Normal file
0
src/pages/CadastroVan.css
Normal file
355
src/pages/CadastroVan.tsx
Normal file
355
src/pages/CadastroVan.tsx
Normal file
@@ -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<boolean>(false);
|
||||
const [toastMessage, setToastMessage] = useState<string>("");
|
||||
const [toastColor, setToastColor] = useState<Color>("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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Cadastro de veículo</IonTitle>
|
||||
<IonButtons slot='start'>
|
||||
<IonBackButton defaultHref='/perfil' />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
<IonList lines="full" class="ion-no-margin">
|
||||
<IonListHeader lines="full">
|
||||
<IonLabel>Informações do veículo</IonLabel>
|
||||
</IonListHeader>
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Placa </IonLabel>
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
maxlength={7}
|
||||
placeholder='Digite a Placa do Veículo'
|
||||
onIonChange={(e: any) => setInputValues({ carPlate: e.target.value })}
|
||||
/>
|
||||
</IonItem>
|
||||
|
||||
{/* TODO, problema de setState para valores vindos de um evento sendo triggerado por um ion-select */}
|
||||
<IonItem>
|
||||
<IonLabel>Marca</IonLabel>
|
||||
<IonSelect onIonChange={(e: any) => { setInputValues({ carBrand: e.detail.value }) }}>
|
||||
{ carModels ? carModels.map((carModel, index) => {
|
||||
return (<IonSelectOption key={index} value={carModel.name}>{carModel.name}</IonSelectOption>)
|
||||
}) : <></> }
|
||||
</IonSelect>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Modelo </IonLabel>
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Digite o Modelo do Veículo'
|
||||
onIonChange={(e: any) => setInputValues({ carModel: e.target.value })}
|
||||
/>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>
|
||||
Número de assentos
|
||||
</IonLabel>
|
||||
<IonInput
|
||||
type='number'
|
||||
min={1}
|
||||
clearInput
|
||||
placeholder='podem ser ocupados por passageiros'
|
||||
onIonChange={(e: any) => setInputValues({ seats_number: e.target.value })}
|
||||
/>
|
||||
</IonItem>
|
||||
</IonList>
|
||||
|
||||
<IonList lines="full" class="ion-no-margin">
|
||||
<IonListHeader lines="full">
|
||||
<IonLabel>Informações do locador</IonLabel>
|
||||
</IonListHeader>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel>O veículo é alugado?</IonLabel>
|
||||
<IonCheckbox checked={inputValues.isRented} onIonChange={e => setInputValues({ isRented: e.detail.checked })} />
|
||||
</IonItem>
|
||||
|
||||
{inputValues.isRented && (
|
||||
<div>
|
||||
<IonItem>
|
||||
<IonLabel position="stacked" />
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Nome completo do Locador'
|
||||
onIonChange={(e: any) => setInputValues({ locator_name: e.target.value })}
|
||||
/>
|
||||
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Endereço do locador'
|
||||
onIonChange={(e: any) => setInputValues({ locator_address: e.target.value })}
|
||||
/>
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Complemento'
|
||||
onIonChange={(e: any) => setInputValues({ locator_complement: e.target.value })}
|
||||
/>
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Cidade'
|
||||
onIonChange={(e: any) => setInputValues({ locator_city: e.target.value })}
|
||||
/>
|
||||
<IonInput
|
||||
type='text'
|
||||
clearInput
|
||||
placeholder='Estado'
|
||||
onIonChange={(e: any) => setInputValues({ locator_state: e.target.value })}
|
||||
/>
|
||||
</IonItem>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<IonButton
|
||||
className='ion-margin-top'
|
||||
expand='block'
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
Salvar
|
||||
</IonButton>
|
||||
</div>
|
||||
</IonList>
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={toastMessage}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default CadastroVan;
|
||||
@@ -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<LocationState>();
|
||||
|
||||
const user = useContext(UserContext);
|
||||
|
||||
const [showToast, setShowToast] = useState(false);
|
||||
const [toastMessage, setToastMessage] = useState('');
|
||||
const [toastColor, setToastColor] = useState<Color>("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 (
|
||||
<IonPage>
|
||||
<IonContent fullscreen>
|
||||
<IonGrid className="ion-padding">
|
||||
<IonRow>
|
||||
<IonCol size="12">
|
||||
<IonCardTitle>Como você deseja se cadastrar?</IonCardTitle>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
<IonRow>
|
||||
<IonCol size="12">
|
||||
<div id='nome-sobrenome'>
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Nome</IonLabel>
|
||||
<IonInput clearInput></IonInput>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Sobrenome</IonLabel>
|
||||
<IonInput clearInput></IonInput>
|
||||
</IonItem>
|
||||
</div>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>E-mail</IonLabel>
|
||||
<IonInput clearInput type='email'></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='stacked'>Data de nascimento</IonLabel>
|
||||
<IonInput type='date'></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Senha</IonLabel>
|
||||
<IonInput clearInput type='password'></IonInput>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonLabel position='floating'>Confirme a senha</IonLabel>
|
||||
<IonInput clearInput type='password'></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonButton className="ion-margin-top" expand="block">Cadastrar-se</IonButton>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
<small className='ion-margin-top'>
|
||||
Ao se cadastrar, você aceita nossos <a href="">Termos e Condições</a> e nossa <a href=""> Política de Privacidade</a>.
|
||||
</small>
|
||||
<Action message="Já tem conta?" text="Login" link="/login" />
|
||||
</IonGrid>
|
||||
<IonContent>
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={toastMessage}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
|
||||
@@ -5,35 +5,34 @@ import {
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
} from "@ionic/react";
|
||||
import React, { useState } from "react";
|
||||
import React, { useContext, useState } from "react";
|
||||
import { IonGrid, IonRow, IonCol, IonToast } from "@ionic/react";
|
||||
import { personCircle } from "ionicons/icons";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import {
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonInput,
|
||||
IonButton,
|
||||
IonIcon,
|
||||
IonAlert,
|
||||
} from "@ionic/react";
|
||||
|
||||
import * as sessionRoutes from '../services/session';
|
||||
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<string>("matheusalb3213@gmail.com");
|
||||
const [password, setPassword] = useState<string>("123456");
|
||||
const [isError, setIsError] = useState<boolean>(false);
|
||||
const [message, setMessage] = useState<string>("");
|
||||
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());
|
||||
}
|
||||
@@ -88,7 +87,13 @@ const Page: React.FC = () => {
|
||||
|
||||
LocalStorage.setToken(token);
|
||||
|
||||
history.push({ pathname: '/home' });
|
||||
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
|
||||
|
||||
@@ -107,15 +112,6 @@ const Page: React.FC = () => {
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<IonIcon
|
||||
style={{ fontSize: "70px", color: "#0040ff" }}
|
||||
icon={personCircle}
|
||||
/>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
@@ -124,19 +120,6 @@ const Page: React.FC = () => {
|
||||
</IonHeader>
|
||||
|
||||
<IonGrid>
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<IonAlert
|
||||
isOpen={isError}
|
||||
onDidDismiss={() => setIsError(false)}
|
||||
cssClass="my-custom-class"
|
||||
header={"Error!"}
|
||||
message={message}
|
||||
buttons={["Dismiss"]}
|
||||
/>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<IonItem>
|
||||
@@ -165,10 +148,6 @@ const Page: React.FC = () => {
|
||||
|
||||
<IonRow>
|
||||
<IonCol>
|
||||
<p style={{ fontSize: "small" }}>
|
||||
Clicando no botão de "Login", você concorda com a nossa{" "}
|
||||
<a href="#">política de termos e serviços</a>
|
||||
</p>
|
||||
<IonButton expand="block" onClick={handleLogin}>
|
||||
Login
|
||||
</IonButton>
|
||||
@@ -180,7 +159,7 @@ const Page: React.FC = () => {
|
||||
</IonGrid>
|
||||
|
||||
<IonToast
|
||||
// cssClass={"toast-notification"}
|
||||
position="top"
|
||||
color='danger'
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
|
||||
118
src/pages/MinhasVans.tsx
Normal file
118
src/pages/MinhasVans.tsx
Normal file
@@ -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<Color>("primary");
|
||||
|
||||
const [userVans, setUserVans] = useState<VanInfo[]>();
|
||||
|
||||
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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Minhas vans</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/perfil" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
{ userVans ? userVans.map((van, index) => {
|
||||
return (
|
||||
<IonCard key={index}>
|
||||
<IonCardHeader>
|
||||
<IonCardTitle>{van.plate}</IonCardTitle>
|
||||
<IonCardSubtitle>{van.brand} - {van.model}</IonCardSubtitle>
|
||||
</IonCardHeader>
|
||||
{ van.locator_name ?
|
||||
<>
|
||||
<IonCardContent>{van.seats_number} assentos - Locador: {van.locator_name}</IonCardContent>
|
||||
</> :
|
||||
<>
|
||||
<IonCardContent>{van.seats_number} assentos - Não é alugado</IonCardContent>
|
||||
</>
|
||||
}
|
||||
</IonCard>
|
||||
)
|
||||
}) : <></>}
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={toastMessage}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default MinhasVans;
|
||||
16
src/pages/Perfil.css
Normal file
16
src/pages/Perfil.css
Normal file
@@ -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;
|
||||
}
|
||||
328
src/pages/Perfil.tsx
Normal file
328
src/pages/Perfil.tsx
Normal file
@@ -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<ScanNewProps> = (props) => {
|
||||
const user = useContext(UserContext);
|
||||
|
||||
const history = useHistory();
|
||||
const location = useLocation<LocationState>();
|
||||
|
||||
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<Color>("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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Seu perfil</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/home" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Seu perfil</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonCard>
|
||||
<IonCardContent>
|
||||
<img src="https://static.generated.photos/vue-static/home/feed/adult.png" alt="avatar" className='avatar' id='avatar'/>
|
||||
{/* <img src="https://lastfm.freetls.fastly.net/i/u/avatar170s/faa68f71f3b2a48ca89228c2c2aa72d3" alt="avatar" className='avatar' id='avatar'/> */}
|
||||
<IonCardHeader>
|
||||
<IonCardTitle class="ion-text-center">{inputValues.name} {inputValues.lastname}</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
|
||||
<div id='profile-status'>
|
||||
{ isDriver ?
|
||||
<>
|
||||
<IonChip>
|
||||
<IonIcon icon={carOutline}></IonIcon>
|
||||
<IonLabel color="primary">Motorista</IonLabel>
|
||||
</IonChip>
|
||||
</> : <></>
|
||||
}
|
||||
<IonChip>
|
||||
<IonIcon icon={personOutline}></IonIcon>
|
||||
<IonLabel color="primary">Passageiro</IonLabel>
|
||||
</IonChip>
|
||||
</div>
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardTitle>Biografia</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
<IonCardContent>
|
||||
{inputValues.bio ? inputValues.bio : 'Sem biografia.' }
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardTitle>Informações de contato</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
<IonCardContent>
|
||||
{ !inputValues.phone_number ?
|
||||
<>Sem informações de contato.</>
|
||||
: <>
|
||||
{
|
||||
inputValues.phone_number ?
|
||||
<>
|
||||
<IonChip>
|
||||
<IonIcon icon={callOutline} />
|
||||
<IonLabel>{inputValues.phone_number}</IonLabel>
|
||||
</IonChip>
|
||||
</> : <></>
|
||||
}
|
||||
</>
|
||||
}
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
|
||||
{ !isVisitor ?
|
||||
<IonList>
|
||||
<IonListHeader>Configurações</IonListHeader>
|
||||
<IonItem button onClick={() => history.push({ pathname: '/perfil/editar', state: { userData: inputValues } })}>
|
||||
<IonIcon icon={createOutline} slot="start" />
|
||||
<IonLabel>Editar perfil</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
{ incompleteProfile ?
|
||||
<>
|
||||
<IonItem button onClick={() => history.push({ pathname: '/perfil/completar', state: { userData: inputValues } })}>
|
||||
<IonIcon icon={shieldCheckmarkOutline} slot="start" />
|
||||
<IonLabel>Completar cadastro</IonLabel>
|
||||
<IonBadge color="primary">{incompleteProfileCounter}</IonBadge>
|
||||
</IonItem>
|
||||
</>
|
||||
: <></> }
|
||||
|
||||
<IonItem button onClick={() => history.push({ pathname: '/cadastro-van'})}>
|
||||
<IonIcon icon={carOutline} slot="start" />
|
||||
<IonLabel>Cadastrar Van</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem button onClick={() => history.push({ pathname: '/minhas-vans'})}>
|
||||
<IonIcon icon={carOutline} slot="start" />
|
||||
<IonLabel>Minhas Vans</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonIcon icon={cardOutline} slot="start" />
|
||||
<IonLabel>Pagamentos</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem>
|
||||
<IonIcon icon={starOutline} slot="start" />
|
||||
<IonLabel>Avaliações</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem button onClick={logoff}>
|
||||
<IonIcon icon={exitOutline} slot="start" />
|
||||
<IonLabel>Sair da conta</IonLabel>
|
||||
</IonItem>
|
||||
</IonList> : <></>
|
||||
}
|
||||
|
||||
<IonToast
|
||||
position="top"
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={toastMessage}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Perfil;
|
||||
200
src/pages/PerfilEditar.tsx
Normal file
200
src/pages/PerfilEditar.tsx
Normal file
@@ -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<LocationState>();
|
||||
|
||||
const [showToast, setShowToast] = useState(false);
|
||||
const [messageToast, setMessageToast] = useState('');
|
||||
const [toastColor, setToastColor] = useState<Color>("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 (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Editar perfil</IonTitle>
|
||||
<IonButtons slot="start">
|
||||
<IonBackButton defaultHref="/perfil" />
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonContent>
|
||||
<IonGrid>
|
||||
<IonRow>
|
||||
<IonCol size="12">
|
||||
<div id='nome-sobrenome'>
|
||||
<IonItem>
|
||||
<IonLabel position="stacked"> Nome</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={inputValues.name}
|
||||
onIonChange={(e) => setInputValues({'name': e.detail.value!})}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position="stacked"> Sobrenome</IonLabel>
|
||||
<IonInput
|
||||
type="text"
|
||||
value={inputValues.lastname}
|
||||
onIonChange={(e) => setInputValues({'lastname': e.detail.value!})}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
</div>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position="stacked"> Email</IonLabel>
|
||||
<IonInput
|
||||
type="email"
|
||||
value={inputValues.email}
|
||||
onIonChange={(e) => setInputValues({'email': e.detail.value!})}
|
||||
></IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position='stacked'>Data de nascimento</IonLabel>
|
||||
<IonInput
|
||||
type='date'
|
||||
value={inputValues.birth_date}
|
||||
onIonInput={(e: any) => setInputValues({'birth_date': e.detail.value!})}
|
||||
>
|
||||
</IonInput>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonLabel position="stacked"> Biografia</IonLabel>
|
||||
<IonTextarea
|
||||
value={inputValues.bio}
|
||||
onIonChange={(e) => setInputValues({'bio': e.detail.value!})}
|
||||
></IonTextarea>
|
||||
</IonItem>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
|
||||
<IonFab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<IonFabButton disabled={hasChangedSinceInitialState()} onClick={handleUpdateUserData}>
|
||||
<IonIcon icon={saveOutline} />
|
||||
</IonFabButton>
|
||||
</IonFab>
|
||||
|
||||
<IonToast
|
||||
color={toastColor}
|
||||
isOpen={showToast}
|
||||
onDidDismiss={() => setShowToast(false)}
|
||||
message={messageToast}
|
||||
duration={2500}
|
||||
/>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default PerfilEditar;
|
||||
18
src/services/api-client.service.ts
Normal file
18
src/services/api-client.service.ts
Normal file
@@ -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<any> {
|
||||
return await this.api
|
||||
.post(url, body)
|
||||
.then(res => {
|
||||
console.log(res.data);
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -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(),
|
||||
25
src/services/api/cars.ts
Normal file
25
src/services/api/cars.ts
Normal file
@@ -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;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import instance from '../services/api';
|
||||
import sessionRoutes from '../constants/routes/sessionRoutes';
|
||||
import LocalStorage from '../LocalStorage';
|
||||
import instance from './api';
|
||||
import sessionRoutes from '../../constants/routes/sessionRoutes';
|
||||
import LocalStorage from '../../LocalStorage';
|
||||
import { AxiosRequestHeaders } from 'axios';
|
||||
|
||||
let token: string | null;
|
||||
@@ -14,8 +14,8 @@ interface createData {
|
||||
function updateHeader() {
|
||||
token = LocalStorage.getToken();
|
||||
header = {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
"Accept": 'application/json',
|
||||
"Content-Type": 'application/json',
|
||||
"Authorization": 'Bearer ' + token
|
||||
}
|
||||
}
|
||||
89
src/services/api/users.ts
Normal file
89
src/services/api/users.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import instance from './api';
|
||||
// import LocalStorage from '../LocalStorage';
|
||||
|
||||
import userRoutes from '../../constants/routes/usersRoutes';
|
||||
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 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;
|
||||
}
|
||||
73
src/services/api/vans.ts
Normal file
73
src/services/api/vans.ts
Normal file
@@ -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;
|
||||
}
|
||||
51
src/services/functions/carsService.ts
Normal file
51
src/services/functions/carsService.ts
Normal file
@@ -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<getAllCarModelsReturn> => {
|
||||
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 };
|
||||
46
src/services/functions/sessionsService.ts
Normal file
46
src/services/functions/sessionsService.ts
Normal file
@@ -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<refreshSessionReturn> => {
|
||||
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 }
|
||||
135
src/services/functions/usersService.ts
Normal file
135
src/services/functions/usersService.ts
Normal file
@@ -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<getByIdReturn> => {
|
||||
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<getByIdReturn> => {
|
||||
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<checkIfUserIsDriverReturn> => {
|
||||
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 }
|
||||
@@ -1,65 +0,0 @@
|
||||
import instance from '../services/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
|
||||
}`
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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("http://localhost:3333/search/inraio", 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("http://localhost:3333/search/", { latitude_from, longitude_from, addres_to });
|
||||
|
||||
console.log(response)
|
||||
setStore(response);
|
||||
}
|
||||
25
src/services/validateCpf.ts
Normal file
25
src/services/validateCpf.ts
Normal file
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user