forked from M3-Academy/desafio-react-e-typescript
feat(fixo/footer): Adiciona menu fixo e responsividade do footer
This commit is contained in:
parent
9e19b13661
commit
6fe04e7981
@ -2,7 +2,7 @@ import { useCallback, useState } from "react";
|
||||
import styles from "./form.module.scss";
|
||||
import stylesInput from "./input.module.scss";
|
||||
import stylesCheckbox from "./checkbox.module.scss";
|
||||
import FormSchema from "../../../../schema/FormSchema";
|
||||
import { FormSchema } from "../../../../schema/FormSchema";
|
||||
|
||||
import { Formik, Form, Field, ErrorMessage } from "formik";
|
||||
|
||||
@ -28,17 +28,6 @@ const initialValues = {
|
||||
|
||||
const RegistrationForm = () => {
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
const handleFormSubmit = (values: FormikValues) => {
|
||||
values.name = "";
|
||||
values.email = "";
|
||||
values.cpf = "";
|
||||
values.data = "";
|
||||
values.tel = "";
|
||||
values.instagram = "";
|
||||
values.acceptTerms = false;
|
||||
setIsSubmit(!isSubmit);
|
||||
};
|
||||
|
||||
const handleTel = useCallback((e: React.FormEvent<HTMLInputElement>) => {
|
||||
let value = e.currentTarget.value;
|
||||
value = value.replace(/\D/g, "");
|
||||
@ -68,7 +57,11 @@ const RegistrationForm = () => {
|
||||
return (
|
||||
<div className={styles["page-main__form"]}>
|
||||
<Formik
|
||||
onSubmit={handleFormSubmit}
|
||||
onSubmit={(values: FormikValues, { resetForm }) => {
|
||||
console.log(values);
|
||||
setIsSubmit(!isSubmit);
|
||||
resetForm({ values: initialValues });
|
||||
}}
|
||||
initialValues={initialValues}
|
||||
validationSchema={FormSchema}
|
||||
>
|
||||
|
@ -3,6 +3,7 @@ import FooterBottom from "./footer-bottom/footer-bottom";
|
||||
import FooterTop from "./footer-top/footerTop";
|
||||
|
||||
import styles from "./footer.module.scss";
|
||||
import IconFixed from "./icon-fixed/icon-fixed";
|
||||
import Newsletter from "./newsletter/Newsletter";
|
||||
|
||||
const Footer = () => {
|
||||
@ -11,6 +12,7 @@ const Footer = () => {
|
||||
<Newsletter />
|
||||
<FooterTop />
|
||||
<FooterBottom />
|
||||
<IconFixed />
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
@ -2,16 +2,19 @@ import React from "react";
|
||||
|
||||
import styles from "../../footer.module.scss";
|
||||
import Img from "../img-footer/img";
|
||||
import Text from "../text/Text";
|
||||
import Text from "../../text/Text";
|
||||
import Vtex from "../assets/Vtex.svg";
|
||||
import M3 from "../assets/M3.svg";
|
||||
|
||||
const Autores = () => {
|
||||
return (
|
||||
<section className={styles["page-footer__footer-autores"]}>
|
||||
<Text text="Powered by" />
|
||||
<Text className={styles["page-footer__footer-text"]} text="Powered by" />
|
||||
<Img className={styles["autores-img"]} img={Vtex} text="vtex" />
|
||||
<Text text="Developed by" />
|
||||
<Text
|
||||
className={styles["page-footer__footer-text"]}
|
||||
text="Developed by"
|
||||
/>
|
||||
<Img className={styles["autores-img"]} img={M3} text="M3" />
|
||||
</section>
|
||||
);
|
||||
|
@ -2,15 +2,16 @@ import React from "react";
|
||||
|
||||
import styles from "../footer.module.scss";
|
||||
import Autores from "./autores/autores";
|
||||
import Text from "./text/Text";
|
||||
import Text from "../text/Text";
|
||||
import Imgs from "./pagamento/imgs";
|
||||
|
||||
const FooterBottom = () => {
|
||||
return (
|
||||
<div className={styles["page-footer__footer-bottom"]}>
|
||||
<section className={styles["page-footer__footer-bottom"]}>
|
||||
<div className={styles["page-footer__footer-bottom-container"]}>
|
||||
<section className={styles["page-footer__container-footer-text"]}>
|
||||
<Text
|
||||
className={styles["page-footer__footer-text"]}
|
||||
text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor"
|
||||
/>
|
||||
@ -18,7 +19,7 @@ const FooterBottom = () => {
|
||||
<Imgs />
|
||||
<Autores />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@ const imgs = () => {
|
||||
<Img className={styles["img"]} img={Hiper} text="Cartão hiper" />
|
||||
<Img className={styles["img"]} img={Pagseguro} text="Pague Seguro" />
|
||||
<Img className={styles["img"]} img={Boleto} text="Pagamento boleto" />
|
||||
<strong></strong>
|
||||
<div></div>
|
||||
<Img className={styles["img-grande"]} img={vtex} text="Vtex" />
|
||||
</section>
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import React, { useState } from "react";
|
||||
import Link from "../../../link/Link";
|
||||
|
||||
import styles from "../../footer.module.scss";
|
||||
import Text from "../../text/Text";
|
||||
import ButtonFooterMobile from "../button/button";
|
||||
import Title from "../title/Title";
|
||||
|
||||
@ -22,17 +23,12 @@ const FaleConosco = () => {
|
||||
/>
|
||||
</div>
|
||||
<div className={isOpen ? styles["active"] : styles["container-link"]}>
|
||||
<Link
|
||||
className={styles["link-negrito"]}
|
||||
link="/"
|
||||
<Text
|
||||
className={styles["text-negrito"]}
|
||||
text="Atendimento Ao Consumidor"
|
||||
/>
|
||||
<Link className={styles["link"]} link="/" text="(11) 4159-9504" />
|
||||
<Link
|
||||
className={styles["link-negrito"]}
|
||||
link="/"
|
||||
text="Atendimento Online"
|
||||
/>
|
||||
<Text className={styles["text-negrito"]} text="Atendimento Online" />
|
||||
<Link
|
||||
className={styles["link-underline"]}
|
||||
link="/"
|
||||
|
@ -5,6 +5,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
&__newsletter {
|
||||
display: flex;
|
||||
@ -35,6 +36,7 @@
|
||||
.input {
|
||||
width: 340px;
|
||||
height: 42px;
|
||||
outline: 0;
|
||||
border: 1px solid $gray-1020;
|
||||
border-radius: 4px;
|
||||
font-weight: 400;
|
||||
@ -49,9 +51,26 @@
|
||||
|
||||
}
|
||||
|
||||
&-form {
|
||||
position: relative;
|
||||
|
||||
}
|
||||
|
||||
&-error {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: -13px;
|
||||
right: 3px;
|
||||
color: $red;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
}
|
||||
|
||||
.button {
|
||||
width: 126px;
|
||||
height: 42px;
|
||||
cursor: pointer;
|
||||
background: $black;
|
||||
box-shadow: 0px 4px 4px rgba($black, 0.25);
|
||||
border-radius: 4px;
|
||||
@ -67,12 +86,14 @@
|
||||
&__top {
|
||||
padding: 50px 0;
|
||||
display: flex;
|
||||
width: 84.4%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&__top-container {
|
||||
display: flex;
|
||||
gap: 121px;
|
||||
justify-content: space-between;
|
||||
width: 65.5%;
|
||||
}
|
||||
|
||||
&__container {
|
||||
@ -97,7 +118,7 @@
|
||||
|
||||
.link,
|
||||
.link-underline,
|
||||
.link-negrito {
|
||||
.text-negrito {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
@ -109,7 +130,7 @@
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
|
||||
.link-negrito {
|
||||
.text-negrito {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@ -160,7 +181,7 @@
|
||||
gap: 12px;
|
||||
flex-wrap: wrap;
|
||||
|
||||
strong {
|
||||
div {
|
||||
width: 1px;
|
||||
background: $gray-900;
|
||||
height: 24px;
|
||||
@ -200,6 +221,37 @@
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&__icon-fixed {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
right: 16px;
|
||||
bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__button-whatsapp {
|
||||
img {
|
||||
width: 34px;
|
||||
}
|
||||
}
|
||||
|
||||
&__button-top {
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background: $gray-900;
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 2500px) {
|
||||
&__newsletter {
|
||||
padding: 16px 0;
|
||||
@ -228,6 +280,10 @@
|
||||
width: 315px;
|
||||
}
|
||||
|
||||
&__top {
|
||||
width: 92%;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 28px;
|
||||
line-height: 33px;
|
||||
@ -235,7 +291,7 @@
|
||||
|
||||
.link,
|
||||
.link-underline,
|
||||
.link-negrito {
|
||||
.text-negrito {
|
||||
font-size: 24px;
|
||||
line-height: 28px;
|
||||
}
|
||||
@ -248,6 +304,51 @@
|
||||
width: 67.9%;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer-bottom {
|
||||
padding: 24.5px 0;
|
||||
}
|
||||
|
||||
&__footer-bottom-container {
|
||||
width: 92%;
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.img-grande {
|
||||
width: 106px;
|
||||
}
|
||||
|
||||
&__footer-autores {
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
&__container-footer-text {
|
||||
max-width: 467px;
|
||||
}
|
||||
|
||||
&__footer-text {
|
||||
font-size: 20px;
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
.autores-img {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
&__button-whatsapp {
|
||||
img {
|
||||
width: 66px;
|
||||
height: 66px;
|
||||
}
|
||||
}
|
||||
|
||||
&__button-top {
|
||||
width: 66px;
|
||||
height: 66px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
@ -271,6 +372,10 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-form {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input,
|
||||
.button {
|
||||
width: 100%;
|
||||
@ -290,6 +395,7 @@
|
||||
&__top-container {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__container {
|
||||
@ -332,12 +438,6 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
&__rede-sociais {
|
||||
.link {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&__footer-bottom {
|
||||
padding: 16px;
|
||||
justify-content: flex-start;
|
||||
@ -362,7 +462,6 @@
|
||||
&__footer-autores {
|
||||
order: 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@media screen and (max-width: 375px) {
|
||||
|
3
src/components/footer/icon-fixed/assets/Seta.svg
Normal file
3
src/components/footer/icon-fixed/assets/Seta.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="25" height="13" viewBox="0 0 25 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.7428 11.3959C23.741 11.6959 23.6177 11.9953 23.373 12.226L23.3728 12.2261C22.8668 12.7035 22.037 12.7035 21.5311 12.2261L21.5232 12.2345L21.5311 12.2261L12.3457 3.5599L12.0712 3.30091L11.7967 3.5599L2.61178 12.2258C2.10549 12.7033 1.27571 12.7032 0.769767 12.2259L0.769708 12.2258C0.525704 11.9957 0.402467 11.6972 0.400037 11.398C0.401876 11.0981 0.525111 10.7986 0.769782 10.5678L0.769785 10.5678L11.1506 0.773762C11.4013 0.537307 11.7333 0.415846 12.0712 0.415846C12.4093 0.415846 12.7415 0.537566 12.9922 0.773969L23.3728 10.568L23.3729 10.5681C23.6171 10.7983 23.7403 11.0968 23.7428 11.3959Z" fill="white" stroke="white" stroke-width="0.8"/>
|
||||
</svg>
|
After Width: | Height: | Size: 764 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
21
src/components/footer/icon-fixed/icon-fixed.tsx
Normal file
21
src/components/footer/icon-fixed/icon-fixed.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import React from "react";
|
||||
import LinkTop from "./link/Link";
|
||||
import Whatsapp from "./assets/whatsapp.svg";
|
||||
import Seta from "./assets/Seta.svg";
|
||||
|
||||
import styles from "../../footer/footer.module.scss";
|
||||
|
||||
const IconFixed = () => {
|
||||
return (
|
||||
<section className={styles["page-footer__icon-fixed"]}>
|
||||
<LinkTop
|
||||
href="https://api.whatsapp.com/send?phone=5511999999999"
|
||||
className={styles["page-footer__button-whatsapp"]}
|
||||
img={Whatsapp}
|
||||
/>
|
||||
<LinkTop className={styles["page-footer__button-top"]} img={Seta} />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default IconFixed;
|
18
src/components/footer/icon-fixed/link/Link.tsx
Normal file
18
src/components/footer/icon-fixed/link/Link.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
|
||||
interface LinkProps {
|
||||
img: string;
|
||||
className: string;
|
||||
href?: string;
|
||||
onClick?: React.MouseEventHandler;
|
||||
}
|
||||
|
||||
const LinkTop = (props: LinkProps) => {
|
||||
return (
|
||||
<a onClick={props.onClick} href={props.href} className={props.className}>
|
||||
<img src={props.img} alt="" />
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default LinkTop;
|
@ -1,20 +1,50 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import Button from "../../button/Button";
|
||||
|
||||
import { Formik, Form, Field, ErrorMessage } from "formik";
|
||||
import styles from "../footer.module.scss";
|
||||
import Input from "./input/Input";
|
||||
import { NewsletterSchema } from "../../../schema/NewsletterSchema";
|
||||
|
||||
interface FormikValues {
|
||||
email: string;
|
||||
}
|
||||
|
||||
const initialValues = {
|
||||
email: "",
|
||||
};
|
||||
|
||||
const Newsletter = () => {
|
||||
const [isSubmit, setIsSubmit] = useState(false);
|
||||
return (
|
||||
<section className={styles["page-footer__newsletter"]}>
|
||||
<div className={styles["page-footer__newsletter-container"]}>
|
||||
<h3 className={styles["page-footer__newsletter-title"]}>
|
||||
ASSINE NOSSA NEWSLETTER
|
||||
</h3>
|
||||
<form className={styles["page-footer__newsletter-section"]}>
|
||||
<Input placeholder="E-mail" />
|
||||
<Button text="ENVIAR" />
|
||||
</form>
|
||||
<Formik
|
||||
onSubmit={(values: FormikValues, { resetForm }) => {
|
||||
console.log(values);
|
||||
setIsSubmit(!isSubmit);
|
||||
resetForm({ values: initialValues });
|
||||
}}
|
||||
initialValues={initialValues}
|
||||
validationSchema={NewsletterSchema}
|
||||
>
|
||||
<Form className={styles["page-footer__newsletter-section"]}>
|
||||
<div className={styles["page-footer__newsletter-form"]}>
|
||||
<Field
|
||||
name="email"
|
||||
className={styles["input"]}
|
||||
placeholder="E-mail"
|
||||
/>
|
||||
<ErrorMessage
|
||||
component="span"
|
||||
name="email"
|
||||
className={styles["page-footer__newsletter-error"]}
|
||||
/>
|
||||
</div>
|
||||
<Button text="ENVIAR" />
|
||||
</Form>
|
||||
</Formik>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
@ -1,19 +0,0 @@
|
||||
import React from "react";
|
||||
|
||||
import styles from "../../footer.module.scss";
|
||||
|
||||
interface InputProps {
|
||||
placeholder: string;
|
||||
}
|
||||
|
||||
const Input = (props: InputProps) => {
|
||||
return (
|
||||
<input
|
||||
placeholder={props.placeholder}
|
||||
type="text"
|
||||
className={styles["input"]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Input;
|
@ -3,12 +3,11 @@ import styles from "../../footer.module.scss";
|
||||
|
||||
interface TextProps {
|
||||
text: string;
|
||||
className: string;
|
||||
}
|
||||
|
||||
const Text = (props: TextProps) => {
|
||||
return (
|
||||
<strong className={styles["page-footer__footer-text"]}>{props.text}</strong>
|
||||
);
|
||||
return <p className={props.className}>{props.text}</p>;
|
||||
};
|
||||
|
||||
export default Text;
|
@ -1,15 +1,18 @@
|
||||
import * as Yup from "yup";
|
||||
|
||||
export default Yup.object().shape({
|
||||
name: Yup.string()
|
||||
.min(3, "mínimo 3 caracteres")
|
||||
.required("*Campo Obrigatório"),
|
||||
email: Yup.string().required("*Campo Obrigatório").email("Email inválido"),
|
||||
cpf: Yup.string().length(14).required("*Campo Obrigatório"),
|
||||
data: Yup.date()
|
||||
.required("*Campo Obrigatório")
|
||||
.max(new Date(), "Não é possível incluir uma data futura"),
|
||||
tel: Yup.string().length(15).required("*Campo Obrigatório"),
|
||||
instagram: Yup.string(),
|
||||
acceptTerms: Yup.bool().oneOf([true], "*"),
|
||||
});
|
||||
const FormSchema = () =>
|
||||
Yup.object().shape({
|
||||
name: Yup.string()
|
||||
.min(3, "mínimo 3 caracteres")
|
||||
.required("*Campo Obrigatório"),
|
||||
email: Yup.string().required("*Campo Obrigatório").email("Email inválido"),
|
||||
cpf: Yup.string().length(14).required("*Campo Obrigatório"),
|
||||
data: Yup.date()
|
||||
.required("*Campo Obrigatório")
|
||||
.max(new Date(), "Não é possível incluir uma data futura"),
|
||||
tel: Yup.string().length(15).required("*Campo Obrigatório"),
|
||||
instagram: Yup.string(),
|
||||
acceptTerms: Yup.bool().oneOf([true], "*"),
|
||||
});
|
||||
|
||||
export { FormSchema };
|
||||
|
7
src/schema/NewsletterSchema.ts
Normal file
7
src/schema/NewsletterSchema.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import * as Yup from "yup";
|
||||
|
||||
const NewsletterSchema = () =>
|
||||
Yup.object().shape({
|
||||
email: Yup.string().required("*Campo Obrigatório").email("Email inválido"),
|
||||
});
|
||||
export { NewsletterSchema };
|
Loading…
Reference in New Issue
Block a user