Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 7 additions & 4 deletions src/components/Announcements/TabContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ type Events = {
interface TabContentProps {
posts: NewsPost[] | Events[];
isEvents?: boolean;
}
onItemClick?: () => void; }

const TabContent: React.FC<TabContentProps> = ({ posts, isEvents = false }) => {
const TabContent: React.FC<TabContentProps> = ({ posts, isEvents = false, onItemClick }) => {
const locale = useLocale();
const handleClick = () => {
onItemClick?.();
};

const formatTimeAgo = (date: string): string => {
const daysAgo = Math.floor((new Date().getTime() - new Date(date).getTime()) / (1000 * 60 * 60 * 24));
Expand All @@ -52,7 +55,7 @@ const TabContent: React.FC<TabContentProps> = ({ posts, isEvents = false }) => {
{posts.map((event, index) => {
const eventItem = event as Events;
return (
<div key={index}>
<div key={index} onClick={handleClick}>
<a href={eventItem.infoLink} target="_blank" rel="noreferrer">
<div className="text-[#c4bfce]">
<p className="text-[12px] leading-[133.333%] text-lightgrey mb-0">
Expand Down Expand Up @@ -93,7 +96,7 @@ const TabContent: React.FC<TabContentProps> = ({ posts, isEvents = false }) => {
const description = isEF ? post.metadata.description : post.metadata.description;
const date = isEF ? post.metadata.date : post.metadata.date;
return (
<div key={index}>
<div key={index} onClick={handleClick}>
{isEF ? (
<a href={link} target="_blank" rel="noopener noreferrer">
<div className="text-[#c4bfce]">
Expand Down
13 changes: 9 additions & 4 deletions src/components/Announcements/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,18 @@ import { fetchLatestEvents } from "@/hooks"

interface AnnouncementsProps {
handleClose: () => void;
onNotificationRead: () => void;
}

const Announcements = ({ handleClose }: AnnouncementsProps) => {
const Announcements = ({ handleClose , onNotificationRead }: AnnouncementsProps) => {
const [latestPosts, setLatestPosts] = useState([])
const [latestReleases, setLatestReleases] = useState([])
const [latestEvents, setLatestEvents] = useState([])
const [active, setActive] = useState("Updates")
const handleNotificationClick = () => {
onNotificationRead();
};


useEffect(() => {
// Fetch latest news posts
Expand Down Expand Up @@ -65,9 +70,9 @@ const Announcements = ({ handleClose }: AnnouncementsProps) => {
</div>
<div className="mt-6 grow overflow-hidden h-full pb-28">
<div className="overflow-auto h-[88%] scroll-sidebar">
{active === "Updates" && <TabContent posts={latestPosts} />}
{active === "Events" && <TabContent posts={latestEvents} isEvents={true} />}
{active === "Releases" && <TabContent posts={latestReleases} />}
{active === "Updates" && <TabContent posts={latestPosts} onItemClick={handleNotificationClick}/>}
{active === "Events" && <TabContent posts={latestEvents} isEvents={true} onItemClick={handleNotificationClick}/>}
{active === "Releases" && <TabContent posts={latestReleases} onItemClick={handleNotificationClick}/>}
</div>
</div>
</Sidebar>
Expand Down
70 changes: 59 additions & 11 deletions src/components/NavBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from "@headlessui/react"
import { FaChevronDown, FaRegBell } from "react-icons/fa"
import { BsXLg, BsList } from "react-icons/bs"
import { fetchLatestEvents } from "@/hooks";

import IconSocial from "@/components/IconSocial"
import LanguageSelector from "@/components/LanguageSelector"
Expand Down Expand Up @@ -157,10 +158,56 @@ const NavBar = ({ locale }: { locale: string }) => {
const [showLastSlide, setShowLastSlide] = useState(false)
const [showAnnouncement, setShowAnnouncement] = useState(false)
const [activeLastSlide, setActiveLastSlide] = useState<NavItem | null>(null)
const [unreadCount, setUnreadCount] = useState(0);
// To prevent hydration mismatch, we'll start with no active paths
const [activePaths, setActivePaths] = useState<Set<string>>(new Set())
const pathname = usePathname();

useEffect(() => {
const fetchUnreadCount = async () => {
try {
const ONE_WEEK_MS = 7 * 24 * 60 * 60 * 1000;
const now = Date.now();

const postsResponse = await fetch("/api/news?numPosts=4");
const postsData = await postsResponse.json();

const releasesResponse = await fetch("/api/news/byTag?tag=release-notes&numPosts=4");
const releasesData = await releasesResponse.json();

const eventsData = await fetchLatestEvents();
const slicedEvents = eventsData.slice(0, 6);

const recentPosts = (postsData.posts || []).filter(
(p: { date: string }) => now - new Date(p.date).getTime() <= ONE_WEEK_MS
);

const recentReleases = (releasesData.posts || []).filter(
(p: { date: string }) => now - new Date(p.date).getTime() <= ONE_WEEK_MS
);

const recentEvents = (slicedEvents || []).filter(
(e: { date: string }) => now - new Date(e.date).getTime() <= ONE_WEEK_MS
);

const totalCount = recentPosts.length + recentReleases.length + recentEvents.length;

setUnreadCount(totalCount);
} catch (error) {
console.error("Error fetching announcement count:", error);
setUnreadCount(0);
}
};

fetchUnreadCount();
}, []);

const handleNotificationRead = () => {
setUnreadCount(prev => Math.max(0, prev - 1));
};



useEffect(() => {
if (!mobileMenuOpen) {
setShowLastSlide(false)
Expand Down Expand Up @@ -201,7 +248,7 @@ const NavBar = ({ locale }: { locale: string }) => {
}`}
>
{showAnnouncement && (
<Announcements handleClose={() => setShowAnnouncement(false)} />
<Announcements handleClose={() => setShowAnnouncement(false)} onNotificationRead={handleNotificationRead} />
)}
{/* Container div to center the nav content */}
<div className="max-w-[1288px] w-full mx-auto px-3">
Expand Down Expand Up @@ -302,16 +349,17 @@ const NavBar = ({ locale }: { locale: string }) => {
<LanguageSelector locale={locale} />
</div>
<div className="p-3 h-full rounded-3xl border-2 border-gray-700 justify-start items-center gap-3 inline-flex cursor-pointer">
<div
aria-label="notifications"
onClick={() => setShowAnnouncement(!showAnnouncement)}
className="relative"
>
<FaRegBell size={20} />
<span className="absolute -top-1 -right-1 h-4 w-4 bg-red-500 rounded-full text-xs text-white font-bold flex items-center justify-center">
1
</span>
</div>
<div
aria-label="notifications"
onClick={() => {setShowAnnouncement(!showAnnouncement);}}
className="relative">
<FaRegBell size={20} />
{unreadCount > 0 && (
<span className="absolute -top-1 -right-1 h-4 w-4 bg-red-500 rounded-full text-xs text-white font-bold flex items-center justify-center">
{unreadCount}
</span>
)}
</div>
</div>
</div>
<div className="flex lg:hidden ml-3">
Expand Down
Loading