feat(fixo/footer): Adiciona menu fixo e responsividade do footer

This commit is contained in:
Amanda de Almeida Fonseca 2023-01-16 23:23:05 -03:00
parent 9e19b13661
commit 6fe04e7981
16 changed files with 238 additions and 82 deletions

View File

@ -2,7 +2,7 @@ import { useCallback, useState } from "react";
import styles from "./form.module.scss"; import styles from "./form.module.scss";
import stylesInput from "./input.module.scss"; import stylesInput from "./input.module.scss";
import stylesCheckbox from "./checkbox.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"; import { Formik, Form, Field, ErrorMessage } from "formik";
@ -28,17 +28,6 @@ const initialValues = {
const RegistrationForm = () => { const RegistrationForm = () => {
const [isSubmit, setIsSubmit] = useState(false); 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>) => { const handleTel = useCallback((e: React.FormEvent<HTMLInputElement>) => {
let value = e.currentTarget.value; let value = e.currentTarget.value;
value = value.replace(/\D/g, ""); value = value.replace(/\D/g, "");
@ -68,7 +57,11 @@ const RegistrationForm = () => {
return ( return (
<div className={styles["page-main__form"]}> <div className={styles["page-main__form"]}>
<Formik <Formik
onSubmit={handleFormSubmit} onSubmit={(values: FormikValues, { resetForm }) => {
console.log(values);
setIsSubmit(!isSubmit);
resetForm({ values: initialValues });
}}
initialValues={initialValues} initialValues={initialValues}
validationSchema={FormSchema} validationSchema={FormSchema}
> >

View File

@ -3,6 +3,7 @@ import FooterBottom from "./footer-bottom/footer-bottom";
import FooterTop from "./footer-top/footerTop"; import FooterTop from "./footer-top/footerTop";
import styles from "./footer.module.scss"; import styles from "./footer.module.scss";
import IconFixed from "./icon-fixed/icon-fixed";
import Newsletter from "./newsletter/Newsletter"; import Newsletter from "./newsletter/Newsletter";
const Footer = () => { const Footer = () => {
@ -11,6 +12,7 @@ const Footer = () => {
<Newsletter /> <Newsletter />
<FooterTop /> <FooterTop />
<FooterBottom /> <FooterBottom />
<IconFixed />
</footer> </footer>
); );
}; };

View File

@ -2,16 +2,19 @@ import React from "react";
import styles from "../../footer.module.scss"; import styles from "../../footer.module.scss";
import Img from "../img-footer/img"; import Img from "../img-footer/img";
import Text from "../text/Text"; import Text from "../../text/Text";
import Vtex from "../assets/Vtex.svg"; import Vtex from "../assets/Vtex.svg";
import M3 from "../assets/M3.svg"; import M3 from "../assets/M3.svg";
const Autores = () => { const Autores = () => {
return ( return (
<section className={styles["page-footer__footer-autores"]}> <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" /> <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" /> <Img className={styles["autores-img"]} img={M3} text="M3" />
</section> </section>
); );

View File

@ -2,15 +2,16 @@ import React from "react";
import styles from "../footer.module.scss"; import styles from "../footer.module.scss";
import Autores from "./autores/autores"; import Autores from "./autores/autores";
import Text from "./text/Text"; import Text from "../text/Text";
import Imgs from "./pagamento/imgs"; import Imgs from "./pagamento/imgs";
const FooterBottom = () => { const FooterBottom = () => {
return ( return (
<div className={styles["page-footer__footer-bottom"]}> <section className={styles["page-footer__footer-bottom"]}>
<div className={styles["page-footer__footer-bottom-container"]}> <div className={styles["page-footer__footer-bottom-container"]}>
<section className={styles["page-footer__container-footer-text"]}> <section className={styles["page-footer__container-footer-text"]}>
<Text <Text
className={styles["page-footer__footer-text"]}
text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor" tempor"
/> />
@ -18,7 +19,7 @@ const FooterBottom = () => {
<Imgs /> <Imgs />
<Autores /> <Autores />
</div> </div>
</div> </section>
); );
}; };

View File

@ -25,7 +25,7 @@ const imgs = () => {
<Img className={styles["img"]} img={Hiper} text="Cartão hiper" /> <Img className={styles["img"]} img={Hiper} text="Cartão hiper" />
<Img className={styles["img"]} img={Pagseguro} text="Pague Seguro" /> <Img className={styles["img"]} img={Pagseguro} text="Pague Seguro" />
<Img className={styles["img"]} img={Boleto} text="Pagamento boleto" /> <Img className={styles["img"]} img={Boleto} text="Pagamento boleto" />
<strong></strong> <div></div>
<Img className={styles["img-grande"]} img={vtex} text="Vtex" /> <Img className={styles["img-grande"]} img={vtex} text="Vtex" />
</section> </section>
); );

View File

@ -2,6 +2,7 @@ import React, { useState } from "react";
import Link from "../../../link/Link"; import Link from "../../../link/Link";
import styles from "../../footer.module.scss"; import styles from "../../footer.module.scss";
import Text from "../../text/Text";
import ButtonFooterMobile from "../button/button"; import ButtonFooterMobile from "../button/button";
import Title from "../title/Title"; import Title from "../title/Title";
@ -22,17 +23,12 @@ const FaleConosco = () => {
/> />
</div> </div>
<div className={isOpen ? styles["active"] : styles["container-link"]}> <div className={isOpen ? styles["active"] : styles["container-link"]}>
<Link <Text
className={styles["link-negrito"]} className={styles["text-negrito"]}
link="/"
text="Atendimento Ao Consumidor" text="Atendimento Ao Consumidor"
/> />
<Link className={styles["link"]} link="/" text="(11) 4159-9504" /> <Link className={styles["link"]} link="/" text="(11) 4159-9504" />
<Link <Text className={styles["text-negrito"]} text="Atendimento Online" />
className={styles["link-negrito"]}
link="/"
text="Atendimento Online"
/>
<Link <Link
className={styles["link-underline"]} className={styles["link-underline"]}
link="/" link="/"

View File

@ -5,6 +5,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
position: relative;
&__newsletter { &__newsletter {
display: flex; display: flex;
@ -35,6 +36,7 @@
.input { .input {
width: 340px; width: 340px;
height: 42px; height: 42px;
outline: 0;
border: 1px solid $gray-1020; border: 1px solid $gray-1020;
border-radius: 4px; border-radius: 4px;
font-weight: 400; 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 { .button {
width: 126px; width: 126px;
height: 42px; height: 42px;
cursor: pointer;
background: $black; background: $black;
box-shadow: 0px 4px 4px rgba($black, 0.25); box-shadow: 0px 4px 4px rgba($black, 0.25);
border-radius: 4px; border-radius: 4px;
@ -67,12 +86,14 @@
&__top { &__top {
padding: 50px 0; padding: 50px 0;
display: flex; display: flex;
width: 84.4%;
justify-content: space-between; justify-content: space-between;
} }
&__top-container { &__top-container {
display: flex; display: flex;
gap: 121px; justify-content: space-between;
width: 65.5%;
} }
&__container { &__container {
@ -97,7 +118,7 @@
.link, .link,
.link-underline, .link-underline,
.link-negrito { .text-negrito {
font-weight: 400; font-weight: 400;
font-size: 12px; font-size: 12px;
line-height: 14px; line-height: 14px;
@ -109,7 +130,7 @@
text-decoration-line: underline; text-decoration-line: underline;
} }
.link-negrito { .text-negrito {
font-weight: 500; font-weight: 500;
} }
@ -160,7 +181,7 @@
gap: 12px; gap: 12px;
flex-wrap: wrap; flex-wrap: wrap;
strong { div {
width: 1px; width: 1px;
background: $gray-900; background: $gray-900;
height: 24px; height: 24px;
@ -200,6 +221,37 @@
height: 16px; 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) { @media screen and (min-width: 2500px) {
&__newsletter { &__newsletter {
padding: 16px 0; padding: 16px 0;
@ -228,6 +280,10 @@
width: 315px; width: 315px;
} }
&__top {
width: 92%;
}
.title { .title {
font-size: 28px; font-size: 28px;
line-height: 33px; line-height: 33px;
@ -235,7 +291,7 @@
.link, .link,
.link-underline, .link-underline,
.link-negrito { .text-negrito {
font-size: 24px; font-size: 24px;
line-height: 28px; line-height: 28px;
} }
@ -248,6 +304,51 @@
width: 67.9%; 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) { @media screen and (max-width: 1024px) {
@ -271,6 +372,10 @@
flex-direction: column; flex-direction: column;
} }
&-form {
width: 100%;
}
.input, .input,
.button { .button {
width: 100%; width: 100%;
@ -290,6 +395,7 @@
&__top-container { &__top-container {
flex-direction: column; flex-direction: column;
gap: 12px; gap: 12px;
width: 100%;
} }
&__container { &__container {
@ -332,12 +438,6 @@
display: none; display: none;
} }
&__rede-sociais {
.link {
display: none;
}
}
&__footer-bottom { &__footer-bottom {
padding: 16px; padding: 16px;
justify-content: flex-start; justify-content: flex-start;
@ -362,7 +462,6 @@
&__footer-autores { &__footer-autores {
order: 3; order: 3;
} }
} }
@media screen and (max-width: 375px) { @media screen and (max-width: 375px) {

View 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

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View 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;

View 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;

View File

@ -1,20 +1,50 @@
import React from "react"; import React, { useState } from "react";
import Button from "../../button/Button"; import Button from "../../button/Button";
import { Formik, Form, Field, ErrorMessage } from "formik";
import styles from "../footer.module.scss"; 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 Newsletter = () => {
const [isSubmit, setIsSubmit] = useState(false);
return ( return (
<section className={styles["page-footer__newsletter"]}> <section className={styles["page-footer__newsletter"]}>
<div className={styles["page-footer__newsletter-container"]}> <div className={styles["page-footer__newsletter-container"]}>
<h3 className={styles["page-footer__newsletter-title"]}> <h3 className={styles["page-footer__newsletter-title"]}>
ASSINE NOSSA NEWSLETTER ASSINE NOSSA NEWSLETTER
</h3> </h3>
<form className={styles["page-footer__newsletter-section"]}> <Formik
<Input placeholder="E-mail" /> onSubmit={(values: FormikValues, { resetForm }) => {
<Button text="ENVIAR" /> console.log(values);
</form> 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> </div>
</section> </section>
); );

View File

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

View File

@ -3,12 +3,11 @@ import styles from "../../footer.module.scss";
interface TextProps { interface TextProps {
text: string; text: string;
className: string;
} }
const Text = (props: TextProps) => { const Text = (props: TextProps) => {
return ( return <p className={props.className}>{props.text}</p>;
<strong className={styles["page-footer__footer-text"]}>{props.text}</strong>
);
}; };
export default Text; export default Text;

View File

@ -1,15 +1,18 @@
import * as Yup from "yup"; import * as Yup from "yup";
export default Yup.object().shape({ const FormSchema = () =>
name: Yup.string() Yup.object().shape({
.min(3, "mínimo 3 caracteres") name: Yup.string()
.required("*Campo Obrigatório"), .min(3, "mínimo 3 caracteres")
email: Yup.string().required("*Campo Obrigatório").email("Email inválido"), .required("*Campo Obrigatório"),
cpf: Yup.string().length(14).required("*Campo Obrigatório"), email: Yup.string().required("*Campo Obrigatório").email("Email inválido"),
data: Yup.date() cpf: Yup.string().length(14).required("*Campo Obrigatório"),
.required("*Campo Obrigatório") data: Yup.date()
.max(new Date(), "Não é possível incluir uma data futura"), .required("*Campo Obrigatório")
tel: Yup.string().length(15).required("*Campo Obrigatório"), .max(new Date(), "Não é possível incluir uma data futura"),
instagram: Yup.string(), tel: Yup.string().length(15).required("*Campo Obrigatório"),
acceptTerms: Yup.bool().oneOf([true], "*"), instagram: Yup.string(),
}); acceptTerms: Yup.bool().oneOf([true], "*"),
});
export { FormSchema };

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