forked from M3-Academy/desafio-react-e-typescript
feature/challenge #1
5
.vscode/extensions.json
vendored
Normal file
5
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esbenp.prettier-vscode"
|
||||
]
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
"@types/node": "^16.7.13",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@types/react-text-mask": "^5.4.11",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"cpf-cnpj-validator": "^1.0.3",
|
||||
"formik": "^2.2.9",
|
||||
@ -19,7 +20,6 @@
|
||||
"react-router-dom": "^6.6.1",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-text-mask": "^5.5.0",
|
||||
"remask": "^0.1.0-alpha.5",
|
||||
"styled-components": "^5.3.6",
|
||||
"typescript": "^4.4.2",
|
||||
"vanilla-masker": "^1.2.0",
|
||||
|
@ -10,15 +10,14 @@ $color-black-transparent: rgba(69, 69, 69, 0.7);
|
||||
$color-black-500: #303030;
|
||||
|
||||
$color-white: #fff;
|
||||
|
||||
$color-primary-200: #B9B7B7;
|
||||
$color-primary-300: #7D7D7D;
|
||||
$color-primary-400: #C4C4C4;
|
||||
$color-primary-500: #C6C6C6;
|
||||
$color-primary-600: #E5E5E5;
|
||||
$color-primary-700: #F2F2F2;
|
||||
|
||||
|
||||
|
||||
$color-red: #ff0000;
|
||||
|
||||
/* Grid breakpoints */
|
||||
$grid-breakpoints: (
|
||||
|
@ -47,6 +47,7 @@
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
&__type{
|
||||
font-family: $font-family;
|
||||
@ -73,6 +74,48 @@
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 12px;
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
color: $color-black;
|
||||
|
||||
@media #{$mq-desktop}, #{$mq-tablet}, #{$mq-mobile} {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
&::placeholder {
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
color: $color-primary-200;
|
||||
|
||||
@media #{$mq-desktop}, #{$mq-tablet}, #{$mq-mobile} {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
top: 15px;
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
color: $color-red;
|
||||
|
||||
@media #{$mq-desktop}, #{$mq-tablet}, #{$mq-mobile} {
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,21 +125,8 @@
|
||||
justify-content: center;
|
||||
margin-bottom: 12px;
|
||||
|
||||
span {
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
color: #ff0000;
|
||||
text-decoration: none;
|
||||
@media #{$mq-desktop}, #{$mq-tablet}, #{$mq-mobile} {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&__type {
|
||||
position: relative;
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
@ -123,6 +153,24 @@
|
||||
height: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&__error {
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
font-family: $font-family;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
color: $color-red;
|
||||
text-decoration: none;
|
||||
|
||||
@media #{$mq-desktop}, #{$mq-tablet}, #{$mq-mobile} {
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
left: -6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__button {
|
||||
|
@ -1,94 +1,217 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import { Formik, Form, Field, ErrorMessage } from 'formik';
|
||||
import { Formik, Form, Field, ErrorMessage } from "formik";
|
||||
import MaskedInput from "react-text-mask";
|
||||
|
||||
import FormSchema from "../../schema/FormSchema";
|
||||
import styles from './FaleConosco.module.scss'
|
||||
import styles from "./FaleConosco.module.scss";
|
||||
|
||||
const initialValues = {
|
||||
name: "",
|
||||
email: "",
|
||||
cpf:"",
|
||||
dataNascimento: "",
|
||||
telefone: "",
|
||||
cpf: "",
|
||||
birthDate: "",
|
||||
celPhone: "",
|
||||
instagram: "",
|
||||
acceptTerms: false,
|
||||
}
|
||||
};
|
||||
|
||||
interface IFormikValues {
|
||||
name: string;
|
||||
email: string;
|
||||
cpf: string;
|
||||
dataNascimento: string;
|
||||
telefone: string;
|
||||
birthDate: string;
|
||||
celPhone: string;
|
||||
instagram: string;
|
||||
acceptTerms: boolean;
|
||||
}
|
||||
|
||||
const FaleConosco = () => {
|
||||
|
||||
const handleFormikSubmit = (values: IFormikValues) => {
|
||||
console.log(values);
|
||||
values.name = '';
|
||||
values.email = '';
|
||||
values.cpf = '';
|
||||
values.dataNascimento = '';
|
||||
values.acceptTerms = false;
|
||||
}
|
||||
values.name = "";
|
||||
values.email = "";
|
||||
values.cpf = "";
|
||||
values.birthDate = "";
|
||||
values.celPhone = "";
|
||||
values.instagram = "";
|
||||
values.acceptTerms = true;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles["form"]}>
|
||||
<Formik onSubmit={handleFormikSubmit} initialValues={initialValues} validationSchema={FormSchema}>
|
||||
{({errors, touched})=> (
|
||||
<Form className={styles["form__wrapper"]}>
|
||||
<h2 className={styles["form__title"]}>Preencha o formulário </h2>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="name">Nome</label>
|
||||
<Field
|
||||
id='name'
|
||||
<Formik
|
||||
onSubmit={handleFormikSubmit}
|
||||
initialValues={initialValues}
|
||||
validationSchema={FormSchema}
|
||||
>
|
||||
<Form className={styles["form__wrapper"]}>
|
||||
<h2 className={styles["form__title"]}>Preencha o formulário </h2>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="name">
|
||||
Nome
|
||||
</label>
|
||||
<Field id="name" name="name" placeholder="Seu nome completo" />
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="name"
|
||||
className={errors.name && touched.name && 'invalid'}
|
||||
/>
|
||||
<ErrorMessage component="span" name="name" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="email">Email</label>
|
||||
<Field id='email' name="email" className={errors.email && touched.email && 'invalid'} />
|
||||
<ErrorMessage component="span" name="email" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="cpf">CPF</label>
|
||||
<Field id='cpf' name="cpf" type="tel" className={errors.cpf && touched.cpf && 'invalid'} />
|
||||
<ErrorMessage component="span" name="cpf" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="dataNascimento">Data de Nascimento:</label>
|
||||
<Field id='dataNascimento' type="tel" name="dataNascimento" className={errors.dataNascimento && touched.dataNascimento && 'invalid'}/>
|
||||
<ErrorMessage component="span" name="dataNascimento" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="telefone">Telefone:</label>
|
||||
<Field id='telefone' name="telefone" type='tel' className={errors.telefone && touched.telefone && 'invalid'}/>
|
||||
<ErrorMessage component="span" name="telefone" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="instagram">Instagram:</label>
|
||||
<Field id='instagram' name="instagram" className={errors.instagram && touched.instagram && 'invalid'}/>
|
||||
<ErrorMessage component="span" name="instagram" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
<div className={styles["form__col-checkbox"]}>
|
||||
<span>*</span>
|
||||
<Link className={styles["form__col-checkbox__type"]} to="/segurancaprivacidade" target='_blank'> Declaro que li e aceito</Link>
|
||||
<Field name="acceptTerms" className={errors.acceptTerms && touched.acceptTerms && 'invalid'}type="checkbox"/>
|
||||
<ErrorMessage component="span" name="acceptTerms" className={styles["form__col__error"]} />
|
||||
</div>
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="email">
|
||||
Email
|
||||
</label>
|
||||
<Field id="email" name="email" placeholder="Seu email" />
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="email"
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="cpf">
|
||||
CPF
|
||||
</label>
|
||||
<Field
|
||||
name="cpf"
|
||||
render={({ field }: any) => (
|
||||
<MaskedInput
|
||||
id="cpf"
|
||||
type="tel"
|
||||
mask={[
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
".",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
".",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
"-",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
]}
|
||||
{...field}
|
||||
placeholder="000.000.000-00"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="cpf"
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="birthDate">
|
||||
Data de Nascimento:
|
||||
</label>
|
||||
<Field
|
||||
type="tel"
|
||||
name="birthDate"
|
||||
render={({ field }: any) => (
|
||||
<MaskedInput
|
||||
id="birthDate"
|
||||
type="tel"
|
||||
mask={[
|
||||
/[0-3]/,
|
||||
/[0-9]/,
|
||||
".",
|
||||
/[0-1]/,
|
||||
/[0-9]/,
|
||||
".",
|
||||
/[0-9]/,
|
||||
/[0-9]/,
|
||||
/[0-9]/,
|
||||
/[0-9]/,
|
||||
]}
|
||||
{...field}
|
||||
placeholder="00.00.0000"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="birthDate"
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="celPhone">
|
||||
Telefone:
|
||||
</label>
|
||||
<Field
|
||||
type="tel"
|
||||
name="celPhone"
|
||||
render={({ field }: any) => (
|
||||
<MaskedInput
|
||||
id="celPhone"
|
||||
type="tel"
|
||||
mask={[
|
||||
"(",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
")",
|
||||
" ",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
"-",
|
||||
/[0-9]/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
/\d/,
|
||||
]}
|
||||
{...field}
|
||||
placeholder="(00) 00000-0000"
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="celPhone"
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col"]}>
|
||||
<label className={styles["form__col__type"]} htmlFor="instagram">
|
||||
Instagram:
|
||||
</label>
|
||||
<Field id="instagram" name="instagram" placeholder="@seuuser" />
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="instagram"
|
||||
className={styles["form__col__error"]}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles["form__col-checkbox"]}>
|
||||
<Link
|
||||
className={styles["form__col-checkbox__type"]}
|
||||
to="/segurancaprivacidade"
|
||||
target="_blank"
|
||||
>
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="acceptTerms"
|
||||
className={styles["form__col-checkbox__error"]}
|
||||
/>{" "}
|
||||
Declaro que li e aceito
|
||||
</Link>
|
||||
<Field name="acceptTerms" type="checkbox" />
|
||||
</div>
|
||||
|
||||
|
||||
<button className={styles["form__button"]} type="submit">CADASTRE-SE</button>
|
||||
</Form>
|
||||
)}
|
||||
<button className={styles["form__button"]} type="submit">
|
||||
CADASTRE-SE
|
||||
</button>
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export { FaleConosco }
|
||||
export { FaleConosco };
|
||||
|
@ -1,13 +1,15 @@
|
||||
import * as Yup from 'yup';
|
||||
import { phoneNumber, cpfNumber } from './validations';
|
||||
import { cpf } from 'cpf-cnpj-validator';
|
||||
|
||||
// const phoneNumber = /\([1-9]{2}\) 9[0-9]\d{3}-\d{4}/;
|
||||
// const cpfNumber = /\d{3}.\d{3}.\d{3}-\d{2}/;
|
||||
|
||||
export default Yup.object().shape({
|
||||
name: Yup.string().required("*Campo Obrigatório").min(3, "*No mínimo 3 digitos"),
|
||||
email: Yup.string().required("*Campo Obrigatório").email("*Email inválido"),
|
||||
cpf: Yup.string().matches(cpfNumber, "* Número Inválido").test((value:any) => cpf.isValid(value)).required("*Campo Obrigatório"),
|
||||
dataNascimento: Yup.date().max(new Date().toLocaleDateString(), "*Data inválida").required("*Campo Obrigatório"),
|
||||
telefone: Yup.string().matches(phoneNumber, "* Número Inválido!").required('*Campo Obrigatório'),
|
||||
email: Yup.string().email("*Email inválido").required("*Campo Obrigatório"),
|
||||
cpf: Yup.string().test((value:any) => cpf.isValid(value)).required("*Campo Obrigatório"),
|
||||
birthDate: Yup.date().max(new Date().toLocaleDateString(), "*Data inválida").required("*Campo Obrigatório"),
|
||||
celPhone: Yup.string().required('*Campo Obrigatório'),
|
||||
instagram: Yup.string(),
|
||||
acceptTerms: Yup.boolean().oneOf([true], '*'),
|
||||
})
|
||||
|
14
yarn.lock
14
yarn.lock
@ -2171,6 +2171,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-text-mask@^5.4.11":
|
||||
version "5.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-text-mask/-/react-text-mask-5.4.11.tgz#dfbfc8642ee27977ed0cdfb1c61b53c85248c01c"
|
||||
integrity sha512-DIJ3/dS4jd7NK3lEgsOwcgpp+ZlVrNJEiUDRayZRE/PNMbV/nLWmOKGdL0BUS29hnx0CDgITgPudKx0BgbF5fA==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^18.0.0":
|
||||
version "18.0.26"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.26.tgz#8ad59fc01fef8eaf5c74f4ea392621749f0b7917"
|
||||
@ -8523,13 +8530,6 @@ relateurl@^0.2.7:
|
||||
resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
|
||||
integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
|
||||
|
||||
remask@^0.1.0-alpha.5:
|
||||
version "0.1.0-alpha.5"
|
||||
resolved "https://registry.yarnpkg.com/remask/-/remask-0.1.0-alpha.5.tgz#003d49b203210501a4e66b6e7c034e6a92b6e417"
|
||||
integrity sha512-oRVGV7FWDvL6aOcATa/TPyNs78PUr9F1gn2495/J2A4G1B6mSGWKnZfyyc5hfoqLkpxmUdF2LR/pICR2Ox9Ovw==
|
||||
dependencies:
|
||||
vanilla-masker "^1.2.0"
|
||||
|
||||
renderkid@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a"
|
||||
|
Loading…
Reference in New Issue
Block a user