import React, { useContext, useEffect, useRef, useState } from "react"; import { makeStyles } from "@material-ui/core/styles"; import { IconButton } from "@mui/material"; import Paper from "@material-ui/core/Paper"; import InputBase from "@material-ui/core/InputBase"; import Tabs from "@material-ui/core/Tabs"; import Tab from "@material-ui/core/Tab"; import Badge from "@material-ui/core/Badge"; import Tooltip from "@material-ui/core/Tooltip"; import SearchIcon from "@material-ui/icons/Search"; import MoveToInboxIcon from "@material-ui/icons/MoveToInbox"; import CheckBoxIcon from "@material-ui/icons/CheckBox"; import MenuIcon from "@material-ui/icons/Menu"; import FindInPageIcon from '@material-ui/icons/FindInPage'; import FormControlLabel from "@material-ui/core/FormControlLabel"; import Switch from "@material-ui/core/Switch"; import NewTicketModal from "../NewTicketModal"; import TicketsList from "../TicketsList"; import TabPanel from "../TabPanel"; import { i18n } from "../../translate/i18n"; import { AuthContext } from "../../context/Auth/AuthContext"; import { Can } from "../Can"; import TicketsQueueSelect from "../TicketsQueueSelect"; import { Button } from "@material-ui/core"; import { TabTicketContext } from "../../context/TabTicketHeaderOption/TabTicketHeaderOption"; import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"; import useTickets from "../../hooks/useTickets" import api from "../../services/api"; import toastError from "../../errors/toastError"; const useStyles = makeStyles((theme) => ({ ticketsWrapper: { position: "relative", display: "flex", height: "100%", flexDirection: "column", overflow: "hidden", borderTopRightRadius: 0, borderBottomRightRadius: 0, }, tabsHeader: { flex: "none", backgroundColor: "#eee", }, settingsIcon: { alignSelf: "center", marginLeft: "auto", padding: 8, }, tab: { minWidth: 120, width: 120, }, ticketOptionsBox: { display: "flex", justifyContent: "space-between", alignItems: "center", background: "#fafafa", padding: theme.spacing(1), }, serachInputWrapper: { flex: 1, display: "flex", flexDirection: "column", gap: "10px", borderRadius: 40, padding: 4, marginRight: theme.spacing(1), }, searchInputHeader: { flex: 1, background: "#fff", display: "flex", borderRadius: 40, padding: 4, marginRight: theme.spacing(1), }, searchContentInput: { flex: 1, background: "#fff", display: "flex", borderRadius: 40, padding: 4, marginRight: theme.spacing(1), }, searchIcon: { color: "grey", marginLeft: 6, marginRight: 6, alignSelf: "center", }, menuSearch: { color: "grey", alignSelf: "center", }, searchInput: { flex: 1, border: "none", borderRadius: 30, }, badge: { right: "-10px", }, show: { display: "block", }, hide: { display: "none !important", }, })); const DEFAULT_SEARCH_PARAM = { searchParam: "", searchParamContent: "" } const TicketsManager = () => { const { tabOption, setTabOption } = useContext(TabTicketContext); const { setSearchTicket } = useContext(SearchTicketContext) const classes = useStyles(); const [searchParam, setSearchParam] = useState(DEFAULT_SEARCH_PARAM); const [tab, setTab] = useState("open"); const [tabOpen, setTabOpen] = useState("open"); const [newTicketModalOpen, setNewTicketModalOpen] = useState(false); const [showAllTickets, setShowAllTickets] = useState(false); const { user } = useContext(AuthContext); const [openCount, setOpenCount] = useState(0); const [pendingCount, setPendingCount] = useState(0); const userQueueIds = user.queues.map((q) => q.id); const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []); const [showContentSearch, setShowContentSearch] = useState(false) const searchInputRef = useRef(); const searchContentInputRef = useRef(); const [inputSearch, setInputSearch] = useState(''); const [inputContentSearch, setInputContentSearch] = useState("") const [openTooltipSearch, setOpenTooltipSearch] = useState(false) const [waitingTime, setWaitingTime] = useState('00:00'); const [tickets, setTickets] = useState([]); const [settings, setSettings] = useState([]) let searchTimeout; let searchContentTimeout; useEffect(() => { if (user.profile.toUpperCase() === "ADMIN" || user.profile.toUpperCase() === "SUPERVISOR" || user.profile.toUpperCase() === "MASTER") { setShowAllTickets(true); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { if (tab === "search") { searchInputRef.current.focus(); } setTabOption(tab) }, [tab, setTabOption]); useEffect(() => { const fetchSession = async () => { try { const { data } = await api.get('/settings') setSettings(data.settings) } catch (err) { toastError(err) } } fetchSession() }, []) const getSettingValue = (key) => { const { value } = settings.find((s) => s.key === key) return value } const fetchTickets = async () =>{ try { const { data } = await api.get("/tickets", { 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, 7000); return () => { clearInterval(intervalId); }; } }, [selectedQueueIds, settings]); useEffect(() => { const calculateAverageTime = () => { if(tickets.length > 0){ const now = new Date(); const differenceTime = tickets?.map(ticket => { const updatedAt = new Date(ticket.updatedAt); const difference = now - updatedAt; return difference; }); const sumDifferences = differenceTime.reduce((total, difference) => total + difference, 0); const averageTimeMilliseconds = sumDifferences / tickets?.length; let hours = Math.floor(averageTimeMilliseconds / 3600000); const minutes = Math.floor((averageTimeMilliseconds % 3600000) / 60000); let days = hours >= 24 ? parseInt(hours/24) : ''; if(days != '') hours = hours - (24*days); const averageTimeFormated = `${days != '' ? `${days}d ` : days}${hours.toString().padStart(2, '0')}h${minutes.toString().padStart(2, '0')}`; return averageTimeFormated; }else return '00:00'; } setWaitingTime(calculateAverageTime()); },[tickets]); useEffect(() => { // clearTimeout(searchContentTimeout); // setSearchParam(prev => ({ ...prev, searchParamContent: "" })) if (!inputContentSearch) return if (!searchContentTimeout) return // searchContentTimeout = setTimeout(() => { // setSearchParam(prev => ({ ...prev, searchParamContent: inputContentSearch })); // }, 500); clearTimeout(searchContentTimeout); setSearchParam(prev => ({ ...prev, searchParamContent: "" })) }, [inputContentSearch, searchContentTimeout]); useEffect(() => { //console.log(selectedQueueIds); if (tabOption === 'open') { setTabOption('') setSearchParam(DEFAULT_SEARCH_PARAM); setInputSearch(''); setInputContentSearch('') setTab("open"); return; } }, [tabOption, setTabOption]) const removeExtraSpace = (str) => { str = str.replace(/^\s+/g, '') return str.replace(/\s+/g, ' ') } const handleSearch = (e) => { let searchedTerm = e.target.value.toLowerCase() setInputSearch(removeExtraSpace(searchedTerm)) setSearchTicket(searchParam.searchParam) clearTimeout(searchTimeout); if (searchedTerm === "") { setSearchParam(prev => ({ ...prev, searchParam: searchedTerm })) setInputSearch(searchedTerm) setShowContentSearch(false) setTab("open"); return; } if (searchedTerm.length < 4) { setSearchParam(prev => ({ ...prev, searchParamContent: "" })) setInputContentSearch('') } searchTimeout = setTimeout(() => { setSearchParam(prev => ({ ...prev, searchParam: searchedTerm })); }, 500); }; const handleContentSearch = e => { let searchedContentText = removeExtraSpace(e.target.value.toLowerCase()) setInputContentSearch(searchedContentText) searchContentTimeout = setTimeout(() => { setSearchParam(prev => ({ ...prev, searchParamContent: searchedContentText })); }, 500); } const handleOpenTooltipSearch = () => { if (searchParam.searchParam.length < 4) { setOpenTooltipSearch(true) } } const handleCloseTooltipSearch = () => { setOpenTooltipSearch(false) if (searchParam.searchParam.length < 4) { searchInputRef.current.focus() } } const handleChangeTab = (e, newValue) => { setTab(newValue); }; const handleChangeTabOpen = (e, newValue) => { setTabOpen(newValue); }; const applyPanelStyle = (status) => { if (tabOpen !== status) { return { width: 0, height: 0 }; } }; return ( setNewTicketModalOpen(false)} /> } label={i18n.t("tickets.tabs.open.title")} classes={{ root: classes.tab }} /> } label={i18n.t("tickets.tabs.closed.title")} classes={{ root: classes.tab }} /> } label={i18n.t("tickets.tabs.search.title")} classes={{ root: classes.tab }} /> {tab === "search" ? (
{/* setShowContentSearch(prev => !prev)}> */} handleOpenTooltipSearch()} onClose={() => handleCloseTooltipSearch()} title="Digite pelo menos 4 caracteres" arrow> setShowContentSearch(prev => !prev)} >
{ // showContentSearch ? (showContentSearch && searchParam.searchParam.length >= 4) ? (
handleContentSearch(e)} />
) : null }
) : ( <> ( setShowAllTickets((prevState) => !prevState) } name="showAllTickets" color="primary" /> } /> )} /> )} setSelectedQueueIds(values)} />
{i18n.t("ticketsList.assignedHeader")} } value={"open"} /> {i18n.t("ticketsList.pendingHeader")} } value={"pending"} />{ (settings?.length > 0 && getSettingValue('waitingTimeTickets') === 'enabled') && } setOpenCount(val)} style={applyPanelStyle("open")} /> setPendingCount(val)} style={applyPanelStyle("pending")} />
); }; export default TicketsManager;