ToastProvider.tsx 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. "use client";
  2. import { type ReactNode, createContext, useContext, useState, useCallback } from "react";
  3. import { ToastContainer } from "@/components/theme/toast/ToastContainer";
  4. export type ToastType = "success" | "danger" | "warning" | "primary";
  5. export interface ToastDataType {
  6. id: string;
  7. message: string;
  8. type: ToastType;
  9. duration?: number;
  10. }
  11. export interface ToastContextType {
  12. toasts: ToastDataType[];
  13. addToast: (_: Omit<ToastDataType, "id">) => void;
  14. removeToast: (_: string) => void;
  15. }
  16. const ToastContext = createContext<ToastContextType | undefined>(undefined);
  17. export const ToastProvider = ({ children }: { children: ReactNode }) => {
  18. const [toasts, setToasts] = useState<ToastDataType[]>([]);
  19. const removeToast = useCallback((id: string) => {
  20. setToasts((prev) => prev.filter((toast) => toast.id !== id));
  21. },[]);
  22. const addToast = useCallback((toast: Omit<ToastDataType, "id">) => {
  23. const id = crypto.randomUUID();
  24. const newToast = { id, ...toast };
  25. setToasts((prev) => [...prev, newToast]);
  26. setTimeout(() => {
  27. removeToast(id);
  28. }, toast.duration || 5000);
  29. },[removeToast]);
  30. return (
  31. <ToastContext.Provider value={{ toasts, addToast, removeToast }}>
  32. <ToastContainer />
  33. {children}
  34. </ToastContext.Provider>
  35. );
  36. };
  37. export const useToast = () => {
  38. const context = useContext(ToastContext);
  39. if (!context) {
  40. throw new Error("useToast must be used within a ToastProvider");
  41. }
  42. return context;
  43. };