update layout do ticket (aguardando/atendimento) em duas abas e o layout de transferir ticket

This commit is contained in:
ertprs
2021-11-14 02:11:26 -03:00
parent f5874032d7
commit 90cbc6bfc7
5 changed files with 169 additions and 38 deletions

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,11 @@ import { useHistory } from "react-router-dom";
import Button from "@material-ui/core/Button"; import Button from "@material-ui/core/Button";
import TextField from "@material-ui/core/TextField"; import TextField from "@material-ui/core/TextField";
import Dialog from "@material-ui/core/Dialog"; 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 DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent"; import DialogContent from "@material-ui/core/DialogContent";
@@ -17,6 +22,13 @@ import { i18n } from "../../translate/i18n";
import api from "../../services/api"; import api from "../../services/api";
import ButtonWithSpinner from "../ButtonWithSpinner"; import ButtonWithSpinner from "../ButtonWithSpinner";
import toastError from "../../errors/toastError"; import toastError from "../../errors/toastError";
import useQueues from "../../hooks/useQueues";
const useStyles = makeStyles((theme) => ({
maxWidth: {
width: "100%",
},
}));
const filterOptions = createFilterOptions({ const filterOptions = createFilterOptions({
trim: true, trim: true,
@@ -25,9 +37,24 @@ const filterOptions = createFilterOptions({
const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => { const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const history = useHistory(); const history = useHistory();
const [options, setOptions] = useState([]); const [options, setOptions] = useState([]);
const [queues, setQueues] = useState([]);
const [allQueues, setAllQueues] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [searchParam, setSearchParam] = useState(""); const [searchParam, setSearchParam] = useState("");
const [selectedUser, setSelectedUser] = useState(null); 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(() => { useEffect(() => {
if (!modalOpen || searchParam.length < 3) { if (!modalOpen || searchParam.length < 3) {
@@ -62,14 +89,26 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
const handleSaveTicket = async e => { const handleSaveTicket = async e => {
e.preventDefault(); e.preventDefault();
if (!ticketid || !selectedUser) return; if (!ticketid) return;
setLoading(true); setLoading(true);
try { try {
await api.put(`/tickets/${ticketid}`, { let data = {};
userId: selectedUser.id,
queueId: null, if (selectedUser) {
status: "open", 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); setLoading(false);
history.push(`/tickets`); history.push(`/tickets`);
} catch (err) { } catch (err) {
@@ -86,10 +125,16 @@ const TransferTicketModal = ({ modalOpen, onClose, ticketid }) => {
</DialogTitle> </DialogTitle>
<DialogContent dividers> <DialogContent dividers>
<Autocomplete <Autocomplete
style={{ width: 300 }} style={{ width: 300, marginBottom: 20 }}
getOptionLabel={option => `${option.name}`} getOptionLabel={option => `${option.name}`}
onChange={(e, newValue) => { onChange={(e, newValue) => {
setSelectedUser(newValue); setSelectedUser(newValue);
if (newValue != null && Array.isArray(newValue.queues)) {
setQueues(newValue.queues);
} else {
setQueues(allQueues);
setSelectedQueue('');
}
}} }}
options={options} options={options}
filterOptions={filterOptions} 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> </DialogContent>
<DialogActions> <DialogActions>
<Button <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;