feat: criado validação e estilização do form. #13

Merged
luizfelipe9627 merged 1 commits from feature/institucional into development 2023-01-19 00:18:49 +00:00
6 changed files with 362 additions and 3 deletions

View File

@ -0,0 +1,31 @@
// Bibliotecas
import React from "react";
import { Routes, Route } from "react-router-dom";
// Estilos
import styleContentInstitucional from "./ContentInstitucional.module.scss";
import { ContentPagamento } from "./ContentPagamento";
import { ContentEntrega } from "./ContentEntrega";
import { ContentTroca } from "./ContentTroca";
import { ContentSeguranca } from "./ContentSeguranca";
import { ContentContato } from "./ContentContato";
import { ContentSobre } from "./ContentSobre";
const ContentInstitucional = () => {
return (
<div className={styleContentInstitucional["contentInstitucional"]}>
<Routes>
<Route path="/" element={<ContentSobre />} />
<Route path="/sobre" element={<ContentSobre />} />
<Route path="/forma-de-pagamento" element={<ContentPagamento />} />
<Route path="/entrega" element={<ContentEntrega />} />
<Route path="/troca-e-devolucao" element={<ContentTroca />} />
<Route path="/seguranca-e-privacidade" element={<ContentSeguranca />} />
<Route path="/contato" element={<ContentContato />} />
</Routes>
</div>
);
};
export { ContentInstitucional };

View File

@ -0,0 +1,101 @@
@import "../../styles/utils/variables.scss";
.contentContato {
width: 100%;
h2 {
font-size: 24px;
font-weight: 700;
line-height: 28px;
margin: 12px 0;
@media (max-width: 1024px) {
text-align: center;
margin-top: 30px;
}
}
form {
.infosForm {
flex-direction: column;
position: relative;
label {
font-size: 14px;
font-weight: 400;
line-height: 16px;
color: $black;
}
.formInvalid {
font-size: 12px;
position: absolute;
right: 15px;
color: $primary-900;
}
input {
min-width: 100%;
height: 46px;
border-radius: 25px;
padding: 15px 20px;
margin: 12px 0;
outline: none;
border: 1px solid #100d0e;
&::placeholder {
font-size: 14px;
font-weight: 400;
line-height: 16px;
color: #b9b7b7;
}
}
}
.checkboxForm {
display: grid;
grid-template-columns: repeat(3, min-content);
justify-content: center;
margin-bottom: 12px;
.formInvalid-checkbox {
font-size: 16px;
color: $primary-900;
grid-row: 1;
@media (max-width: 620px) {
bottom: 25px;
}
}
label {
margin: 0 4px;
text-decoration: underline;
color: #100d0e;
font-size: 14px;
font-weight: 400;
line-height: 16px;
width: 137px;
}
input {
width: 18px;
}
}
button {
width: 100%;
height: 52px;
border-radius: 25px;
background-color: $black;
color: $white;
font-size: 16px;
font-weight: 400;
line-height: 19px;
letter-spacing: 0.05em;
text-transform: uppercase;
outline: none;
border: none;
}
}
}

View File

@ -0,0 +1,159 @@
// Bibliotecas
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
// Componentes
import FormSchema from "./FormSchema";
// Estilos
import styleFormContato from "./FormContato.module.scss";
const FormContato = () => {
interface FormikValues {
nome: string;
email: string;
cpf: string;
nascimento: string;
telefone: string;
instagram: string;
termos: boolean;
}
const initialValues = {
nome: "",
email: "",
cpf: "",
nascimento: "",
telefone: "",
instagram: "",
termos: false,
};
return (
<div className={styleFormContato["contentContato"]}>
<Formik
onSubmit={(values: FormikValues, actions) => {
actions.resetForm();
console.log(values);
}}
initialValues={initialValues}
validationSchema={FormSchema}
>
{({ errors, touched }) => (
<Form>
<h2>Preencha o formulário</h2>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="nome">Nome</label>
<Field
name="nome"
id="nome"
className={errors.nome && touched.nome && "Invalid"}
placeholder="Seu nome completo"
/>
<ErrorMessage
component="span"
name="nome"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="email">E-mail</label>
<Field
name="email"
id="email"
className={errors.email && touched.email && "Invalid"}
placeholder="Seu e-mail"
/>
<ErrorMessage
component="span"
name="email"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="cpf">CPF</label>
<Field
name="cpf"
id="cpf"
className={errors.cpf && touched.cpf && "Invalid"}
placeholder="000.000.000-00"
/>
<ErrorMessage
component="span"
name="cpf"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="nascimento">Data de Nascimento</label>
<Field
name="nascimento"
id="nascimento"
className={errors.nascimento && touched.nascimento && "Invalid"}
placeholder="00.00.0000"
/>
<ErrorMessage
component="span"
name="nascimento"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="telefone">Telefone</label>
<Field
name="telefone"
id="telefone"
className={errors.nascimento && touched.nascimento && "Invalid"}
placeholder="(00) 00000-0000"
/>
<ErrorMessage
component="span"
name="telefone"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["infosForm"]}>
<label htmlFor="instagram">Instagram</label>
<Field
name="instagram"
id="instagram"
className={errors.instagram && touched.instagram && "Invalid"}
placeholder="@seuuser"
/>
<ErrorMessage
component="span"
name="instagram"
className={styleFormContato["formInvalid"]}
/>
</div>
<div className={styleFormContato["checkboxForm"]}>
<label htmlFor="termos">Declaro que li e aceito</label>
<Field
type="checkbox"
id="termos"
name="termos"
className={errors.termos && touched.termos && "Invalid"}
/>
<ErrorMessage
component="span"
name="termos"
className={styleFormContato["formInvalid-checkbox"]}
/>
</div>
<button type="submit">Cadastre-se</button>
</Form>
)}
</Formik>
</div>
);
};
export { FormContato };

View File

@ -0,0 +1,22 @@
// Bibliotecas
import * as Yup from "yup";
export default Yup.object().shape({
nome: Yup.string()
.required("*Campo Obrigatório.")
.min(3, "Insira seu nome completo."),
email: Yup.string().required("*Campo Obrigatório.").email("Email inválido."),
cpf: Yup.string()
.required("*Campo Obrigatório.")
.min(11, "CPF inválido.")
.max(11, "CPF inválido."),
nascimento: Yup.string()
.required("*Campo Obrigatório.")
.min(8, "Data de nascimento inválido.")
.max(8, "Data de nascimento inválido."),
telefone: Yup.string()
.required("*Campo Obrigatório.")
.min(11, "Telefone inválido.")
.max(11, "Telefone inválido."),
termos: Yup.boolean().oneOf([true], "*"),
});

View File

@ -0,0 +1,46 @@
// Bibliotecas
import React from "react";
// Estilos
import styleNavInstitucional from "./NavInstitucional.module.scss";
import { ContentPagamento } from "./ContentPagamento";
import { ContentEntrega } from "./ContentEntrega";
import { ContentTroca } from "./ContentTroca";
import { ContentSeguranca } from "./ContentSeguranca";
import { ContentContato } from "./ContentContato";
import { ContentSobre } from "./ContentSobre";
const NavInstitucional = () => {
return (
<nav className={styleNavInstitucional["navInstitucional"]}>
<ul>
<li className={styleNavInstitucional["active"]} >
<a href="sobre">Sobre</a>
</li>
<li>
<a href="forma-de-pagamento">Forma de Pagamento</a>
</li>
<li>
<a href="entrega">Entrega</a>
</li>
<li>
<a href="troca-e-devolucao">Troca e Evolução</a>
</li>
<li>
<a href="seguranca-e-privacidade">Segurança e Privacidade</a>
</li>
<li>
<a href="contato">Contato</a>
</li>
</ul>
</nav>
);
};
export { NavInstitucional };

View File

@ -7,7 +7,7 @@ import { ContentPagamento } from "./ContentPagamento";
import { ContentEntrega } from "./ContentEntrega";
import { ContentTroca } from "./ContentTroca";
import { ContentSeguranca } from "./ContentSeguranca";
import { ContentContato } from "./ContentContato";
import { FormContato } from "./FormContato";
import { ContentSobre } from "./ContentSobre";
// Estilos
@ -24,7 +24,7 @@ const Institucional = () => {
className={({ isActive }) =>
isActive ? styleNavInstitucional.active : undefined
}
to="/sobre"
to="/"
>
Sobre
</NavLink>
@ -94,7 +94,7 @@ const Institucional = () => {
<Route path="/entrega" element={<ContentEntrega />} />
<Route path="/troca-e-devolucao" element={<ContentTroca />} />
<Route path="/seguranca-e-privacidade" element={<ContentSeguranca />} />
<Route path="/contato" element={<ContentContato />} />
<Route path="/contato" element={<FormContato />} />
</Routes>
</section>
);