diff --git a/.gitignore b/.gitignore index 17b8c74608ee..d673fa71784d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,4 @@ coverage deno.lock cypress/videos cypress/screenshots +next-env.d.ts diff --git a/components/campaigns/AnnouncementHero.tsx b/components/campaigns/AnnouncementHero.tsx index 19cea6690953..205546d4a63b 100644 --- a/components/campaigns/AnnouncementHero.tsx +++ b/components/campaigns/AnnouncementHero.tsx @@ -20,8 +20,26 @@ interface IAnnouncementHeroProps { */ export default function AnnouncementHero({ className = '', small = false }: IAnnouncementHeroProps) { const [activeIndex, setActiveIndex] = useState(0); + const [isBannerVisible, setIsBannerVisible] = useState(true); + + // Load banner visibility from localStorage + useEffect(() => { + const hidden = typeof window !== 'undefined' ? localStorage.getItem('bannerClosed') : null; + + if (hidden === 'true') setIsBannerVisible(false); + }, []); + + // Filter banners dynamically based on dismissed banners + const visibleBanners = useMemo(() => { + if (typeof window === 'undefined') return []; + + const dismissedBanners = JSON.parse(localStorage.getItem('dismissedBanners') || '[]'); + + return banners + .filter((banner) => shouldShowBanner(banner.cfpDeadline)) + .filter((b) => !dismissedBanners.includes(b.eventName)); + }, []); - const visibleBanners = useMemo(() => banners.filter((banner) => shouldShowBanner(banner.cfpDeadline)), [banners]); const numberOfVisibleBanners = visibleBanners.length; const goToPrevious = () => { @@ -36,57 +54,85 @@ export default function AnnouncementHero({ className = '', small = false }: IAnn setActiveIndex(index); }; - useEffect(() => { - const interval = setInterval(() => setActiveIndex((index) => (index + 1) % numberOfVisibleBanners), 10000); + const handleClose = () => { + if (typeof window === 'undefined') return; + + const currentBanner = visibleBanners[activeIndex]; + const dismissedBanners = JSON.parse(localStorage.getItem('dismissedBanners') || '[]'); + dismissedBanners.push(currentBanner.eventName); + localStorage.setItem('dismissedBanners', JSON.stringify(dismissedBanners)); + + const remainingBanners = visibleBanners.filter( + (b) => !dismissedBanners.includes(b.eventName) + ); - return () => { - clearInterval(interval); - }; + if (remainingBanners.length === 0) { + setIsBannerVisible(false); + } else { + setActiveIndex((prev) => prev % remainingBanners.length); + } + }; + + useEffect(() => { + const interval = setInterval( + () => setActiveIndex((index) => (index + 1) % numberOfVisibleBanners), + 10000 + ); + return () => clearInterval(interval); }, [numberOfVisibleBanners]); - if (numberOfVisibleBanners === 0) { + if (numberOfVisibleBanners === 0 || !isBannerVisible) { return null; } return ( - -
+ +
{numberOfVisibleBanners > 1 && (
- +
)} -
-
- {visibleBanners.map((banner, index) => { - // Only render the active banner - const isVisible = index === activeIndex; - if (!isVisible) return null; +
+
+ {visibleBanners.map((banner, index) => { + if (index !== activeIndex) return null; return ( - +
+ {/* Close Button inside the card */} + + + +
); })}
-
- {visibleBanners.map((banner, index) => ( + +
+ {visibleBanners.map((_, index) => (
+ {numberOfVisibleBanners > 1 && (
- +
)}