feature/challenge #1

Merged
BernardoWaldhelm merged 38 commits from feature/challenge into main 2023-01-15 15:25:18 +00:00
7 changed files with 272 additions and 95 deletions
Showing only changes of commit 9010e5f2c1 - Show all commits

5
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"recommendations": [
"esbenp.prettier-vscode"
]
}

View File

@ -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",

View File

@ -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: (

View File

@ -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 {

View File

@ -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 };

View File

@ -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], '*'),
})

View File

@ -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"