68 lines
1.5 KiB
TypeScript
68 lines
1.5 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
type FlashMessageProps = {
|
|
type: "success" | "error";
|
|
message: string;
|
|
clearDelayMs?: number;
|
|
};
|
|
|
|
export function FlashMessage({
|
|
type,
|
|
message,
|
|
clearDelayMs = 4000,
|
|
}: FlashMessageProps) {
|
|
const pathname = usePathname();
|
|
const router = useRouter();
|
|
const searchParams = useSearchParams();
|
|
const [visible, setVisible] = useState(true);
|
|
|
|
useEffect(() => {
|
|
setVisible(true);
|
|
}, [message, pathname, searchParams]);
|
|
|
|
useEffect(() => {
|
|
if (!message) {
|
|
return undefined;
|
|
}
|
|
|
|
const timeoutId = window.setTimeout(() => {
|
|
setVisible(false);
|
|
|
|
const nextParams = new URLSearchParams(searchParams.toString());
|
|
nextParams.delete("success");
|
|
nextParams.delete("error");
|
|
|
|
const nextQuery = nextParams.toString();
|
|
router.replace(nextQuery ? `${pathname}?${nextQuery}` : pathname, {
|
|
scroll: false,
|
|
});
|
|
}, clearDelayMs);
|
|
|
|
return () => {
|
|
window.clearTimeout(timeoutId);
|
|
};
|
|
}, [clearDelayMs, message, pathname, router, searchParams]);
|
|
|
|
if (!visible) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<p
|
|
className={cn(
|
|
"rounded-md border px-4 py-3 text-sm",
|
|
type === "success"
|
|
? "border-status-success/30 bg-status-success/10 text-status-success"
|
|
: "border-destructive/30 bg-destructive/10 text-destructive",
|
|
)}
|
|
>
|
|
{message}
|
|
</p>
|
|
);
|
|
}
|