fix: whereby consent not displaying (#505)

This commit is contained in:
2025-07-22 12:20:26 -06:00
committed by GitHub
parent 6fedbbe63f
commit 24fabe3e86
3 changed files with 156 additions and 24 deletions

View File

@@ -1,7 +1,14 @@
"use client";
// Simple toaster implementation for migration
// This is a temporary solution until we properly configure Chakra UI v3 toasts
import {
createContext,
useContext,
useState,
useEffect,
useCallback,
} from "react";
import { createPortal } from "react-dom";
import { Box } from "@chakra-ui/react";
interface ToastOptions {
placement?: string;
@@ -9,41 +16,162 @@ interface ToastOptions {
render: (props: { dismiss: () => void }) => React.ReactNode;
}
interface Toast extends ToastOptions {
id: string;
}
interface ToasterContextType {
toasts: Toast[];
addToast: (options: ToastOptions) => string;
removeToast: (id: string) => void;
}
const ToasterContext = createContext<ToasterContextType | null>(null);
export const ToasterProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [toasts, setToasts] = useState<Toast[]>([]);
const addToast = useCallback((options: ToastOptions) => {
const id = String(Date.now() + Math.random());
setToasts((prev) => [...prev, { ...options, id }]);
if (options.duration !== null) {
setTimeout(() => {
removeToast(id);
}, options.duration || 5000);
}
return id;
}, []);
const removeToast = useCallback((id: string) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id));
}, []);
return (
<ToasterContext.Provider value={{ toasts, addToast, removeToast }}>
{children}
<ToastContainer />
</ToasterContext.Provider>
);
};
const ToastContainer = () => {
const context = useContext(ToasterContext);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!context || !mounted) return null;
return createPortal(
<Box
position="fixed"
top="20px"
left="50%"
transform="translateX(-50%)"
zIndex={9999}
pointerEvents="none"
>
{context.toasts.map((toast) => (
<Box key={toast.id} mb={3} pointerEvents="auto">
{toast.render({ dismiss: () => context.removeToast(toast.id) })}
</Box>
))}
</Box>,
document.body,
);
};
class ToasterClass {
private toasts: Map<string, any> = new Map();
private listeners: ((action: { type: string; payload: any }) => void)[] = [];
private nextId = 1;
private toastsMap: Map<string, boolean> = new Map();
subscribe(listener: (action: { type: string; payload: any }) => void) {
this.listeners.push(listener);
return () => {
this.listeners = this.listeners.filter((l) => l !== listener);
};
}
private notify(action: { type: string; payload: any }) {
this.listeners.forEach((listener) => listener(action));
}
create(options: ToastOptions): Promise<string> {
const id = String(this.nextId++);
this.toasts.set(id, options);
this.toastsMap.set(id, true);
this.notify({ type: "ADD_TOAST", payload: { ...options, id } });
// For now, we'll render toasts using a portal or modal
// This is a simplified implementation
if (typeof window !== "undefined") {
console.log("Toast created:", id, options);
// Auto-dismiss after duration if specified
if (options.duration !== null) {
setTimeout(() => {
this.dismiss(id);
}, options.duration || 5000);
}
if (options.duration !== null) {
setTimeout(() => {
this.dismiss(id);
}, options.duration || 5000);
}
return Promise.resolve(id);
}
dismiss(id: string) {
this.toasts.delete(id);
console.log("Toast dismissed:", id);
this.toastsMap.delete(id);
this.notify({ type: "REMOVE_TOAST", payload: id });
}
isActive(id: string): boolean {
return this.toasts.has(id);
return this.toastsMap.has(id);
}
}
export const toaster = new ToasterClass();
// Empty Toaster component for now
export const Toaster = () => null;
// Bridge component to connect the class-based API with React
export const Toaster = () => {
const [toasts, setToasts] = useState<Toast[]>([]);
useEffect(() => {
const unsubscribe = toaster.subscribe((action) => {
if (action.type === "ADD_TOAST") {
setToasts((prev) => [...prev, action.payload]);
} else if (action.type === "REMOVE_TOAST") {
setToasts((prev) =>
prev.filter((toast) => toast.id !== action.payload),
);
}
});
return unsubscribe;
}, []);
const [mounted, setMounted] = useState(false);
useEffect(() => {
setMounted(true);
}, []);
if (!mounted) return null;
return createPortal(
<Box
position="fixed"
top="20px"
left="50%"
transform="translateX(-50%)"
zIndex={9999}
pointerEvents="none"
>
{toasts.map((toast) => (
<Box key={toast.id} mb={3} pointerEvents="auto">
{toast.render({ dismiss: () => toaster.dismiss(toast.id) })}
</Box>
))}
</Box>,
document.body,
);
};