#
vincentlu
2025-04-18 a957c1c914f6890c8a6a8c477495809b065fcbcf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import React, { createContext, useContext, useState, useCallback, useMemo } from 'react';
import { Snackbar, Alert, Portal, Slide } from '@mui/material';
 
const NotificationContext = createContext();
 
const SlideTransition = (props) => {
    return <Slide {...props} direction="up" />;
}
 
export const NotificationProvider = ({ children }) => {
    const [notification, setNotification] = useState({
        open: false,
        message: '',
        severity: 'info',
    });
 
    const showNotification = useCallback((message, severity = 'info') => {
        setNotification({ open: true, message, severity });
    }, []);
 
    const handleClose = useCallback(() => {
        setNotification((prev) => ({ ...prev, open: false }));
    }, []);
 
    const notify = useMemo(() => ({
        info: (msg) => showNotification(msg, 'info'),
        success: (msg) => showNotification(msg, 'success'),
        warning: (msg) => showNotification(msg, 'warning'),
        error: (msg) => showNotification(msg, 'error'),
        // Optional: If you prefer 'warn' instead of 'warning', uncomment the line below
        // warn: (msg) => showNotification(msg, 'warning'),
    }), [showNotification]);
 
    return (
        <NotificationContext.Provider value={notify}>
            {children}
            <Portal>
                <Snackbar
                    open={notification.open}
                    autoHideDuration={3000}
                    onClose={handleClose}
                    TransitionComponent={SlideTransition}
                    anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
                    sx={{
                        zIndex: 2000,
                    }}
                >
                    <Alert
                        onClose={handleClose}
                        severity={notification.severity}
                        sx={{ width: '300px', zIndex: 2000 }}
                        variant="filled" // standard' | 'filled' | 'outlined
                    >
                        {notification.message}
                    </Alert>
                </Snackbar>
            </Portal>
        </NotificationContext.Provider>
    );
};
 
export const useNotification = () => {
    const context = useContext(NotificationContext);
    if (!context) {
        throw new Error('useNotification must be used within a NotificationProvider');
    }
    return context;
};