"use client"; import { useEffect, useRef } from "react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { toast } from "sonner"; const TOAST_PARAM_NAMES = ["success", "error"] as const; const PENDING_TOAST_STORAGE_KEY = "mohfarawati-pending-toast"; export function QueryToastBridge() { const pathname = usePathname(); const router = useRouter(); const searchParams = useSearchParams(); const handledKeyRef = useRef(null); useEffect(() => { const rawToast = window.sessionStorage.getItem(PENDING_TOAST_STORAGE_KEY); if (!rawToast) { return; } try { const pendingToast = JSON.parse(rawToast) as { message?: string; type?: "success" | "error"; }; if (!pendingToast.message) { return; } if (pendingToast.type === "error") { toast.error(pendingToast.message); } else if (pendingToast.type === "success") { toast.success(pendingToast.message); } else { toast(pendingToast.message); } } finally { window.sessionStorage.removeItem(PENDING_TOAST_STORAGE_KEY); } }, [pathname]); useEffect(() => { const successMessage = searchParams.get("success"); const errorMessage = searchParams.get("error"); if (!successMessage && !errorMessage) { handledKeyRef.current = null; return; } const handledKey = `${pathname}:${successMessage ?? ""}:${errorMessage ?? ""}`; if (handledKeyRef.current === handledKey) { return; } handledKeyRef.current = handledKey; if (successMessage) { toast.success(successMessage); } if (errorMessage) { toast.error(errorMessage); } const nextParams = new URLSearchParams(searchParams.toString()); for (const name of TOAST_PARAM_NAMES) { nextParams.delete(name); } const nextQuery = nextParams.toString(); router.replace(nextQuery ? `${pathname}?${nextQuery}` : pathname, { scroll: false, }); }, [pathname, router, searchParams]); return null; }