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

422 lines
9.4 KiB
JavaScript

import React, { useState, useEffect, useReducer, useContext } from "react"
//import openSocket from "socket.io-client"
import { socket } from "../../services/socket"
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"
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
import { Divider } from "@material-ui/core"
import { ticketsContext } from "../../context/TicketsProvider/TicketsProvider"
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 message = action.payload.message
const ticket = action.payload.ticket
const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
if (ticketIndex !== -1) {
if (!message.fromMe) {
ticket.unreadMessages += 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, searchParamContent, showAll, selectedQueueIds, updateCount, style, tab } = props
const classes = useStyles()
const [pageNumber, setPageNumber] = useState(1)
const [ticketsList, dispatch] = useReducer(reducer, [])
const { user, setting, } = useContext(AuthContext)
const { searchTicket } = useContext(SearchTicketContext)
const [_remoteTicketsControll, setRemoteTicketsControll] = useState([])
const [settings, setSettings] = useState([])
useEffect(() => {
setSettings(setting)
}, [setting])
const { setTickets } = useContext(ticketsContext)
useEffect(() => {
dispatch({ type: "RESET" })
setPageNumber(1)
}, [status, searchParam, searchParamContent, showAll, selectedQueueIds, searchTicket])
let { tickets, hasMore, loading, remoteTicketsControll } = useTickets({
pageNumber,
searchParam,
searchParamContent,
status,
showAll,
queueIds: JSON.stringify(selectedQueueIds),
tab,
unlimited: status === 'open' ? "all" : "false"
})
useEffect(() => {
setRemoteTicketsControll(remoteTicketsControll)
}, [remoteTicketsControll])
useEffect(() => {
if (!status && !searchParam) return
// if (searchParam) {
//
// dispatch({ type: "RESET" });
// }
if ((searchParam && searchParam.trim().length > 0) &&
(tickets && tickets.length === 0) &&
pageNumber === 1) {
dispatch({ type: "RESET" })
}
dispatch({ type: "LOAD_TICKETS", payload: tickets, })
}, [tickets, status, searchParam, pageNumber])
useEffect(() => {
// if (tab=='search')return
//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
const onConnectTicketList = () => {
if (status) {
socket.emit("joinTickets", status)
} else {
socket.emit("joinNotification")
}
}
onConnectTicketList()
socket.on("connect", onConnectTicketList)
const onTicketTicketList = data => {
if (data.action === "updateUnread") {
if (tab === 'search' && data.ticket && data.ticket.status === 'pending') return
dispatch({
type: "RESET_UNREAD",
payload: data.ticketId,
})
}
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
if (tab === 'search' && data.ticket && (data.ticket.status === 'pending' || data.ticket.status === 'closed')) return
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("ticket", onTicketTicketList)
const onAppMessageTicketList = data => {
if (data.action === "create" && shouldUpdateTicket(data.ticket)) {
if (tab === 'search') return
dispatch({
type: "UPDATE_TICKET_UNREAD_MESSAGES",
// payload: data.ticket,
payload: data,
})
}
}
socket.on("appMessage", onAppMessageTicketList)
socket.on("contact", data => {
if (data.action === "update") {
dispatch({
type: "UPDATE_TICKET_CONTACT",
payload: data.contact,
})
}
})
socket.on('remoteTickesControll', (data) => {
console.log('REMOTE TICKETS CONTROLL UPDATE 1: ', data.tickets)
if (data.action === 'update') {
setRemoteTicketsControll(data.tickets)
}
})
const onSettingsTicketList = (data) => {
if (data.action === 'update') {
setSettings((prevState) => {
const aux = [...prevState]
const settingIndex = aux.findIndex((s) => s.key === data.setting.key)
aux[settingIndex].value = data.setting.value
return aux
})
}
}
socket.on('settings', onSettingsTicketList)
return () => {
socket.off("ticket", onTicketTicketList)
socket.off('appMessage', onAppMessageTicketList);
socket.removeAllListeners("contact")
socket.off('connect', onConnectTicketList);
socket.off('settings', onSettingsTicketList);
socket.removeAllListeners('remoteTickesControll');
}
}, [status, showAll, user, selectedQueueIds, tab])
useEffect(() => {
if (typeof updateCount === "function") {
updateCount(ticketsList.length)
}
if (ticketsList && status === "pending") {
setTickets(ticketsList)
}
// else{
// setTickets([])
// }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ticketsList])
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 (
<Paper className={classes.ticketsListWrapper} style={style}>
<Paper
square
name="closed"
elevation={0}
className={classes.ticketsList}
onScroll={handleScroll}
>
<List style={{ paddingTop: 0 }}>
{ticketsList.length === 0 && !loading ? (
<div className={classes.noTicketsDiv}>
<span className={classes.noTicketsTitle}>
{i18n.t("ticketsList.noTicketsTitle")}
</span>
<p className={classes.noTicketsText}>
{i18n.t("ticketsList.noTicketsMessage")}
</p>
</div>
) : (
<>
{ticketsList.map(ticket => (
<TicketListItem ticket={ticket} key={ticket.id} remoteTicketsControll={_remoteTicketsControll} settings={settings} />
))}
</>
)}
{loading && <TicketsListSkeleton />}
</List>
</Paper>
</Paper>
)
}
export default TicketsList