Comunidade ZDG © 2020 | Praça Getúlio Vargas, 176, Alfenas – MG, CEP 37.130-073 | Tel: (35) 9 8875-4197 | E-mail: [email protected] | Política de Privacidade | Termos de Uso
Art. 49 do Código de Defesa do Consumidor | GARANTIA TOTAL DE 7 DIAS | Este produto não garante a obtenção de resultados. Qualquer referência ao desempenho de uma estratégia não deve ser interpretada como uma garantia de resultados.
Node: link para download
GIT: link para download
import React, { useState, useEffect, useReducer, useContext } from "react";
import openSocket from "socket.io-client";
import { makeStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import Paper from "@material-ui/core/Paper";
import TicketListItem from "../TicketListItem";
import TicketsListSkeleton from "../TicketsListSkeleton";
import useTickets from "../../hooks/useTickets";
import { i18n } from "../../translate/i18n";
import { AuthContext } from "../../context/Auth/AuthContext";
const useStyles = makeStyles(theme => ({
ticketsListWrapper: {
position: "relative",
display: "flex",
height: "100%",
flexDirection: "column",
overflow: "hidden",
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
},
ticketsList: {
flex: 1,
overflowY: "scroll",
...theme.scrollbarStyles,
borderTop: "2px solid rgba(0, 0, 0, 0.12)",
},
ticketsListHeader: {
color: "rgb(67, 83, 105)",
zIndex: 2,
backgroundColor: "white",
borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
},
ticketsCount: {
fontWeight: "normal",
color: "rgb(104, 121, 146)",
marginLeft: "8px",
fontSize: "14px",
},
noTicketsText: {
textAlign: "center",
color: "rgb(104, 121, 146)",
fontSize: "14px",
lineHeight: "1.4",
},
noTicketsTitle: {
textAlign: "center",
fontSize: "16px",
fontWeight: "600",
margin: "0px",
},
noTicketsDiv: {
display: "flex",
height: "100px",
margin: 40,
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
}));
const reducer = (state, action) => {
if (action.type === "LOAD_TICKETS") {
const newTickets = action.payload;
newTickets.forEach(ticket => {
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
if (ticket.unreadMessages > 0) {
state.unshift(state.splice(ticketIndex, 1)[0]);
}
} else {
state.push(ticket);
}
});
return [...state];
}
if (action.type === "RESET_UNREAD") {
const ticketId = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticketId);
if (ticketIndex !== -1) {
state[ticketIndex].unreadMessages = 0;
}
return [...state];
}
if (action.type === "UPDATE_TICKET") {
const ticket = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
} else {
state.unshift(ticket);
}
return [...state];
}
if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") {
const ticket = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
state.unshift(state.splice(ticketIndex, 1)[0]);
} else {
state.unshift(ticket);
}
return [...state];
}
if (action.type === "UPDATE_TICKET_CONTACT") {
const contact = action.payload;
const ticketIndex = state.findIndex(t => t.contactId === contact.id);
if (ticketIndex !== -1) {
state[ticketIndex].contact = contact;
}
return [...state];
}
if (action.type === "DELETE_TICKET") {
const ticketId = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticketId);
if (ticketIndex !== -1) {
state.splice(ticketIndex, 1);
}
return [...state];
}
if (action.type === "RESET") {
return [];
}
};
const TicketsList = (props) => {
const { status, searchParam, showAll, selectedQueueIds, updateCount, style } = props;
const classes = useStyles();
const [pageNumber, setPageNumber] = useState(1);
const [ticketsList, dispatch] = useReducer(reducer, []);
const { user } = useContext(AuthContext);
useEffect(() => {
dispatch({ type: "RESET" });
setPageNumber(1);
}, [status, searchParam, dispatch, showAll, selectedQueueIds]);
const { tickets, hasMore, loading } = useTickets({
pageNumber,
searchParam,
status,
showAll,
queueIds: JSON.stringify(selectedQueueIds),
});
useEffect(() => {
if (!status && !searchParam) return;
dispatch({
type: "LOAD_TICKETS",
payload: tickets,
});
}, [tickets, status, searchParam]);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
const shouldUpdateTicket = ticket =>
(!ticket.userId || ticket.userId === user?.id || showAll) &&
(!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1);
const notBelongsToUserQueues = ticket =>
ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1;
socket.on("connect", () => {
if (status) {
socket.emit("joinTickets", status);
} else {
socket.emit("joinNotification");
}
});
socket.on("ticket", data => {
if (data.action === "updateUnread") {
dispatch({
type: "RESET_UNREAD",
payload: data.ticketId,
});
}
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
dispatch({
type: "UPDATE_TICKET",
payload: data.ticket,
});
}
if (data.action === "update" && notBelongsToUserQueues(data.ticket)) {
dispatch({ type: "DELETE_TICKET", payload: data.ticket.id });
}
if (data.action === "delete") {
dispatch({ type: "DELETE_TICKET", payload: data.ticketId });
}
});
socket.on("appMessage", data => {
if (data.action === "create" && shouldUpdateTicket(data.ticket)) {
dispatch({
type: "UPDATE_TICKET_UNREAD_MESSAGES",
payload: data.ticket,
});
}
});
socket.on("contact", data => {
if (data.action === "update") {
dispatch({
type: "UPDATE_TICKET_CONTACT",
payload: data.contact,
});
}
});
return () => {
socket.disconnect();
};
}, [status, showAll, user, selectedQueueIds]);
useEffect(() => {
const count = ticketsList.filter(ticket => !ticket.isGroup).length;
if (typeof updateCount === "function") {
updateCount(count);
}
}, [ticketsList, updateCount]);
const loadMore = () => {
setPageNumber(prevState => prevState + 1);
};
const handleScroll = e => {
if (!hasMore || loading) return;
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
if (scrollHeight - (scrollTop + 100) < clientHeight) {
loadMore();
}
};
return (
{ticketsList.length === 0 && !loading ? (
{i18n.t("ticketsList.noTicketsTitle")}
{i18n.t("ticketsList.noTicketsMessage")}
) : (
<>
{ticketsList
.filter(ticket => ticket.isGroup.toString() === "false")
.map(ticket => (
))}
>
)}
{loading && }
);
};
export default TicketsList;
import React, { useState, useEffect, useReducer, useContext } from "react";
import openSocket from "socket.io-client";
import { makeStyles } from "@material-ui/core/styles";
import List from "@material-ui/core/List";
import Paper from "@material-ui/core/Paper";
import TicketListItem from "../TicketListItem";
import TicketsListSkeleton from "../TicketsListSkeleton";
import useTickets from "../../hooks/useTickets";
import { i18n } from "../../translate/i18n";
import { AuthContext } from "../../context/Auth/AuthContext";
const useStyles = makeStyles(theme => ({
ticketsListWrapper: {
position: "relative",
display: "flex",
height: "100%",
flexDirection: "column",
overflow: "hidden",
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
},
ticketsList: {
flex: 1,
overflowY: "scroll",
...theme.scrollbarStyles,
borderTop: "2px solid rgba(0, 0, 0, 0.12)",
},
ticketsListHeader: {
color: "rgb(67, 83, 105)",
zIndex: 2,
backgroundColor: "white",
borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
},
ticketsCount: {
fontWeight: "normal",
color: "rgb(104, 121, 146)",
marginLeft: "8px",
fontSize: "14px",
},
noTicketsText: {
textAlign: "center",
color: "rgb(104, 121, 146)",
fontSize: "14px",
lineHeight: "1.4",
},
noTicketsTitle: {
textAlign: "center",
fontSize: "16px",
fontWeight: "600",
margin: "0px",
},
noTicketsDiv: {
display: "flex",
height: "100px",
margin: 40,
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
},
}));
const reducer = (state, action) => {
if (action.type === "LOAD_TICKETS") {
const newTickets = action.payload;
newTickets.forEach(ticket => {
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
if (ticket.unreadMessages > 0) {
state.unshift(state.splice(ticketIndex, 1)[0]);
}
} else {
state.push(ticket);
}
});
return [...state];
}
if (action.type === "RESET_UNREAD") {
const ticketId = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticketId);
if (ticketIndex !== -1) {
state[ticketIndex].unreadMessages = 0;
}
return [...state];
}
if (action.type === "UPDATE_TICKET") {
const ticket = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
} else {
state.unshift(ticket);
}
return [...state];
}
if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") {
const ticket = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticket.id);
if (ticketIndex !== -1) {
state[ticketIndex] = ticket;
state.unshift(state.splice(ticketIndex, 1)[0]);
} else {
state.unshift(ticket);
}
return [...state];
}
if (action.type === "UPDATE_TICKET_CONTACT") {
const contact = action.payload;
const ticketIndex = state.findIndex(t => t.contactId === contact.id);
if (ticketIndex !== -1) {
state[ticketIndex].contact = contact;
}
return [...state];
}
if (action.type === "DELETE_TICKET") {
const ticketId = action.payload;
const ticketIndex = state.findIndex(t => t.id === ticketId);
if (ticketIndex !== -1) {
state.splice(ticketIndex, 1);
}
return [...state];
}
if (action.type === "RESET") {
return [];
}
};
const TicketsList = (props) => {
const { status, searchParam, showAll, selectedQueueIds, updateCount, style } = props;
const classes = useStyles();
const [pageNumber, setPageNumber] = useState(1);
const [ticketsList, dispatch] = useReducer(reducer, []);
const { user } = useContext(AuthContext);
useEffect(() => {
dispatch({ type: "RESET" });
setPageNumber(1);
}, [status, searchParam, dispatch, showAll, selectedQueueIds]);
const { tickets, hasMore, loading } = useTickets({
pageNumber,
searchParam,
status,
showAll,
queueIds: JSON.stringify(selectedQueueIds),
});
useEffect(() => {
if (!status && !searchParam) return;
dispatch({
type: "LOAD_TICKETS",
payload: tickets,
});
}, [tickets, status, searchParam]);
useEffect(() => {
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
const shouldUpdateTicket = ticket =>
(!ticket.userId || ticket.userId === user?.id || showAll) &&
(!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1);
const notBelongsToUserQueues = ticket =>
ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1;
socket.on("connect", () => {
if (status) {
socket.emit("joinTickets", status);
} else {
socket.emit("joinNotification");
}
});
socket.on("ticket", data => {
if (data.action === "updateUnread") {
dispatch({
type: "RESET_UNREAD",
payload: data.ticketId,
});
}
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
dispatch({
type: "UPDATE_TICKET",
payload: data.ticket,
});
}
if (data.action === "update" && notBelongsToUserQueues(data.ticket)) {
dispatch({ type: "DELETE_TICKET", payload: data.ticket.id });
}
if (data.action === "delete") {
dispatch({ type: "DELETE_TICKET", payload: data.ticketId });
}
});
socket.on("appMessage", data => {
if (data.action === "create" && shouldUpdateTicket(data.ticket)) {
dispatch({
type: "UPDATE_TICKET_UNREAD_MESSAGES",
payload: data.ticket,
});
}
});
socket.on("contact", data => {
if (data.action === "update") {
dispatch({
type: "UPDATE_TICKET_CONTACT",
payload: data.contact,
});
}
});
return () => {
socket.disconnect();
};
}, [status, showAll, user, selectedQueueIds]);
useEffect(() => {
const count = ticketsList.filter(ticket => ticket.isGroup).length;
if (typeof updateCount === "function") {
updateCount(count);
}
}, [ticketsList, updateCount]);
const loadMore = () => {
setPageNumber(prevState => prevState + 1);
};
const handleScroll = e => {
if (!hasMore || loading) return;
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
if (scrollHeight - (scrollTop + 100) < clientHeight) {
loadMore();
}
};
return (
{ticketsList.length === 0 && !loading ? (
{i18n.t("ticketsList.noTicketsTitle")}
{i18n.t("ticketsList.noTicketsMessage")}
) : (
<>
{ticketsList
.filter(ticket => ticket.isGroup.toString() === "true")
.map(ticket => (
))}
>
)}
{loading && }
);
};
export default TicketsList;
Oiê! Tem alguma dúvida? Clique aqui!