import { CheckCircle, Error, Info, Undo, Warning } from '@mui/icons-material' import { Box, Button, Snackbar, Typography } from '@mui/joy' import React, { createContext, useContext, useState } from 'react' const NotificationContext = createContext() export const useNotification = () => useContext(NotificationContext) // For backward compatibility export const useError = () => { const { showError } = useNotification() return { showError } } // Notification types configuration with default titles const NOTIFICATION_TYPES = { error: { color: 'danger', icon: , autoHideDuration: 6000, showDismissButton: true, defaultTitle: 'Error', }, success: { color: 'success', icon: , autoHideDuration: 5000, showDismissButton: false, defaultTitle: 'Success', }, undo: { color: 'success', icon: , autoHideDuration: null, showDismissButton: false, defaultTitle: 'Undone Successfully', }, warning: { color: 'warning', icon: , autoHideDuration: 4000, showDismissButton: false, defaultTitle: 'Warning', }, info: { color: 'primary', icon: , autoHideDuration: 4000, showDismissButton: false, defaultTitle: 'Information', }, custom: { color: 'neutral', icon: null, autoHideDuration: null, showDismissButton: false, defaultTitle: 'Notification', }, } export const NotificationProvider = ({ children }) => { const [notifications, setNotifications] = useState([]) const addNotification = notification => { const id = Date.now() + Math.random() const newNotification = { id, ...notification, timestamp: Date.now(), } setNotifications(prev => [...prev, newNotification]) // Auto-remove notification if it has a duration const config = NOTIFICATION_TYPES[notification.type] || NOTIFICATION_TYPES.info if (config.autoHideDuration) { setTimeout(() => { removeNotification(id) }, config.autoHideDuration) } return id } const removeNotification = id => { setNotifications(prev => prev.filter(n => n.id !== id)) } const clearAllNotifications = () => { setNotifications([]) } // Helper function to normalize notification input const normalizeNotification = (input, type) => { if (typeof input === 'string') { return { type, message: input, } } if (typeof input === 'object' && input !== null) { // If it's already a properly structured notification if (input.title || input.message) { return { type, ...input, } } // If it's a simple object with just message content return { type, message: input.message || input.toString(), title: input.title, ...input, } } return { type, message: input?.toString() || 'Unknown notification', } } // Unified notification method const showNotification = notification => { // Handle different input formats if (typeof notification === 'string') { return addNotification(normalizeNotification(notification, 'info')) } return addNotification( normalizeNotification(notification, notification.type || 'info'), ) } // Specific notification methods with enhanced language const showError = error => { return addNotification(normalizeNotification(error, 'error')) } const showUndo = message => { return addNotification(normalizeNotification(message, 'undo')) } const showSuccess = message => { return addNotification(normalizeNotification(message, 'success')) } const showWarning = message => { return addNotification(normalizeNotification(message, 'warning')) } const showInfo = message => { return addNotification(normalizeNotification(message, 'info')) } const renderNotification = notification => { const config = NOTIFICATION_TYPES[notification.type] || NOTIFICATION_TYPES.info // Handle custom notifications with components if (notification.type === 'custom' && notification.component) { return ( removeNotification(notification.id)} anchorOrigin={ notification.anchorOrigin || { vertical: 'bottom', horizontal: 'right', } } {...(notification.snackbarProps || {})} > {React.cloneElement(notification.component, { onClose: () => removeNotification(notification.id), ...notification.componentProps, })} ) } // Handle standard notifications // Determine the icon to use const notificationIcon = notification.icon || config.icon // Determine title and message const title = notification.title || config.defaultTitle const message = notification.message return ( removeNotification(notification.id)} startDecorator={notificationIcon} endDecorator={ notification.undoAction ? ( ) : config.showDismissButton ? ( ) : null } anchorOrigin={ notification.anchorOrigin || { vertical: 'bottom', horizontal: 'right', } } {...(notification.snackbarProps || {})} > {/* Enhanced structure like ErrorProvider - always show title and message for consistency */} {title && message ? ( {title} {message} ) : ( {message || title || 'Notification'} )} ) } return ( {children} {notifications.map(renderNotification)} ) }