Merge pull request #295 from ertprs/master

update layout do ticket (aguardando/atendimento) em duas abas  e o la…
This commit is contained in:
Cassio Santos
2021-11-24 19:17:31 -03:00
committed by GitHub
8 changed files with 178 additions and 41 deletions

View File

@@ -11,7 +11,7 @@
"@testing-library/user-event": "^12.1.7",
"axios": "^0.21.1",
"date-fns": "^2.16.1",
"emoji-mart": "^3.0.0",
"emoji-mart": "^3.0.1",
"formik": "^2.2.0",
"i18next": "^19.8.2",
"i18next-browser-languagedetector": "^6.0.1",

View File

@@ -10,7 +10,6 @@ import TicketsListSkeleton from "../TicketsListSkeleton";
import useTickets from "../../hooks/useTickets";
import { i18n } from "../../translate/i18n";
import { ListSubheader } from "@material-ui/core";
import { AuthContext } from "../../context/Auth/AuthContext";
const useStyles = makeStyles(theme => ({
@@ -153,7 +152,9 @@ const reducer = (state, action) => {
}
};
const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => {
const TicketsList = (props) => {
const { status, searchParam, showAll, selectedQueueIds, updateCount, style } =
props;
const classes = useStyles();
const [pageNumber, setPageNumber] = useState(1);
const [ticketsList, dispatch] = useReducer(reducer, []);
@@ -245,6 +246,13 @@ const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => {
};
}, [status, showAll, user, selectedQueueIds]);
useEffect(() => {
if (typeof updateCount === "function") {
updateCount(ticketsList.length);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ticketsList]);
const loadMore = () => {
setPageNumber(prevState => prevState + 1);
};
@@ -260,7 +268,7 @@ const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => {
};
return (
<div className={classes.ticketsListWrapper}>
<Paper className={classes.ticketsListWrapper} style={style}>
<Paper
square
name="closed"
@@ -269,26 +277,6 @@ const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => {
onScroll={handleScroll}
>
<List style={{ paddingTop: 0 }}>
{status === "open" && (
<ListSubheader className={classes.ticketsListHeader}>
<div>
{i18n.t("ticketsList.assignedHeader")}
<span className={classes.ticketsCount}>
{ticketsList.length}
</span>
</div>
</ListSubheader>
)}
{status === "pending" && (
<ListSubheader className={classes.ticketsListHeader}>
<div>
{i18n.t("ticketsList.pendingHeader")}
<span className={classes.ticketsCount}>
{ticketsList.length}
</span>
</div>
</ListSubheader>
)}
{ticketsList.length === 0 && !loading ? (
<div className={classes.noTicketsDiv}>
<span className={classes.noTicketsTitle}>
@@ -308,7 +296,7 @@ const TicketsList = ({ status, searchParam, showAll, selectedQueueIds }) => {
{loading && <TicketsListSkeleton />}
</List>
</Paper>
</div>
</Paper>
);
};

View File

@@ -6,6 +6,7 @@ import SearchIcon from "@material-ui/icons/Search";
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 MoveToInboxIcon from "@material-ui/icons/MoveToInbox";
import CheckBoxIcon from "@material-ui/icons/CheckBox";
@@ -78,6 +79,16 @@ const useStyles = makeStyles((theme) => ({
border: "none",
borderRadius: 30,
},
badge: {
right: "-10px",
},
show: {
display: "block",
},
hide: {
display: "none !important",
},
}));
const TicketsManager = () => {
@@ -85,14 +96,25 @@ const TicketsManager = () => {
const [searchParam, setSearchParam] = useState("");
const [tab, setTab] = useState("open");
const [tabOpen, setTabOpen] = useState("open");
const [newTicketModalOpen, setNewTicketModalOpen] = useState(false);
const [showAllTickets, setShowAllTickets] = useState(false);
const searchInputRef = useRef();
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 || []);
useEffect(() => {
if (user.profile.toUpperCase() === "ADMIN") {
setShowAllTickets(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (tab === "search") {
searchInputRef.current.focus();
@@ -121,6 +143,16 @@ const TicketsManager = () => {
setTab(newValue);
};
const handleChangeTabOpen = (e, newValue) => {
setTabOpen(newValue);
};
const applyPanelStyle = (status) => {
if (tabOpen !== status) {
return { width: 0, height: 0 };
}
};
return (
<Paper elevation={0} variant="outlined" className={classes.ticketsWrapper}>
<NewTicketModal
@@ -208,12 +240,53 @@ const TicketsManager = () => {
/>
</Paper>
<TabPanel value={tab} name="open" className={classes.ticketsWrapper}>
<TicketsList
status="open"
showAll={showAllTickets}
selectedQueueIds={selectedQueueIds}
/>
<TicketsList status="pending" selectedQueueIds={selectedQueueIds} />
<Tabs
value={tabOpen}
onChange={handleChangeTabOpen}
indicatorColor="primary"
textColor="primary"
variant="fullWidth"
>
<Tab
label={
<Badge
className={classes.badge}
badgeContent={openCount}
color="primary"
>
{i18n.t("ticketsList.assignedHeader")}
</Badge>
}
value={"open"}
/>
<Tab
label={
<Badge
className={classes.badge}
badgeContent={pendingCount}
color="secondary"
>
{i18n.t("ticketsList.pendingHeader")}
</Badge>
}
value={"pending"}
/>
</Tabs>
<Paper className={classes.ticketsWrapper}>
<TicketsList
status="open"
showAll={showAllTickets}
selectedQueueIds={selectedQueueIds}
updateCount={(val) => setOpenCount(val)}
style={applyPanelStyle("open")}
/>
<TicketsList
status="pending"
selectedQueueIds={selectedQueueIds}
updateCount={(val) => setPendingCount(val)}
style={applyPanelStyle("pending")}
/>
</Paper>
</TabPanel>
<TabPanel value={tab} name="closed" className={classes.ticketsWrapper}>
<TicketsList

View File

@@ -4,6 +4,11 @@ import { useHistory } from "react-router-dom";
import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField";
import Dialog from "@material-ui/core/Dialog";
import Select from "@material-ui/core/Select";
import FormControl from "@material-ui/core/FormControl";
import InputLabel from "@material-ui/core/InputLabel";
import MenuItem from "@material-ui/core/MenuItem";
import { makeStyles } from "@material-ui/core";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
@@ -17,6 +22,13 @@ import { i18n } from "../../translate/i18n";
import api from "../../services/api";
import ButtonWithSpinner from "../ButtonWithSpinner";
import toastError from "../../errors/toastError";
import useQueues from "../../hooks/useQueues";
const useStyles = makeStyles((theme) => ({
maxWidth: {
width: "100%",
},
}));
const filterOptions = createFilterOptions({
trim: true,
@@ -25,9 +37,24 @@ const filterOptions = createFilterOptions({
const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const history = useHistory();
const [options, setOptions] = useState([]);
const [queues, setQueues] = useState([]);
const [allQueues, setAllQueues] = useState([]);
const [loading, setLoading] = useState(false);
const [searchParam, setSearchParam] = useState("");
const [selectedUser, setSelectedUser] = useState(null);
const [selectedQueue, setSelectedQueue] = useState('');
const classes = useStyles();
const { findAll: findAllQueues } = useQueues();
useEffect(() => {
const loadQueues = async () => {
const list = await findAllQueues();
setAllQueues(list);
setQueues(list);
}
loadQueues();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (!modalOpen || searchParam.length < 3) {
@@ -62,14 +89,26 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const handleSaveTicket = async e => {
e.preventDefault();
if (!ticketid || !selectedUser) return;
if (!ticketid) return;
setLoading(true);
try {
await api.put(`/tickets/${ticketid}`, {
userId: selectedUser.id,
queueId: null,
status: "open",
});
let data = {};
if (selectedUser) {
data.userId = selectedUser.id
}
if (selectedQueue && selectedQueue !== null) {
data.queueId = selectedQueue
if (!selectedUser) {
data.status = 'pending';
data.userId = null;
}
}
await api.put(`/tickets/${ticketid}`, data);
setLoading(false);
history.push(`/tickets`);
} catch (err) {
@@ -86,10 +125,16 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
</DialogTitle>
<DialogContent dividers>
<Autocomplete
style={{ width: 300 }}
style={{ width: 300, marginBottom: 20 }}
getOptionLabel={option => `${option.name}`}
onChange={(e, newValue) => {
setSelectedUser(newValue);
if (newValue != null && Array.isArray(newValue.queues)) {
setQueues(newValue.queues);
} else {
setQueues(allQueues);
setSelectedQueue('');
}
}}
options={options}
filterOptions={filterOptions}
@@ -119,6 +164,19 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
/>
)}
/>
<FormControl variant="outlined" className={classes.maxWidth}>
<InputLabel>{i18n.t("transferTicketModal.fieldQueueLabel")}</InputLabel>
<Select
value={selectedQueue}
onChange={(e) => setSelectedQueue(e.target.value)}
label={i18n.t("transferTicketModal.fieldQueuePlaceholder")}
>
<MenuItem value={''}>&nbsp;</MenuItem>
{queues.map((queue) => (
<MenuItem key={queue.id} value={queue.id}>{queue.name}</MenuItem>
))}
</Select>
</FormControl>
</DialogContent>
<DialogActions>
<Button

View File

@@ -0,0 +1,12 @@
import api from "../../services/api";
const useQueues = () => {
const findAll = async () => {
const { data } = await api.get("/queue");
return data;
}
return { findAll };
};
export default useQueues;

View File

@@ -247,6 +247,8 @@ const messages = {
transferTicketModal: {
title: "Transfer Ticket",
fieldLabel: "Type to search for users",
fieldQueueLabel: "Transfer to queue",
fieldQueuePlaceholder: "Please select a queue",
noOptions: "No user found with this name",
buttons: {
ok: "Transfer",
@@ -377,7 +379,7 @@ const messages = {
},
},
messagesInput: {
placeholderOpen: "Type a message",
placeholderOpen: "Type a message or press ''/'' to use the registered quick responses",
placeholderClosed: "Reopen or accept this ticket to send a message.",
signMessage: "Sign",
},

View File

@@ -250,6 +250,8 @@ const messages = {
transferTicketModal: {
title: "Transferir Ticket",
fieldLabel: "Escriba para buscar usuarios",
fieldQueueLabel: "Transferir a la cola",
fieldQueuePlaceholder: "Seleccione una cola",
noOptions: "No se encontraron usuarios con ese nombre",
buttons: {
ok: "Transferir",
@@ -382,7 +384,7 @@ const messages = {
},
},
messagesInput: {
placeholderOpen: "Escribe un mensaje",
placeholderOpen: "Escriba un mensaje o presione '' / '' para usar las respuestas rápidas registradas",
placeholderClosed:
"Vuelva a abrir o acepte este ticket para enviar un mensaje.",
signMessage: "Firmar",

View File

@@ -249,6 +249,8 @@ const messages = {
transferTicketModal: {
title: "Transferir Ticket",
fieldLabel: "Digite para buscar usuários",
fieldQueueLabel: "Transferir para fila",
fieldQueuePlaceholder: "Selecione uma fila",
noOptions: "Nenhum usuário encontrado com esse nome",
buttons: {
ok: "Transferir",
@@ -381,7 +383,7 @@ const messages = {
},
},
messagesInput: {
placeholderOpen: "Digite uma mensagem",
placeholderOpen: "Digite uma mensagem ou tecle ''/'' para utilizar as respostas rápidas cadastrada",
placeholderClosed:
"Reabra ou aceite esse ticket para enviar uma mensagem.",
signMessage: "Assinar",