Files
aso/frontend/hospital-portal/src/layouts/dashboard/header/NotificationsPopover.tsx
ivan-sim 82eca4b58a Update
2024-10-07 15:04:50 +07:00

286 lines
7.8 KiB
TypeScript
Executable File

import { noCase } from 'change-case';
import { useState, useEffect, useContext } from 'react';
// @mui
import {
Box,
List,
Badge,
Button,
Avatar,
Tooltip,
Divider,
Typography,
ListItemText,
ListSubheader,
ListItemAvatar,
ListItemButton,
Stack
} from '@mui/material';
// utils
import { fToNow } from '@/utils/formatTime';
// _mock_
//import { _notifications } from '@/_mock';
// components
import Iconify from '@/components/Iconify';
import Scrollbar from '@/components/Scrollbar';
import MenuPopover from '@/components/MenuPopover';
import { IconButtonAnimate } from '@/components/animate';
import axios from '@/utils/axios';
import { useSnackbar } from 'notistack';
import { LanguageContext } from '@/contexts/LanguageContext';
// ----------------------------------------------------------------------
export default function NotificationsPopover() {
const { localeData }: any = useContext(LanguageContext);
const [notifications, setNotifications] = useState([]);
const {enqueueSnackbar} = useSnackbar();
const getDataNotifications = async () => {
axios
.get('notifications/1')
.then((response) => {
setNotifications(response.data.data.notifications);
})
.catch((error) => {
enqueueSnackbar(error.response.data.meta.message, {variant : "error"});
});
};
useEffect(() => {
getDataNotifications();
}, []);
const totalUnRead = notifications.filter((item) => item.isUnRead === 1).length;
const [open, setOpen] = useState<HTMLElement | null>(null);
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
setOpen(event.currentTarget);
};
const handleClose = () => {
setOpen(null);
};
const handleMarkAllAsRead = () => {
setNotifications(
notifications.map((notification) => ({
...notification,
isUnRead: 0,
}))
);
};
return (
<>
<IconButtonAnimate
color={open ? 'primary' : 'default'}
onClick={handleOpen}
sx={{ width: 40, height: 40 }}
>
<Badge badgeContent={totalUnRead} color="error">
<Iconify icon="eva:bell-fill" width={20} height={20} />
</Badge>
</IconButtonAnimate>
<MenuPopover
open={Boolean(open)}
anchorEl={open}
onClose={handleClose}
sx={{ width: 360, p: 0, mt: 1.5, ml: 0.75 }}
>
<Box sx={{ display: 'flex', alignItems: 'center', py: 2, px: 2.5 }}>
<Box sx={{ flexGrow: 1 }}>
<Typography variant="subtitle1">{localeData.txtNotifications}</Typography>
<Typography variant="body2" sx={{ color: 'text.secondary' }}>
{localeData.txtYouHave} {totalUnRead} {localeData.txtUnm}
</Typography>
</Box>
{/* {totalUnRead > 0 && (
<Tooltip title=" Mark all as read">
<IconButtonAnimate color="primary" onClick={handleMarkAllAsRead}>
<Iconify icon="eva:done-all-fill" width={20} height={20} />
</IconButtonAnimate>
</Tooltip>
)} */}
</Box>
<Divider sx={{ borderStyle: 'dashed' }} />
<Scrollbar sx={{ height: { xs: 340, sm: 'auto' } }}>
{notifications && notifications.length > 0 ? (
<>
<List
disablePadding
subheader={
<ListSubheader disableSticky sx={{ py: 1, px: 2.5, typography: 'overline' }}>
{localeData.txtNew}
</ListSubheader>
}
>
{notifications.slice(0, 2).map((notification) => (
<NotificationItem key={notification.id} notification={notification} getDataNotifications={getDataNotifications}/>
))}
</List>
<List
disablePadding
subheader={
<ListSubheader disableSticky sx={{ py: 1, px: 2.5, typography: 'overline' }}>
{localeData.txtBeforeThat}
</ListSubheader>
}
>
{notifications.slice(2, 5).map((notification) => (
<NotificationItem key={notification.id} notification={notification} getDataNotifications={getDataNotifications}/>
))}
</List>
</>
): ''}
</Scrollbar>
<Divider sx={{ borderStyle: 'dashed' }} />
{/* <Box sx={{ p: 1 }}>
<Button fullWidth disableRipple>
View All
</Button>
</Box> */}
</MenuPopover>
</>
);
}
// ----------------------------------------------------------------------
type NotificationItemProps = {
id: string;
title: string;
description: string;
avatar: string | null;
type: string;
createdAt: Date;
isUnRead: boolean;
};
function NotificationItem({ notification, getDataNotifications }: { notification: NotificationItemProps, getDataNotifications: () => void}) {
const { avatar, title } = renderContent(notification);
const {enqueueSnackbar} = useSnackbar();
const handleClick = () => {
const data = {
'user_id' : 1,
'id' : notification.id,
};
if(notification.isUnRead)
{
axios
.post('set-read-notification', data)
.then((response) => {
enqueueSnackbar(response.data.meta.message, {variant : "success"});
getDataNotifications();
})
.catch((error) => {
enqueueSnackbar(error.response.data.meta.message, {variant : "error"});
});
}
};
return (
<ListItemButton
onClick={handleClick}
sx={{
py: 1.5,
px: 2.5,
mt: '1px',
...(notification.isUnRead && {
bgcolor: 'action.selected',
}),
}}
>
<ListItemAvatar>
<Avatar sx={{ bgcolor: 'background.neutral' }}>{avatar}</Avatar>
</ListItemAvatar>
<ListItemText
primary={title}
secondary={
<Typography
variant="caption"
sx={{
mt: 0.5,
display: 'flex',
alignItems: 'center',
color: 'text.disabled',
}}
>
<Iconify icon="eva:clock-outline" sx={{ mr: 0.5, width: 16, height: 16 }} />
{fToNow(notification.createdAt)}
</Typography>
}
/>
</ListItemButton>
);
}
// ----------------------------------------------------------------------
function renderContent(notification: NotificationItemProps) {
const title = (
<Stack direction="column">
<Typography variant="subtitle2">{notification.title}</Typography>
<Typography component="span" variant="body2" sx={{ color: 'text.secondary' }}>
{notification.description}
</Typography>
</Stack>
);
if (notification.type === 'order_placed') {
return {
avatar: (
<img
alt={notification.title}
src="https://minimal-assets-api.vercel.app/assets/icons/ic_notification_package.svg"
/>
),
title,
};
}
if (notification.type === 'order_shipped') {
return {
avatar: (
<img
alt={notification.title}
src="https://minimal-assets-api.vercel.app/assets/icons/ic_notification_shipping.svg"
/>
),
title,
};
}
if (notification.type === 'mail' || notification.type === 'request_document' || notification.type === 'grab_status') {
return {
avatar: (
<img
alt={notification.title}
src="/icons/ic_mail.svg"
/>
),
title,
};
}
if (notification.type === 'chat_message') {
return {
avatar: (
<img
alt={notification.title}
src="https://minimal-assets-api.vercel.app/assets/icons/ic_notification_chat.svg"
/>
),
title,
};
}
return {
avatar: notification.avatar ? <img alt={notification.title} src={notification.avatar} /> : null,
title,
};
}