From 6d02069ae7ea7d3067006d6c9db154628f5038de Mon Sep 17 00:00:00 2001 From: Byancaam Date: Sat, 16 Apr 2022 20:03:41 -0300 Subject: [PATCH 1/3] Estrutura inicial para cadastro das vans --- mock/db.json | 12 ++++ package.json | 1 + src/App.tsx | 2 + src/models/van.model.ts | 7 ++ src/pages/Vans.css | 0 src/pages/Vans.tsx | 155 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 177 insertions(+) create mode 100644 mock/db.json create mode 100644 src/models/van.model.ts create mode 100644 src/pages/Vans.css create mode 100644 src/pages/Vans.tsx diff --git a/mock/db.json b/mock/db.json new file mode 100644 index 0000000..0838572 --- /dev/null +++ b/mock/db.json @@ -0,0 +1,12 @@ +{ + "cadastro-van":[ + { + "id": 1, + "placa": "DBE2356", + "marca": "Fiat", + "modelo": "Ducatto", + "numPassageiros": 14, + "alugado" : false + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index ad7c9c5..b9cf076 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ }, "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" diff --git a/src/App.tsx b/src/App.tsx index 5b3a726..ce21495 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,6 +6,7 @@ import { } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import Cadastro from './pages/Cadastro'; +import Vans from './pages/Vans'; import MainPages from './pages/MainPages'; /* Core CSS required for Ionic components to work properly */ @@ -36,6 +37,7 @@ const App: React.FC = () => ( + diff --git a/src/models/van.model.ts b/src/models/van.model.ts new file mode 100644 index 0000000..38ca95c --- /dev/null +++ b/src/models/van.model.ts @@ -0,0 +1,7 @@ +export type Van = { + id: number; + placa: string; + modelo: string; + numPassageiros: number; + alugado: boolean +} \ No newline at end of file diff --git a/src/pages/Vans.css b/src/pages/Vans.css new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/Vans.tsx b/src/pages/Vans.tsx new file mode 100644 index 0000000..844e39c --- /dev/null +++ b/src/pages/Vans.tsx @@ -0,0 +1,155 @@ +import { + IonIcon, + IonItem, + IonLabel, + IonInput, + IonBackButton, + IonButton, + IonButtons, + IonCardTitle, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonPage, + IonRow, + IonToolbar, + IonTitle, + IonList, + IonRadioGroup, + IonListHeader, + IonRadio +} from "@ionic/react"; +import { arrowBack } from "ionicons/icons"; +import React, { useState } from "react"; +//import { Van } from "../models/van.model"; +import "./Vans.css"; + +const Vans: React.FC = () => { + // const van: Van; + + const [placa, setPlaca] = useState(""); + const [marca, setMarca] = useState(""); + const [modelo, setModelo] = useState(""); + const [numPassageiros, setNumPassageiros] = useState(""); + const [tipoSelecionado, setTipoSelecionado] = useState("Não"); + + const placaChangeHandle = (event: any) => { + setPlaca(event.target.value); + }; + + const marcaChangeHandle = (event: any) => { + setMarca(event.target.value); + }; + + const modeloChangeHandle = (event: any) => { + setModelo(event.target.value); + }; + + const numPassageirosChangeHandle = (event: any) => { + setNumPassageiros(event.target.value); + }; + + const tipoSelecionadoChangeHandle = (event: any) => { + setTipoSelecionado(event.target.value); + }; + + return ( + + + + + + + Return + + + + + + +
+ Cadastro da Veículo + + + Placa * + setPlaca(e.detail.value!)} + > + + + + Marca * + + + + + Modelo * + + + + + + Digite o número total de passageiros * + + + + + + + + Veículo Alugado ? + + + + Sim + + + + + Não + + + + + + + Salvar + +
+
+
+ ); +}; + +export default Vans; From 87bbb968c248b4658587a12aee175b30a2aab0f7 Mon Sep 17 00:00:00 2001 From: Byancaam Date: Sun, 17 Apr 2022 22:53:11 -0300 Subject: [PATCH 2/3] Ajustes na estrutura do projeto | Tela do cadastro de vans com validacao --- mock/db.json | 4 +- package-lock.json | 56 ++++++++ package.json | 3 + src/App.tsx | 2 +- src/models/van.model.ts | 11 +- src/pages/{Vans.css => CadastroVan.css} | 0 src/pages/CadastroVan.tsx | 178 ++++++++++++++++++++++++ src/pages/Vans.tsx | 155 --------------------- src/services/api-client.service.ts | 18 +++ 9 files changed, 264 insertions(+), 163 deletions(-) rename src/pages/{Vans.css => CadastroVan.css} (100%) create mode 100644 src/pages/CadastroVan.tsx delete mode 100644 src/pages/Vans.tsx create mode 100644 src/services/api-client.service.ts diff --git a/mock/db.json b/mock/db.json index 0838572..6b1251a 100644 --- a/mock/db.json +++ b/mock/db.json @@ -1,12 +1,12 @@ { - "cadastro-van":[ + "cadastro-van": [ { "id": 1, "placa": "DBE2356", "marca": "Fiat", "modelo": "Ducatto", "numPassageiros": 14, - "alugado" : false + "alugado": false } ] } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 650964e..657578e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@capacitor/haptics": "1.1.4", "@capacitor/keyboard": "1.2.2", "@capacitor/status-bar": "1.0.8", + "@hookform/error-message": "^2.0.0", "@ionic/react": "^6.0.0", "@ionic/react-router": "^6.0.0", "@testing-library/jest-dom": "^5.11.9", @@ -24,9 +25,11 @@ "@types/react-dom": "^16.9.10", "@types/react-router": "^5.1.11", "@types/react-router-dom": "^5.1.7", + "axios": "^0.26.1", "ionicons": "^5.4.0", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^5.0.0", @@ -2239,6 +2242,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@hookform/error-message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.0.tgz", + "integrity": "sha512-Y90nHzjgL2MP7GFy75kscdvxrCTjtyxGmOLLxX14nd08OXRIh9lMH/y9Kpdo0p1IPowJBiZMHyueg7p+yrqynQ==", + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0", + "react-hook-form": "^7.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -4549,6 +4562,14 @@ "node": ">=4" } }, + "node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -12339,6 +12360,21 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz", "integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" }, + "node_modules/react-hook-form": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", + "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -16917,6 +16953,12 @@ } } }, + "@hookform/error-message": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@hookform/error-message/-/error-message-2.0.0.tgz", + "integrity": "sha512-Y90nHzjgL2MP7GFy75kscdvxrCTjtyxGmOLLxX14nd08OXRIh9lMH/y9Kpdo0p1IPowJBiZMHyueg7p+yrqynQ==", + "requires": {} + }, "@humanwhocodes/config-array": { "version": "0.9.5", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", @@ -18653,6 +18695,14 @@ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.4.1.tgz", "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==" }, + "axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "requires": { + "follow-redirects": "^1.14.8" + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -24237,6 +24287,12 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.10.tgz", "integrity": "sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA==" }, + "react-hook-form": { + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", + "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "requires": {} + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", diff --git a/package.json b/package.json index b9cf076..d789785 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "@capacitor/haptics": "1.1.4", "@capacitor/keyboard": "1.2.2", "@capacitor/status-bar": "1.0.8", + "@hookform/error-message": "^2.0.0", "@ionic/react": "^6.0.0", "@ionic/react-router": "^6.0.0", "@testing-library/jest-dom": "^5.11.9", @@ -19,9 +20,11 @@ "@types/react-dom": "^16.9.10", "@types/react-router": "^5.1.11", "@types/react-router-dom": "^5.1.7", + "axios": "^0.26.1", "ionicons": "^5.4.0", "react": "^17.0.1", "react-dom": "^17.0.1", + "react-hook-form": "^7.30.0", "react-router": "^5.2.0", "react-router-dom": "^5.2.0", "react-scripts": "^5.0.0", diff --git a/src/App.tsx b/src/App.tsx index ce21495..7716476 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,7 +6,7 @@ import { } from '@ionic/react'; import { IonReactRouter } from '@ionic/react-router'; import Cadastro from './pages/Cadastro'; -import Vans from './pages/Vans'; +import Vans from './pages/CadastroVan'; import MainPages from './pages/MainPages'; /* Core CSS required for Ionic components to work properly */ diff --git a/src/models/van.model.ts b/src/models/van.model.ts index 38ca95c..ae90e2b 100644 --- a/src/models/van.model.ts +++ b/src/models/van.model.ts @@ -1,7 +1,8 @@ export type Van = { id: number; - placa: string; - modelo: string; - numPassageiros: number; - alugado: boolean -} \ No newline at end of file + carPlate: string; + carBrand: string; + carModel: string; + maxPassengers: number; + isRent: string; +}; diff --git a/src/pages/Vans.css b/src/pages/CadastroVan.css similarity index 100% rename from src/pages/Vans.css rename to src/pages/CadastroVan.css diff --git a/src/pages/CadastroVan.tsx b/src/pages/CadastroVan.tsx new file mode 100644 index 0000000..8d83e81 --- /dev/null +++ b/src/pages/CadastroVan.tsx @@ -0,0 +1,178 @@ +import { + IonIcon, + IonItem, + IonLabel, + IonInput, + IonBackButton, + IonButton, + IonButtons, + IonCardTitle, + IonCol, + IonContent, + IonGrid, + IonHeader, + IonPage, + IonRow, + IonToolbar, + IonTitle, + IonText, + IonList, + IonRadioGroup, + IonListHeader, + IonRadio +} from "@ionic/react"; + +import React, { useEffect } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { ErrorMessage } from "@hookform/error-message"; + +import { ApiClient } from "../services/api-client.service"; +import { arrowBack } from "ionicons/icons"; +import "./CadastroVan.css"; + +const CadastroVan: React.FC = () => { + const { + handleSubmit, + control, + setValue, + register, + getValues, + formState: { errors } + } = useForm({ + defaultValues: { + carPlate: "", + carBrand: "", + carModel: "", + maxPassengers: "", + isRent: "NO" + } + }); + + useEffect(() => { + + },[]); + + const onSubmit = async (van: any) => { + await ApiClient.doPost("/cadastro-van", van); + }; + + return ( + + + + VanMos App v1.0 + + + Return + + + + + + +
+ Cadastro do Veículo + + + Placa * + + + } + /> + + + Marca * + + + } + /> + + + Modelo * + + + } + /> + + + + Número Máximo de Passageiros * + + + + } + /> + + + +
+ Veículo alugado? +
+
+ setValue("isRent", e.detail.value)} + > + + Sim + + + + + Não + + + +
+
+
+ {errors.isRent && ( + This field is required + )} + + {getValues("isRent") === "YES" &&
Teste Novos Campos
} + +
+ + Salvar + +
+ +
+
+ ); +}; + +export default CadastroVan; diff --git a/src/pages/Vans.tsx b/src/pages/Vans.tsx deleted file mode 100644 index 844e39c..0000000 --- a/src/pages/Vans.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { - IonIcon, - IonItem, - IonLabel, - IonInput, - IonBackButton, - IonButton, - IonButtons, - IonCardTitle, - IonCol, - IonContent, - IonGrid, - IonHeader, - IonPage, - IonRow, - IonToolbar, - IonTitle, - IonList, - IonRadioGroup, - IonListHeader, - IonRadio -} from "@ionic/react"; -import { arrowBack } from "ionicons/icons"; -import React, { useState } from "react"; -//import { Van } from "../models/van.model"; -import "./Vans.css"; - -const Vans: React.FC = () => { - // const van: Van; - - const [placa, setPlaca] = useState(""); - const [marca, setMarca] = useState(""); - const [modelo, setModelo] = useState(""); - const [numPassageiros, setNumPassageiros] = useState(""); - const [tipoSelecionado, setTipoSelecionado] = useState("Não"); - - const placaChangeHandle = (event: any) => { - setPlaca(event.target.value); - }; - - const marcaChangeHandle = (event: any) => { - setMarca(event.target.value); - }; - - const modeloChangeHandle = (event: any) => { - setModelo(event.target.value); - }; - - const numPassageirosChangeHandle = (event: any) => { - setNumPassageiros(event.target.value); - }; - - const tipoSelecionadoChangeHandle = (event: any) => { - setTipoSelecionado(event.target.value); - }; - - return ( - - - - - - - Return - - - - - - -
- Cadastro da Veículo - - - Placa * - setPlaca(e.detail.value!)} - > - - - - Marca * - - - - - Modelo * - - - - - - Digite o número total de passageiros * - - - - - - - - Veículo Alugado ? - - - - Sim - - - - - Não - - - - - - - Salvar - -
-
-
- ); -}; - -export default Vans; diff --git a/src/services/api-client.service.ts b/src/services/api-client.service.ts new file mode 100644 index 0000000..970a8f3 --- /dev/null +++ b/src/services/api-client.service.ts @@ -0,0 +1,18 @@ +import axios from "axios"; + +export class ApiClient{ + private static api = axios.create({ + baseURL: "http://localhost:8080" + }); + + public static async doPost (url: string, body: any): Promise { + return await this.api + .post(url, body) + .then(res => { + console.log(res.data); + }) + .catch(error => { + console.log(error); + }); + }; +} \ No newline at end of file From 6518fd52a38c27cf3cf4d8bd1ca6e49c1a3bac86 Mon Sep 17 00:00:00 2001 From: Byancaam Date: Sun, 1 May 2022 21:39:07 -0300 Subject: [PATCH 3/3] adicionando a validacao dos campos --- src/pages/CadastroVan.tsx | 299 +++++++++++++++++++++++++++++--------- 1 file changed, 234 insertions(+), 65 deletions(-) diff --git a/src/pages/CadastroVan.tsx b/src/pages/CadastroVan.tsx index 8d83e81..4fec045 100644 --- a/src/pages/CadastroVan.tsx +++ b/src/pages/CadastroVan.tsx @@ -1,5 +1,5 @@ import { - IonIcon, + IonToast, IonItem, IonLabel, IonInput, @@ -7,53 +7,157 @@ import { IonButton, IonButtons, IonCardTitle, - IonCol, IonContent, - IonGrid, IonHeader, IonPage, - IonRow, IonToolbar, IonTitle, IonText, - IonList, IonRadioGroup, - IonListHeader, IonRadio } from "@ionic/react"; -import React, { useEffect } from "react"; -import { useForm, Controller } from "react-hook-form"; -import { ErrorMessage } from "@hookform/error-message"; +import React, { useState } from "react"; import { ApiClient } from "../services/api-client.service"; import { arrowBack } from "ionicons/icons"; import "./CadastroVan.css"; + const CadastroVan: React.FC = () => { - const { - handleSubmit, - control, - setValue, - register, - getValues, - formState: { errors } - } = useForm({ - defaultValues: { - carPlate: "", - carBrand: "", - carModel: "", - maxPassengers: "", - isRent: "NO" + + const [showToast, setShowToast] = useState(false); + const [toastMessage, setToastMessage] = useState(""); + + const [carPlate, setCarPlate] = useState(""); + const [carBrand, setCarBrand] = useState(""); + const [carModel, setCarModel] = useState(""); + const [maxPassengers, setMaxPassengers] = useState(1); + const [isRent, setIsRent] = useState(false); + const [carRentalName, setCarRentalName] = useState(""); + const [postalCode, setPostalCode] = useState(""); + const [street, setStreet] = useState(""); + const [number, setNumber] = useState(""); + const [complement, setComplement] = useState(""); + const [city, setCity] = useState(""); + const [state, setState] = useState(""); + + const vanForm = { + carPlate, + carBrand, + carModel, + maxPassengers, + isRent, + carRentalName, + carRentalAddress: { + postalCode, + street, + number, + complement, + city, + state } - }); + }; - useEffect(() => { + const clearRentalData = () => { + setCarRentalName(""); + setPostalCode(""); + setStreet(""); + setNumber(""); + setComplement(""); + setCity(""); + setState(""); + }; - },[]); + const validateForm = (): boolean => { + 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; + } - const onSubmit = async (van: any) => { - await ApiClient.doPost("/cadastro-van", van); + 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.maxPassengers || !parseInt(`${vanForm.maxPassengers}`)) { + setToastMessage("Número de passageiros inválido"); + setShowToast(true); + return false; + } + + if (vanForm.isRent) { + return validateRentalForm(); + } else { + clearRentalData(); + } + + return true; + }; + + const validateRentalForm = (): boolean => { + if (!vanForm.carRentalName) { + setToastMessage("Nome do Locador é obrigatório"); + setShowToast(true); + return false; + } + + if ( + !vanForm.carRentalAddress.postalCode || + vanForm.carRentalAddress.postalCode.length !== 8 || + !vanForm.carRentalAddress.postalCode.match(/([0-9]){8}/g) + ) { + setToastMessage("Cep inválido"); + setShowToast(true); + return false; + } + + if ( + !vanForm.carRentalAddress.number || + !parseInt(`${vanForm.carRentalAddress.number}`) + ) { + setToastMessage("Número inválido"); + setShowToast(true); + return false; + } + + if ( + !vanForm.carRentalAddress.city || + !vanForm.carRentalAddress.city.match(/([A-zà-úÀ-Ú])/g) + ) { + setToastMessage("Cidade inválido"); + setShowToast(true); + return false; + } + + if ( + !vanForm.carRentalAddress.state || + !vanForm.carRentalAddress.state.match(/([A-zà-úÀ-Ú])/g) + ) { + setToastMessage("Estado inválido"); + setShowToast(true); + return false; + } + + return true; + }; + + const handleSubmit = async () => { + if (validateForm()) { + await ApiClient.doPost("/cadastro-van", vanForm); + } }; return ( @@ -70,68 +174,50 @@ const CadastroVan: React.FC = () => { -
+ Cadastro do Veículo Placa * setCarPlate(e.target.value)} /> - } - /> Marca * setCarBrand(e.target.value)} /> - } - /> Modelo * setCarModel(e.target.value)} /> - } - /> Número Máximo de Passageiros * setMaxPassengers(e.target.value)} /> - } - /> @@ -141,35 +227,118 @@ const CadastroVan: React.FC = () => {
setValue("isRent", e.detail.value)} + onIonChange={(e: any) => setIsRent(e.target.value)} > Sim - + Não - +
- {errors.isRent && ( - This field is required + + {isRent && ( +
+ + Nome do Locador * + setCarRentalName(e.target.value)} + /> + + +
+ Endereço do Locador +
+ + CEP* + setPostalCode(e.target.value)} + /> + + + Logradouro* + setStreet(e.target.value)} + /> + + + + Número* + setNumber(e.target.value)} + /> + + + + Complemento* + setComplement(e.target.value)} + /> + + + + Cidade* + setCity(e.target.value)} + /> + + + + Estado* + setState(e.target.value)} + /> + +
+
)} - {getValues("isRent") === "YES" &&
Teste Novos Campos
} -
- + Salvar
+ setShowToast(false)} + message={toastMessage} + duration={2500} + />
);