Last active 1751413089

banner.tsx Raw
1import { useCallback, useEffect, useState } from "react";
2
3// Check that the Enzuzo script has loaded
4// Polling is the only option for global variables that are not part of React
5function useEnzuzoLoaded() {
6 const [isLoaded, setIsLoaded] = useState(false);
7
8 useEffect(() => {
9 if (isLoaded) return;
10 const interval = setInterval(() => {
11 if (typeof window !== "undefined" && window.__ENZUZO_STARTED__) {
12 setIsLoaded(true);
13 clearInterval(interval);
14 }
15 }, 1_000);
16 return () => clearInterval(interval);
17 }, [isLoaded]);
18
19 return isLoaded;
20}
21
22// Hook to capture a single element
23function useCapturedElement<T extends HTMLElement>(selector: string) {
24 const [element, setElement] = useState<T | null>(null);
25 const [content, setContent] = useState<string>("");
26 const isEnzuzoLoaded = useEnzuzoLoaded();
27
28 useEffect(() => {
29 if (!isEnzuzoLoaded) return;
30 const el = document.querySelector(selector) as T | null;
31 if (!el) return;
32 setElement(el);
33 setContent(el.textContent?.trim() || "");
34 }, [selector, isEnzuzoLoaded]);
35
36 const trigger = useCallback(() => {
37 if (!element || !("click" in element)) return;
38 const event = new MouseEvent("click", {
39 bubbles: true,
40 cancelable: true,
41 view: window
42 });
43 element.dispatchEvent(event);
44 }, [element]);
45
46 return { element, content, trigger };
47}
48
49function AcceptButton() {
50 const selector = "#ez-cookie-notification__accept";
51 const { content, trigger } = useCapturedElement<HTMLButtonElement>(selector);
52 return <button onClick={trigger}>{content}</button>;
53}
54
55function DeclineButton() {
56 const selector = "#ez-cookie-notification__decline";
57 const { content, trigger } = useCapturedElement<HTMLButtonElement>(selector);
58 return <button onClick={trigger}>{content}</button>;
59}
60
61function SettingsButton() {
62 const selector = "#notificationManagerLink";
63 const { content, trigger } = useCapturedElement<HTMLButtonElement>(selector);
64 return <button onClick={trigger}>{content}</button>;
65}
66
67function CloseButton() {
68 const selector = "#close-notification";
69 const { content, trigger } = useCapturedElement<HTMLButtonElement>(selector);
70 return <button onClick={trigger}>{content}</button>;
71}
72
73function PrivacyPolicyLink() {
74 const selector = "#notificationPolicyLink";
75 const { element, content } = useCapturedElement<HTMLAnchorElement>(selector);
76 return <a href={element?.href}>{content}</a>;
77}
78
79function CookieBannerText() {
80 const selector = ".enzuzo-notification-desc p";
81 const { content } = useCapturedElement<HTMLElement>(selector);
82 return <p>{content}</p>;
83}
84
85export function CookieBanner() {
86 const [isOpen, setIsOpen] = useState(true);
87 const { element } = useCapturedElement<HTMLDivElement>("#ez-cookie-notification");
88
89 useEffect(() => {
90 if (!element) return;
91 if (element.style.display !== "none") setIsOpen(true);
92 element.style.display = "none";
93 }, [element]);
94
95 if (!isOpen) return null;
96
97 const bannerStyles = {
98 position: "fixed" as const,
99 top: "16px",
100 right: "16px",
101 width: "500px",
102 backgroundColor: "white",
103 borderRadius: "8px",
104 boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
105 border: "2px solid red",
106 padding: "24px",
107 zIndex: 2147483647
108 };
109
110 return (
111 <div style={bannerStyles}>
112 <CloseButton />
113 <CookieBannerText />
114 <PrivacyPolicyLink />
115 <SettingsButton />
116 <AcceptButton />
117 <DeclineButton />
118 </div>
119 );
120}
121