106 lines
3.3 KiB
TypeScript
106 lines
3.3 KiB
TypeScript
import CloseIcon from '@mui/icons-material/Close'
|
|
import { Snackbar, Alert, IconButton, Button } from '@mui/material'
|
|
import { useUnit } from 'effector-react'
|
|
import { useNavigate } from 'react-router-dom'
|
|
import { $notifications, dismissNotification as dismissNotificationEvent } from '../../model/notification'
|
|
|
|
const GAP = 76
|
|
|
|
export function NotificationStack() {
|
|
const notifications = useUnit($notifications)
|
|
const dismissNotification = useUnit(dismissNotificationEvent)
|
|
const navigate = useNavigate()
|
|
|
|
if (notifications.length === 0) return null
|
|
|
|
return (
|
|
<>
|
|
{notifications.map((n, index) => (
|
|
<Snackbar
|
|
key={n.id}
|
|
open
|
|
autoHideDuration={n.autoHideDuration}
|
|
onClose={() => dismissNotification(n.id)}
|
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
|
sx={{
|
|
bottom: `${88 + (notifications.length - 1 - index) * GAP}px !important`,
|
|
zIndex: 2000 + index,
|
|
}}
|
|
>
|
|
<Alert
|
|
severity={n.type}
|
|
variant="standard"
|
|
onClose={() => dismissNotification(n.id)}
|
|
sx={(theme) => ({
|
|
width: '100%',
|
|
minWidth: 360,
|
|
maxWidth: 440,
|
|
px: 2,
|
|
py: 1.5,
|
|
alignItems: 'center',
|
|
color: `${theme.palette.primary.main} !important`,
|
|
boxShadow: '0 4px 16px rgba(0,0,0,0.08)',
|
|
WebkitBackdropFilter: 'blur(8px)',
|
|
backdropFilter: 'blur(8px)',
|
|
'& .MuiAlert-icon': {
|
|
py: 0.5,
|
|
mr: 1.5,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
color: `${theme.palette.primary.main} !important`,
|
|
},
|
|
'& .MuiAlert-message': {
|
|
py: 0.5,
|
|
fontSize: '0.875rem',
|
|
fontWeight: 600,
|
|
lineHeight: 1.5,
|
|
},
|
|
'& .MuiAlert-action': {
|
|
py: 0.5,
|
|
pr: 0,
|
|
ml: 1.5,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 1,
|
|
},
|
|
})}
|
|
action={
|
|
<>
|
|
{n.actionLabel && n.actionPath && (
|
|
<Button
|
|
size="small"
|
|
variant="text"
|
|
onClick={() => {
|
|
dismissNotification(n.id)
|
|
navigate(n.actionPath!)
|
|
}}
|
|
sx={{
|
|
fontWeight: 700,
|
|
fontSize: '0.8125rem',
|
|
px: 1.5,
|
|
py: 0.5,
|
|
borderRadius: 8,
|
|
whiteSpace: 'nowrap',
|
|
color: 'primary.main',
|
|
'&:hover': {
|
|
bgcolor: 'action.hover',
|
|
},
|
|
}}
|
|
>
|
|
{n.actionLabel}
|
|
</Button>
|
|
)}
|
|
<IconButton size="small" onClick={() => dismissNotification(n.id)} sx={{ color: 'primary.main' }}>
|
|
<CloseIcon fontSize="small" />
|
|
</IconButton>
|
|
</>
|
|
}
|
|
>
|
|
{n.message}
|
|
</Alert>
|
|
</Snackbar>
|
|
))}
|
|
</>
|
|
)
|
|
}
|