114 lines
4.2 KiB
JavaScript
114 lines
4.2 KiB
JavaScript
import { Virtuoso } from "react-virtuoso";
|
|
import { Badge, Button, Space, Spin, Switch, Tooltip, Typography } from "antd";
|
|
import { CheckCircleFilled, CheckCircleOutlined, EyeFilled, EyeOutlined } from "@ant-design/icons";
|
|
import { useTranslation } from "react-i18next";
|
|
import { useNavigate } from "react-router-dom";
|
|
import "./notification-center.styles.scss";
|
|
import day from "../../utils/day.js";
|
|
import { forwardRef } from "react";
|
|
import { DateTimeFormat } from "../../utils/DateFormatter.jsx";
|
|
|
|
const { Text, Title } = Typography;
|
|
|
|
/**
|
|
* Notification Center Component
|
|
* @type {React.ForwardRefExoticComponent<React.PropsWithoutRef<{readonly visible?: *, readonly onClose?: *, readonly notifications?: *, readonly loading?: *, readonly showUnreadOnly?: *, readonly toggleUnreadOnly?: *, readonly markAllRead?: *, readonly loadMore?: *, readonly onNotificationClick?: *, readonly unreadCount?: *}> & React.RefAttributes<unknown>>}
|
|
*/
|
|
const NotificationCenterComponent = forwardRef(
|
|
(
|
|
{
|
|
visible,
|
|
onClose,
|
|
notifications,
|
|
loading,
|
|
showUnreadOnly,
|
|
toggleUnreadOnly,
|
|
markAllRead,
|
|
loadMore,
|
|
onNotificationClick,
|
|
unreadCount
|
|
},
|
|
ref
|
|
) => {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
|
|
const renderNotification = (index, notification) => {
|
|
const handleClick = () => {
|
|
if (!notification.read) {
|
|
onNotificationClick(notification.id);
|
|
}
|
|
navigate(`/manage/jobs/${notification.jobid}`);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
key={`${notification.id}-${index}`}
|
|
className={`notification-item ${notification.read ? "notification-read" : "notification-unread"}`}
|
|
onClick={handleClick}
|
|
>
|
|
<Badge dot={!notification.read}>
|
|
<div className="notification-content">
|
|
<Title level={5} className="notification-title">
|
|
<span className="ro-number">
|
|
{t("notifications.labels.ro-number", { ro_number: notification.roNumber })}
|
|
</span>
|
|
<Text type="secondary" className="relative-time" title={DateTimeFormat(notification.created_at)}>
|
|
{day(notification.created_at).fromNow()}
|
|
</Text>
|
|
</Title>
|
|
<Text strong={!notification.read} className="notification-body">
|
|
<ul>
|
|
{notification.scenarioText.map((text, idx) => (
|
|
<li key={`${notification.id}-${idx}`}>{text}</li>
|
|
))}
|
|
</ul>
|
|
</Text>
|
|
</div>
|
|
</Badge>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className={`notification-center ${visible ? "visible" : ""}`} ref={ref}>
|
|
<div className="notification-header">
|
|
<Space direction="horizontal">
|
|
<h3>{t("notifications.labels.notification-center")}</h3>
|
|
{loading && <Spin spinning={loading} size="small"></Spin>}
|
|
</Space>
|
|
<div className="notification-controls">
|
|
<Tooltip title={t("notifications.labels.show-unread-only")}>
|
|
<Space size={4} align="center" className="notification-toggle">
|
|
{showUnreadOnly ? (
|
|
<EyeFilled className="notification-toggle-icon" />
|
|
) : (
|
|
<EyeOutlined className="notification-toggle-icon" />
|
|
)}
|
|
<Switch checked={showUnreadOnly} onChange={(checked) => toggleUnreadOnly(checked)} size="small" />
|
|
</Space>
|
|
</Tooltip>
|
|
<Tooltip title={t("notifications.labels.mark-all-read")}>
|
|
<Button
|
|
type="link"
|
|
icon={!unreadCount ? <CheckCircleFilled /> : <CheckCircleOutlined />}
|
|
onClick={markAllRead}
|
|
disabled={!unreadCount}
|
|
/>
|
|
</Tooltip>
|
|
</div>
|
|
</div>
|
|
<Virtuoso
|
|
style={{ height: "400px", width: "100%" }}
|
|
data={notifications}
|
|
totalCount={notifications.length}
|
|
endReached={loadMore}
|
|
itemContent={renderNotification}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
);
|
|
|
|
export default NotificationCenterComponent;
|