projeto-hit/frontend/src/components/NotificationsPopOver/index.js

293 lines
6.9 KiB
JavaScript
Raw Normal View History

import React, { useState, useRef, useEffect, useContext } from "react";
import { useHistory } from "react-router-dom";
import { format } from "date-fns";
import openSocket from "socket.io-client";
import useSound from "use-sound";
import Popover from "@material-ui/core/Popover";
//import IconButton from "@material-ui/core/IconButton";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import { makeStyles } from "@material-ui/core/styles";
//import Badge from "@material-ui/core/Badge";
//import ChatIcon from "@material-ui/icons/Chat";
import TicketListItem from "../TicketListItem";
import { i18n } from "../../translate/i18n";
import useTickets from "../../hooks/useTickets";
import alertSound from "../../assets/sound.mp3";
import { AuthContext } from "../../context/Auth/AuthContext";
const useStyles = makeStyles(theme => ({
tabContainer: {
overflowY: "auto",
maxHeight: 350,
...theme.scrollbarStyles,
},
popoverPaper: {
width: "100%",
maxWidth: 350,
marginLeft: theme.spacing(2),
marginRight: theme.spacing(1),
[theme.breakpoints.down("sm")]: {
maxWidth: 270,
},
},
noShadow: {
boxShadow: "none !important",
},
}));
const NotificationsPopOver = () => {
const classes = useStyles();
const history = useHistory();
const { user } = useContext(AuthContext);
const ticketIdUrl = +history.location.pathname.split("/")[2];
const ticketIdRef = useRef(ticketIdUrl);
const anchorEl = useRef();
const [isOpen, setIsOpen] = useState(false);
const [notifications, setNotifications] = useState([]);
const [, setDesktopNotifications] = useState([]);
const { tickets } = useTickets({ withUnreadMessages: "true" });
const [play] = useSound(alertSound);
const soundAlertRef = useRef();
const historyRef = useRef(history);
const { handleLogout } = useContext(AuthContext);
useEffect(() => {
soundAlertRef.current = play;
if (!("Notification" in window)) {
console.log("This browser doesn't support notifications");
} else {
Notification.requestPermission();
}
}, [play]);
useEffect(() => {
setNotifications(tickets);
}, [tickets]);
useEffect(() => {
ticketIdRef.current = ticketIdUrl;
}, [ticketIdUrl]);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.on("onlineStatus", (data) => {
if(data.action === "logout"){
console.log('___________data.userId: ', data.userOnlineTime['status'])
if(`${user.id}` === data.userOnlineTime['userId']){
socket.emit("online", {logoutUserId: user.id})
handleLogout();
}
}
});
socket.on("isOnline", (data) => {
// console.log('___________data.userId: ', data.userId)
if(data.action === "online"){
if(data.userId === user.id){
socket.emit("online", user.id)
}
}
});
return () => {
socket.disconnect();
};
2022-05-16 03:33:09 +00:00
}, [user.id, handleLogout]);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.on("connect", () => socket.emit("joinNotification"));
socket.on("ticket", data => {
if (data.action === "updateUnread" || data.action === "delete") {
setNotifications(prevState => {
const ticketIndex = prevState.findIndex(t => t.id === data.ticketId);
if (ticketIndex !== -1) {
prevState.splice(ticketIndex, 1);
return [...prevState];
}
return prevState;
});
setDesktopNotifications(prevState => {
const notfiticationIndex = prevState.findIndex(
n => n.tag === String(data.ticketId)
);
if (notfiticationIndex !== -1) {
prevState[notfiticationIndex].close();
prevState.splice(notfiticationIndex, 1);
return [...prevState];
}
return prevState;
});
}
});
socket.on("appMessage", data => {
if (
data.action === "create" &&
!data.message.read &&
(data.ticket.userId === user?.id || !data.ticket.userId)
) {
// console.log(`data.ticket.userId: ${data.ticket.userId }\n
// data.ticket.status: ${data.ticket.status}\n
// data.ticket.userId: ${data.ticket.userId }`)
setNotifications(prevState => {
const ticketIndex = prevState.findIndex(t => t.id === data.ticket.id);
if (ticketIndex !== -1) {
prevState[ticketIndex] = data.ticket;
return [...prevState];
}
return [data.ticket, ...prevState];
});
const shouldNotNotificate =
(data.message.ticketId === ticketIdRef.current &&
document.visibilityState === "visible") ||
(data.ticket.userId && data.ticket.userId !== user?.id) ||
data.ticket.isGroup || !data.ticket.userId;
if (shouldNotNotificate) return;
handleNotifications(data);
}
});
return () => {
socket.disconnect();
};
}, [user]);
const handleNotifications = data => {
const { message, contact, ticket } = data;
const options = {
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
icon: contact.profilePicUrl,
tag: ticket.id,
renotify: true,
};
const notification = new Notification(
`${i18n.t("tickets.notification.message")} ${contact.name}`,
options
);
notification.onclick = e => {
e.preventDefault();
window.focus();
historyRef.current.push(`/tickets/${ticket.id}`);
};
setDesktopNotifications(prevState => {
const notfiticationIndex = prevState.findIndex(
n => n.tag === notification.tag
);
if (notfiticationIndex !== -1) {
prevState[notfiticationIndex] = notification;
return [...prevState];
}
return [notification, ...prevState];
});
soundAlertRef.current();
};
// const handleClick = () => {
// setIsOpen(prevState => !prevState);
// };
const handleClickAway = () => {
setIsOpen(false);
};
const NotificationTicket = ({ children }) => {
return <div onClick={handleClickAway}>{children}</div>;
};
return (
<>
{/* <IconButton
onClick={handleClick}
// buttonRef={anchorEl}
ref={anchorEl}
aria-label="Open Notifications"
color="inherit"
>
<Badge badgeContent={notifications.length} color="secondary">
<ChatIcon />
</Badge>
</IconButton> */}
<Popover
disableScrollLock
open={isOpen}
anchorEl={anchorEl.current}
anchorOrigin={{
vertical: "bottom",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
classes={{ paper: classes.popoverPaper }}
onClose={handleClickAway}
>
<List dense className={classes.tabContainer}>
{notifications.length === 0 ? (
<ListItem>
<ListItemText>{i18n.t("notifications.noTickets")}</ListItemText>
</ListItem>
) : (
notifications.map(ticket => (
<NotificationTicket key={ticket.id}>
<TicketListItem ticket={ticket} />
</NotificationTicket>
))
)}
</List>
</Popover>
</>
);
};
export default NotificationsPopOver;