feat: starting appbar notifications

This commit is contained in:
canove
2020-08-24 17:16:26 -03:00
parent 3fe436fd34
commit ea4ff654ff
17 changed files with 1113 additions and 305 deletions

View File

@@ -0,0 +1,179 @@
import React, { useState, useRef, useCallback, useEffect } from "react";
import { format } from "date-fns";
import openSocket from "socket.io-client";
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 { toast } from "react-toastify";
import { useHistory } from "react-router-dom";
import { i18n } from "../../translate/i18n";
import useTickets from "../../hooks/useTickets";
const useStyles = makeStyles(theme => ({
tabContainer: {
overflowY: "auto",
maxHeight: 350,
"&::-webkit-scrollbar": {
width: "8px",
height: "8px",
},
"&::-webkit-scrollbar-thumb": {
boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)",
backgroundColor: "#e8e8e8",
},
},
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 userId = +localStorage.getItem("userId");
const soundAlert = useRef(new Audio(require("../../assets/sound.mp3")));
const ticketId = +history.location.pathname.split("/")[2];
const anchorEl = useRef();
const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
if (!("Notification" in window)) {
console.log("This browser doesn't support notifications");
} else {
Notification.requestPermission();
}
}, []);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.emit("joinNotification");
socket.on("appMessage", data => {
if (data.action === "create") {
if (
(ticketId &&
data.message.ticketId === +ticketId &&
document.visibilityState === "visible") ||
(data.ticket.userId !== userId && data.ticket.userId)
)
return;
showDesktopNotification(data);
}
});
return () => {
socket.disconnect();
};
}, [history, ticketId, userId]);
const { tickets } = useTickets({ status: "open" });
const showDesktopNotification = ({ message, contact, ticket }) => {
const options = {
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
icon: contact.profilePicUrl,
tag: ticket.id,
};
let notification = new Notification(
`${i18n.t("tickets.notification.message")} ${contact.name}`,
options
);
notification.onclick = function (event) {
event.preventDefault(); //
window.open(`/chat/${ticket.id}`, "_self");
};
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
notification.close();
}
});
soundAlert.current.play();
};
const handleClick = useCallback(() => {
setIsOpen(!isOpen);
}, [isOpen, setIsOpen]);
const handleClickAway = useCallback(() => {
setIsOpen(false);
}, [setIsOpen]);
const handleSelectTicket = (e, ticket) => {
history.push(`/chat/${ticket.id}`);
handleClickAway();
};
return (
<>
<IconButton
onClick={handleClick}
buttonRef={anchorEl}
aria-label="Open Notifications"
color="inherit"
>
<Badge badgeContent={tickets.length} color="secondary">
<ChatIcon />
</Badge>
</IconButton>
<Popover
disableScrollLock
open={isOpen}
anchorEl={anchorEl.current}
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
classes={{ paper: classes.popoverPaper }}
onClose={handleClickAway}
>
<List dense className={classes.tabContainer}>
{tickets.length === 0 ? (
<ListItem>
<ListItemText>
You haven&apos;t received any messages yet.
</ListItemText>
</ListItem>
) : (
tickets.map(ticket => (
<TicketListItem
key={ticket.id}
ticket={ticket}
handleSelectTicket={handleSelectTicket}
/>
))
)}
</List>
</Popover>
</>
);
};
export default NotificationsPopOver;

View File

@@ -1,32 +1,22 @@
import React, { useState, useContext, useEffect, useRef } from "react";
import React, { useState, useContext, useEffect } from "react";
import clsx from "clsx";
import { makeStyles } from "@material-ui/core/styles";
import Drawer from "@material-ui/core/Drawer";
import AppBar from "@material-ui/core/AppBar";
import Toolbar from "@material-ui/core/Toolbar";
import List from "@material-ui/core/List";
import Typography from "@material-ui/core/Typography";
import Divider from "@material-ui/core/Divider";
import IconButton from "@material-ui/core/IconButton";
import Badge from "@material-ui/core/Badge";
import MenuIcon from "@material-ui/icons/Menu";
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
import NotificationsIcon from "@material-ui/icons/Notifications";
import MainListItems from "./MainListItems";
import AccountCircle from "@material-ui/icons/AccountCircle";
import MenuItem from "@material-ui/core/MenuItem";
import Menu from "@material-ui/core/Menu";
import IconButton from "@material-ui/core/IconButton";
import ChevronLeftIcon from "@material-ui/icons/ChevronLeft";
import AccountCircle from "@material-ui/icons/AccountCircle";
import openSocket from "socket.io-client";
import { format } from "date-fns";
// import { toast } from "react-toastify";
import { useHistory } from "react-router-dom";
import { i18n } from "../../translate/i18n";
import MainListItems from "./MainListItems";
import NotificationsPopOver from "./NotificationsPopOver";
import { AuthContext } from "../../context/Auth/AuthContext";
const drawerWidth = 240;
@@ -115,80 +105,20 @@ const MainDrawer = ({ appTitle, children }) => {
const classes = useStyles();
const [open, setOpen] = useState(true);
const [anchorEl, setAnchorEl] = React.useState(null);
const menuOpen = Boolean(anchorEl);
const [menuOpen, setMenuOpen] = useState(false);
const drawerState = localStorage.getItem("drawerOpen");
const history = useHistory();
const ticketId = +history.location.pathname.split("/")[2];
const soundAlert = useRef(new Audio(require("../../assets/sound.mp3")));
const userId = +localStorage.getItem("userId");
// const [notifications, setNotifications] = useState([]);
useEffect(() => {
if (!("Notification" in window)) {
console.log("This browser doesn't support notifications");
} else {
Notification.requestPermission();
}
}, []);
useEffect(() => {
if (drawerState === "0") {
setOpen(false);
}
}, [drawerState]);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.emit("joinNotification");
socket.on("appMessage", data => {
if (data.action === "create") {
if (
(ticketId &&
data.message.ticketId === +ticketId &&
document.visibilityState === "visible") ||
(data.ticket.userId !== userId && data.ticket.userId)
)
return;
showDesktopNotification(data);
}
});
return () => {
socket.disconnect();
};
}, [history, ticketId, userId]);
const showDesktopNotification = ({ message, contact, ticket }) => {
const options = {
body: `${message.body} - ${format(new Date(), "HH:mm")}`,
icon: contact.profilePicUrl,
tag: ticket.id,
};
let notification = new Notification(
`${i18n.t("tickets.notification.message")} ${contact.name}`,
options
);
notification.onclick = function (event) {
event.preventDefault(); //
window.open(`/chat/${ticket.id}`, "_self");
};
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
notification.close();
}
});
soundAlert.current.play();
};
const handleDrawerOpen = () => {
setOpen(true);
localStorage.setItem("drawerOpen", 1);
};
const handleDrawerClose = () => {
setOpen(false);
localStorage.setItem("drawerOpen", 0);
@@ -196,10 +126,12 @@ const MainDrawer = ({ appTitle, children }) => {
const handleMenu = event => {
setAnchorEl(event.currentTarget);
setMenuOpen(true);
};
const handleClose = () => {
const handleCloseMenu = () => {
setAnchorEl(null);
setMenuOpen(false);
};
return (
@@ -225,7 +157,7 @@ const MainDrawer = ({ appTitle, children }) => {
<AppBar
position="absolute"
className={clsx(classes.appBar, open && classes.appBarShift)}
color={process.env.NODE_ENV === "development" ? "secondary" : "primary"}
color={process.env.NODE_ENV === "development" ? "inherit" : "primary"}
>
<Toolbar variant="dense" className={classes.toolbar}>
<IconButton
@@ -249,11 +181,7 @@ const MainDrawer = ({ appTitle, children }) => {
>
{appTitle}
</Typography>
<IconButton color="inherit">
<Badge badgeContent={0} color="secondary">
<NotificationsIcon />
</Badge>
</IconButton>
<NotificationsPopOver />
<div>
<IconButton
@@ -278,9 +206,9 @@ const MainDrawer = ({ appTitle, children }) => {
horizontal: "right",
}}
open={menuOpen}
onClose={handleClose}
onClose={handleCloseMenu}
>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleCloseMenu}>Profile</MenuItem>
<MenuItem onClick={handleLogout}>Logout</MenuItem>
</Menu>
</div>