import React, { useState, useEffect } from 'react'; import piml from 'piml'; import { motion, AnimatePresence } from 'framer-motion'; import { InfoIcon, WarningIcon, WarningOctagonIcon, XIcon, ArrowRightIcon, } from '@phosphor-icons/react'; import { Link } from 'react-router-dom'; const DISMISSED_BANNERS_KEY = 'dismissed-banners'; const Banner = () => { const [banner, setBanner] = useState(null); const [isVisible, setIsVisible] = useState(true); useEffect(() => { const fetchBanner = async () => { try { const response = await fetch('/banner.piml'); if (!response.ok) return; const text = await response.text(); const parsed = piml.parse(text); let bannerList = []; if (parsed.banners) { if (Array.isArray(parsed.banners)) { bannerList = parsed.banners; } else if (parsed.banners.banner) { bannerList = Array.isArray(parsed.banners.banner) ? parsed.banners.banner : [parsed.banners.banner]; } else { bannerList = [parsed.banners]; } } else if (parsed.banner) { bannerList = Array.isArray(parsed.banner) ? parsed.banner : [parsed.banner]; } const now = new Date(); const dismissedBannersRaw = localStorage.getItem(DISMISSED_BANNERS_KEY); const dismissedBanners = dismissedBannersRaw ? JSON.parse(dismissedBannersRaw) : []; const activeBanner = bannerList.find((b) => { const isActive = String(b.isActive).toLowerCase() === 'true'; if (!isActive) return false; const fromDate = b.from ? new Date(b.from) : null; const toDate = b.to ? new Date(b.to) : null; if (fromDate && now < fromDate) return false; if (toDate && now > toDate) return false; // Check dismissal from array return !dismissedBanners.includes(b.id); }); if (activeBanner) { setBanner(activeBanner); } } catch (error) { console.error('Failed to fetch banner:', error); } }; fetchBanner(); }, []); const handleDismiss = () => { setIsVisible(false); if (banner && banner.id) { const dismissedBannersRaw = localStorage.getItem(DISMISSED_BANNERS_KEY); const dismissedBanners = dismissedBannersRaw ? JSON.parse(dismissedBannersRaw) : []; if (!dismissedBanners.includes(banner.id)) { dismissedBanners.push(banner.id); localStorage.setItem( DISMISSED_BANNERS_KEY, JSON.stringify(dismissedBanners), ); } } }; if (!banner || !isVisible) return null; const getTypeStyles = () => { switch (banner.type) { case 'error': return { bg: 'bg-red-600', text: 'text-white', icon: , accent: 'border-red-400', }; case 'warning': return { bg: 'bg-amber-500', text: 'text-black', icon: , accent: 'border-amber-300', }; case 'info': default: return { bg: 'bg-emerald-600', text: 'text-white', icon: , accent: 'border-emerald-400', }; } }; const styles = getTypeStyles(); return ( {isVisible && ( {/* Brutalist glitch line at bottom */}
)} ); }; export default Banner;