cspj-application/client/src/contexts/NotificationContext.tsx

68 lines
2 KiB
TypeScript

import { Alert, Snackbar, useTheme } from "@mui/material";
import { FC, ReactNode, createContext, useContext, useState } from "react";
import { v4 } from "uuid";
type Notification = {
id: string;
message: string;
color?: string;
duration?: number;
};
type NotificationContextProps = {
notifications: Notification[];
openNotification: (message: string, color?: string, duration?: number) => void;
closeNotification: (id: string) => void;
};
const NotificationContext = createContext<NotificationContextProps | undefined>(undefined);
export const NotificationProvider: FC<{ children: ReactNode }> = ({ children }) => {
const theme = useTheme();
const [notifications, setNotifications] = useState<Notification[]>([]);
const openNotification = (message: string, color?: string, duration: number = 3000) => {
const id = v4();
setNotifications((prevNotifications) => [...prevNotifications, { id, message, color, duration }]);
setTimeout(() => {
closeNotification(id);
}, duration);
};
const closeNotification = (id: string) => {
setNotifications((prevNotifications) => prevNotifications.filter((notification) => notification.id !== id));
};
return (
<NotificationContext.Provider value={{ notifications, openNotification, closeNotification }}>
{children}
{notifications.map((notification) => (
<Snackbar
key={notification.id}
autoHideDuration={notification.duration}
open={true}
>
<Alert
icon={false}
variant='filled'
sx={{
backgroundColor: notification.color || theme.palette.primary.main,
}}
>
{notification.message}
</Alert>
</Snackbar>
))}
</NotificationContext.Provider>
);
};
export const useNotification = () => {
const context = useContext(NotificationContext);
if (context === undefined) {
throw new Error("useNotification must be used within a NotificationProvider");
}
return context;
};