Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRDCDH-2269 Refactor Footer Components, Replace Newsletter Topic #609

Merged
merged 5 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/components/Footer/FooterDesktop.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { render } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import { axe } from "jest-axe";
import FooterDesktop from "./FooterDesktop";

describe("Accessibility", () => {
it("should not have any accessibility violations", async () => {
const { container } = render(<FooterDesktop />, { wrapper: (p) => <BrowserRouter {...p} /> });

expect(await axe(container)).toHaveNoViolations();
});
});

describe("Basic Functionality", () => {
it("should render without crashing", () => {
expect(() =>
render(<FooterDesktop />, { wrapper: (p) => <BrowserRouter {...p} /> })
).not.toThrow();
});
});
262 changes: 100 additions & 162 deletions src/components/Footer/FooterDesktop.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useState, useRef } from "react";
import { styled } from "@mui/material";
import { Link } from "react-router-dom";
import FooterData from "../../config/FooterConfig";
import NewsletterForm from "./NewsletterForm";

const FooterStyled = styled("div")({
const StyledFooter = styled("footer")({
backgroundColor: "#1B496E",
borderTop: "1px solid #6C727B",
bottom: 0,
Expand All @@ -12,7 +12,7 @@ const FooterStyled = styled("div")({
position: "relative",
});

const FooterContainer = styled("div")({
const StyledTopContainer = styled("div")({
padding: "2rem",
maxWidth: "1400px",
marginLeft: "auto",
Expand All @@ -21,7 +21,7 @@ const FooterContainer = styled("div")({
justifyContent: "space-between",
});

const FooterEmailSignupContainer = styled("form")({
const StyledNewsletterForm = styled(NewsletterForm)({
width: "33.3%",
"& .signUpTitle": {
fontFamily: "poppins",
Expand Down Expand Up @@ -99,7 +99,7 @@ const FooterLinksContainer = styled("div")({
},
});

const BottomFooter = styled("div")({
const StyledBottomContainer = styled("div")({
background: "#14315C",
"& span": {
display: "block",
Expand Down Expand Up @@ -196,169 +196,107 @@ const BottomFooter = styled("div")({
},
});

const FooterDesktop = () => {
const [emailContent, setEmailContent] = useState("");
const emailForm = useRef<HTMLFormElement>(null);
const emailInput = useRef<HTMLInputElement>(null);
function validateEmail(email) {
const reg = /^[A-Za-z0-9]+([_.-][A-Za-z0-9]+)*@([A-Za-z0-9-]+\.)+[A-Za-z]{2,6}$/;
return reg.test(email);
}

const handleSubmit = (e) => {
emailForm.current.reportValidity();
if (!validateEmail(emailContent)) {
emailInput.current.setCustomValidity("Please enter valid email");
e.preventDefault();
} else {
emailInput.current.setCustomValidity("");
emailForm.current.submit();
}
};

const handleChange = (e) => {
setEmailContent(e.target.value);
};

return (
<>
<FooterStyled role="contentinfo">
<FooterContainer>
<FooterLinksContainer>
{FooterData.link_sections.map((linkItem) => (
<div className="footItem" key={`link_${linkItem.title}`}>
<div className="footItemTitle">{linkItem.title}</div>
{linkItem.items.map((item) => {
if (typeof item?.link !== "string") {
return (
<div className="footItemSubtitle" key={item?.text}>
{item.text}
</div>
);
}

return (
<div className="footItemSubtitle" key={item?.text}>
{item.link.includes("http") ? (
<a
className="footItemLink"
href={item.link}
target="_blank"
rel="noopener noreferrer"
>
{item.text}
</a>
) : (
<Link className="footItemLink" to={item.link}>
{item.text}
</Link>
)}
</div>
);
})}
</div>
))}
</FooterLinksContainer>
<FooterEmailSignupContainer
onSubmit={handleSubmit}
ref={emailForm}
action="https://public.govdelivery.com/accounts/USNIHNCI/subscribers/qualify"
method="post"
target="_blank"
id="signup"
noValidate
>
<input type="hidden" name="topic_id" id="topic_id" value="USNIHNCI_223" />
<div className="signUpTitle">Sign up for email updates</div>
<div className="enterTitle">
<label htmlFor="email">
Sign up for the newsletter
<input
ref={emailInput}
id="email"
type="email"
name="email"
className="signUpInputBox"
value={emailContent}
onChange={(e) => handleChange(e)}
/>
</label>
</div>
<button type="submit" className="signUpButton">
Sign up
</button>
</FooterEmailSignupContainer>
</FooterContainer>
</FooterStyled>
<BottomFooter>
<div className="bottom-footer-container">
<div id="bottom-footer-header">
<a
className="logoText"
href="https://www.cancer.gov"
target="_blank"
rel="noopener noreferrer"
>
<div className="logoUpperText">National Cancer Institute</div>
<div className="logoLowerText">at the National Institutes of Health</div>
</a>
</div>
<div id="bottom-footer-contact-us">
Contact Us
<div id="bottom-footer-contact-links">
{FooterData.contact_links.map((contactItem, contactidx) => {
const contactkey = `contact_${contactidx}`;
return contactItem.link.includes("http") ? (
<a
key={contactkey}
href={contactItem.link}
target="_blank"
rel="noopener noreferrer"
>
{contactItem.text}
</a>
) : (
<a key={contactkey} href={contactItem.link}>
{contactItem.text}
</a>
);
})}
</div>
</div>
<div className="break" />
<div id="bottom-footer-follow-us">
Follow Us
<div id="bottom-footer-follow-us-links">
{FooterData.followUs_links.map((followItem, followidx) => {
const followkey = `follow_${followidx}`;
const FooterDesktop = () => (
<StyledFooter role="contentinfo" data-testid="desktop-footer">
<StyledTopContainer>
<FooterLinksContainer>
{FooterData.link_sections.map((linkItem) => (
<div className="footItem" key={`link_${linkItem.title}`}>
<div className="footItemTitle">{linkItem.title}</div>
{linkItem.items.map((item) => {
if (typeof item?.link !== "string") {
return (
<a
key={followkey}
className={followidx !== 0 ? "bottom-footer-social-media-imgs" : ""}
href={followItem.link}
target="_blank"
rel="noopener noreferrer"
>
<img src={followItem.img} alt={followItem.description} />
</a>
<div className="footItemSubtitle" key={item?.text}>
{item.text}
</div>
);
})}
</div>
</div>
<div id="bottom-footer-gov-links">
{FooterData.global_footer_links.map((linkItem, idx) => {
const linkitemkey = `linkitem_${idx}`;
}

return (
<a key={linkitemkey} href={linkItem.link} target="_blank" rel="noopener noreferrer">
{linkItem.text}
</a>
<div className="footItemSubtitle" key={item?.text}>
{item.link.includes("http") ? (
<a
className="footItemLink"
href={item.link}
target="_blank"
rel="noopener noreferrer"
>
{item.text}
</a>
) : (
<Link className="footItemLink" to={item.link}>
{item.text}
</Link>
)}
</div>
);
})}
</div>
))}
</FooterLinksContainer>
<StyledNewsletterForm />
</StyledTopContainer>
<StyledBottomContainer>
<div className="bottom-footer-container">
<div id="bottom-footer-header">
<a
className="logoText"
href="https://www.cancer.gov"
target="_blank"
rel="noopener noreferrer"
>
<div className="logoUpperText">National Cancer Institute</div>
<div className="logoLowerText">at the National Institutes of Health</div>
</a>
</div>
<div id="bottom-footer-contact-us">
Contact Us
<div id="bottom-footer-contact-links">
{FooterData.contact_links.map((contactItem) =>
contactItem.link.includes("http") ? (
<a
key={contactItem.link}
href={contactItem.link}
target="_blank"
rel="noopener noreferrer"
>
{contactItem.text}
</a>
) : (
<a key={contactItem.link} href={contactItem.link}>
{contactItem.text}
</a>
)
)}
</div>
</div>
<div className="break" />
<div id="bottom-footer-follow-us">
Follow Us
<div id="bottom-footer-follow-us-links">
{FooterData.followUs_links.map((followItem, idx) => (
<a
key={followItem.link}
className={idx !== 0 ? "bottom-footer-social-media-imgs" : ""}
href={followItem.link}
target="_blank"
rel="noopener noreferrer"
>
<img src={followItem.img} alt={followItem.description} />
</a>
))}
</div>
</div>
<div id="bottom-footer-gov-links">
{FooterData.global_footer_links.map((linkItem) => (
<a key={linkItem?.text} href={linkItem.link} target="_blank" rel="noopener noreferrer">
{linkItem.text}
</a>
))}
</div>
</BottomFooter>
</>
);
};
</div>
</StyledBottomContainer>
</StyledFooter>
);

export default FooterDesktop;
37 changes: 37 additions & 0 deletions src/components/Footer/FooterMobile.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { render, within } from "@testing-library/react";
import { BrowserRouter } from "react-router-dom";
import { axe } from "jest-axe";
import userEvent from "@testing-library/user-event";
import FooterMobile from "./FooterMobile";

describe("Accessibility", () => {
it("should not have any accessibility violations", async () => {
const { container } = render(<FooterMobile />, { wrapper: (p) => <BrowserRouter {...p} /> });

expect(await axe(container)).toHaveNoViolations();
});
});

describe("Basic Functionality", () => {
it("should render without crashing", () => {
expect(() =>
render(<FooterMobile />, { wrapper: (p) => <BrowserRouter {...p} /> })
).not.toThrow();
});

it("should toggle the expand of sections on click", () => {
const { getAllByTestId } = render(<FooterMobile />, {
wrapper: (p) => <BrowserRouter {...p} />,
});

const allGroups = getAllByTestId("dropdown-section-group");

userEvent.click(within(allGroups[0]).getByRole("button"));

expect(within(allGroups[0]).getByTestId("dropdown-section-content")).toBeVisible();

userEvent.click(within(allGroups[0]).getByRole("button"));

expect(within(allGroups[0]).getByTestId("dropdown-section-content")).not.toBeVisible();
});
});
Loading