feat: adiciona validação inputs formulário

This commit is contained in:
Rafael Sampaio de Oliveira 2023-01-09 14:55:48 -03:00
parent 9bf366f55f
commit 05e22c8278
11 changed files with 2024 additions and 1656 deletions

129
package-lock.json generated
View File

@ -15,17 +15,21 @@
"@types/node": "^16.18.11",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.10",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-modal": "^3.16.1",
"react-router-dom": "^6.6.1",
"react-scripts": "5.0.1",
"react-text-mask": "^5.5.0",
"sass": "^1.57.1",
"typescript": "^4.9.4",
"web-vitals": "^2.1.4"
"web-vitals": "^2.1.4",
"yup": "^0.32.11"
},
"devDependencies": {
"@types/react-modal": "^3.13.1"
"@types/react-modal": "^3.13.1",
"@types/react-text-mask": "^5.4.11"
}
},
"node_modules/@adobe/css-tools": {
@ -3815,6 +3819,11 @@
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="
},
"node_modules/@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
"integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ=="
},
"node_modules/@types/mime": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
@ -3882,6 +3891,15 @@
"@types/react": "*"
}
},
"node_modules/@types/react-text-mask": {
"version": "5.4.11",
"resolved": "https://registry.npmjs.org/@types/react-text-mask/-/react-text-mask-5.4.11.tgz",
"integrity": "sha512-DIJ3/dS4jd7NK3lEgsOwcgpp+ZlVrNJEiUDRayZRE/PNMbV/nLWmOKGdL0BUS29hnx0CDgITgPudKx0BgbF5fA==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/resolve": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
@ -7980,6 +7998,42 @@
"node": ">= 6"
}
},
"node_modules/formik": {
"version": "2.2.9",
"resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz",
"integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==",
"funding": [
{
"type": "individual",
"url": "https://opencollective.com/formik"
}
],
"dependencies": {
"deepmerge": "^2.1.1",
"hoist-non-react-statics": "^3.3.0",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"react-fast-compare": "^2.0.1",
"tiny-warning": "^1.0.2",
"tslib": "^1.10.0"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/formik/node_modules/deepmerge": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
"integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/formik/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
@ -8355,6 +8409,19 @@
"he": "bin/he"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@ -11425,6 +11492,11 @@
"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",
@ -11750,6 +11822,11 @@
"multicast-dns": "cli.js"
}
},
"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.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@ -13652,6 +13729,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",
@ -13961,6 +14043,11 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
"node_modules/react-fast-compare": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
"integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
},
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@ -14099,6 +14186,17 @@
}
}
},
"node_modules/react-text-mask": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/react-text-mask/-/react-text-mask-5.5.0.tgz",
"integrity": "sha512-SLJlJQxa0uonMXsnXRpv5abIepGmHz77ylQcra0GNd7Jtk4Wj2Mtp85uGQHv1avba2uI8ZvRpIEQPpJKsqRGYw==",
"dependencies": {
"prop-types": "^15.5.6"
},
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -15557,6 +15655,11 @@
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
"integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="
},
"node_modules/tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
"node_modules/tmpl": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
@ -15589,6 +15692,11 @@
"node": ">=0.6"
}
},
"node_modules/toposort": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
},
"node_modules/tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
@ -16897,6 +17005,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"
}
}
}
}

View File

@ -16,6 +16,7 @@
"react-modal": "^3.16.1",
"react-router-dom": "^6.6.1",
"react-scripts": "5.0.1",
"react-text-mask": "^5.5.0",
"sass": "^1.57.1",
"typescript": "^4.9.4",
"web-vitals": "^2.1.4",
@ -46,6 +47,7 @@
]
},
"devDependencies": {
"@types/react-modal": "^3.13.1"
"@types/react-modal": "^3.13.1",
"@types/react-text-mask": "^5.4.11"
}
}

View File

@ -272,11 +272,11 @@
.search-desktop {
&__input {
width: 28.716%;
width: 25.53%;
height: 57px;
padding: 12px 0 12px 16px;
&::placeholder {
padding: 12px 0 12px 16px;
font-size: 28px;
line-height: 32px;
}

View File

@ -1,29 +1,84 @@
import React from "react";
import React, { useState } from "react";
import { MainMenu } from "../MainMenu";
import styles from "./styles.module.scss";
import { Formik, Form, Field, ErrorMessage, FormikHelpers } from "formik";
import { Formik, Form, Field, ErrorMessage } from "formik";
import FormSchema from "../../../schema/FormSchema";
import MaskedInput from "react-text-mask";
interface FormikValues {
name: string;
email: string;
cpf: number;
birthDate: number;
phone: number;
cpf: string;
birthDate: string;
phone: string;
instagram: string;
acceptTerms: boolean;
}
const initialValues = {
name: "",
email: "",
cpf: 0,
birthDate: 0,
phone: 0,
cpf: "",
birthDate: "",
phone: "",
instagram: "",
acceptTerms: false,
};
const cpfNumberMask = [
/\d/,
/\d/,
/\d/,
".",
/\d/,
/\d/,
/\d/,
".",
/\d/,
/\d/,
/\d/,
"-",
/\d/,
/\d/,
];
const bhirtDateMask = [
/\d/,
/\d/,
".",
/\d/,
/\d/,
".",
/\d/,
/\d/,
/\d/,
/\d/,
];
const phoneNumberMask = [
"(",
/[1-9]/,
/\d/,
")",
" ",
/\d/,
/\d/,
/\d/,
/\d/,
/\d/,
"-",
/\d/,
/\d/,
/\d/,
/\d/,
];
const Contact = () => {
const handleFormikSubmit = (values: FormikValues) => {
console.log(values);
const [successMessage, setSuccessMessage] = useState(false);
const handleFormikSubmit = (values: FormikValues, { resetForm }: any) => {
resetForm({ values: "" });
setSuccessMessage(true);
};
return (
@ -31,38 +86,110 @@ const Contact = () => {
<MainMenu />
<div className={styles["content__text"]}>
<h1>Preencha o Formulário</h1>
<Formik onSubmit={handleFormikSubmit} initialValues={initialValues}>
<Formik
onSubmit={handleFormikSubmit}
initialValues={initialValues}
validationSchema={FormSchema}
>
<Form className={styles["form"]}>
<div className={styles["form__input"]}>
<label htmlFor="name">Nome</label>
<Field id="name" name="name" placeholder="Seu nome completo" />
<ErrorMessage
component="span"
name="name"
className={styles["form__invalidFeedback"]}
/>
</div>
<div className={styles["form__input"]}>
<label htmlFor="email">E-mail</label>
<Field id="email" name="email" placeholder="Seu e-mail" />
<ErrorMessage
component="span"
name="email"
className={styles["form__invalidFeedback"]}
/>
</div>
<div className={styles["form__input"]}>
<label htmlFor="cpf">CPF</label>
<Field id="cpf" name="cpf" />
<Field
id="cpf"
name="cpf"
render={({ field }: any) => (
<MaskedInput
{...field}
mask={cpfNumberMask}
id="cpf"
placeholder="000.000.000-00"
type="text"
/>
)}
/>
<ErrorMessage
component="span"
name="cpf"
className={styles["form__invalidFeedback"]}
/>
</div>
<div className={styles["form__input"]}>
<label htmlFor="birthDate">Data de Nascimento:</label>
<Field id="birthDate" name="birthDate" />
<Field
id="birthDate"
name="birthDate"
render={({ field }: any) => (
<MaskedInput
{...field}
mask={bhirtDateMask}
id="birthDate"
placeholder="00.00.0000"
type="text"
/>
)}
/>
<ErrorMessage
component="span"
name="birthDate"
className={styles["form__invalidFeedback"]}
/>
</div>
<div className={styles["form__input"]}>
<label htmlFor="phone">Telefone:</label>
<Field id="phone" name="phone" />
<Field
id="phone"
name="phone"
render={({ field }: any) => (
<MaskedInput
{...field}
mask={phoneNumberMask}
id="phone"
placeholder="(00) 00000-0000"
type="text"
/>
)}
/>
<ErrorMessage
component="span"
name="phone"
className={styles["form__invalidFeedback"]}
/>
</div>
<div className={styles["form__input"]}>
<label htmlFor="instagram">Instagram</label>
<Field id="instagram" name="instagram" placeholder="@seuuser" />
</div>
<div className={styles["form__checkbox"]}>
<span>*</span>
<label htmlFor="">Declaro que li e aceito</label>
<input type="checkbox" />
<label htmlFor="acceptTerms">Declaro que li e aceito</label>
<Field type="checkbox" name="acceptTerms" />
<ErrorMessage component="span" name="acceptTerms" />
</div>
<button type="submit">CADASTRE-SE</button>
{successMessage ? (
<span className={styles["form__successMessage"]}>
*Formulário enviado com sucesso!
</span>
) : (
""
)}
</Form>
</Formik>
</div>

View File

@ -29,14 +29,18 @@
.form {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
height: auto;
position: relative;
&__input {
display: flex;
flex-direction: column;
gap: 12px;
margin-bottom: 12px;
position: relative;
width: 100%;
label {
font-style: normal;
@ -67,6 +71,17 @@
color: var(--gray-201);
}
}
span {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 14px;
color: var(--red-500);
position: absolute;
right: 2.5%;
top: 20%;
}
}
&__checkbox {
@ -79,9 +94,13 @@
font-size: 14px;
line-height: 16px;
margin-bottom: 12px;
position: relative;
max-width: 169.92px;
span {
color: var(--red-500);
position: absolute;
left: -5%;
}
label {
@ -100,6 +119,18 @@
line-height: 19px;
letter-spacing: 0.05em;
color: var(--white-500);
width: 100%;
}
&__successMessage {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 14px;
color: var(--green-500);
position: absolute;
bottom: -4%;
left: 0;
}
}
}
@ -142,9 +173,17 @@
}
}
span {
font-size: 24px;
line-height: 28px;
right: 1.5%;
top: 15%;
}
&__checkbox {
font-size: 28px;
line-height: 33px;
max-width: 333.68px;
input {
width: 36.4px;
@ -158,6 +197,10 @@
font-size: 32px;
line-height: 38px;
}
&__successMessage {
top: 101% !important;
}
}
}
}

View File

@ -4,6 +4,7 @@
border-color: var(--black-500);
width: 27.963%;
height: 100%;
padding-bottom: 51px;
li {
height: 39px;

View File

@ -1,13 +1,14 @@
import React from "react";
import styles from "./styles.module.scss";
import { Formik, Form, Field, ErrorMessage, FormikHelpers } from "formik";
import FormSchema from "../../schema/FormSchema";
interface FormikValues {
email: string;
newsLetter: string;
}
const initialValues = {
email: "",
newsLetter: "",
};
const NewsLetter = () => {
@ -20,14 +21,19 @@ const NewsLetter = () => {
<div className={styles["newsLetter__title"]}>
<h1>Assine nossa Newsletter</h1>
</div>
<Formik onSubmit={handleFormikSubmit} initialValues={initialValues}>
<Formik
onSubmit={handleFormikSubmit}
initialValues={initialValues}
validationSchema={FormSchema}
>
<Form className={styles["newsLetter__container"]}>
<Field
id="email"
name="email"
id="newsLetter"
name="newsLetter"
className={styles["newsLetter__input"]}
placeholder="E-mail"
/>
<ErrorMessage component="span" name="newsLetter" />
<button className={styles["newsLetter__button"]} type="submit">
Enviar
</button>

View File

@ -7,6 +7,7 @@
border-color: var(--black-500);
width: 100%;
padding: 16px 0;
position: relative;
&__title {
width: 37.09%;
@ -31,6 +32,17 @@
height: 42px;
width: 37.09%;
max-width: 474.75px;
span {
font-style: normal;
font-weight: 400;
font-size: 12px;
line-height: 14px;
color: var(--red-500);
position: absolute;
top: 31%;
right: 43%;
}
}
&__input {

17
src/schema/FormSchema.ts Normal file
View File

@ -0,0 +1,17 @@
import * as Yup from "yup";
export default Yup.object().shape({
name: Yup.string().required("*Campo Obrigatório"),
email: Yup.string().required("*Campo Obrigatório").email("e-Mail inválido"),
cpf: Yup.string()
.matches(/^\d{3}.\d{3}.\d{3}-\d{2}$/, "CPF inválido")
.required("*Campo Obrigatório"),
birthDate: Yup.string()
.matches(/^\d{2}([./-])\d{2}\1\d{4}$/, "Data inválida")
.required("*Campo Obrigatório"),
phone: Yup.string()
.matches(/(\(?\d{2}\)?\s)?(\d{4,5}\-\d{4})/g, "Número de telefone inválido")
.required("*Campo Obrigatório"),
acceptTerms: Yup.bool().oneOf([true], "*"),
newsLetter: Yup.string().email("e-Mail inválido"),
});

View File

@ -20,6 +20,8 @@
--gray-300: #7d7d7d;
--red-500: #ff0000;
--green-500: #008000;
}
a {

3291
yarn.lock

File diff suppressed because it is too large Load Diff