fix: correct code errors
Details: - Addressed various code errors and made necessary fixes. feat: add column 'type' to the Reports Mtable to differentiate remote tickets from regular ones Details: - Added a new column named 'type' to the Reports Mtable to differentiate between remote tickets and regular ones.feat-scaling-ticket-remote-creation
parent
0e8fbd8400
commit
fea60cf80c
|
@ -14,13 +14,26 @@ const CountStatusChatEndService = async (
|
||||||
endDate: string,
|
endDate: string,
|
||||||
queueIds?: number[]
|
queueIds?: number[]
|
||||||
) => {
|
) => {
|
||||||
const countStatusChatEnd: any = await sequelize.query(
|
let countStatusChatEnd: any
|
||||||
|
|
||||||
|
if(queueIds && queueIds.length > 0){
|
||||||
|
countStatusChatEnd = await sequelize.query(
|
||||||
|
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
||||||
|
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
||||||
|
AND t.queueId IN (${queueIds})
|
||||||
|
group by s.id;`,
|
||||||
|
{ type: QueryTypes.SELECT }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
countStatusChatEnd = await sequelize.query(
|
||||||
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
`select t.id, s.name, count(t.id) as count from Tickets t join StatusChatEnds s on
|
||||||
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
t.statusChatEndId = s.id and DATE(t.createdAt) BETWEEN '${startDate} 00:00:00.000000' AND '${endDate} 23:59:59.999999'
|
||||||
AND t.queueId IN (${queueIds})
|
group by s.id;`,
|
||||||
group by s.id;`,
|
{ type: QueryTypes.SELECT }
|
||||||
{ type: QueryTypes.SELECT }
|
);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
|
||||||
return countStatusChatEnd;
|
return countStatusChatEnd;
|
||||||
};
|
};
|
||||||
|
|
|
@ -98,6 +98,7 @@ const ShowTicketReport = async ({
|
||||||
"id",
|
"id",
|
||||||
"status",
|
"status",
|
||||||
"statusChatEnd",
|
"statusChatEnd",
|
||||||
|
"isRemote",
|
||||||
[
|
[
|
||||||
Sequelize.fn(
|
Sequelize.fn(
|
||||||
"DATE_FORMAT",
|
"DATE_FORMAT",
|
||||||
|
|
|
@ -59,12 +59,18 @@ const ListUser = async ({
|
||||||
where_clause = {
|
where_clause = {
|
||||||
id: { [Op.in]: userIds }
|
id: { [Op.in]: userIds }
|
||||||
};
|
};
|
||||||
} else if (profiles) {
|
}
|
||||||
|
else if (profiles && userIdInQueues.length > 0) {
|
||||||
where_clause = {
|
where_clause = {
|
||||||
profile: { [Op.in]: profiles },
|
profile: { [Op.in]: profiles },
|
||||||
id: {[Op.in]: userIdInQueues}
|
id: {[Op.in]: userIdInQueues}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
else if (profiles) {
|
||||||
|
where_clause = {
|
||||||
|
profile: { [Op.in]: profiles },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const users = await User.findAll({
|
const users = await User.findAll({
|
||||||
where: where_clause,
|
where: where_clause,
|
||||||
|
|
|
@ -12,7 +12,7 @@ interface UserData {
|
||||||
positionId?: string;
|
positionId?: string;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
queueIds?: number[];
|
queueIds?: number[];
|
||||||
transferToOtherQueues: boolean;
|
transferToOtherQueues?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
|
|
|
@ -15,6 +15,7 @@ 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"
|
||||||
|
import { ticketsContext } from "../../context/TicketsProvider/TicketsProvider"
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
ticketsListWrapper: {
|
ticketsListWrapper: {
|
||||||
|
@ -184,6 +185,8 @@ const TicketsList = (props) => {
|
||||||
const { user } = useContext(AuthContext)
|
const { user } = useContext(AuthContext)
|
||||||
|
|
||||||
const { searchTicket } = useContext(SearchTicketContext)
|
const { searchTicket } = useContext(SearchTicketContext)
|
||||||
|
const { setTickets } = useContext(ticketsContext)
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -197,7 +200,7 @@ const TicketsList = (props) => {
|
||||||
searchParam,
|
searchParam,
|
||||||
searchParamContent,
|
searchParamContent,
|
||||||
status,
|
status,
|
||||||
showAll,
|
showAll,
|
||||||
queueIds: JSON.stringify(selectedQueueIds),
|
queueIds: JSON.stringify(selectedQueueIds),
|
||||||
tab,
|
tab,
|
||||||
unlimited: status === 'open' ? "all" : "false"
|
unlimited: status === 'open' ? "all" : "false"
|
||||||
|
@ -311,6 +314,12 @@ const TicketsList = (props) => {
|
||||||
if (typeof updateCount === "function") {
|
if (typeof updateCount === "function") {
|
||||||
updateCount(ticketsList.length)
|
updateCount(ticketsList.length)
|
||||||
}
|
}
|
||||||
|
if (ticketsList && status === "pending"){
|
||||||
|
setTickets(ticketsList)
|
||||||
|
}
|
||||||
|
// else{
|
||||||
|
// setTickets([])
|
||||||
|
// }
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [ticketsList])
|
}, [ticketsList])
|
||||||
|
|
||||||
|
|
|
@ -1,42 +1,45 @@
|
||||||
import React, { useContext, useEffect, useRef, useState } from "react";
|
import React, { useContext, useEffect, useRef, useState } from "react"
|
||||||
|
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles"
|
||||||
import { IconButton } from "@mui/material";
|
import { IconButton } from "@mui/material"
|
||||||
import Paper from "@material-ui/core/Paper";
|
import Paper from "@material-ui/core/Paper"
|
||||||
import InputBase from "@material-ui/core/InputBase";
|
import InputBase from "@material-ui/core/InputBase"
|
||||||
import Tabs from "@material-ui/core/Tabs";
|
import Tabs from "@material-ui/core/Tabs"
|
||||||
import Tab from "@material-ui/core/Tab";
|
import Tab from "@material-ui/core/Tab"
|
||||||
import Badge from "@material-ui/core/Badge";
|
import Badge from "@material-ui/core/Badge"
|
||||||
|
|
||||||
import Tooltip from "@material-ui/core/Tooltip";
|
import Tooltip from "@material-ui/core/Tooltip"
|
||||||
|
|
||||||
|
|
||||||
import SearchIcon from "@material-ui/icons/Search";
|
import SearchIcon from "@material-ui/icons/Search"
|
||||||
import MoveToInboxIcon from "@material-ui/icons/MoveToInbox";
|
import MoveToInboxIcon from "@material-ui/icons/MoveToInbox"
|
||||||
import CheckBoxIcon from "@material-ui/icons/CheckBox";
|
import CheckBoxIcon from "@material-ui/icons/CheckBox"
|
||||||
import MenuIcon from "@material-ui/icons/Menu";
|
import MenuIcon from "@material-ui/icons/Menu"
|
||||||
import FindInPageIcon from '@material-ui/icons/FindInPage';
|
import FindInPageIcon from '@material-ui/icons/FindInPage'
|
||||||
|
|
||||||
import FormControlLabel from "@material-ui/core/FormControlLabel";
|
import FormControlLabel from "@material-ui/core/FormControlLabel"
|
||||||
import Switch from "@material-ui/core/Switch";
|
import Switch from "@material-ui/core/Switch"
|
||||||
import openSocket from "socket.io-client"
|
import openSocket from "socket.io-client"
|
||||||
|
|
||||||
import NewTicketModal from "../NewTicketModal";
|
import NewTicketModal from "../NewTicketModal"
|
||||||
import TicketsList from "../TicketsList";
|
import TicketsList from "../TicketsList"
|
||||||
import TabPanel from "../TabPanel";
|
import TabPanel from "../TabPanel"
|
||||||
|
|
||||||
import { i18n } from "../../translate/i18n";
|
import { i18n } from "../../translate/i18n"
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
import { Can } from "../Can";
|
import { Can } from "../Can"
|
||||||
import TicketsQueueSelect from "../TicketsQueueSelect";
|
import TicketsQueueSelect from "../TicketsQueueSelect"
|
||||||
import { Button } from "@material-ui/core";
|
import { Button } from "@material-ui/core"
|
||||||
|
|
||||||
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption";
|
import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption"
|
||||||
|
|
||||||
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket";
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
|
||||||
import useTickets from "../../hooks/useTickets"
|
import useTickets from "../../hooks/useTickets"
|
||||||
import api from "../../services/api";
|
import api from "../../services/api"
|
||||||
import toastError from "../../errors/toastError";
|
import toastError from "../../errors/toastError"
|
||||||
|
|
||||||
|
import { ticketsContext } from "../../context/TicketsProvider/TicketsProvider"
|
||||||
|
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
ticketsWrapper: {
|
ticketsWrapper: {
|
||||||
|
@ -128,147 +131,114 @@ const useStyles = makeStyles((theme) => ({
|
||||||
hide: {
|
hide: {
|
||||||
display: "none !important",
|
display: "none !important",
|
||||||
},
|
},
|
||||||
}));
|
}))
|
||||||
|
|
||||||
const DEFAULT_SEARCH_PARAM = { searchParam: "", searchParamContent: "" }
|
const DEFAULT_SEARCH_PARAM = { searchParam: "", searchParamContent: "" }
|
||||||
|
|
||||||
const TicketsManager = () => {
|
const TicketsManager = () => {
|
||||||
|
|
||||||
const { tabOption, setTabOption } = useContext(TabTicketContext);
|
const { tabOption, setTabOption } = useContext(TabTicketContext)
|
||||||
|
|
||||||
const { setSearchTicket } = useContext(SearchTicketContext)
|
const { setSearchTicket } = useContext(SearchTicketContext)
|
||||||
|
|
||||||
const classes = useStyles();
|
const classes = useStyles()
|
||||||
|
|
||||||
const [searchParam, setSearchParam] = useState(DEFAULT_SEARCH_PARAM);
|
const [searchParam, setSearchParam] = useState(DEFAULT_SEARCH_PARAM)
|
||||||
const [tab, setTab] = useState("open");
|
const [tab, setTab] = useState("open")
|
||||||
const [tabOpen, setTabOpen] = useState("open");
|
const [tabOpen, setTabOpen] = useState("open")
|
||||||
const [newTicketModalOpen, setNewTicketModalOpen] = useState(false);
|
const [newTicketModalOpen, setNewTicketModalOpen] = useState(false)
|
||||||
const [showAllTickets, setShowAllTickets] = useState(false);
|
const [showAllTickets, setShowAllTickets] = useState(false)
|
||||||
const { user } = useContext(AuthContext);
|
const { user, setting, getSettingValue } = useContext(AuthContext)
|
||||||
|
|
||||||
const [openCount, setOpenCount] = useState(0);
|
const [openCount, setOpenCount] = useState(0)
|
||||||
const [pendingCount, setPendingCount] = useState(0);
|
const [pendingCount, setPendingCount] = useState(0)
|
||||||
|
|
||||||
const userQueueIds = user.queues.map((q) => q.id);
|
const userQueueIds = user.queues.map((q) => q.id)
|
||||||
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
|
const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || [])
|
||||||
|
|
||||||
const [showContentSearch, setShowContentSearch] = useState(false)
|
const [showContentSearch, setShowContentSearch] = useState(false)
|
||||||
const searchInputRef = useRef();
|
const searchInputRef = useRef()
|
||||||
const searchContentInputRef = useRef();
|
const searchContentInputRef = useRef()
|
||||||
const [inputSearch, setInputSearch] = useState('');
|
const [inputSearch, setInputSearch] = useState('')
|
||||||
const [inputContentSearch, setInputContentSearch] = useState("")
|
const [inputContentSearch, setInputContentSearch] = useState("")
|
||||||
|
|
||||||
const [openTooltipSearch, setOpenTooltipSearch] = useState(false)
|
const [openTooltipSearch, setOpenTooltipSearch] = useState(false)
|
||||||
|
|
||||||
const [waitingTime, setWaitingTime] = useState('00:00');
|
const [waitingTime, setWaitingTime] = useState('00:00')
|
||||||
const [tickets, setTickets] = useState([]);
|
// const [tickets, setTickets] = useState([]);
|
||||||
const [settings, setSettings] = useState([])
|
const [settings, setSettings] = useState([])
|
||||||
|
|
||||||
let searchTimeout;
|
let searchTimeout
|
||||||
let searchContentTimeout;
|
let searchContentTimeout
|
||||||
|
|
||||||
|
const { tickets, } = useContext(ticketsContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user.profile.toUpperCase() === "ADMIN" ||
|
setSettings(setting)
|
||||||
user.profile.toUpperCase() === "SUPERVISOR" ||
|
}, [setting])
|
||||||
user.profile.toUpperCase() === "MASTER") {
|
|
||||||
setShowAllTickets(true);
|
useEffect(() => {
|
||||||
|
if (user.profile.toUpperCase() === "ADMIN" ||
|
||||||
|
user.profile.toUpperCase() === "SUPERVISOR" ||
|
||||||
|
user.profile.toUpperCase() === "MASTER") {
|
||||||
|
setShowAllTickets(true)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (tab === "search") {
|
if (tab === "search") {
|
||||||
searchInputRef.current.focus();
|
searchInputRef.current.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
setTabOption(tab)
|
setTabOption(tab)
|
||||||
|
|
||||||
}, [tab, setTabOption]);
|
}, [tab, setTabOption])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchSession = async () => {
|
|
||||||
try {
|
|
||||||
const { data } = await api.get('/settings')
|
|
||||||
setSettings(data.settings)
|
|
||||||
} catch (err) {
|
|
||||||
toastError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fetchSession()
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const getSettingValue = (key) => {
|
if (settings?.length > 0 && getSettingValue('waitingTimeTickets') !== 'enabled') return
|
||||||
const { value } = settings.find((s) => s.key === key)
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchTickets = async () =>{
|
const calculateAverageTime = () => {
|
||||||
try {
|
if (tickets.length > 0) {
|
||||||
const { data } = await api.get("/tickets", {
|
const now = new Date()
|
||||||
params: {
|
|
||||||
status: 'pending',
|
|
||||||
queueIds: JSON.stringify(selectedQueueIds)
|
|
||||||
},
|
|
||||||
});
|
|
||||||
setTickets(data.tickets);
|
|
||||||
} catch (err) {
|
|
||||||
toastError(err);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
useEffect(() => {
|
|
||||||
if(settings?.length > 0 && getSettingValue('waitingTimeTickets') === 'enabled') {
|
|
||||||
fetchTickets();
|
|
||||||
const intervalId = setInterval(fetchTickets, 55000);
|
|
||||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
|
||||||
|
|
||||||
socket.on("ticketStatus", (data) => {
|
|
||||||
if (data.action === "update") {
|
|
||||||
fetchTickets();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return () => {
|
|
||||||
socket.disconnect()
|
|
||||||
clearInterval(intervalId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [selectedQueueIds, settings]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const calculateAverageTime = () => {
|
|
||||||
if(tickets.length > 0){
|
|
||||||
const now = new Date();
|
|
||||||
const differenceTime = tickets?.map(ticket => {
|
const differenceTime = tickets?.map(ticket => {
|
||||||
const updatedAt = new Date(ticket.updatedAt);
|
const createdAt = new Date(ticket.createdAt)
|
||||||
const difference = now - updatedAt;
|
const difference = now - createdAt
|
||||||
return difference;
|
return difference
|
||||||
});
|
})
|
||||||
const sumDifferences = differenceTime.reduce((total, difference) => total + difference, 0);
|
const sumDifferences = differenceTime.reduce((total, difference) => total + difference, 0)
|
||||||
const averageTimeMilliseconds = sumDifferences / tickets?.length;
|
const averageTimeMilliseconds = sumDifferences / tickets?.length
|
||||||
let hours = Math.floor(averageTimeMilliseconds / 3600000);
|
let hours = Math.floor(averageTimeMilliseconds / 3600000)
|
||||||
const minutes = Math.floor((averageTimeMilliseconds % 3600000) / 60000);
|
const minutes = Math.floor((averageTimeMilliseconds % 3600000) / 60000)
|
||||||
|
|
||||||
let days = hours >= 24 ? parseInt(hours/24) : '';
|
let days = hours >= 24 ? parseInt(hours / 24) : ''
|
||||||
|
|
||||||
if(days != '') hours = hours - (24*days);
|
if (days != '') hours = hours - (24 * days)
|
||||||
|
|
||||||
const averageTimeFormated = `${days != '' ? `${days}d ` : days}${hours.toString().padStart(2, '0')}h${minutes.toString().padStart(2, '0')}`;
|
const averageTimeFormated = `${days != '' ? `${days}d ` : days}${hours.toString().padStart(2, '0')}h${minutes.toString().padStart(2, '0')}`
|
||||||
|
|
||||||
return averageTimeFormated;
|
return averageTimeFormated
|
||||||
}else return '00:00';
|
} else return '00:00'
|
||||||
}
|
}
|
||||||
|
|
||||||
setWaitingTime(calculateAverageTime());
|
setWaitingTime(calculateAverageTime())
|
||||||
},[tickets]);
|
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
setWaitingTime(calculateAverageTime())
|
||||||
|
}, 10000)
|
||||||
|
|
||||||
|
return () => clearInterval(intervalId)
|
||||||
|
|
||||||
|
}, [tickets])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
// clearTimeout(searchContentTimeout);
|
// clearTimeout(searchContentTimeout);
|
||||||
|
|
||||||
// setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
// setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
||||||
|
|
||||||
if (!inputContentSearch) return
|
if (!inputContentSearch) return
|
||||||
|
|
||||||
if (!searchContentTimeout) return
|
if (!searchContentTimeout) return
|
||||||
|
|
||||||
|
@ -278,12 +248,12 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
// }, 500);
|
// }, 500);
|
||||||
|
|
||||||
clearTimeout(searchContentTimeout);
|
clearTimeout(searchContentTimeout)
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
setSearchParam(prev => ({ ...prev, searchParamContent: "" }))
|
||||||
|
|
||||||
|
|
||||||
}, [inputContentSearch, searchContentTimeout]);
|
}, [inputContentSearch, searchContentTimeout])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
@ -291,16 +261,16 @@ const TicketsManager = () => {
|
||||||
if (tabOption === 'open') {
|
if (tabOption === 'open') {
|
||||||
|
|
||||||
setTabOption('')
|
setTabOption('')
|
||||||
setSearchParam(DEFAULT_SEARCH_PARAM);
|
setSearchParam(DEFAULT_SEARCH_PARAM)
|
||||||
setInputSearch('');
|
setInputSearch('')
|
||||||
setInputContentSearch('')
|
setInputContentSearch('')
|
||||||
setTab("open");
|
setTab("open")
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}, [tabOption, setTabOption])
|
}, [tabOption, setTabOption])
|
||||||
|
|
||||||
|
|
||||||
const removeExtraSpace = (str) => {
|
const removeExtraSpace = (str) => {
|
||||||
|
|
||||||
str = str.replace(/^\s+/g, '')
|
str = str.replace(/^\s+/g, '')
|
||||||
|
@ -315,14 +285,14 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
setSearchTicket(searchParam.searchParam)
|
setSearchTicket(searchParam.searchParam)
|
||||||
|
|
||||||
clearTimeout(searchTimeout);
|
clearTimeout(searchTimeout)
|
||||||
|
|
||||||
if (searchedTerm === "") {
|
if (searchedTerm === "") {
|
||||||
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
||||||
setInputSearch(searchedTerm)
|
setInputSearch(searchedTerm)
|
||||||
setShowContentSearch(false)
|
setShowContentSearch(false)
|
||||||
setTab("open");
|
setTab("open")
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (searchedTerm.length < 4) {
|
if (searchedTerm.length < 4) {
|
||||||
|
@ -333,22 +303,22 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
searchTimeout = setTimeout(() => {
|
searchTimeout = setTimeout(() => {
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }));
|
setSearchParam(prev => ({ ...prev, searchParam: searchedTerm }))
|
||||||
|
|
||||||
}, 500);
|
}, 500)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleContentSearch = e => {
|
const handleContentSearch = e => {
|
||||||
|
|
||||||
let searchedContentText = removeExtraSpace(e.target.value.toLowerCase())
|
let searchedContentText = removeExtraSpace(e.target.value.toLowerCase())
|
||||||
|
|
||||||
setInputContentSearch(searchedContentText)
|
setInputContentSearch(searchedContentText)
|
||||||
|
|
||||||
searchContentTimeout = setTimeout(() => {
|
searchContentTimeout = setTimeout(() => {
|
||||||
|
|
||||||
setSearchParam(prev => ({ ...prev, searchParamContent: searchedContentText }));
|
setSearchParam(prev => ({ ...prev, searchParamContent: searchedContentText }))
|
||||||
|
|
||||||
}, 500);
|
}, 500)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,18 +336,18 @@ const TicketsManager = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleChangeTab = (e, newValue) => {
|
const handleChangeTab = (e, newValue) => {
|
||||||
setTab(newValue);
|
setTab(newValue)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleChangeTabOpen = (e, newValue) => {
|
const handleChangeTabOpen = (e, newValue) => {
|
||||||
setTabOpen(newValue);
|
setTabOpen(newValue)
|
||||||
};
|
}
|
||||||
|
|
||||||
const applyPanelStyle = (status) => {
|
const applyPanelStyle = (status) => {
|
||||||
if (tabOpen !== status) {
|
if (tabOpen !== status) {
|
||||||
return { width: 0, height: 0 };
|
return { width: 0, height: 0 }
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper elevation={0} variant="outlined" className={classes.ticketsWrapper}>
|
<Paper elevation={0} variant="outlined" className={classes.ticketsWrapper}>
|
||||||
|
@ -534,14 +504,22 @@ const TicketsManager = () => {
|
||||||
value={"pending"}
|
value={"pending"}
|
||||||
/>{
|
/>{
|
||||||
(settings?.length > 0 && getSettingValue('waitingTimeTickets') === 'enabled') &&
|
(settings?.length > 0 && getSettingValue('waitingTimeTickets') === 'enabled') &&
|
||||||
<span style={{display: 'flex', alignItems: 'center', flexDirection:'column', justifyContent: 'flex-start'}}>
|
|
||||||
<label style ={{color: 'red',fontWeight: 'bold', padding: '.1rem', fontSize: '8px', textAlign:'center', margin:'0'}}>
|
<Tooltip
|
||||||
<i>ESPERA</i>
|
arrow
|
||||||
</label>
|
placement="right"
|
||||||
<label style={{color: 'gray',fontWeight: 'bold', padding: '.1rem', textDecoration: 'underline', fontSize: '13px'}}>
|
title={"Tempo de espera aguardando"}
|
||||||
{waitingTime}
|
>
|
||||||
</label>
|
<span style={{ display: 'flex', alignItems: 'center', flexDirection: 'column', justifyContent: 'flex-start', marginRight: '20px', marginTop: '10px' }}>
|
||||||
</span>
|
{/* <label style={{ color: 'red', fontWeight: 'bold', padding: '.1rem', fontSize: '8px', textAlign: 'center', margin: '0' }}>
|
||||||
|
<i>ESPERA</i>
|
||||||
|
</label> */}
|
||||||
|
<label style={{ color: 'gray', fontWeight: 'bold', padding: '5px'/*, textDecoration: 'underline'*/, fontSize: '13px' }}>
|
||||||
|
{waitingTime}
|
||||||
|
</label>
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
|
||||||
}
|
}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
<Paper className={classes.ticketsWrapper}>
|
<Paper className={classes.ticketsWrapper}>
|
||||||
|
@ -580,7 +558,7 @@ const TicketsManager = () => {
|
||||||
|
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default TicketsManager;
|
export default TicketsManager
|
|
@ -0,0 +1,17 @@
|
||||||
|
import React, { useState, createContext } from "react"
|
||||||
|
|
||||||
|
const ticketsContext = createContext()
|
||||||
|
|
||||||
|
|
||||||
|
const TicketsProvider = ({ children }) => {
|
||||||
|
|
||||||
|
const [tickets, setTickets] = useState(0)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ticketsContext.Provider value={{ tickets, setTickets }}>
|
||||||
|
{children}
|
||||||
|
</ticketsContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { ticketsContext, TicketsProvider }
|
|
@ -262,7 +262,7 @@ const Dashboard = () => {
|
||||||
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 })
|
const [ticketsStatus, setTicktsStatus] = useState({ open: 0, openAll: 0, pending: 0, closed: 0 })
|
||||||
const [ticketStatusChatEnd, setTicketStatusChatEnd] = useState([])
|
const [ticketStatusChatEnd, setTicketStatusChatEnd] = useState([])
|
||||||
|
|
||||||
const userQueueIds = user.queues.map((q) => q.id);
|
const userQueueIds = user.queues?.map((q) => q.id);
|
||||||
const [selectedQueue, setSelectedQueue] = useState(userQueueIds || []);
|
const [selectedQueue, setSelectedQueue] = useState(userQueueIds || []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -224,6 +224,7 @@ Item.propTypes = {
|
||||||
|
|
||||||
|
|
||||||
let columnsData = [
|
let columnsData = [
|
||||||
|
{ title: `Tipo`, field: 'isRemote' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column0_4")}`, field: 'contact.number' },
|
{ title: `${i18n.t("reports.listColumns.column0_4")}`, field: 'contact.number' },
|
||||||
|
@ -241,6 +242,8 @@ let columnsData = [
|
||||||
]
|
]
|
||||||
|
|
||||||
let columnsDataSuper = [
|
let columnsDataSuper = [
|
||||||
|
{ title: `Tipo`, field: 'isRemote' },
|
||||||
|
{ title: `${i18n.t("reports.listColumns.column1_0")}`, field: 'isRemote' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_1")}`, field: 'whatsapp.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
{ title: `${i18n.t("reports.listColumns.column1_2")}`, field: 'user.name' },
|
||||||
{ title: `${i18n.t("reports.listColumns.column0_3")}`, field: 'contact.name' },
|
{ title: `${i18n.t("reports.listColumns.column0_3")}`, field: 'contact.name' },
|
||||||
|
@ -375,11 +378,14 @@ const Report = () => {
|
||||||
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name)
|
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name)
|
||||||
}
|
}
|
||||||
data.tickets = filterQueuesTickets
|
data.tickets = filterQueuesTickets
|
||||||
const tickets = data.tickets.map(ticket => ({
|
const tickets = data.tickets.map(ticket => {
|
||||||
|
ticket.isRemote = ticket.isRemote ? 'Remoto' : 'Comum';
|
||||||
|
return ({
|
||||||
...ticket,
|
...ticket,
|
||||||
messagesToFilter: ticket.messages.map(message => message.body).join(' '),
|
messagesToFilter: ticket.messages.map(message => message.body).join(' '),
|
||||||
link: `${process.env.REACT_APP_FRONTEND_URL}/tickets/${ticket.id}`
|
link: `${process.env.REACT_APP_FRONTEND_URL}/tickets/${ticket.id}`
|
||||||
}))
|
})
|
||||||
|
})
|
||||||
dispatchQ({ type: "LOAD_QUERY", payload: tickets })
|
dispatchQ({ type: "LOAD_QUERY", payload: tickets })
|
||||||
setHasMore(data.hasMore)
|
setHasMore(data.hasMore)
|
||||||
setTotalCountTickets(data.count)
|
setTotalCountTickets(data.count)
|
||||||
|
|
|
@ -11,6 +11,7 @@ import { i18n } from "../../translate/i18n";
|
||||||
import Hidden from "@material-ui/core/Hidden";
|
import Hidden from "@material-ui/core/Hidden";
|
||||||
|
|
||||||
import { SearchTicketProvider } from "../../context/SearchTicket/SearchTicket";
|
import { SearchTicketProvider } from "../../context/SearchTicket/SearchTicket";
|
||||||
|
import { TicketsProvider } from "../../context/TicketsProvider/TicketsProvider"
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
chatContainer: {
|
chatContainer: {
|
||||||
|
@ -82,7 +83,9 @@ const Chat = () => {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SearchTicketProvider>
|
<SearchTicketProvider>
|
||||||
<TicketsManager />
|
<TicketsProvider>
|
||||||
|
<TicketsManager />
|
||||||
|
</TicketsProvider>
|
||||||
</SearchTicketProvider>
|
</SearchTicketProvider>
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue