Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 72x 10x 10x 2x 2x 72x 72x 10x 72x 14x 14x 14x 14x 14x 2x 14x 6x 6x 7x 6x 6x 6x 14x 14x 1x 1x 14x 14x 10x | import { useEffect, useRef, useState } from "react"; import { Alert, AlertVariant } from "../Alert"; import { Check, X } from "lucide-react"; import { useLocation } from "react-router"; import { Observer } from "@/utils/basic-observable"; export type Banner = { header: string; body: string; variant?: AlertVariant; pathnameToDisplayOn: string; }; class BannerObserver extends Observer<Banner> { create = (data: Banner) => { this.publish(data); this.observed = { ...data }; }; dismiss = () => { this.publish(null); this.observed = null; }; } const bannerState = new BannerObserver(); export const banner = (newBanner: Banner) => { return bannerState.create(newBanner); }; export const Banner = () => { const bannerObserverRef = useRef<(() => void) | null>(null); const [activeBanner, setActiveBanner] = useState<Banner | null>(null); const { pathname } = useLocation(); const previousPathRef = useRef(pathname); const onClose = () => { bannerState.dismiss(); }; useEffect(() => { Eif (bannerObserverRef.current === null) { bannerObserverRef.current = bannerState.subscribe((banner) => { setActiveBanner(banner); }); return () => { bannerObserverRef.current?.(); bannerObserverRef.current = null; }; } }, []); useEffect(() => { // only run cleanup if: // 1. we've actually navigated (pathname changed from previous render) // 2. there's an active banner to clean up // 3. the banner's target pathname doesn't match where we navigated to if (pathname !== previousPathRef.current) { Eif (activeBanner && activeBanner.pathnameToDisplayOn !== pathname) { onClose(); } } // store current pathname for next render's comparison previousPathRef.current = pathname; }, [pathname, activeBanner]); if (activeBanner && activeBanner.pathnameToDisplayOn === pathname) { return ( <Alert variant={activeBanner.variant} className="mt-4 mb-8 flex-row text-sm"> <div className="flex items-start justify-between"> <Check /> <div className="ml-2 w-full"> <h3 className="text-lg font-bold" data-testid="banner-header"> {activeBanner.header} </h3> <p data-testid="banner-body">{activeBanner.body}</p> </div> <button onClick={onClose} data-testid="banner-close"> <X size={20} /> </button> </div> </Alert> ); } return null; }; |