| import React, { createContext, useContext, useState, useCallback } from 'react'; |
|
|
| type ToastType = 'success' | 'error' | 'info'; |
|
|
| interface Toast { |
| id: string; |
| message: string; |
| type: ToastType; |
| } |
|
|
| interface NotificationContextType { |
| showToast: (message: string, type: ToastType) => void; |
| } |
|
|
| const NotificationContext = createContext<NotificationContextType | undefined>(undefined); |
|
|
| export const NotificationProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { |
| const [toasts, setToasts] = useState<Toast[]>([]); |
|
|
| const showToast = useCallback((message: string, type: ToastType) => { |
| const id = Math.random().toString(36).substring(7); |
| setToasts((prev) => [...prev, { id, message, type }]); |
| setTimeout(() => { |
| setToasts((prev) => prev.filter((t) => t.id !== id)); |
| }, 5000); |
| }, []); |
|
|
| return ( |
| <NotificationContext.Provider value={{ showToast }}> |
| {children} |
| <div className="fixed top-4 right-4 z-50 space-y-2"> |
| {toasts.map((toast) => ( |
| <div key={toast.id} className={`p-4 rounded-lg shadow-lg text-white font-medium ${toast.type === 'success' ? 'bg-emerald-600' : toast.type === 'error' ? 'bg-red-600' : 'bg-blue-600'}`}> |
| {toast.message} |
| </div> |
| ))} |
| </div> |
| </NotificationContext.Provider> |
| ); |
| }; |
|
|
| export const useNotification = () => { |
| const context = useContext(NotificationContext); |
| if (!context) throw new Error('useNotification must be used within NotificationProvider'); |
| return context; |
| }; |
|
|