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.description}
+
+
+
+ )
+}
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;
+}