feat: Update to display total number of pending and waiting tickets

feat-scaling-ticket-remote-creation
adriano 2024-02-26 16:58:39 -03:00
parent 237fa8124e
commit c9905eefb7
6 changed files with 109 additions and 121 deletions

View File

@ -95,7 +95,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
if (queueIdsStringified) { if (queueIdsStringified) {
queueIds = JSON.parse(queueIdsStringified); queueIds = JSON.parse(queueIdsStringified);
} }
const { tickets, count, hasMore } = await ListTicketsService({ const { tickets, count, hasMore } = await ListTicketsService({
searchParam, searchParam,
@ -109,7 +109,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
unlimited, unlimited,
searchParamContent searchParamContent
}); });
return res.status(200).json({ tickets, count, hasMore }); return res.status(200).json({ tickets, count, hasMore });
}; };
@ -127,9 +127,9 @@ export const remoteTicketCreation = async (
return res return res
.status(400) .status(400)
.json({ error: `Property '${prop}' is undefined.` }); .json({ error: `Property '${prop}' is undefined.` });
if(validateOnlyNumber.includes(prop)){ if (validateOnlyNumber.includes(prop)) {
if(!(/^\d+$/.test(req.body[prop]))){ if (!/^\d+$/.test(req.body[prop])) {
return res return res
.status(400) .status(400)
.json({ error: `The property '${prop}' must be a number` }); .json({ error: `The property '${prop}' must be a number` });
@ -237,11 +237,9 @@ export const remoteTicketCreation = async (
console.log( console.log(
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit` `REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit`
); );
return res return res.status(500).json({
.status(500) msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit`
.json({ });
msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit`
});
}; };
export const store = async (req: Request, res: Response): Promise<Response> => { export const store = async (req: Request, res: Response): Promise<Response> => {

View File

@ -5,7 +5,6 @@ import * as TicketController from "../controllers/TicketController";
const ticketRoutes = express.Router(); const ticketRoutes = express.Router();
// ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache); // ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache);
ticketRoutes.get("/tickets/count", isAuth, TicketController.count); ticketRoutes.get("/tickets/count", isAuth, TicketController.count);

View File

@ -59,13 +59,8 @@ const ListTicketsService = async ({
let whereCondition: Filterable["where"] = { [Op.or]: [{ userId }, { status: "pending" }], queueId: { [Op.or]: [queueIds, null] } }; let whereCondition: Filterable["where"] = { [Op.or]: [{ userId }, { status: "pending" }], queueId: { [Op.or]: [queueIds, null] } };
console.log('PAGE NUMBER TICKET: ', pageNumber) console.log('PAGE NUMBER TICKET: ', pageNumber)
//TEST DEL
// const url = await getWbot(46)
// console.log('---------> URL: ', url)
//
if (pageNumber.trim().length == 0) { if (pageNumber.trim().length == 0) {
pageNumber = '1' pageNumber = '1'
} }
@ -136,15 +131,14 @@ const ListTicketsService = async ({
whereCondition = { ...whereCondition, status }; whereCondition = { ...whereCondition, status };
if (unlimited === 'true' && status !== 'pending') { if (unlimited === "current" && status !== "pending") {
whereCondition = { whereCondition = {
...whereCondition, ...whereCondition,
createdAt: { createdAt: {
[Op.gte]: dateToday.fullDate + ' 00:00:00.000000', [Op.gte]: dateToday.fullDate + " 00:00:00.000000",
[Op.lte]: dateToday.fullDate + ' 23:59:59.999999' [Op.lte]: dateToday.fullDate + " 23:59:59.999999"
} }
} };
} }
} }
@ -196,8 +190,8 @@ const ListTicketsService = async ({
if ( if (
userProfile.dataValues.profile != "admin" && userProfile.dataValues.profile != "admin" &&
userProfile.dataValues.profile != "master" userProfile.dataValues.profile != "master" &&
// userProfile.dataValues.profile != "supervisor" userProfile.dataValues.profile != "supervisor"
) { ) {
whereCondition = { ...whereCondition, userId }; whereCondition = { ...whereCondition, userId };
} }
@ -224,9 +218,10 @@ const ListTicketsService = async ({
}; };
} }
const limit = unlimited === 'true' ? 100000 : 40; const limit = unlimited === "current" || unlimited === "all" ? 100000 : 40;
const offset = limit * (+pageNumber - 1); const offset = limit * (+pageNumber - 1);
console.log("kkkkkkkkk limit: ", limit);
const { count, rows: tickets } = await Ticket.findAndCountAll({ const { count, rows: tickets } = await Ticket.findAndCountAll({
where: whereCondition, where: whereCondition,

View File

@ -1,20 +1,20 @@
import React, { useState, useEffect, useReducer, useContext } from "react"; import React, { useState, useEffect, useReducer, useContext } from "react"
import openSocket from "socket.io-client"; import openSocket from "socket.io-client"
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles"
import List from "@material-ui/core/List"; import List from "@material-ui/core/List"
import Paper from "@material-ui/core/Paper"; import Paper from "@material-ui/core/Paper"
import TicketListItem from "../TicketListItem"; import TicketListItem from "../TicketListItem"
import TicketsListSkeleton from "../TicketsListSkeleton"; import TicketsListSkeleton from "../TicketsListSkeleton"
import useTickets from "../../hooks/useTickets"; import useTickets from "../../hooks/useTickets"
import { i18n } from "../../translate/i18n"; import { i18n } from "../../translate/i18n"
import { AuthContext } from "../../context/Auth/AuthContext"; import { AuthContext } from "../../context/Auth/AuthContext"
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"; import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(theme => ({
ticketsListWrapper: { ticketsListWrapper: {
@ -73,64 +73,64 @@ const useStyles = makeStyles(theme => ({
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
}, },
})); }))
const reducer = (state, action) => { const reducer = (state, action) => {
if (action.type === "LOAD_TICKETS") { if (action.type === "LOAD_TICKETS") {
const newTickets = action.payload; const newTickets = action.payload
newTickets.forEach(ticket => { newTickets.forEach(ticket => {
const ticketIndex = state.findIndex(t => +t.id === +ticket.id); const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
state[ticketIndex] = ticket; state[ticketIndex] = ticket
if (+ticket.unreadMessages > 0) { if (+ticket.unreadMessages > 0) {
state.unshift(state.splice(ticketIndex, 1)[0]); state.unshift(state.splice(ticketIndex, 1)[0])
} }
} else { } else {
state.push(ticket); state.push(ticket)
} }
}); })
return [...state]; return [...state]
} }
if (action.type === "RESET_UNREAD") { if (action.type === "RESET_UNREAD") {
const ticketId = action.payload; const ticketId = action.payload
const ticketIndex = state.findIndex(t => +t.id === +ticketId); const ticketIndex = state.findIndex(t => +t.id === +ticketId)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
state[ticketIndex].unreadMessages = 0; state[ticketIndex].unreadMessages = 0
} }
return [...state]; return [...state]
} }
if (action.type === "UPDATE_TICKET") { if (action.type === "UPDATE_TICKET") {
const ticket = action.payload; const ticket = action.payload
const ticketIndex = state.findIndex(t => +t.id === +ticket.id); const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
state[ticketIndex] = ticket; state[ticketIndex] = ticket
} else { } else {
state.unshift(ticket); state.unshift(ticket)
} }
return [...state]; return [...state]
} }
if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") { if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") {
const message = action.payload.message const message = action.payload.message
const ticket = action.payload.ticket; const ticket = action.payload.ticket
const ticketIndex = state.findIndex(t => +t.id === +ticket.id); const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
@ -142,69 +142,70 @@ const reducer = (state, action) => {
ticket.unreadMessages += 1 ticket.unreadMessages += 1
} }
state[ticketIndex] = ticket; state[ticketIndex] = ticket
state.unshift(state.splice(ticketIndex, 1)[0]); state.unshift(state.splice(ticketIndex, 1)[0])
} else { } else {
state.unshift(ticket); state.unshift(ticket)
} }
return [...state]; return [...state]
} }
if (action.type === "UPDATE_TICKET_CONTACT") { if (action.type === "UPDATE_TICKET_CONTACT") {
const contact = action.payload; const contact = action.payload
const ticketIndex = state.findIndex(t => +t.contactId === +contact.id); const ticketIndex = state.findIndex(t => +t.contactId === +contact.id)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
state[ticketIndex].contact = contact; state[ticketIndex].contact = contact
} }
return [...state]; return [...state]
} }
if (action.type === "DELETE_TICKET") { if (action.type === "DELETE_TICKET") {
const ticketId = action.payload; const ticketId = action.payload
const ticketIndex = state.findIndex(t => +t.id === +ticketId); const ticketIndex = state.findIndex(t => +t.id === +ticketId)
if (ticketIndex !== -1) { if (ticketIndex !== -1) {
state.splice(ticketIndex, 1); state.splice(ticketIndex, 1)
} }
return [...state]; return [...state]
} }
if (action.type === "RESET") { if (action.type === "RESET") {
return []; return []
} }
}; }
const TicketsList = (props) => { const TicketsList = (props) => {
const { status, searchParam, searchParamContent, showAll, selectedQueueIds, updateCount, style, tab } = props; const { status, searchParam, searchParamContent, showAll, selectedQueueIds, updateCount, style, tab } = props
const classes = useStyles(); const classes = useStyles()
const [pageNumber, setPageNumber] = useState(1); const [pageNumber, setPageNumber] = useState(1)
const [ticketsList, dispatch] = useReducer(reducer, []); const [ticketsList, dispatch] = useReducer(reducer, [])
const { user } = useContext(AuthContext); const { user } = useContext(AuthContext)
const { searchTicket } = useContext(SearchTicketContext) const { searchTicket } = useContext(SearchTicketContext)
useEffect(() => { useEffect(() => {
dispatch({ type: "RESET" }); dispatch({ type: "RESET" })
setPageNumber(1); setPageNumber(1)
}, [status, searchParam, searchParamContent, showAll, selectedQueueIds, searchTicket]); }, [status, searchParam, searchParamContent, showAll, selectedQueueIds, searchTicket])
const { tickets, hasMore, loading } = useTickets({ const { tickets, hasMore, loading } = useTickets({
pageNumber, pageNumber,
searchParam, searchParam,
searchParamContent, searchParamContent,
status, status,
showAll, showAll,
queueIds: JSON.stringify(selectedQueueIds), queueIds: JSON.stringify(selectedQueueIds),
tab tab,
}); unlimited:"all"
})
useEffect(() => { useEffect(() => {
if (!status && !searchParam) return; if (!status && !searchParam) return
// if (searchParam) { // if (searchParam) {
// //
@ -217,31 +218,31 @@ const TicketsList = (props) => {
dispatch({ type: "RESET" }) dispatch({ type: "RESET" })
} }
dispatch({ type: "LOAD_TICKETS", payload: tickets, }); dispatch({ type: "LOAD_TICKETS", payload: tickets, })
}, [tickets, status, searchParam, pageNumber]); }, [tickets, status, searchParam, pageNumber])
useEffect(() => { useEffect(() => {
// if (tab=='search')return // if (tab=='search')return
const socket = openSocket(process.env.REACT_APP_BACKEND_URL); const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
const shouldUpdateTicket = ticket => const shouldUpdateTicket = ticket =>
(!ticket.userId || ticket.userId === user?.id || showAll) && (!ticket.userId || ticket.userId === user?.id || showAll) &&
(!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1); (!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1)
const notBelongsToUserQueues = ticket => const notBelongsToUserQueues = ticket =>
ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1; ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1
socket.on("connect", () => { socket.on("connect", () => {
if (status) { if (status) {
socket.emit("joinTickets", status); socket.emit("joinTickets", status)
} else { } else {
socket.emit("joinNotification"); socket.emit("joinNotification")
} }
}); })
@ -254,7 +255,7 @@ const TicketsList = (props) => {
dispatch({ dispatch({
type: "RESET_UNREAD", type: "RESET_UNREAD",
payload: data.ticketId, payload: data.ticketId,
}); })
} }
if (data.action === "update" && shouldUpdateTicket(data.ticket)) { if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
@ -264,17 +265,17 @@ const TicketsList = (props) => {
dispatch({ dispatch({
type: "UPDATE_TICKET", type: "UPDATE_TICKET",
payload: data.ticket, payload: data.ticket,
}); })
} }
if (data.action === "update" && notBelongsToUserQueues(data.ticket)) { if (data.action === "update" && notBelongsToUserQueues(data.ticket)) {
dispatch({ type: "DELETE_TICKET", payload: data.ticket.id }); dispatch({ type: "DELETE_TICKET", payload: data.ticket.id })
} }
if (data.action === "delete") { if (data.action === "delete") {
dispatch({ type: "DELETE_TICKET", payload: data.ticketId }); dispatch({ type: "DELETE_TICKET", payload: data.ticketId })
} }
}); })
socket.on("appMessage", data => { socket.on("appMessage", data => {
@ -287,51 +288,49 @@ const TicketsList = (props) => {
type: "UPDATE_TICKET_UNREAD_MESSAGES", type: "UPDATE_TICKET_UNREAD_MESSAGES",
// payload: data.ticket, // payload: data.ticket,
payload: data, payload: data,
}); })
} }
}); })
socket.on("contact", data => { socket.on("contact", data => {
if (data.action === "update") { if (data.action === "update") {
dispatch({ dispatch({
type: "UPDATE_TICKET_CONTACT", type: "UPDATE_TICKET_CONTACT",
payload: data.contact, payload: data.contact,
}); })
} }
}); })
return () => { return () => {
socket.disconnect(); socket.disconnect()
}; }
}, [status, showAll, user, selectedQueueIds, tab]); }, [status, showAll, user, selectedQueueIds, tab])
useEffect(() => { useEffect(() => {
if (typeof updateCount === "function") { if (typeof updateCount === "function") {
updateCount(ticketsList.length); updateCount(ticketsList.length)
} }
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [ticketsList]); }, [ticketsList])
const loadMore = () => { const loadMore = () => {
setPageNumber(prevState => prevState + 1); setPageNumber(prevState => prevState + 1)
}; }
const handleScroll = e => { const handleScroll = e => {
if (!hasMore || loading) return; if (!hasMore || loading) return
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; const { scrollTop, scrollHeight, clientHeight } = e.currentTarget
if (scrollHeight - (scrollTop + 100) < clientHeight) { if (scrollHeight - (scrollTop + 100) < clientHeight) {
loadMore(); loadMore()
} }
}; }
return ( return (
<Paper className={classes.ticketsListWrapper} style={style}> <Paper className={classes.ticketsListWrapper} style={style}>
@ -363,7 +362,7 @@ const TicketsList = (props) => {
</List> </List>
</Paper> </Paper>
</Paper> </Paper>
); )
}; }
export default TicketsList; export default TicketsList

View File

@ -31,10 +31,7 @@ const VcardPreview = ({ contact, numbers }) => {
number: numbers !== undefined && numbers.replace(/\D/g, ""), number: numbers !== undefined && numbers.replace(/\D/g, ""),
email: "" email: ""
} }
console.log('contactObj: ', contactObj)
// return
const { data } = await api.post("/contact", contactObj); const { data } = await api.post("/contact", contactObj);
setContact(data) setContact(data)

View File

@ -20,7 +20,7 @@ const Chart = (props) => {
const theme = useTheme(); const theme = useTheme();
const date = useRef(new Date().toISOString()); const date = useRef(new Date().toISOString());
let { tickets } = useTickets({ date: date.current, unlimited: "true" }); let { tickets } = useTickets({ date: date.current, unlimited: "current" });
const [chartData, setChartData] = useState([ const [chartData, setChartData] = useState([
{ time: "08:00", amount: 0 }, { time: "08:00", amount: 0 },