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

418 lines
9.1 KiB
JavaScript

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 { socket } from "../../services/socket"
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"
import api from "../../services/api";
import toastError from "../../errors/toastError";
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",
},
}))
let _fifo
// const onlineEmitter = async (socket, user) => {
// try {
// clearInterval(_fifo);
// socket.emit("online", user.id)
// } catch (error) {
// console.log('error on onlineEmitter: ', error)
// }
// finally {
// _fifo = setInterval(onlineEmitter, 3000);
// }
// }
// _fifo = setInterval(onlineEmitter, 3000);
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)
const [settings, setSettings] = useState([]);
// const [lastRef] = useState(+history.location.pathname.split("/")[2])
useEffect(() => {
soundAlertRef.current = play
if (!("Notification" in window)) {
} else {
Notification.requestPermission()
}
}, [play])
useEffect(() => {
setNotifications(tickets)
}, [tickets])
useEffect(() => {
ticketIdRef.current = ticketIdUrl
}, [ticketIdUrl])
useEffect(() => {
const fetchSession = async () => {
try {
const { data } = await api.get('/settings')
setSettings(data.settings)
} catch (err) {
toastError(err)
}
}
fetchSession()
}, [])
const getSettingValue = (key) => {
const { value } = settings.find((s) => s.key === key)
return value
}
useEffect(() => {
//const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
socket.on("reload_page", (data) => {
if (user.id === data.userId) {
window.location.reload(true)
}
})
socket.on("onlineStatus", (data) => {
if (data.action === "logout") {
if (`${user.id}` === data.userOnlineTime['userId']) {
socket.emit("online", { logoutUserId: user.id })
handleLogout()
}
}
})
// socket.on("isOnline", (data) => {
// if (data.action === "online") {
// if (data.userId === user.id) {
// socket.emit("online", user.id)
// }
// }
// });
if (user.profile === 'user') {
if (_fifo) {
clearInterval(_fifo)
}
_fifo = setInterval(() => {
socket.emit("online", user.id)
}, 3000)
}
return () => {
socket.removeAllListeners('reload_page');
socket.removeAllListeners('onlineStatus');
}
}, [user.id, handleLogout, user.profile])
useEffect(() => {
//const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
const onConnectNotifications = () => {
socket.emit("joinNotification")
}
onConnectNotifications()
socket.on("connect", onConnectNotifications)
const onTicketNotifications = 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("ticket", onTicketNotifications)
const onAppMessageNotifications = data => {
if (
data.action === "create" &&
!data.message.read &&
(data.ticket.userId === user?.id || !data.ticket.userId)
) {
setNotifications(prevState => {
// prevState.forEach((e)=>{
//
// })
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)
}
}
socket.on("appMessage", onAppMessageNotifications)
socket.on('notifyPeding', data => {
if (settings?.length > 0 && getSettingValue('notificationTransferQueue') === 'enabled') handleNotifications("", data);
});
return () => {
socket.off('connect', onConnectNotifications);
socket.off('ticket', onTicketNotifications);
socket.off('appMessage', onAppMessageNotifications);
socket.removeAllListeners('notifyPeding');
}
}, [user, settings])
const handleNotifications = (data, notify) => {
let isQueue = false;
if (!notify) {
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]
})
} else {
user.queues.forEach(queue => {
if (queue.id === notify.data?.queue?.id) {
isQueue = true;
}
})
if (!isQueue) {
return;
} else {
const notification = new Notification(`${i18n.t("tickets.notification.messagePeding")} ${notify.data?.queue?.name}`);
notification.onclick = e => {
e.preventDefault()
window.focus()
historyRef.current.push(`/tickets`)
}
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