diff --git a/components/InTheNews/InTheNews.tsx b/components/InTheNews/InTheNews.tsx new file mode 100644 index 000000000..fc6f91b82 --- /dev/null +++ b/components/InTheNews/InTheNews.tsx @@ -0,0 +1,209 @@ +import { useState } from "react" +import { Col, Row, Container, Badge, Spinner } from "../bootstrap" +import Tab from "react-bootstrap/Tab" +import Nav from "react-bootstrap/Nav" +import Dropdown from "react-bootstrap/Dropdown" +import { useMediaQuery } from "usehooks-ts" +import { useTranslation } from "next-i18next" +import { NewsCard } from "./NewsCard" +import { NewsType, NewsItem, useNews } from "components/db/news" + +type NewsFeedProps = { + type: NewsType + newsItems: NewsItem[] +} + +type TabCounts = { + media: number + awards: number + books: number +} + +const NewsFeed = ({ type, newsItems }: NewsFeedProps) => { + return ( +
+ {newsItems + .filter(item => item.type === type) + .map((item, index) => ( + + ))} +
+ ) +} + +export const InTheNews = () => { + const { t } = useTranslation("inTheNews") + const isMobile = useMediaQuery("(max-width: 768px)") + const { result: newsItems, loading } = useNews() + + const counts: TabCounts | null = newsItems + ? { + media: newsItems.filter(item => item.type === "article").length, + awards: newsItems.filter(item => item.type === "award").length, + books: newsItems.filter(item => item.type === "book").length + } + : null + + return ( + +

+ {t("title")} +

+
+ + {isMobile ? ( + + ) : ( + + )} + + + {loading ? ( +
+ + Loading... + +
+ ) : ( + + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+ )} + +
+
+
+
+ ) +} + +const TabGroup = ({ counts }: { counts: TabCounts | null }) => { + const { t } = useTranslation("inTheNews") + return ( + + + + + + + + + + + + ) +} + +const TabDropdown = ({ counts }: { counts: TabCounts | null }) => { + const { t } = useTranslation("inTheNews") + const [selectedTab, setSelectedTab] = useState("Media") + + const handleTabClick = (tabTitle: string) => { + setSelectedTab(tabTitle) + } + + return ( + + + + + {selectedTab} + + + handleTabClick("Media")} + > + {t("media.title")} + + + handleTabClick("Awards")} + > + {t("awards.title")} + + + handleTabClick("Books")} + > + {t("books.title")} + + + + + + ) +} diff --git a/components/InTheNews/NewsCard.tsx b/components/InTheNews/NewsCard.tsx new file mode 100644 index 000000000..cb545e354 --- /dev/null +++ b/components/InTheNews/NewsCard.tsx @@ -0,0 +1,68 @@ +import ArrowForward from "@mui/icons-material/ArrowForward" +import { useTranslation } from "next-i18next" +import { NewsItem } from "components/db" + +type NewsCardProps = { + newsItem: NewsItem +} + +export const NewsCard = ({ newsItem }: NewsCardProps) => { + const { t } = useTranslation("inTheNews") + return ( +
+
+
+

+ {new Date(newsItem.publishDate).toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + timeZone: "UTC" + })} +

+
+

{newsItem.author}

+
+
+ + {newsItem.title} + +
+
{newsItem.description}
+
+
+ + {t("readMoreButton")} + + +
+
+ ) +} diff --git a/components/Navbar.tsx b/components/Navbar.tsx index 029bcc35f..401ac8f17 100644 --- a/components/Navbar.tsx +++ b/components/Navbar.tsx @@ -16,6 +16,7 @@ import { NavbarLinkEffective, NavbarLinkFAQ, NavbarLinkGoals, + NavbarLinkInTheNews, NavbarLinkLogo, NavbarLinkNewsfeed, NavbarLinkProcess, @@ -92,6 +93,7 @@ const MobileNav: React.FC> = () => { + @@ -228,6 +230,7 @@ const DesktopNav: React.FC> = () => { +
diff --git a/components/NavbarComponents.tsx b/components/NavbarComponents.tsx index 458c56cb6..4395c134e 100644 --- a/components/NavbarComponents.tsx +++ b/components/NavbarComponents.tsx @@ -378,3 +378,24 @@ export const NavbarLinkWhyUse: React.FC< ) } + +export const NavbarLinkInTheNews: React.FC< + React.PropsWithChildren<{ + handleClick?: any + other?: any + }> +> = ({ handleClick, other }) => { + const isMobile = useMediaQuery("(max-width: 768px)") + const { t } = useTranslation(["common", "auth"]) + return ( + + + {t("navigation.inTheNews")} + + + ) +} diff --git a/components/db/news.ts b/components/db/news.ts index fb4dca211..8c8d587c2 100644 --- a/components/db/news.ts +++ b/components/db/news.ts @@ -1,4 +1,10 @@ -import { collection, getDocs, orderBy, Timestamp } from "firebase/firestore" +import { + collection, + getDocs, + orderBy, + query, + Timestamp +} from "firebase/firestore" import { useAsync } from "react-async-hook" import { firestore } from "../firebase" @@ -17,7 +23,8 @@ export type NewsItem = { export async function listNews(): Promise { const newsRef = collection(firestore, "news") - const result = await getDocs(newsRef) + const q = query(newsRef, orderBy("publishDate", "desc")) + const result = await getDocs(q) return result.docs.map(d => ({ id: d.id, ...d.data() } as NewsItem)) } diff --git a/pages/about/in-the-news.tsx b/pages/about/in-the-news.tsx new file mode 100644 index 000000000..1eff2c707 --- /dev/null +++ b/pages/about/in-the-news.tsx @@ -0,0 +1,17 @@ +import { createPage } from "../../components/page" +import { InTheNews } from "../../components/InTheNews/InTheNews" +import { createGetStaticTranslationProps } from "components/translations" + +export default createPage({ + titleI18nKey: "titles.in_the_news", + Page: () => { + return + } +}) + +export const getStaticProps = createGetStaticTranslationProps([ + "auth", + "common", + "footer", + "inTheNews" +]) diff --git a/public/locales/en/common.json b/public/locales/en/common.json index a0a3d5fe2..8c6b7daf7 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -128,6 +128,7 @@ "aboutTestimony": "About Testimony", "viewProfile": "View Profile", "whyUseMaple": "Why Use MAPLE", + "inTheNews": "In The News", "login": "Login" }, "new_feature": "*NEW*", @@ -180,6 +181,7 @@ "legislative_process": "How To Have Impact Through Legislative Testimony", "submit_testimony": "Submit Testimony", "support_maple": "How to Support MAPLE", + "in_the_news": "In The News", "testimony": "Testimony", "policies": "Policies", "unsubscribe": "Unsubscribe", diff --git a/public/locales/en/inTheNews.json b/public/locales/en/inTheNews.json new file mode 100644 index 000000000..5d1cb3243 --- /dev/null +++ b/public/locales/en/inTheNews.json @@ -0,0 +1,13 @@ +{ + "title": "Media, Articles & Insights", + "readMoreButton": "READ MORE", + "media": { + "title": "Media" + }, + "awards": { + "title": "Awards" + }, + "books": { + "title": "Books" + } +} diff --git a/styles/bootstrap.scss b/styles/bootstrap.scss index d526ca4f8..9412d68b0 100644 --- a/styles/bootstrap.scss +++ b/styles/bootstrap.scss @@ -149,3 +149,9 @@ $utilities: ( .tracking-widest { letter-spacing: 0.1em; } + +.hover-underline { + &:hover { + text-decoration: underline !important; + } +} diff --git a/styles/globals.css b/styles/globals.css index f3a8f052e..61c2cac36 100644 --- a/styles/globals.css +++ b/styles/globals.css @@ -159,3 +159,19 @@ letter-spacing: 0.015em; padding: 7px, 8px, 7px, 8px; } + +/* Custom style in "In The News" Page */ +.in-the-news .nav-item .nav-link { + color: black; + font-weight: 600; + border-bottom: 2px solid; + border-color: #0000001a; +} +.in-the-news .nav-item .nav-link:hover { + color: #15276a; +} +.in-the-news .nav-item .nav-link.active { + color: #15276a; + border-bottom: 4px solid; + border-color: #15276a; +}