import React, { useContext, useReducer, useEffect, useState } from "react"; import Paper from "@material-ui/core/Paper"; import Container from "@material-ui/core/Container"; import Grid from "@material-ui/core/Grid"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; import Tooltip from "@mui/material/Tooltip"; import Zoom from "@mui/material/Zoom"; import IconButton from "@mui/material/IconButton"; import Info from "@material-ui/icons/Info"; import useTickets from "../../hooks/useTickets"; import { AuthContext } from "../../context/Auth/AuthContext"; import { i18n } from "../../translate/i18n"; import Chart from "./Chart"; import openSocket from "socket.io-client"; import api from "../../services/api"; import { Can } from "../../components/Can"; import CardUser from "../../components/DashboardUser/CardUser"; import TableUser from "../../components/DashboardUser/TableUser"; const useStyles = makeStyles((theme) => ({ container: { paddingTop: theme.spacing(4), paddingBottom: theme.spacing(4), }, fixedHeightPaper: { padding: theme.spacing(2), display: "flex", overflow: "auto", flexDirection: "column", height: 240, }, customFixedHeightPaper: { padding: theme.spacing(2), display: "flex", overflow: "auto", flexDirection: "column", height: 120, }, customFixedHeightPaperLg: { padding: theme.spacing(2), display: "flex", overflow: "auto", flexDirection: "column", height: "100%", }, containerPaperFix: { width: "100%", textTransform: "capitalize", padding: theme.spacing(2), paddingBottom: theme.spacing(4), height: "auto", overflowY: "hidden", }, cardPaperFix: { textTransform: "capitalize", paddingLeft: theme.spacing(4), paddingRight: theme.spacing(4), height: window.innerWidth <= 992 ? "500px" : "auto", overflowY: "hidden", }, cardStyleFix: { display: "flex", flexDirection: "row", justifyContent: "left", alignItems: "center", gap: "32px", }, logginBtn: { position: "absolute", bottom: "21px", right: "21px", fontSize: "12px", }, tableRowHead: { backgroundColor: "lightgrey", }, tableRowBody: { textAlign: "center", " &:nth-child(even)": { backgroundColor: "#f7f7f7", }, }, tableCounterOpen: { color: "white", backgroundColor: "green", width: "25px", textAlign: "center", borderRadius: "5px", }, tableCounterClosed: { color: "white", backgroundColor: "red", width: "25px", textAlign: "center", borderRadius: "5px", }, })); const reducer = (state, action) => { if (action.type === "DELETE_USER_STATUS") { const userId = action.payload; const userIndex = state.findIndex((u) => `${u.id}` === `${userId}`); if (userIndex !== -1) { state.splice(userIndex, 1); } return [...state]; } if (action.type === "LOAD_QUERY") { const queries = action.payload; const newQueries = []; queries.forEach((query) => { const queryIndex = state.findIndex((q) => q.id === query.id); if (queryIndex !== -1) { state[queryIndex] = query; } else { newQueries.push(query); } }); return [...state, ...newQueries]; } if (action.type === "UPDATE_STATUS_ONLINE") { let onlineUser = action.payload; let index = -1; let onlySumOpenClosed = false; if (onlineUser.sumOpen || onlineUser.sumClosed) { index = state.findIndex( (e) => (onlineUser.sumOpen && e.id === onlineUser.sumOpen.userId) || (onlineUser.sumClosed && e.id === onlineUser.sumClosed.userId) ); onlySumOpenClosed = true; } else { index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`); } if (index !== -1) { if (!onlySumOpenClosed) { if (!("statusOnline" in state[index])) { state[index].statusOnline = onlineUser; } else if ("statusOnline" in state[index]) { state[index].statusOnline["status"] = onlineUser.status; } } if ("onlineTime" in onlineUser) { if ("sumOnlineTime" in state[index]) { state[index].sumOnlineTime["sum"] = onlineUser.onlineTime.split(" ")[1]; } else if (!("sumOnlineTime" in state[index])) { state[index].sumOnlineTime = { userId: onlineUser.userId, sum: onlineUser.onlineTime.split(" ")[1], }; } } if (onlineUser.sumOpen) { if ("sumOpen" in state[index]) { state[index].sumOpen["count"] = onlineUser.sumOpen.count; } else if (!("sumOpen" in state[index])) { state[index].sumOpen = onlineUser.sumOpen; } } if (onlineUser.sumClosed) { if ("sumClosed" in state[index]) { state[index].sumClosed["count"] = onlineUser.sumClosed.count; } else if (!("sumClosed" in state[index])) { state[index].sumClosed = onlineUser.sumClosed; } } } return [...state]; } if (action.type === "RESET") { return []; } }; const Dashboard = () => { const classes = useStyles(); const [usersOnlineInfo, dispatch] = useReducer(reducer, []); const { user } = useContext(AuthContext); var userQueueIds = []; if (user.queues && user.queues.length > 0) { userQueueIds = user.queues.map((q) => q.id); } const GetTickets = (status, showAll, withUnreadMessages, unlimited) => { const { tickets } = useTickets({ status: status, showAll: showAll, withUnreadMessages: withUnreadMessages, queueIds: JSON.stringify(userQueueIds), unlimited: unlimited, }); return tickets.length; }; useEffect(() => { dispatch({ type: "RESET" }); }, []); const handleLogouOnlineUser = async (userId) => { try { await api.get(`/users/logout/${userId}`); //toast.success(("Desloged!")); //handleDeleteRows(scheduleId) } catch (err) { // toastError(err); } }; useEffect(() => { //setLoading(true); const delayDebounceFn = setTimeout(() => { // setLoading(true); const fetchQueries = async () => { try { let date = new Date().toLocaleDateString("pt-BR").split("/"); let dateToday = `${date[2]}-${date[1]}-${date[0]}`; const dataQuery = await api.get("/reports/user/services", { params: { userId: null, startDate: dateToday, endDate: dateToday }, }); dispatch({ type: "RESET" }); dispatch({ type: "LOAD_QUERY", payload: dataQuery.data }); //console.log() } catch (err) { console.log(err); } }; fetchQueries(); }, 500); return () => clearTimeout(delayDebounceFn); }, []); useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL); socket.on("onlineStatus", (data) => { if (data.action === "logout" || data.action === "update") { dispatch({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime }); } else if (data.action === "delete") { dispatch({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime }); } }); socket.on("user", (data) => { if (data.action === "delete") { // console.log(' entrou no delete user: ', data) dispatch({ type: "DELETE_USER", payload: +data.userId }); } }); return () => { socket.disconnect(); }; }, []); return ( <Can role={user.profile} perform="dashboard-view:show" yes={() => ( <Container maxWidth="lg" className={classes.container}> <Grid container spacing={3}> <Paper className={classes.containerPaperFix} sx={12}> <Grid item sx={4}> <Typography component="h1" variant="h4" color="primary" style={{ marginBottom: "16px" }} > tickets <Tooltip title={`Os dados informados abaixo é baseado na data: ${new Date().toLocaleDateString()}`} color="primary" TransitionComponent={Zoom} > <IconButton> <Info /> </IconButton> </Tooltip> </Typography> </Grid> <Grid container spacing={3}> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> {i18n.t("dashboard.messages.inAttendance.title")} </Typography> <Grid item> <Typography component="h1" variant="h4"> {GetTickets("open", "true", "false", "true")} </Typography> </Grid> </Paper> </Grid> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> {i18n.t("dashboard.messages.waiting.title")} </Typography> <Grid item> <Typography component="h1" variant="h4"> {GetTickets("pending", "true", "false", "true")} </Typography> </Grid> </Paper> </Grid> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> {i18n.t("dashboard.messages.closed.title")} </Typography> <Grid item> <Typography component="h1" variant="h4"> {GetTickets("closed", "true", "false", "true")} </Typography> </Grid> </Paper> </Grid> <Grid item xs={12}> <Paper className={classes.fixedHeightPaper} variant="outlined"> <Chart /> </Paper> </Grid> </Grid> </Paper> <Paper className={classes.containerPaperFix} style={{ marginTop: "21px" }} sx={12}> <Grid item sx={4}> <Typography component="h1" variant="h4" color="primary" style={{ marginBottom: "16px" }} > Usuários <Tooltip title={`Os dados informados abaixo é baseado na data: ${new Date().toLocaleDateString()}`} color="primary" TransitionComponent={Zoom} > <IconButton> <Info /> </IconButton> </Tooltip> </Typography> </Grid> <Grid container spacing={3}> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> Total de Agentes </Typography> <Grid item> <Typography component="h1" variant="h4"> {usersOnlineInfo.length} </Typography> </Grid> </Paper> </Grid> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> Online </Typography> <Grid item> <Typography component="h1" variant="h4"> { usersOnlineInfo.filter( (status) => status.statusOnline && status.statusOnline.status === "online" ).length } </Typography> </Grid> </Paper> </Grid> <Grid item xs={12} sm={6} md={6} lg={4}> <Paper className={classes.customFixedHeightPaper} style={{ overflow: "hidden" }} variant="outlined" > <Typography component="h3" variant="h6" color="primary" paragraph> Offline </Typography> <Grid item> <Typography component="h1" variant="h4"> { usersOnlineInfo.filter( (status) => !status.statusOnline || status.statusOnline.status === "offline" ).length } </Typography> </Grid> </Paper> </Grid> {window.innerWidth <= 992 ? ( <CardUser classes={classes} usersOnlineInfo={usersOnlineInfo} logout={handleLogouOnlineUser} /> ) : ( <TableUser classes={classes} usersOnlineInfo={usersOnlineInfo} logout={handleLogouOnlineUser} /> )} </Grid> </Paper> </Grid> </Container> )} /> /**/ ); }; export default Dashboard;