projeto-hit/frontend/src/pages/Report/index.js

700 lines
20 KiB
JavaScript

import React, { useState, useEffect, useReducer, useContext, useRef } from "react";
import MainContainer from "../../components/MainContainer";
import api from "../../services/api";
import SelectField from "../../components/Report/SelectField";
//import { data } from '../../components/Report/MTable/data';
import DatePicker1 from "../../components/Report/DatePicker";
import DatePicker2 from "../../components/Report/DatePicker";
import MTable from "../../components/Report/MTable";
import PropTypes from "prop-types";
import Box from "@mui/material/Box";
import { AuthContext } from "../../context/Auth/AuthContext";
import { Can } from "../../components/Can";
import { Button } from "@material-ui/core";
import ReportModal from "../../components/ReportModal";
import MaterialTable from "material-table";
import LogoutIcon from "@material-ui/icons/CancelOutlined";
import { CSVLink } from "react-csv";
import openSocket from "socket.io-client";
const report = [
{ value: "1", label: "Atendimento por atendentes" },
{ value: "2", label: "Usuários online/offline" },
];
let columns = [
{
key: "ticket.whatsapp.name",
label: "Loja",
},
{
key: "id",
label: "id Mensagem",
},
{
key: "ticket.id",
label: "id Conversa",
},
{
key: "ticket.contact.name",
label: "Cliente",
},
{
key: "ticket.user.name",
label: "Atendente",
},
{
key: "body",
label: "Mensagem",
},
{
key: "fromMe",
label: "Sentido",
},
{
key: "createdAt",
label: "Criada",
},
{
key: "ticket.contact.number",
label: "Telefone cliente",
},
{
key: "ticket.queue.name",
label: "Fila",
},
{
key: "ticket.status",
label: "Status",
},
{
key: "ticket.statusChatEnd",
label: "Status de encerramento",
},
];
//
const reducerQ = (state, action) => {
if (action.type === "DELETE_USER_STATUS") {
const userId = action.payload;
//console.log('Entrou no delete user status userId: ', userId)
const userIndex = state.findIndex((u) => `${u.id}` === `${userId}`);
// console.log('>>>>>>>>>>>>>>>>>>>>> userIndex: ', userIndex)
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;
// console.log('sssssssssstate: ', state, ' | ONLINE USERS: onlineUser.userId ', onlineUser.userId)
if (onlineUser.sumOpen || onlineUser.sumClosed) {
index = state.findIndex(
(e) =>
(onlineUser.sumOpen && e.id === onlineUser.sumOpen.userId) ||
(onlineUser.sumClosed && e.id === onlineUser.sumClosed.userId)
);
} else {
index = state.findIndex((e) => `${e.id}` === `${onlineUser.userId}`);
}
//console.log(' *********************** index: ', index)
if (index !== -1) {
// console.log('ENTROU NO INDEX')
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]) {
// console.log(' >>>>>>>>>>>>>>>>>> sumOpen 1 | state[index].sumOpen["count"]: ', state[index].sumOpen['count'], ' | onlineUser.sumOpen.count: ', onlineUser.sumOpen.count)
state[index].sumOpen["count"] = onlineUser.sumOpen.count;
} else if (!("sumOpen" in state[index])) {
// console.log(' >>>>>>>>>>>>>>>>>> sumOpen 1')
state[index].sumOpen = onlineUser.sumOpen;
}
}
if (onlineUser.sumClosed) {
if ("sumClosed" in state[index]) {
// console.log(' >>>>>>>>>>>>>>>>>> sumClosed 1 | state[index].sumClosed["count"]: ', state[index].sumClosed['count'], ' | onlineUser.sumClosed.count: ', onlineUser.sumClosed.count)
state[index].sumClosed["count"] = onlineUser.sumClosed.count;
} else if (!("sumClosed" in state[index])) {
// console.log(' >>>>>>>>>>>>>>>>>> sumOpen 1')
state[index].sumClosed = onlineUser.sumClosed;
}
}
}
return [...state];
}
if (action.type === "RESET") {
return [];
}
};
const reducer = (state, action) => {
if (action.type === "LOAD_USERS") {
const users = action.payload;
const newUsers = [];
users.forEach((user) => {
const userIndex = state.findIndex((u) => u.id === user.id);
if (userIndex !== -1) {
state[userIndex] = user;
} else {
newUsers.push(user);
}
});
return [...state, ...newUsers];
}
if (action.type === "DELETE_USER") {
const userId = action.payload;
const userIndex = state.findIndex((u) => u.id === userId);
if (userIndex !== -1) {
state.splice(userIndex, 1);
}
return [...state];
}
if (action.type === "RESET") {
return [];
}
};
function Item(props) {
const { sx, ...other } = props;
return (
<Box
sx={{
bgcolor: (theme) => (theme.palette.mode === "dark" ? "#101010" : "#fff"),
color: (theme) => (theme.palette.mode === "dark" ? "grey.300" : "grey.800"),
border: "1px solid",
borderColor: (theme) => (theme.palette.mode === "dark" ? "grey.800" : "grey.300"),
p: 1,
m: 1,
borderRadius: 2,
fontSize: "0.875rem",
fontWeight: "700",
...sx,
}}
{...other}
/>
);
}
Item.propTypes = {
sx: PropTypes.oneOfType([
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])),
PropTypes.func,
PropTypes.object,
]),
};
let columnsData = [
{ title: "Unidade", field: "whatsapp.name" },
{ title: "Atendente", field: "user.name" },
{ title: "Contato", field: "contact.number" },
{ title: "Nome", field: "contact.name" },
{ title: "Assunto", field: "queue.name" },
{ title: "Status", field: "status" },
{ title: "Criado", field: "createdAt" },
//{title: 'Atualizado', field: 'updatedAt'},
{ title: "Status de encerramento", field: "statusChatEnd" },
];
const Report = () => {
const csvLink = useRef();
const { user: userA } = useContext(AuthContext);
//--------
const [searchParam] = useState("");
//const [loading, setLoading] = useState(false);
//const [hasMore, setHasMore] = useState(false);
const [pageNumber, setPageNumber] = useState(1);
const [users, dispatch] = useReducer(reducer, []);
//const [columns, setColums] = useState([])
const [startDate, setDatePicker1] = useState(new Date());
const [endDate, setDatePicker2] = useState(new Date());
const [userId, setUser] = useState(null);
const [query, dispatchQ] = useReducer(reducerQ, []);
const [dataCSV, setDataCSV] = useState([]);
const [isMount, setIsMount] = useState(true);
const [reportOption, setReport] = useState("1");
const [reporList] = useState(report);
const [profile, setProfile] = useState("");
const [dataRows, setData] = useState([]);
useEffect(() => {
dispatch({ type: "RESET" });
dispatchQ({ type: "RESET" });
setPageNumber(1);
}, [searchParam, profile]);
useEffect(() => {
//setLoading(true);
const delayDebounceFn = setTimeout(() => {
const fetchUsers = async () => {
try {
//console.log('profile: ', profile)
const { data } = await api.get("/users/", {
params: { searchParam, pageNumber, profile },
});
dispatch({ type: "LOAD_USERS", payload: data.users });
//setHasMore(data.hasMore);
//setLoading(false);
} catch (err) {
console.log(err);
}
};
fetchUsers();
}, 500);
return () => clearTimeout(delayDebounceFn);
}, [searchParam, pageNumber, reportOption, profile]);
useEffect(() => {
//setLoading(true);
const delayDebounceFn = setTimeout(() => {
const fetchQueries = async () => {
try {
if (reportOption === "1") {
const dataQuery = await api.get("/reports/", {
params: { userId, startDate, endDate },
});
dispatchQ({ type: "RESET" });
dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data });
//setLoading(false);
// console.log('dataQuery: ', dataQuery.data)
// console.log()
} else if (reportOption === "2") {
const dataQuery = await api.get("/reports/user/services", {
params: { userId, startDate, endDate },
});
dispatchQ({ type: "RESET" });
dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data });
//setLoading(false);
// console.log('REPORT 2 dataQuery : ', dataQuery.data)
//console.log()
}
} catch (err) {
console.log(err);
}
};
fetchQueries();
}, 500);
return () => clearTimeout(delayDebounceFn);
}, [userId, startDate, endDate, reportOption]);
// Get from child 1
const datePicker1Value = (data) => {
setDatePicker1(data);
};
// Get from child 2
const datePicker2Value = (data) => {
setDatePicker2(data);
};
// Get from child 3
const textFieldSelectUser = (data) => {
setUser(data);
};
// Get from report option
const reportValue = (data) => {
setReport(data);
// console.log(' data: ', data)
};
useEffect(() => {
if (reportOption === "1") {
setProfile("");
} else if (reportOption === "2") {
setProfile("user");
}
}, [reportOption]);
// useEffect(() => {
// console.log('>>>>>>>>>>>>>>>>>> New query: ', query)
// }, [query])
// test del
const handleCSVMessages = () => {
// setLoading(true);
const fetchQueries = async () => {
try {
const dataQuery = await api.get("/reports/messages", {
params: { userId, startDate, endDate },
});
// console.log('dataQuery messages: ', dataQuery.data)
if (dataQuery.data.length > 0) {
let dataCSVFormat = dataQuery.data;
for (var i = 0; i < dataCSVFormat.length; i++) {
if (dataCSVFormat[i].fromMe) {
dataCSVFormat[i].fromMe = "Atendente";
} else {
dataCSVFormat[i].fromMe = "Cliente";
}
}
// console.log('dataCSVFormat: ', dataCSVFormat)
setDataCSV(dataCSVFormat);
setIsMount(false);
// setDataCSV(dataQuery.data)
}
// setLoading(false);
} catch (err) {
console.log(err);
}
};
fetchQueries();
};
useEffect(() => {
if (isMount) {
return;
}
csvLink.current.link.click();
}, [dataCSV, isMount, csvLink]);
useEffect(() => {
if (reportOption === "2") {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
socket.on("onlineStatus", (data) => {
// setLoading(true);
let date = new Date().toLocaleDateString("pt-BR").split("/");
let dateToday = `${date[2]}-${date[1]}-${date[0]}`;
// console.log('date: ', new Date(startDate).toLocaleDateString('pt-BR'))
// console.log('date2: ', startDate)
if (
data.action === "logout" ||
(data.action === "update" &&
`${startDate}` === `${endDate}` &&
`${endDate}` === `${dateToday}` &&
`${startDate}` === `${dateToday}`)
) {
//console.log('UPDATE FROM ONLINE/OFFLINE LOGED USERS: ', data.userOnlineTime, ' | data.action : ', data.action)
dispatchQ({ type: "UPDATE_STATUS_ONLINE", payload: data.userOnlineTime });
} else if (data.action === "delete") {
dispatchQ({ type: "DELETE_USER_STATUS", payload: data.userOnlineTime });
}
// setLoading(false);
});
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();
};
}
}, [reportOption, startDate, endDate]);
// const handleDeleteRows = (id) => {
// let _data = [...dataRows];
// _data.forEach(rd => {
// _data = _data.filter(t => t.id !== id);
// });
// setData(_data);
// };
useEffect(() => {
//if (!loading) {
// setData(query.map(({ scheduleReminder, ...others }) => (
// { ...others, 'scheduleReminder': `${others.statusChatEndId}` === '3' ? 'Agendamento' : 'Lembrete' }
// )))
// }
setData(
query.map((column) => {
return { ...column };
})
);
}, [query]);
const handleLogouOnlineUser = async (userId) => {
try {
await api.get(`/users/logout/${userId}`);
//toast.success(("Desloged!"));
//handleDeleteRows(scheduleId)
} catch (err) {
// toastError(err);
}
};
return (
<Can
role={userA.profile}
perform="ticket-report:show"
yes={() => (
<MainContainer>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
<Item><SelectField func={textFieldSelectUser} emptyField={true} header={'Usuário'} currencies={users.map((obj) => {
return { 'value': obj.id, 'label': obj.name }
})} /></Item>
<Item><DatePicker1 func={datePicker1Value} minDate={true} startEmpty={false} title={'Data inicio'} /></Item>
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={'Data fim'} /></Item>
<Item>
<DatePicker1
func={datePicker1Value}
minDate={false}
startEmpty={false}
title={"Data inicio"}
/>
</Item>
<Item>
<DatePicker2
func={datePicker2Value}
minDate={false}
startEmpty={false}
title={"Data fim"}
/>
</Item>
<Item sx={{ display: "grid", gridColumn: "4 / 5" }}>
<ReportModal currencies={reporList} func={reportValue} reportOption={reportOption} />
<div style={{ margin: "2px" }}></div>
<div>
{/* <Button
variant="contained"
color="primary"
onClick={(e) => handleCSVMessages()}
>
{"CSV ALL"}
</Button> */}
<div>
<CSVLink
data={dataCSV}
headers={columns}
filename={"Relatorio_detalhado_atendimento_atendentes.csv"}
target={"_blank"}
ref={csvLink}
/>
</div>
</div>
)}
</Item>
</Box>
<Box
sx={{
display: "grid",
}}
>
<Item sx={{ gridColumn: "1", gridRow: "span 1" }}>
{reportOption === "1" && (
<MTable
data={query}
columns={columnsData}
hasChild={true}
removeClickRow={false}
table_title={"Atendimento por atendentes"}
/>
)}
{reportOption === "2" && (
<MaterialTable
localization={{
header: {
actions: "Deslogar",
},
}}
title="Usuários online/offline"
columns={[
// { title: 'Foto', field: 'ticket.contact.profilePicUrl', render: rowData => <img src={rowData['ticket.contact.profilePicUrl']} alt="imagem de perfil do whatsapp" style={{ width: 40, borderRadius: '50%' }} /> },
{ title: "Nome", field: "name", cellStyle: { whiteSpace: "nowrap" } },
{
title: "Status",
field: "statusOnline.status",
cellStyle: (e, rowData) => {
if (rowData["statusOnline"] && rowData["statusOnline"].status) {
if (rowData["statusOnline"].status === "offline") {
return { color: "red" };
} else if (rowData["statusOnline"].status === "online") {
return { color: "green" };
} else if (rowData["statusOnline"].status === "logout...") {
return { color: "orange" };
} else if (rowData["statusOnline"].status === "waiting...") {
return { color: "orange" };
}
}
},
},
{ title: "Tempo online", field: "sumOnlineTime.sum" },
{ title: "Data inicio", field: "startDate" },
{ title: "Data fim", field: "endDate" },
{ title: "Em atendimento", field: "sumOpen.count" },
{ title: "Finalizado", field: "sumClosed.count" },
]}
data={dataRows}
// icons={tableIcons}
actions={[
(rowData) => {
if (
rowData.statusOnline &&
rowData.statusOnline["status"] &&
rowData.statusOnline["status"] === "online"
) {
return {
icon: LogoutIcon,
tooltip: "deslogar",
disable: false,
onClick: (event, rowData) => {
// console.log(' ROW DATA INFO: ', rowData, ' | rowData: ', rowData.id)
handleLogouOnlineUser(rowData.id);
},
};
}
},
]}
options={{
search: true,
selection: false,
paging: false,
padding: "dense",
sorting: true,
//loadingType: 'linear',
searchFieldStyle: {
width: 300,
},
pageSize: 20,
headerStyle: {
position: "sticky",
top: "0",
},
maxBodyHeight: "400px",
rowStyle: {
fontSize: 14,
},
// cellStyle: (rowData) => {
// return {
// fontSize: 12,
// color: "#fff",
// };
// }
}}
/>
)}
</Item>
</Box>
</MainContainer>
)}
/>
);
};
export default Report;