forked from M3-Academy/desafio-react-e-typescript
feat: criado validação e estilização do form. #13
31
src/components/section/ContentInstitucional.tsx
Normal file
31
src/components/section/ContentInstitucional.tsx
Normal 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 };
|
101
src/components/section/FormContato.module.scss
Normal file
101
src/components/section/FormContato.module.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
159
src/components/section/FormContato.tsx
Normal file
159
src/components/section/FormContato.tsx
Normal 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 };
|
22
src/components/section/FormSchema.tsx
Normal file
22
src/components/section/FormSchema.tsx
Normal 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], "*"),
|
||||
});
|
46
src/components/section/NavInstitucional.tsx
Normal file
46
src/components/section/NavInstitucional.tsx
Normal 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 };
|
@ -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>
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user