Skip to content
Merged
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
Binary file added public/events/clueminati.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/events/cookoff.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
111 changes: 93 additions & 18 deletions src/components/CatalogueContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { FilterProvider, useFilters } from "@/context/filterContext";
import EmptyState from "./ui/EmptyState";
import SidebarButton from "./SidebarButton";
import SortComponent from "./ui/sorting";
import Announcement from "./ui/announcement/Announcement";
import { getSubjectEvent, EVENTS, type EventData } from "@/config/events";

const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
const [isMounted, setIsMounted] = useState(false);
Expand Down Expand Up @@ -235,6 +237,95 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
setAppliedFilters,
]);

const [activeEvent, setActiveEvent] = useState<EventData | null>(null);
const [isGridEventsDismissed, setIsGridEventsDismissed] = useState<boolean>(false);

useEffect(() => {
try {
setIsGridEventsDismissed(
window.sessionStorage.getItem("announcement:global-grid-card:dismissed") === "true",
);
} catch {
setIsGridEventsDismissed(false);
}
}, []);

const handleDismissGridEvents = () => {
setIsGridEventsDismissed(true);
try {
window.sessionStorage.setItem(
"announcement:global-grid-card:dismissed",
"true",
);
} catch {}
};

useEffect(() => {
setActiveEvent(getSubjectEvent(subject));
}, [subject]);

const renderGridItems = (paperList: IPaper[]) => {
if (paperList.length === 0) return null;
const currentEvent = activeEvent ?? EVENTS[0]!;

const items: React.ReactNode[] = [];
paperList.forEach((paper, index) => {
if (index === 2 && !isGridEventsDismissed) {
items.push(
<Announcement
key={`grid-event-${subject ?? "all"}`}
id={`grid-card-${currentEvent.id}`}
variant="card"
title={currentEvent.title}
message={currentEvent.description}
badge={currentEvent.badge}
logoType={currentEvent.logoType}
imageUrl={currentEvent.imageUrl}
accent={currentEvent.accent}
ctaLabel="Register Now"
href={currentEvent.registrationUrl}
secondaryCtaLabel="Learn More"
secondaryHref={currentEvent.landingPageUrl}
dismissible={true}
onDismiss={handleDismissGridEvents}
/>,
);
}
items.push(
<Card
key={paper._id}
paper={paper}
onSelect={handleSelectPaper}
isSelected={selectedPapers.some((p) => p._id === paper._id)}
/>,
);
});

if (paperList.length > 0 && paperList.length < 2 && !isGridEventsDismissed) {
items.push(
<Announcement
key={`grid-event-${subject ?? "all"}`}
id={`grid-card-${currentEvent.id}`}
variant="card"
title={currentEvent.title}
message={currentEvent.description}
badge={currentEvent.badge}
logoType={currentEvent.logoType}
imageUrl={currentEvent.imageUrl}
accent={currentEvent.accent}
ctaLabel="Register Now"
href={currentEvent.registrationUrl}
secondaryCtaLabel="Learn More"
secondaryHref={currentEvent.landingPageUrl}
dismissible={true}
onDismiss={handleDismissGridEvents}
/>,
);
}

return items;
};

// Render loading state until mounted to avoid hydration mismatch
if (!isMounted) {
return <Loader />;
Expand Down Expand Up @@ -338,30 +429,14 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => {
>
{appliedFilters ? (
paginatedPapers.length > 0 ? (
paginatedPapers.map((paper: IPaper) => (
<Card
key={paper._id}
paper={paper}
onSelect={handleSelectPaper}
isSelected={selectedPapers.some(
(p) => p._id === paper._id,
)}
/>
))
renderGridItems(paginatedPapers)
) : (
<div className="col-span-full flex justify-center">
<EmptyState />
</div>
)
) : (
paginatedPapers.map((paper: IPaper) => (
<Card
key={paper._id}
paper={paper}
onSelect={handleSelectPaper}
isSelected={selectedPapers.some((p) => p._id === paper._id)}
/>
))
renderGridItems(paginatedPapers)
)}
</div>
{totalPages > 1 && (
Expand Down
80 changes: 67 additions & 13 deletions src/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,48 @@ import {
import { useCourses } from "@/context/courseContext";
import PinnedModal from "./ui/PinnedModal";
import RequestModal from "./ui/RequestModal";
//import CookoffBanner from "./CookoffBanner";
import Announcement from "./ui/announcement/Announcement";
import { EVENTS } from "@/config/events";

function Navbar() {
const pathname: string = usePathname() ?? "/";

const [dropdownOpen, setDropdownOpen] = useState<boolean>(false);
const [currentBannerIndex, setCurrentBannerIndex] = useState<number>(0);
const [isPaused, setIsPaused] = useState<boolean>(false);
const [isTopBannerDismissed, setIsTopBannerDismissed] = useState<boolean>(false);
const { courses } = useCourses();

useEffect(() => {
if (pathname !== "/catalogue") return;
}, [pathname]);
try {
setIsTopBannerDismissed(
window.sessionStorage.getItem("announcement:global-top-banner:dismissed") === "true",
);
} catch {
setIsTopBannerDismissed(false);
}
}, []);

useEffect(() => {
if (isPaused || EVENTS.length <= 1) return;

const interval = setInterval(() => {
setCurrentBannerIndex((prevIndex) => (prevIndex + 1) % EVENTS.length);
}, 5000);

return () => clearInterval(interval);
}, [isPaused]);

const handleDismissTopBanner = (e?: React.MouseEvent) => {
e?.stopPropagation();
setIsTopBannerDismissed(true);
try {
window.sessionStorage.setItem(
"announcement:global-top-banner:dismissed",
"true",
);
} catch {}
};

const renderHomePageButtons = () => (
<>
Expand All @@ -59,16 +90,39 @@ function Navbar() {

return (
<div className="sticky top-0 z-[50] w-full bg-[#B2B8FF] dark:bg-[#130E1F]">
{/*<Banner
bannerId="freshers"
bgColor="#fef3c7"
textColor="#5a3000"
iconColor="#d97706"
accentColor="#78350f"
title="Attention Freshers!"
message="If papers for your subject are not yet available, click on your subject and explore related subjects until papers become available, as these are newly introduced courses."
/>*/}
{/* <CookoffBanner /> */}
{EVENTS.length > 0 && !isTopBannerDismissed && (
<div
className="relative w-full overflow-hidden"
onMouseEnter={() => setIsPaused(true)}
onMouseLeave={() => setIsPaused(false)}
>
<div
className="flex w-full transition-transform duration-700 ease-in-out"
style={{ transform: `translateX(-${currentBannerIndex * 100}%)` }}
>
{EVENTS.map((event) => (
<div key={event.id} className="w-full min-w-full flex-shrink-0">
<Announcement
id={`top-banner-${event.id}`}
variant="banner"
title="Registrations are Live at Gravitas!"
message={event.tagline}
badge={event.badge}
logoType={event.logoType}
imageUrl={event.imageUrl}
accent={event.accent}
ctaLabel="Register Now"
href={event.registrationUrl}
secondaryCtaLabel="Event Details"
secondaryHref={event.landingPageUrl}
dismissible={true}
onDismiss={handleDismissTopBanner}
/>
</div>
))}
</div>
</div>
)}

<div className="flex items-center justify-between bg-inherit px-4 py-4 md:px-8 md:py-5">
{}
Expand Down
Loading
Loading