diff --git a/frontend/src/App.js b/frontend/src/App.js
index f1dfbde..ff22dac 100644
--- a/frontend/src/App.js
+++ b/frontend/src/App.js
@@ -2,46 +2,46 @@ import React, { useState, useEffect } from "react";
import Routes from "./routes";
import "react-toastify/dist/ReactToastify.css";
-import { createMuiTheme, ThemeProvider } from "@material-ui/core/styles";
+import { createTheme, ThemeProvider } from "@material-ui/core/styles";
import { ptBR } from "@material-ui/core/locale";
const App = () => {
- const [locale, setLocale] = useState();
+ const [locale, setLocale] = useState();
- const theme = createMuiTheme(
- {
- scrollbarStyles: {
- "&::-webkit-scrollbar": {
- width: "8px",
- height: "8px",
- },
- "&::-webkit-scrollbar-thumb": {
- boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)",
- backgroundColor: "#e8e8e8",
- },
- },
- palette: {
- primary: { main: "#2576d2" },
- },
- },
- locale
- );
+ const theme = createTheme(
+ {
+ scrollbarStyles: {
+ "&::-webkit-scrollbar": {
+ width: "8px",
+ height: "8px",
+ },
+ "&::-webkit-scrollbar-thumb": {
+ boxShadow: "inset 0 0 6px rgba(0, 0, 0, 0.3)",
+ backgroundColor: "#e8e8e8",
+ },
+ },
+ palette: {
+ primary: { main: "#2576d2" },
+ },
+ },
+ locale
+ );
- useEffect(() => {
- const i18nlocale = localStorage.getItem("i18nextLng");
- const browserLocale =
- i18nlocale.substring(0, 2) + i18nlocale.substring(3, 5);
+ useEffect(() => {
+ const i18nlocale = localStorage.getItem("i18nextLng");
+ const browserLocale =
+ i18nlocale.substring(0, 2) + i18nlocale.substring(3, 5);
- if (browserLocale === "ptBR") {
- setLocale(ptBR);
- }
- }, []);
+ if (browserLocale === "ptBR") {
+ setLocale(ptBR);
+ }
+ }, []);
- return (
-
-
-
- );
+ return (
+
+
+
+ );
};
export default App;
diff --git a/frontend/src/components/ColorPicker/index.js b/frontend/src/components/ColorPicker/index.js
index b89b233..c10360e 100644
--- a/frontend/src/components/ColorPicker/index.js
+++ b/frontend/src/components/ColorPicker/index.js
@@ -4,28 +4,28 @@ import React, { useState } from "react";
import { GithubPicker } from "react-color";
const ColorPicker = ({ onChange, currentColor, handleClose, open }) => {
- const [selectedColor, setSelectedColor] = useState(currentColor);
+ const [selectedColor, setSelectedColor] = useState(currentColor);
- const handleChange = color => {
- setSelectedColor(color.hex);
- handleClose();
- };
+ const handleChange = (color) => {
+ setSelectedColor(color.hex);
+ handleClose();
+ };
- return (
-
- );
+ return (
+
+ );
};
export default ColorPicker;
diff --git a/frontend/src/components/MainContainer/index.js b/frontend/src/components/MainContainer/index.js
index 24b7b9a..0045703 100644
--- a/frontend/src/components/MainContainer/index.js
+++ b/frontend/src/components/MainContainer/index.js
@@ -3,29 +3,31 @@ import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import Container from "@material-ui/core/Container";
-const useStyles = makeStyles(theme => ({
- mainContainer: {
- flex: 1,
- padding: theme.spacing(2),
- height: `calc(100% - 48px)`,
- },
+const useStyles = makeStyles((theme) => ({
+ mainContainer: {
+ flex: 1,
+ // padding: theme.spacing(2),
+ // height: `calc(100% - 48px)`,
+ padding: 0,
+ height: "100%",
+ },
- contentWrapper: {
- height: "100%",
- overflowY: "hidden",
- display: "flex",
- flexDirection: "column",
- },
+ contentWrapper: {
+ height: "100%",
+ overflowY: "hidden",
+ display: "flex",
+ flexDirection: "column",
+ },
}));
const MainContainer = ({ children }) => {
- const classes = useStyles();
+ const classes = useStyles();
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
};
export default MainContainer;
diff --git a/frontend/src/components/MessageInput/index.js b/frontend/src/components/MessageInput/index.js
index f297786..3a33829 100644
--- a/frontend/src/components/MessageInput/index.js
+++ b/frontend/src/components/MessageInput/index.js
@@ -12,6 +12,7 @@ import CircularProgress from "@material-ui/core/CircularProgress";
import { green } from "@material-ui/core/colors";
import AttachFileIcon from "@material-ui/icons/AttachFile";
import IconButton from "@material-ui/core/IconButton";
+import MoreVert from "@material-ui/icons/MoreVert";
import MoodIcon from "@material-ui/icons/Mood";
import SendIcon from "@material-ui/icons/Send";
import CancelIcon from "@material-ui/icons/Cancel";
@@ -19,7 +20,13 @@ import ClearIcon from "@material-ui/icons/Clear";
import MicIcon from "@material-ui/icons/Mic";
import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline";
import HighlightOffIcon from "@material-ui/icons/HighlightOff";
-import { FormControlLabel, Switch } from "@material-ui/core";
+import {
+ FormControlLabel,
+ Hidden,
+ Menu,
+ MenuItem,
+ Switch,
+} from "@material-ui/core";
import ClickAwayListener from "@material-ui/core/ClickAwayListener";
import { i18n } from "../../translate/i18n";
@@ -39,6 +46,11 @@ const useStyles = makeStyles((theme) => ({
flexDirection: "column",
alignItems: "center",
borderTop: "1px solid rgba(0, 0, 0, 0.12)",
+ [theme.breakpoints.down("sm")]: {
+ position: "fixed",
+ bottom: 0,
+ width: "100%",
+ },
},
newMessageBox: {
@@ -56,6 +68,7 @@ const useStyles = makeStyles((theme) => ({
display: "flex",
borderRadius: 20,
flex: 1,
+ position: "relative",
},
messageInput: {
@@ -200,6 +213,7 @@ const MessageInput = ({ ticketStatus }) => {
const [quickAnswers, setQuickAnswer] = useState([]);
const [typeBar, setTypeBar] = useState(false);
const inputRef = useRef();
+ const [anchorEl, setAnchorEl] = useState(null);
const { setReplyingMessage, replyingMessage } =
useContext(ReplyMessageContext);
const { user } = useContext(AuthContext);
@@ -363,6 +377,14 @@ const MessageInput = ({ ticketStatus }) => {
}
};
+ const handleOpenMenuClick = (event) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleMenuItemClick = (event) => {
+ setAnchorEl(null);
+ };
+
const renderReplyingMessage = (message) => {
return (
@@ -429,60 +451,126 @@ const MessageInput = ({ ticketStatus }) => {
{replyingMessage && renderReplyingMessage(replyingMessage)}
-
setShowEmoji((prevState) => !prevState)}
- >
-
-
- {showEmoji ? (
-
-
setShowEmoji(false)}>
-
-
-
- ) : null}
-
-
-
-
{
- setSignMessage(e.target.checked);
- }}
- name="showAllTickets"
- color="primary"
- />
- }
- />
+ {showEmoji ? (
+
+
setShowEmoji(false)}>
+
+
+
+ ) : null}
+
+
+
+ {
+ setSignMessage(e.target.checked);
+ }}
+ name="showAllTickets"
+ color="primary"
+ />
+ }
+ />
+
+
+
+
+
+
+
{
diff --git a/frontend/src/components/MessageOptionsMenu/index.js b/frontend/src/components/MessageOptionsMenu/index.js
index 83a0b6e..ea0dd0b 100644
--- a/frontend/src/components/MessageOptionsMenu/index.js
+++ b/frontend/src/components/MessageOptionsMenu/index.js
@@ -10,62 +10,62 @@ import { ReplyMessageContext } from "../../context/ReplyingMessage/ReplyingMessa
import toastError from "../../errors/toastError";
const MessageOptionsMenu = ({ message, menuOpen, handleClose, anchorEl }) => {
- const { setReplyingMessage } = useContext(ReplyMessageContext);
- const [confirmationOpen, setConfirmationOpen] = useState(false);
+ const { setReplyingMessage } = useContext(ReplyMessageContext);
+ const [confirmationOpen, setConfirmationOpen] = useState(false);
- const handleDeleteMessage = async () => {
- try {
- await api.delete(`/messages/${message.id}`);
- } catch (err) {
- toastError(err);
- }
- };
+ const handleDeleteMessage = async () => {
+ try {
+ await api.delete(`/messages/${message.id}`);
+ } catch (err) {
+ toastError(err);
+ }
+ };
- const hanldeReplyMessage = () => {
- setReplyingMessage(message);
- handleClose();
- };
+ const hanldeReplyMessage = () => {
+ setReplyingMessage(message);
+ handleClose();
+ };
- const handleOpenConfirmationModal = e => {
- setConfirmationOpen(true);
- handleClose();
- };
+ const handleOpenConfirmationModal = (e) => {
+ setConfirmationOpen(true);
+ handleClose();
+ };
- return (
- <>
-
- {i18n.t("messageOptionsMenu.confirmationModal.message")}
-
-
- >
- );
+ return (
+ <>
+
+ {i18n.t("messageOptionsMenu.confirmationModal.message")}
+
+
+ >
+ );
};
export default MessageOptionsMenu;
diff --git a/frontend/src/components/MessagesList/index.js b/frontend/src/components/MessagesList/index.js
index e22af75..ef91b81 100644
--- a/frontend/src/components/MessagesList/index.js
+++ b/frontend/src/components/MessagesList/index.js
@@ -6,19 +6,19 @@ import clsx from "clsx";
import { green } from "@material-ui/core/colors";
import {
- Button,
- CircularProgress,
- Divider,
- IconButton,
- makeStyles,
+ Button,
+ CircularProgress,
+ Divider,
+ IconButton,
+ makeStyles,
} from "@material-ui/core";
import {
- AccessTime,
- Block,
- Done,
- DoneAll,
- ExpandMore,
- GetApp,
+ AccessTime,
+ Block,
+ Done,
+ DoneAll,
+ ExpandMore,
+ GetApp,
} from "@material-ui/icons";
import MarkdownWrapper from "../MarkdownWrapper";
@@ -29,623 +29,626 @@ import whatsBackground from "../../assets/wa-background.png";
import api from "../../services/api";
import toastError from "../../errors/toastError";
-const useStyles = makeStyles(theme => ({
- messagesListWrapper: {
- overflow: "hidden",
- position: "relative",
- display: "flex",
- flexDirection: "column",
- flexGrow: 1,
- },
+const useStyles = makeStyles((theme) => ({
+ messagesListWrapper: {
+ overflow: "hidden",
+ position: "relative",
+ display: "flex",
+ flexDirection: "column",
+ flexGrow: 1,
+ },
- messagesList: {
- backgroundImage: `url(${whatsBackground})`,
- display: "flex",
- flexDirection: "column",
- flexGrow: 1,
- padding: "20px 20px 20px 20px",
- overflowY: "scroll",
- ...theme.scrollbarStyles,
- },
+ messagesList: {
+ backgroundImage: `url(${whatsBackground})`,
+ display: "flex",
+ flexDirection: "column",
+ flexGrow: 1,
+ padding: "20px 20px 20px 20px",
+ overflowY: "scroll",
+ [theme.breakpoints.down("sm")]: {
+ paddingBottom: "90px",
+ },
+ ...theme.scrollbarStyles,
+ },
- circleLoading: {
- color: green[500],
- position: "absolute",
- opacity: "70%",
- top: 0,
- left: "50%",
- marginTop: 12,
- },
+ circleLoading: {
+ color: green[500],
+ position: "absolute",
+ opacity: "70%",
+ top: 0,
+ left: "50%",
+ marginTop: 12,
+ },
- messageLeft: {
- marginRight: 20,
- marginTop: 2,
- minWidth: 100,
- maxWidth: 600,
- height: "auto",
- display: "block",
- position: "relative",
- "&:hover #messageActionsButton": {
- display: "flex",
- position: "absolute",
- top: 0,
- right: 0,
- },
+ messageLeft: {
+ marginRight: 20,
+ marginTop: 2,
+ minWidth: 100,
+ maxWidth: 600,
+ height: "auto",
+ display: "block",
+ position: "relative",
+ "&:hover #messageActionsButton": {
+ display: "flex",
+ position: "absolute",
+ top: 0,
+ right: 0,
+ },
- whiteSpace: "pre-wrap",
- backgroundColor: "#ffffff",
- color: "#303030",
- alignSelf: "flex-start",
- borderTopLeftRadius: 0,
- borderTopRightRadius: 8,
- borderBottomLeftRadius: 8,
- borderBottomRightRadius: 8,
- paddingLeft: 5,
- paddingRight: 5,
- paddingTop: 5,
- paddingBottom: 0,
- boxShadow: "0 1px 1px #b3b3b3",
- },
+ whiteSpace: "pre-wrap",
+ backgroundColor: "#ffffff",
+ color: "#303030",
+ alignSelf: "flex-start",
+ borderTopLeftRadius: 0,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 8,
+ paddingLeft: 5,
+ paddingRight: 5,
+ paddingTop: 5,
+ paddingBottom: 0,
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
- quotedContainerLeft: {
- margin: "-3px -80px 6px -6px",
- overflow: "hidden",
- backgroundColor: "#f0f0f0",
- borderRadius: "7.5px",
- display: "flex",
- position: "relative",
- },
+ quotedContainerLeft: {
+ margin: "-3px -80px 6px -6px",
+ overflow: "hidden",
+ backgroundColor: "#f0f0f0",
+ borderRadius: "7.5px",
+ display: "flex",
+ position: "relative",
+ },
- quotedMsg: {
- padding: 10,
- maxWidth: 300,
- height: "auto",
- display: "block",
- whiteSpace: "pre-wrap",
- overflow: "hidden",
- },
+ quotedMsg: {
+ padding: 10,
+ maxWidth: 300,
+ height: "auto",
+ display: "block",
+ whiteSpace: "pre-wrap",
+ overflow: "hidden",
+ },
- quotedSideColorLeft: {
- flex: "none",
- width: "4px",
- backgroundColor: "#6bcbef",
- },
+ quotedSideColorLeft: {
+ flex: "none",
+ width: "4px",
+ backgroundColor: "#6bcbef",
+ },
- messageRight: {
- marginLeft: 20,
- marginTop: 2,
- minWidth: 100,
- maxWidth: 600,
- height: "auto",
- display: "block",
- position: "relative",
- "&:hover #messageActionsButton": {
- display: "flex",
- position: "absolute",
- top: 0,
- right: 0,
- },
+ messageRight: {
+ marginLeft: 20,
+ marginTop: 2,
+ minWidth: 100,
+ maxWidth: 600,
+ height: "auto",
+ display: "block",
+ position: "relative",
+ "&:hover #messageActionsButton": {
+ display: "flex",
+ position: "absolute",
+ top: 0,
+ right: 0,
+ },
- whiteSpace: "pre-wrap",
- backgroundColor: "#dcf8c6",
- color: "#303030",
- alignSelf: "flex-end",
- borderTopLeftRadius: 8,
- borderTopRightRadius: 8,
- borderBottomLeftRadius: 8,
- borderBottomRightRadius: 0,
- paddingLeft: 5,
- paddingRight: 5,
- paddingTop: 5,
- paddingBottom: 0,
- boxShadow: "0 1px 1px #b3b3b3",
- },
+ whiteSpace: "pre-wrap",
+ backgroundColor: "#dcf8c6",
+ color: "#303030",
+ alignSelf: "flex-end",
+ borderTopLeftRadius: 8,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 0,
+ paddingLeft: 5,
+ paddingRight: 5,
+ paddingTop: 5,
+ paddingBottom: 0,
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
- quotedContainerRight: {
- margin: "-3px -80px 6px -6px",
- overflowY: "hidden",
- backgroundColor: "#cfe9ba",
- borderRadius: "7.5px",
- display: "flex",
- position: "relative",
- },
+ quotedContainerRight: {
+ margin: "-3px -80px 6px -6px",
+ overflowY: "hidden",
+ backgroundColor: "#cfe9ba",
+ borderRadius: "7.5px",
+ display: "flex",
+ position: "relative",
+ },
- quotedMsgRight: {
- padding: 10,
- maxWidth: 300,
- height: "auto",
- whiteSpace: "pre-wrap",
- },
+ quotedMsgRight: {
+ padding: 10,
+ maxWidth: 300,
+ height: "auto",
+ whiteSpace: "pre-wrap",
+ },
- quotedSideColorRight: {
- flex: "none",
- width: "4px",
- backgroundColor: "#35cd96",
- },
+ quotedSideColorRight: {
+ flex: "none",
+ width: "4px",
+ backgroundColor: "#35cd96",
+ },
- messageActionsButton: {
- display: "none",
- position: "relative",
- color: "#999",
- zIndex: 1,
- backgroundColor: "inherit",
- opacity: "90%",
- "&:hover, &.Mui-focusVisible": { backgroundColor: "inherit" },
- },
+ messageActionsButton: {
+ display: "none",
+ position: "relative",
+ color: "#999",
+ zIndex: 1,
+ backgroundColor: "inherit",
+ opacity: "90%",
+ "&:hover, &.Mui-focusVisible": { backgroundColor: "inherit" },
+ },
- messageContactName: {
- display: "flex",
- color: "#6bcbef",
- fontWeight: 500,
- },
+ messageContactName: {
+ display: "flex",
+ color: "#6bcbef",
+ fontWeight: 500,
+ },
- textContentItem: {
- overflowWrap: "break-word",
- padding: "3px 80px 6px 6px",
- },
+ textContentItem: {
+ overflowWrap: "break-word",
+ padding: "3px 80px 6px 6px",
+ },
- textContentItemDeleted: {
- fontStyle: "italic",
- color: "rgba(0, 0, 0, 0.36)",
- overflowWrap: "break-word",
- padding: "3px 80px 6px 6px",
- },
+ textContentItemDeleted: {
+ fontStyle: "italic",
+ color: "rgba(0, 0, 0, 0.36)",
+ overflowWrap: "break-word",
+ padding: "3px 80px 6px 6px",
+ },
- messageMedia: {
- objectFit: "cover",
- width: 250,
- height: 200,
- borderTopLeftRadius: 8,
- borderTopRightRadius: 8,
- borderBottomLeftRadius: 8,
- borderBottomRightRadius: 8,
- },
+ messageMedia: {
+ objectFit: "cover",
+ width: 250,
+ height: 200,
+ borderTopLeftRadius: 8,
+ borderTopRightRadius: 8,
+ borderBottomLeftRadius: 8,
+ borderBottomRightRadius: 8,
+ },
- timestamp: {
- fontSize: 11,
- position: "absolute",
- bottom: 0,
- right: 5,
- color: "#999",
- },
+ timestamp: {
+ fontSize: 11,
+ position: "absolute",
+ bottom: 0,
+ right: 5,
+ color: "#999",
+ },
- dailyTimestamp: {
- alignItems: "center",
- textAlign: "center",
- alignSelf: "center",
- width: "110px",
- backgroundColor: "#e1f3fb",
- margin: "10px",
- borderRadius: "10px",
- boxShadow: "0 1px 1px #b3b3b3",
- },
+ dailyTimestamp: {
+ alignItems: "center",
+ textAlign: "center",
+ alignSelf: "center",
+ width: "110px",
+ backgroundColor: "#e1f3fb",
+ margin: "10px",
+ borderRadius: "10px",
+ boxShadow: "0 1px 1px #b3b3b3",
+ },
- dailyTimestampText: {
- color: "#808888",
- padding: 8,
- alignSelf: "center",
- marginLeft: "0px",
- },
+ dailyTimestampText: {
+ color: "#808888",
+ padding: 8,
+ alignSelf: "center",
+ marginLeft: "0px",
+ },
- ackIcons: {
- fontSize: 18,
- verticalAlign: "middle",
- marginLeft: 4,
- },
+ ackIcons: {
+ fontSize: 18,
+ verticalAlign: "middle",
+ marginLeft: 4,
+ },
- deletedIcon: {
- fontSize: 18,
- verticalAlign: "middle",
- marginRight: 4,
- },
+ deletedIcon: {
+ fontSize: 18,
+ verticalAlign: "middle",
+ marginRight: 4,
+ },
- ackDoneAllIcon: {
- color: green[500],
- fontSize: 18,
- verticalAlign: "middle",
- marginLeft: 4,
- },
+ ackDoneAllIcon: {
+ color: green[500],
+ fontSize: 18,
+ verticalAlign: "middle",
+ marginLeft: 4,
+ },
- downloadMedia: {
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- backgroundColor: "inherit",
- padding: 10,
- },
+ downloadMedia: {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ backgroundColor: "inherit",
+ padding: 10,
+ },
}));
const reducer = (state, action) => {
- if (action.type === "LOAD_MESSAGES") {
- const messages = action.payload;
- const newMessages = [];
+ if (action.type === "LOAD_MESSAGES") {
+ const messages = action.payload;
+ const newMessages = [];
- messages.forEach(message => {
- const messageIndex = state.findIndex(m => m.id === message.id);
- if (messageIndex !== -1) {
- state[messageIndex] = message;
- } else {
- newMessages.push(message);
- }
- });
+ messages.forEach((message) => {
+ const messageIndex = state.findIndex((m) => m.id === message.id);
+ if (messageIndex !== -1) {
+ state[messageIndex] = message;
+ } else {
+ newMessages.push(message);
+ }
+ });
- return [...newMessages, ...state];
- }
+ return [...newMessages, ...state];
+ }
- if (action.type === "ADD_MESSAGE") {
- const newMessage = action.payload;
- const messageIndex = state.findIndex(m => m.id === newMessage.id);
+ if (action.type === "ADD_MESSAGE") {
+ const newMessage = action.payload;
+ const messageIndex = state.findIndex((m) => m.id === newMessage.id);
- if (messageIndex !== -1) {
- state[messageIndex] = newMessage;
- } else {
- state.push(newMessage);
- }
+ if (messageIndex !== -1) {
+ state[messageIndex] = newMessage;
+ } else {
+ state.push(newMessage);
+ }
- return [...state];
- }
+ return [...state];
+ }
- if (action.type === "UPDATE_MESSAGE") {
- const messageToUpdate = action.payload;
- const messageIndex = state.findIndex(m => m.id === messageToUpdate.id);
+ if (action.type === "UPDATE_MESSAGE") {
+ const messageToUpdate = action.payload;
+ const messageIndex = state.findIndex((m) => m.id === messageToUpdate.id);
- if (messageIndex !== -1) {
- state[messageIndex] = messageToUpdate;
- }
+ if (messageIndex !== -1) {
+ state[messageIndex] = messageToUpdate;
+ }
- return [...state];
- }
+ return [...state];
+ }
- if (action.type === "RESET") {
- return [];
- }
+ if (action.type === "RESET") {
+ return [];
+ }
};
const MessagesList = ({ ticketId, isGroup }) => {
- const classes = useStyles();
+ const classes = useStyles();
- const [messagesList, dispatch] = useReducer(reducer, []);
- const [pageNumber, setPageNumber] = useState(1);
- const [hasMore, setHasMore] = useState(false);
- const [loading, setLoading] = useState(false);
- const lastMessageRef = useRef();
+ const [messagesList, dispatch] = useReducer(reducer, []);
+ const [pageNumber, setPageNumber] = useState(1);
+ const [hasMore, setHasMore] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const lastMessageRef = useRef();
- const [selectedMessage, setSelectedMessage] = useState({});
- const [anchorEl, setAnchorEl] = useState(null);
- const messageOptionsMenuOpen = Boolean(anchorEl);
- const currentTicketId = useRef(ticketId);
+ const [selectedMessage, setSelectedMessage] = useState({});
+ const [anchorEl, setAnchorEl] = useState(null);
+ const messageOptionsMenuOpen = Boolean(anchorEl);
+ const currentTicketId = useRef(ticketId);
- useEffect(() => {
- dispatch({ type: "RESET" });
- setPageNumber(1);
+ useEffect(() => {
+ dispatch({ type: "RESET" });
+ setPageNumber(1);
- currentTicketId.current = ticketId;
- }, [ticketId]);
+ currentTicketId.current = ticketId;
+ }, [ticketId]);
- useEffect(() => {
- setLoading(true);
- const delayDebounceFn = setTimeout(() => {
- const fetchMessages = async () => {
- try {
- const { data } = await api.get("/messages/" + ticketId, {
- params: { pageNumber },
- });
+ useEffect(() => {
+ setLoading(true);
+ const delayDebounceFn = setTimeout(() => {
+ const fetchMessages = async () => {
+ try {
+ const { data } = await api.get("/messages/" + ticketId, {
+ params: { pageNumber },
+ });
- if (currentTicketId.current === ticketId) {
- dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
- setHasMore(data.hasMore);
- setLoading(false);
- }
+ if (currentTicketId.current === ticketId) {
+ dispatch({ type: "LOAD_MESSAGES", payload: data.messages });
+ setHasMore(data.hasMore);
+ setLoading(false);
+ }
- if (pageNumber === 1 && data.messages.length > 1) {
- scrollToBottom();
- }
- } catch (err) {
- setLoading(false);
- toastError(err);
- }
- };
- fetchMessages();
- }, 500);
- return () => {
- clearTimeout(delayDebounceFn);
- };
- }, [pageNumber, ticketId]);
+ if (pageNumber === 1 && data.messages.length > 1) {
+ scrollToBottom();
+ }
+ } catch (err) {
+ setLoading(false);
+ toastError(err);
+ }
+ };
+ fetchMessages();
+ }, 500);
+ return () => {
+ clearTimeout(delayDebounceFn);
+ };
+ }, [pageNumber, ticketId]);
- useEffect(() => {
- const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
+ useEffect(() => {
+ const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
- socket.on("connect", () => socket.emit("joinChatBox", ticketId));
+ socket.on("connect", () => socket.emit("joinChatBox", ticketId));
- socket.on("appMessage", data => {
- if (data.action === "create") {
- dispatch({ type: "ADD_MESSAGE", payload: data.message });
- scrollToBottom();
- }
+ socket.on("appMessage", (data) => {
+ if (data.action === "create") {
+ dispatch({ type: "ADD_MESSAGE", payload: data.message });
+ scrollToBottom();
+ }
- if (data.action === "update") {
- dispatch({ type: "UPDATE_MESSAGE", payload: data.message });
- }
- });
+ if (data.action === "update") {
+ dispatch({ type: "UPDATE_MESSAGE", payload: data.message });
+ }
+ });
- return () => {
- socket.disconnect();
- };
- }, [ticketId]);
+ return () => {
+ socket.disconnect();
+ };
+ }, [ticketId]);
- const loadMore = () => {
- setPageNumber(prevPageNumber => prevPageNumber + 1);
- };
+ const loadMore = () => {
+ setPageNumber((prevPageNumber) => prevPageNumber + 1);
+ };
- const scrollToBottom = () => {
- if (lastMessageRef.current) {
- lastMessageRef.current.scrollIntoView({});
- }
- };
+ const scrollToBottom = () => {
+ if (lastMessageRef.current) {
+ lastMessageRef.current.scrollIntoView({});
+ }
+ };
- const handleScroll = e => {
- if (!hasMore) return;
- const { scrollTop } = e.currentTarget;
+ const handleScroll = (e) => {
+ if (!hasMore) return;
+ const { scrollTop } = e.currentTarget;
- if (scrollTop === 0) {
- document.getElementById("messagesList").scrollTop = 1;
- }
+ if (scrollTop === 0) {
+ document.getElementById("messagesList").scrollTop = 1;
+ }
- if (loading) {
- return;
- }
+ if (loading) {
+ return;
+ }
- if (scrollTop < 50) {
- loadMore();
- }
- };
+ if (scrollTop < 50) {
+ loadMore();
+ }
+ };
- const handleOpenMessageOptionsMenu = (e, message) => {
- setAnchorEl(e.currentTarget);
- setSelectedMessage(message);
- };
+ const handleOpenMessageOptionsMenu = (e, message) => {
+ setAnchorEl(e.currentTarget);
+ setSelectedMessage(message);
+ };
- const handleCloseMessageOptionsMenu = e => {
- setAnchorEl(null);
- };
+ const handleCloseMessageOptionsMenu = (e) => {
+ setAnchorEl(null);
+ };
- const checkMessageMedia = message => {
- if (message.mediaType === "image") {
- return ;
- }
- if (message.mediaType === "audio") {
- return (
-
- );
- }
+ const checkMessageMedia = (message) => {
+ if (message.mediaType === "image") {
+ return ;
+ }
+ if (message.mediaType === "audio") {
+ return (
+
+ );
+ }
- if (message.mediaType === "video") {
- return (
-
- );
- } else {
- return (
- <>
-
- }
- color="primary"
- variant="outlined"
- target="_blank"
- href={message.mediaUrl}
- >
- Download
-
-
-
- >
- );
- }
- };
+ if (message.mediaType === "video") {
+ return (
+
+ );
+ } else {
+ return (
+ <>
+
+ }
+ color="primary"
+ variant="outlined"
+ target="_blank"
+ href={message.mediaUrl}
+ >
+ Download
+
+
+
+ >
+ );
+ }
+ };
- const renderMessageAck = message => {
- if (message.ack === 0) {
- return ;
- }
- if (message.ack === 1) {
- return ;
- }
- if (message.ack === 2) {
- return ;
- }
- if (message.ack === 3 || message.ack === 4) {
- return ;
- }
- };
+ const renderMessageAck = (message) => {
+ if (message.ack === 0) {
+ return ;
+ }
+ if (message.ack === 1) {
+ return ;
+ }
+ if (message.ack === 2) {
+ return ;
+ }
+ if (message.ack === 3 || message.ack === 4) {
+ return ;
+ }
+ };
- const renderDailyTimestamps = (message, index) => {
- if (index === 0) {
- return (
-
-
- {format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
-
-
- );
- }
- if (index < messagesList.length - 1) {
- let messageDay = parseISO(messagesList[index].createdAt);
- let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
+ const renderDailyTimestamps = (message, index) => {
+ if (index === 0) {
+ return (
+
+
+ {format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
+
+
+ );
+ }
+ if (index < messagesList.length - 1) {
+ let messageDay = parseISO(messagesList[index].createdAt);
+ let previousMessageDay = parseISO(messagesList[index - 1].createdAt);
- if (!isSameDay(messageDay, previousMessageDay)) {
- return (
-
-
- {format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
-
-
- );
- }
- }
- if (index === messagesList.length - 1) {
- return (
-
- );
- }
- };
+ if (!isSameDay(messageDay, previousMessageDay)) {
+ return (
+
+
+ {format(parseISO(messagesList[index].createdAt), "dd/MM/yyyy")}
+
+
+ );
+ }
+ }
+ if (index === messagesList.length - 1) {
+ return (
+
+ );
+ }
+ };
- const renderMessageDivider = (message, index) => {
- if (index < messagesList.length && index > 0) {
- let messageUser = messagesList[index].fromMe;
- let previousMessageUser = messagesList[index - 1].fromMe;
+ const renderMessageDivider = (message, index) => {
+ if (index < messagesList.length && index > 0) {
+ let messageUser = messagesList[index].fromMe;
+ let previousMessageUser = messagesList[index - 1].fromMe;
- if (messageUser !== previousMessageUser) {
- return (
-
- );
- }
- }
- };
+ if (messageUser !== previousMessageUser) {
+ return (
+
+ );
+ }
+ }
+ };
- const renderQuotedMessage = message => {
- return (
-
-
-
- {!message.quotedMsg?.fromMe && (
-
- {message.quotedMsg?.contact?.name}
-
- )}
- {message.quotedMsg?.body}
-
-
- );
- };
+ const renderQuotedMessage = (message) => {
+ return (
+
+
+
+ {!message.quotedMsg?.fromMe && (
+
+ {message.quotedMsg?.contact?.name}
+
+ )}
+ {message.quotedMsg?.body}
+
+
+ );
+ };
- const renderMessages = () => {
- if (messagesList.length > 0) {
- const viewMessagesList = messagesList.map((message, index) => {
- if (!message.fromMe) {
- return (
-
- {renderDailyTimestamps(message, index)}
- {renderMessageDivider(message, index)}
-
-
handleOpenMessageOptionsMenu(e, message)}
- >
-
-
- {isGroup && (
-
- {message.contact?.name}
-
- )}
- {message.mediaUrl && checkMessageMedia(message)}
-
- {message.quotedMsg && renderQuotedMessage(message)}
- {message.body}
-
- {format(parseISO(message.createdAt), "HH:mm")}
-
-
-
-
- );
- } else {
- return (
-
- {renderDailyTimestamps(message, index)}
- {renderMessageDivider(message, index)}
-
-
handleOpenMessageOptionsMenu(e, message)}
- >
-
-
- {message.mediaUrl && checkMessageMedia(message)}
-
- {message.isDeleted && (
-
- )}
- {message.quotedMsg && renderQuotedMessage(message)}
- {message.body}
-
- {format(parseISO(message.createdAt), "HH:mm")}
- {renderMessageAck(message)}
-
-
-
-
- );
- }
- });
- return viewMessagesList;
- } else {
- return Say hello to your new contact!
;
- }
- };
+ const renderMessages = () => {
+ if (messagesList.length > 0) {
+ const viewMessagesList = messagesList.map((message, index) => {
+ if (!message.fromMe) {
+ return (
+
+ {renderDailyTimestamps(message, index)}
+ {renderMessageDivider(message, index)}
+
+
handleOpenMessageOptionsMenu(e, message)}
+ >
+
+
+ {isGroup && (
+
+ {message.contact?.name}
+
+ )}
+ {message.mediaUrl && checkMessageMedia(message)}
+
+ {message.quotedMsg && renderQuotedMessage(message)}
+ {message.body}
+
+ {format(parseISO(message.createdAt), "HH:mm")}
+
+
+
+
+ );
+ } else {
+ return (
+
+ {renderDailyTimestamps(message, index)}
+ {renderMessageDivider(message, index)}
+
+
handleOpenMessageOptionsMenu(e, message)}
+ >
+
+
+ {message.mediaUrl && checkMessageMedia(message)}
+
+ {message.isDeleted && (
+
+ )}
+ {message.quotedMsg && renderQuotedMessage(message)}
+ {message.body}
+
+ {format(parseISO(message.createdAt), "HH:mm")}
+ {renderMessageAck(message)}
+
+
+
+
+ );
+ }
+ });
+ return viewMessagesList;
+ } else {
+ return Say hello to your new contact!
;
+ }
+ };
- return (
-
-
-
- {messagesList.length > 0 ? renderMessages() : []}
-
- {loading && (
-
-
-
- )}
-
- );
+ return (
+
+
+
+ {messagesList.length > 0 ? renderMessages() : []}
+
+ {loading && (
+
+
+
+ )}
+
+ );
};
export default MessagesList;
diff --git a/frontend/src/components/Ticket/index.js b/frontend/src/components/Ticket/index.js
index c2cdd37..f5b041b 100644
--- a/frontend/src/components/Ticket/index.js
+++ b/frontend/src/components/Ticket/index.js
@@ -19,144 +19,167 @@ import toastError from "../../errors/toastError";
const drawerWidth = 320;
-const useStyles = makeStyles(theme => ({
- root: {
- display: "flex",
- height: "100%",
- position: "relative",
- overflow: "hidden",
- },
+const useStyles = makeStyles((theme) => ({
+ root: {
+ display: "flex",
+ height: "100%",
+ position: "relative",
+ overflow: "hidden",
+ },
- mainWrapper: {
- flex: 1,
- height: "100%",
- display: "flex",
- flexDirection: "column",
- overflow: "hidden",
- borderTopLeftRadius: 0,
- borderBottomLeftRadius: 0,
- borderLeft: "0",
- marginRight: -drawerWidth,
- transition: theme.transitions.create("margin", {
- easing: theme.transitions.easing.sharp,
- duration: theme.transitions.duration.leavingScreen,
- }),
- },
+ ticketInfo: {
+ maxWidth: "50%",
+ flexBasis: "50%",
+ [theme.breakpoints.down("sm")]: {
+ maxWidth: "80%",
+ flexBasis: "80%",
+ },
+ },
+ ticketActionButtons: {
+ maxWidth: "50%",
+ flexBasis: "50%",
+ display: "flex",
+ [theme.breakpoints.down("sm")]: {
+ maxWidth: "100%",
+ flexBasis: "100%",
+ marginBottom: "5px",
+ },
+ },
- mainWrapperShift: {
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- transition: theme.transitions.create("margin", {
- easing: theme.transitions.easing.easeOut,
- duration: theme.transitions.duration.enteringScreen,
- }),
- marginRight: 0,
- },
+ mainWrapper: {
+ flex: 1,
+ height: "100%",
+ display: "flex",
+ flexDirection: "column",
+ overflow: "hidden",
+ borderTopLeftRadius: 0,
+ borderBottomLeftRadius: 0,
+ borderLeft: "0",
+ marginRight: -drawerWidth,
+ transition: theme.transitions.create("margin", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+
+ mainWrapperShift: {
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ transition: theme.transitions.create("margin", {
+ easing: theme.transitions.easing.easeOut,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ marginRight: 0,
+ },
}));
const Ticket = () => {
- const { ticketId } = useParams();
- const history = useHistory();
- const classes = useStyles();
+ const { ticketId } = useParams();
+ const history = useHistory();
+ const classes = useStyles();
- const [drawerOpen, setDrawerOpen] = useState(false);
- const [loading, setLoading] = useState(true);
- const [contact, setContact] = useState({});
- const [ticket, setTicket] = useState({});
+ const [drawerOpen, setDrawerOpen] = useState(false);
+ const [loading, setLoading] = useState(true);
+ const [contact, setContact] = useState({});
+ const [ticket, setTicket] = useState({});
- useEffect(() => {
- setLoading(true);
- const delayDebounceFn = setTimeout(() => {
- const fetchTicket = async () => {
- try {
- const { data } = await api.get("/tickets/" + ticketId);
+ useEffect(() => {
+ setLoading(true);
+ const delayDebounceFn = setTimeout(() => {
+ const fetchTicket = async () => {
+ try {
+ const { data } = await api.get("/tickets/" + ticketId);
- setContact(data.contact);
- setTicket(data);
- setLoading(false);
- } catch (err) {
- setLoading(false);
- toastError(err);
- }
- };
- fetchTicket();
- }, 500);
- return () => clearTimeout(delayDebounceFn);
- }, [ticketId, history]);
+ setContact(data.contact);
+ setTicket(data);
+ setLoading(false);
+ } catch (err) {
+ setLoading(false);
+ toastError(err);
+ }
+ };
+ fetchTicket();
+ }, 500);
+ return () => clearTimeout(delayDebounceFn);
+ }, [ticketId, history]);
- useEffect(() => {
- const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
+ useEffect(() => {
+ const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
- socket.on("connect", () => socket.emit("joinChatBox", ticketId));
+ socket.on("connect", () => socket.emit("joinChatBox", ticketId));
- socket.on("ticket", data => {
- if (data.action === "update") {
- setTicket(data.ticket);
- }
+ socket.on("ticket", (data) => {
+ if (data.action === "update") {
+ setTicket(data.ticket);
+ }
- if (data.action === "delete") {
- toast.success("Ticket deleted sucessfully.");
- history.push("/tickets");
- }
- });
+ if (data.action === "delete") {
+ toast.success("Ticket deleted sucessfully.");
+ history.push("/tickets");
+ }
+ });
- socket.on("contact", data => {
- if (data.action === "update") {
- setContact(prevState => {
- if (prevState.id === data.contact?.id) {
- return { ...prevState, ...data.contact };
- }
- return prevState;
- });
- }
- });
+ socket.on("contact", (data) => {
+ if (data.action === "update") {
+ setContact((prevState) => {
+ if (prevState.id === data.contact?.id) {
+ return { ...prevState, ...data.contact };
+ }
+ return prevState;
+ });
+ }
+ });
- return () => {
- socket.disconnect();
- };
- }, [ticketId, history]);
+ return () => {
+ socket.disconnect();
+ };
+ }, [ticketId, history]);
- const handleDrawerOpen = () => {
- setDrawerOpen(true);
- };
+ const handleDrawerOpen = () => {
+ setDrawerOpen(true);
+ };
- const handleDrawerClose = () => {
- setDrawerOpen(false);
- };
+ const handleDrawerClose = () => {
+ setDrawerOpen(false);
+ };
- return (
-
- );
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
export default Ticket;
diff --git a/frontend/src/components/TicketHeader/index.js b/frontend/src/components/TicketHeader/index.js
index d05c296..453d52b 100644
--- a/frontend/src/components/TicketHeader/index.js
+++ b/frontend/src/components/TicketHeader/index.js
@@ -1,32 +1,44 @@
import React from "react";
-import { Card } from "@material-ui/core";
+import { Card, Button } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import TicketHeaderSkeleton from "../TicketHeaderSkeleton";
+import ArrowBackIos from "@material-ui/icons/ArrowBackIos";
+import { useHistory } from "react-router-dom";
-const useStyles = makeStyles(theme => ({
- ticketHeader: {
- display: "flex",
- backgroundColor: "#eee",
- flex: "none",
- borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
- },
+const useStyles = makeStyles((theme) => ({
+ ticketHeader: {
+ display: "flex",
+ backgroundColor: "#eee",
+ flex: "none",
+ borderBottom: "1px solid rgba(0, 0, 0, 0.12)",
+ [theme.breakpoints.down("sm")]: {
+ flexWrap: "wrap",
+ },
+ },
}));
const TicketHeader = ({ loading, children }) => {
- const classes = useStyles();
+ const classes = useStyles();
+ const history = useHistory();
+ const handleBack = () => {
+ history.push("/tickets");
+ };
- return (
- <>
- {loading ? (
-
- ) : (
-
- {children}
-
- )}
- >
- );
+ return (
+ <>
+ {loading ? (
+
+ ) : (
+
+
+ {children}
+
+ )}
+ >
+ );
};
export default TicketHeader;
diff --git a/frontend/src/components/TicketsManager/index.js b/frontend/src/components/TicketsManager/index.js
index dbcf0af..53e0e7a 100644
--- a/frontend/src/components/TicketsManager/index.js
+++ b/frontend/src/components/TicketsManager/index.js
@@ -22,215 +22,215 @@ import { Can } from "../Can";
import TicketsQueueSelect from "../TicketsQueueSelect";
import { Button } from "@material-ui/core";
-const useStyles = makeStyles(theme => ({
- ticketsWrapper: {
- position: "relative",
- display: "flex",
- height: "100%",
- flexDirection: "column",
- overflow: "hidden",
- borderTopRightRadius: 0,
- borderBottomRightRadius: 0,
- },
+const useStyles = makeStyles((theme) => ({
+ ticketsWrapper: {
+ position: "relative",
+ display: "flex",
+ height: "100%",
+ flexDirection: "column",
+ overflow: "hidden",
+ borderTopRightRadius: 0,
+ borderBottomRightRadius: 0,
+ },
- tabsHeader: {
- flex: "none",
- backgroundColor: "#eee",
- },
+ tabsHeader: {
+ flex: "none",
+ backgroundColor: "#eee",
+ },
- settingsIcon: {
- alignSelf: "center",
- marginLeft: "auto",
- padding: 8,
- },
+ settingsIcon: {
+ alignSelf: "center",
+ marginLeft: "auto",
+ padding: 8,
+ },
- tab: {
- minWidth: 120,
- width: 120,
- },
+ tab: {
+ minWidth: 120,
+ width: 120,
+ },
- ticketOptionsBox: {
- display: "flex",
- justifyContent: "space-between",
- alignItems: "center",
- background: "#fafafa",
- padding: theme.spacing(1),
- },
+ ticketOptionsBox: {
+ display: "flex",
+ justifyContent: "space-between",
+ alignItems: "center",
+ background: "#fafafa",
+ padding: theme.spacing(1),
+ },
- serachInputWrapper: {
- flex: 1,
- background: "#fff",
- display: "flex",
- borderRadius: 40,
- padding: 4,
- marginRight: theme.spacing(1),
- },
+ serachInputWrapper: {
+ flex: 1,
+ background: "#fff",
+ display: "flex",
+ borderRadius: 40,
+ padding: 4,
+ marginRight: theme.spacing(1),
+ },
- searchIcon: {
- color: "grey",
- marginLeft: 6,
- marginRight: 6,
- alignSelf: "center",
- },
+ searchIcon: {
+ color: "grey",
+ marginLeft: 6,
+ marginRight: 6,
+ alignSelf: "center",
+ },
- searchInput: {
- flex: 1,
- border: "none",
- borderRadius: 30,
- },
+ searchInput: {
+ flex: 1,
+ border: "none",
+ borderRadius: 30,
+ },
}));
const TicketsManager = () => {
- const classes = useStyles();
+ const classes = useStyles();
- const [searchParam, setSearchParam] = useState("");
- const [tab, setTab] = useState("open");
- const [newTicketModalOpen, setNewTicketModalOpen] = useState(false);
- const [showAllTickets, setShowAllTickets] = useState(false);
- const searchInputRef = useRef();
- const { user } = useContext(AuthContext);
+ const [searchParam, setSearchParam] = useState("");
+ const [tab, setTab] = useState("open");
+ const [newTicketModalOpen, setNewTicketModalOpen] = useState(false);
+ const [showAllTickets, setShowAllTickets] = useState(false);
+ const searchInputRef = useRef();
+ const { user } = useContext(AuthContext);
- const userQueueIds = user.queues.map(q => q.id);
- const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
+ const userQueueIds = user.queues.map((q) => q.id);
+ const [selectedQueueIds, setSelectedQueueIds] = useState(userQueueIds || []);
- useEffect(() => {
- if (tab === "search") {
- searchInputRef.current.focus();
- }
- }, [tab]);
+ useEffect(() => {
+ if (tab === "search") {
+ searchInputRef.current.focus();
+ }
+ }, [tab]);
- let searchTimeout;
+ let searchTimeout;
- const handleSearch = e => {
- const searchedTerm = e.target.value.toLowerCase();
+ const handleSearch = (e) => {
+ const searchedTerm = e.target.value.toLowerCase();
- clearTimeout(searchTimeout);
+ clearTimeout(searchTimeout);
- if (searchedTerm === "") {
- setSearchParam(searchedTerm);
- setTab("open");
- return;
- }
+ if (searchedTerm === "") {
+ setSearchParam(searchedTerm);
+ setTab("open");
+ return;
+ }
- searchTimeout = setTimeout(() => {
- setSearchParam(searchedTerm);
- }, 500);
- };
+ searchTimeout = setTimeout(() => {
+ setSearchParam(searchedTerm);
+ }, 500);
+ };
- const handleChangeTab = (e, newValue) => {
- setTab(newValue);
- };
+ const handleChangeTab = (e, newValue) => {
+ setTab(newValue);
+ };
- 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" ? (
-
-
-
-
- ) : (
- <>
-
- (
-
- setShowAllTickets(prevState => !prevState)
- }
- name="showAllTickets"
- color="primary"
- />
- }
- />
- )}
- />
- >
- )}
- setSelectedQueueIds(values)}
- />
-
-
-
-
-
-
-
-
-
-
-
-
- );
+ 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" ? (
+
+
+
+
+ ) : (
+ <>
+
+ (
+
+ setShowAllTickets((prevState) => !prevState)
+ }
+ name="showAllTickets"
+ color="primary"
+ />
+ }
+ />
+ )}
+ />
+ >
+ )}
+ setSelectedQueueIds(values)}
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ );
};
export default TicketsManager;
diff --git a/frontend/src/pages/Contacts/index.js b/frontend/src/pages/Contacts/index.js
index e516228..1261cb5 100644
--- a/frontend/src/pages/Contacts/index.js
+++ b/frontend/src/pages/Contacts/index.js
@@ -36,314 +36,314 @@ import { AuthContext } from "../../context/Auth/AuthContext";
import { Can } from "../../components/Can";
const reducer = (state, action) => {
- if (action.type === "LOAD_CONTACTS") {
- const contacts = action.payload;
- const newContacts = [];
+ if (action.type === "LOAD_CONTACTS") {
+ const contacts = action.payload;
+ const newContacts = [];
- contacts.forEach(contact => {
- const contactIndex = state.findIndex(c => c.id === contact.id);
- if (contactIndex !== -1) {
- state[contactIndex] = contact;
- } else {
- newContacts.push(contact);
- }
- });
+ contacts.forEach((contact) => {
+ const contactIndex = state.findIndex((c) => c.id === contact.id);
+ if (contactIndex !== -1) {
+ state[contactIndex] = contact;
+ } else {
+ newContacts.push(contact);
+ }
+ });
- return [...state, ...newContacts];
- }
+ return [...state, ...newContacts];
+ }
- if (action.type === "UPDATE_CONTACTS") {
- const contact = action.payload;
- const contactIndex = state.findIndex(c => c.id === contact.id);
+ if (action.type === "UPDATE_CONTACTS") {
+ const contact = action.payload;
+ const contactIndex = state.findIndex((c) => c.id === contact.id);
- if (contactIndex !== -1) {
- state[contactIndex] = contact;
- return [...state];
- } else {
- return [contact, ...state];
- }
- }
+ if (contactIndex !== -1) {
+ state[contactIndex] = contact;
+ return [...state];
+ } else {
+ return [contact, ...state];
+ }
+ }
- if (action.type === "DELETE_CONTACT") {
- const contactId = action.payload;
+ if (action.type === "DELETE_CONTACT") {
+ const contactId = action.payload;
- const contactIndex = state.findIndex(c => c.id === contactId);
- if (contactIndex !== -1) {
- state.splice(contactIndex, 1);
- }
- return [...state];
- }
+ const contactIndex = state.findIndex((c) => c.id === contactId);
+ if (contactIndex !== -1) {
+ state.splice(contactIndex, 1);
+ }
+ return [...state];
+ }
- if (action.type === "RESET") {
- return [];
- }
+ if (action.type === "RESET") {
+ return [];
+ }
};
-const useStyles = makeStyles(theme => ({
- mainPaper: {
- flex: 1,
- padding: theme.spacing(1),
- overflowY: "scroll",
- ...theme.scrollbarStyles,
- },
+const useStyles = makeStyles((theme) => ({
+ mainPaper: {
+ flex: 1,
+ padding: theme.spacing(1),
+ overflowY: "scroll",
+ ...theme.scrollbarStyles,
+ },
}));
const Contacts = () => {
- const classes = useStyles();
- const history = useHistory();
+ const classes = useStyles();
+ const history = useHistory();
- const { user } = useContext(AuthContext);
+ const { user } = useContext(AuthContext);
- const [loading, setLoading] = useState(false);
- const [pageNumber, setPageNumber] = useState(1);
- const [searchParam, setSearchParam] = useState("");
- const [contacts, dispatch] = useReducer(reducer, []);
- const [selectedContactId, setSelectedContactId] = useState(null);
- const [contactModalOpen, setContactModalOpen] = useState(false);
- const [deletingContact, setDeletingContact] = useState(null);
- const [confirmOpen, setConfirmOpen] = useState(false);
- const [hasMore, setHasMore] = useState(false);
+ const [loading, setLoading] = useState(false);
+ const [pageNumber, setPageNumber] = useState(1);
+ const [searchParam, setSearchParam] = useState("");
+ const [contacts, dispatch] = useReducer(reducer, []);
+ const [selectedContactId, setSelectedContactId] = useState(null);
+ const [contactModalOpen, setContactModalOpen] = useState(false);
+ const [deletingContact, setDeletingContact] = useState(null);
+ const [confirmOpen, setConfirmOpen] = useState(false);
+ const [hasMore, setHasMore] = useState(false);
- useEffect(() => {
- dispatch({ type: "RESET" });
- setPageNumber(1);
- }, [searchParam]);
+ useEffect(() => {
+ dispatch({ type: "RESET" });
+ setPageNumber(1);
+ }, [searchParam]);
- useEffect(() => {
- setLoading(true);
- const delayDebounceFn = setTimeout(() => {
- const fetchContacts = async () => {
- try {
- const { data } = await api.get("/contacts/", {
- params: { searchParam, pageNumber },
- });
- dispatch({ type: "LOAD_CONTACTS", payload: data.contacts });
- setHasMore(data.hasMore);
- setLoading(false);
- } catch (err) {
- toastError(err);
- }
- };
- fetchContacts();
- }, 500);
- return () => clearTimeout(delayDebounceFn);
- }, [searchParam, pageNumber]);
+ useEffect(() => {
+ setLoading(true);
+ const delayDebounceFn = setTimeout(() => {
+ const fetchContacts = async () => {
+ try {
+ const { data } = await api.get("/contacts/", {
+ params: { searchParam, pageNumber },
+ });
+ dispatch({ type: "LOAD_CONTACTS", payload: data.contacts });
+ setHasMore(data.hasMore);
+ setLoading(false);
+ } catch (err) {
+ toastError(err);
+ }
+ };
+ fetchContacts();
+ }, 500);
+ return () => clearTimeout(delayDebounceFn);
+ }, [searchParam, pageNumber]);
- useEffect(() => {
- const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
+ useEffect(() => {
+ const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
- socket.on("contact", data => {
- if (data.action === "update" || data.action === "create") {
- dispatch({ type: "UPDATE_CONTACTS", payload: data.contact });
- }
+ socket.on("contact", (data) => {
+ if (data.action === "update" || data.action === "create") {
+ dispatch({ type: "UPDATE_CONTACTS", payload: data.contact });
+ }
- if (data.action === "delete") {
- dispatch({ type: "DELETE_CONTACT", payload: +data.contactId });
- }
- });
+ if (data.action === "delete") {
+ dispatch({ type: "DELETE_CONTACT", payload: +data.contactId });
+ }
+ });
- return () => {
- socket.disconnect();
- };
- }, []);
+ return () => {
+ socket.disconnect();
+ };
+ }, []);
- const handleSearch = event => {
- setSearchParam(event.target.value.toLowerCase());
- };
+ const handleSearch = (event) => {
+ setSearchParam(event.target.value.toLowerCase());
+ };
- const handleOpenContactModal = () => {
- setSelectedContactId(null);
- setContactModalOpen(true);
- };
+ const handleOpenContactModal = () => {
+ setSelectedContactId(null);
+ setContactModalOpen(true);
+ };
- const handleCloseContactModal = () => {
- setSelectedContactId(null);
- setContactModalOpen(false);
- };
+ const handleCloseContactModal = () => {
+ setSelectedContactId(null);
+ setContactModalOpen(false);
+ };
- const handleSaveTicket = async contactId => {
- if (!contactId) return;
- setLoading(true);
- try {
- const { data: ticket } = await api.post("/tickets", {
- contactId: contactId,
- userId: user?.id,
- status: "open",
- });
- history.push(`/tickets/${ticket.id}`);
- } catch (err) {
- toastError(err);
- }
- setLoading(false);
- };
+ const handleSaveTicket = async (contactId) => {
+ if (!contactId) return;
+ setLoading(true);
+ try {
+ const { data: ticket } = await api.post("/tickets", {
+ contactId: contactId,
+ userId: user?.id,
+ status: "open",
+ });
+ history.push(`/tickets/${ticket.id}`);
+ } catch (err) {
+ toastError(err);
+ }
+ setLoading(false);
+ };
- const hadleEditContact = contactId => {
- setSelectedContactId(contactId);
- setContactModalOpen(true);
- };
+ const hadleEditContact = (contactId) => {
+ setSelectedContactId(contactId);
+ setContactModalOpen(true);
+ };
- const handleDeleteContact = async contactId => {
- try {
- await api.delete(`/contacts/${contactId}`);
- toast.success(i18n.t("contacts.toasts.deleted"));
- } catch (err) {
- toastError(err);
- }
- setDeletingContact(null);
- setSearchParam("");
- setPageNumber(1);
- };
+ const handleDeleteContact = async (contactId) => {
+ try {
+ await api.delete(`/contacts/${contactId}`);
+ toast.success(i18n.t("contacts.toasts.deleted"));
+ } catch (err) {
+ toastError(err);
+ }
+ setDeletingContact(null);
+ setSearchParam("");
+ setPageNumber(1);
+ };
- const handleimportContact = async () => {
- try {
- await api.post("/contacts/import");
- history.go(0);
- } catch (err) {
- toastError(err);
- }
- };
+ const handleimportContact = async () => {
+ try {
+ await api.post("/contacts/import");
+ history.go(0);
+ } catch (err) {
+ toastError(err);
+ }
+ };
- const loadMore = () => {
- setPageNumber(prevState => prevState + 1);
- };
+ const loadMore = () => {
+ setPageNumber((prevState) => prevState + 1);
+ };
- const handleScroll = e => {
- if (!hasMore || loading) return;
- const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
- if (scrollHeight - (scrollTop + 100) < clientHeight) {
- loadMore();
- }
- };
+ const handleScroll = (e) => {
+ if (!hasMore || loading) return;
+ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
+ if (scrollHeight - (scrollTop + 100) < clientHeight) {
+ loadMore();
+ }
+ };
- return (
-
-
-
- deletingContact
- ? handleDeleteContact(deletingContact.id)
- : handleimportContact()
- }
- >
- {deletingContact
- ? `${i18n.t("contacts.confirmationModal.deleteMessage")}`
- : `${i18n.t("contacts.confirmationModal.importMessage")}`}
-
-
- {i18n.t("contacts.title")}
-
-
-
-
- ),
- }}
- />
-
-
-
-
-
-
-
-
-
- {i18n.t("contacts.table.name")}
-
- {i18n.t("contacts.table.whatsapp")}
-
-
- {i18n.t("contacts.table.email")}
-
-
- {i18n.t("contacts.table.actions")}
-
-
-
-
- <>
- {contacts.map(contact => (
-
-
- {}
-
- {contact.name}
- {contact.number}
- {contact.email}
-
- handleSaveTicket(contact.id)}
- >
-
-
- hadleEditContact(contact.id)}
- >
-
-
- (
- {
- setConfirmOpen(true);
- setDeletingContact(contact);
- }}
- >
-
-
- )}
- />
-
-
- ))}
- {loading && }
- >
-
-
-
-
- );
+ return (
+
+
+
+ deletingContact
+ ? handleDeleteContact(deletingContact.id)
+ : handleimportContact()
+ }
+ >
+ {deletingContact
+ ? `${i18n.t("contacts.confirmationModal.deleteMessage")}`
+ : `${i18n.t("contacts.confirmationModal.importMessage")}`}
+
+
+ {i18n.t("contacts.title")}
+
+
+
+
+ ),
+ }}
+ />
+
+
+
+
+
+
+
+
+
+ {i18n.t("contacts.table.name")}
+
+ {i18n.t("contacts.table.whatsapp")}
+
+
+ {i18n.t("contacts.table.email")}
+
+
+ {i18n.t("contacts.table.actions")}
+
+
+
+
+ <>
+ {contacts.map((contact) => (
+
+
+ {}
+
+ {contact.name}
+ {contact.number}
+ {contact.email}
+
+ handleSaveTicket(contact.id)}
+ >
+
+
+ hadleEditContact(contact.id)}
+ >
+
+
+ (
+ {
+ setConfirmOpen(true);
+ setDeletingContact(contact);
+ }}
+ >
+
+
+ )}
+ />
+
+
+ ))}
+ {loading && }
+ >
+
+
+
+
+ );
};
export default Contacts;
diff --git a/frontend/src/pages/Login/index.js b/frontend/src/pages/Login/index.js
index ebb98d6..56c4f5d 100644
--- a/frontend/src/pages/Login/index.js
+++ b/frontend/src/pages/Login/index.js
@@ -30,105 +30,105 @@ import { AuthContext } from "../../context/Auth/AuthContext";
// );
// };
-const useStyles = makeStyles(theme => ({
- paper: {
- marginTop: theme.spacing(8),
- display: "flex",
- flexDirection: "column",
- alignItems: "center",
- },
- avatar: {
- margin: theme.spacing(1),
- backgroundColor: theme.palette.secondary.main,
- },
- form: {
- width: "100%", // Fix IE 11 issue.
- marginTop: theme.spacing(1),
- },
- submit: {
- margin: theme.spacing(3, 0, 2),
- },
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ avatar: {
+ margin: theme.spacing(1),
+ backgroundColor: theme.palette.secondary.main,
+ },
+ form: {
+ width: "100%", // Fix IE 11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ margin: theme.spacing(3, 0, 2),
+ },
}));
const Login = () => {
- const classes = useStyles();
+ const classes = useStyles();
- const [user, setUser] = useState({ email: "", password: "" });
+ const [user, setUser] = useState({ email: "", password: "" });
- const { handleLogin } = useContext(AuthContext);
+ const { handleLogin } = useContext(AuthContext);
- const handleChangeInput = e => {
- setUser({ ...user, [e.target.name]: e.target.value });
- };
+ const handleChangeInput = (e) => {
+ setUser({ ...user, [e.target.name]: e.target.value });
+ };
- const handlSubmit = e => {
- e.preventDefault();
- handleLogin(user);
- };
+ const handlSubmit = (e) => {
+ e.preventDefault();
+ handleLogin(user);
+ };
- return (
-
-
-
-
-
-
-
- {i18n.t("login.title")}
-
-
-
- {/* */}
-
- );
+ return (
+
+
+
+
+
+
+
+ {i18n.t("login.title")}
+
+
+
+ {/* */}
+
+ );
};
export default Login;
diff --git a/frontend/src/pages/Queues/index.js b/frontend/src/pages/Queues/index.js
index 632fea3..0e239ee 100644
--- a/frontend/src/pages/Queues/index.js
+++ b/frontend/src/pages/Queues/index.js
@@ -3,16 +3,16 @@ import React, { useEffect, useReducer, useState } from "react";
import openSocket from "socket.io-client";
import {
- Button,
- IconButton,
- makeStyles,
- Paper,
- Table,
- TableBody,
- TableCell,
- TableHead,
- TableRow,
- Typography,
+ Button,
+ IconButton,
+ makeStyles,
+ Paper,
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableRow,
+ Typography,
} from "@material-ui/core";
import MainContainer from "../../components/MainContainer";
@@ -28,241 +28,241 @@ import QueueModal from "../../components/QueueModal";
import { toast } from "react-toastify";
import ConfirmationModal from "../../components/ConfirmationModal";
-const useStyles = makeStyles(theme => ({
- mainPaper: {
- flex: 1,
- padding: theme.spacing(1),
- overflowY: "scroll",
- ...theme.scrollbarStyles,
- },
- customTableCell: {
- display: "flex",
- alignItems: "center",
- justifyContent: "center",
- },
+const useStyles = makeStyles((theme) => ({
+ mainPaper: {
+ flex: 1,
+ padding: theme.spacing(1),
+ overflowY: "scroll",
+ ...theme.scrollbarStyles,
+ },
+ customTableCell: {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
}));
const reducer = (state, action) => {
- if (action.type === "LOAD_QUEUES") {
- const queues = action.payload;
- const newQueues = [];
+ if (action.type === "LOAD_QUEUES") {
+ const queues = action.payload;
+ const newQueues = [];
- queues.forEach(queue => {
- const queueIndex = state.findIndex(q => q.id === queue.id);
- if (queueIndex !== -1) {
- state[queueIndex] = queue;
- } else {
- newQueues.push(queue);
- }
- });
+ queues.forEach((queue) => {
+ const queueIndex = state.findIndex((q) => q.id === queue.id);
+ if (queueIndex !== -1) {
+ state[queueIndex] = queue;
+ } else {
+ newQueues.push(queue);
+ }
+ });
- return [...state, ...newQueues];
- }
+ return [...state, ...newQueues];
+ }
- if (action.type === "UPDATE_QUEUES") {
- const queue = action.payload;
- const queueIndex = state.findIndex(u => u.id === queue.id);
+ if (action.type === "UPDATE_QUEUES") {
+ const queue = action.payload;
+ const queueIndex = state.findIndex((u) => u.id === queue.id);
- if (queueIndex !== -1) {
- state[queueIndex] = queue;
- return [...state];
- } else {
- return [queue, ...state];
- }
- }
+ if (queueIndex !== -1) {
+ state[queueIndex] = queue;
+ return [...state];
+ } else {
+ return [queue, ...state];
+ }
+ }
- if (action.type === "DELETE_QUEUE") {
- const queueId = action.payload;
- const queueIndex = state.findIndex(q => q.id === queueId);
- if (queueIndex !== -1) {
- state.splice(queueIndex, 1);
- }
- return [...state];
- }
+ if (action.type === "DELETE_QUEUE") {
+ const queueId = action.payload;
+ const queueIndex = state.findIndex((q) => q.id === queueId);
+ if (queueIndex !== -1) {
+ state.splice(queueIndex, 1);
+ }
+ return [...state];
+ }
- if (action.type === "RESET") {
- return [];
- }
+ if (action.type === "RESET") {
+ return [];
+ }
};
const Queues = () => {
- const classes = useStyles();
+ const classes = useStyles();
- const [queues, dispatch] = useReducer(reducer, []);
- const [loading, setLoading] = useState(false);
+ const [queues, dispatch] = useReducer(reducer, []);
+ const [loading, setLoading] = useState(false);
- const [queueModalOpen, setQueueModalOpen] = useState(false);
- const [selectedQueue, setSelectedQueue] = useState(null);
- const [confirmModalOpen, setConfirmModalOpen] = useState(false);
+ const [queueModalOpen, setQueueModalOpen] = useState(false);
+ const [selectedQueue, setSelectedQueue] = useState(null);
+ const [confirmModalOpen, setConfirmModalOpen] = useState(false);
- useEffect(() => {
- (async () => {
- setLoading(true);
- try {
- const { data } = await api.get("/queue");
- dispatch({ type: "LOAD_QUEUES", payload: data });
+ useEffect(() => {
+ (async () => {
+ setLoading(true);
+ try {
+ const { data } = await api.get("/queue");
+ dispatch({ type: "LOAD_QUEUES", payload: data });
- setLoading(false);
- } catch (err) {
- toastError(err);
- setLoading(false);
- }
- })();
- }, []);
+ setLoading(false);
+ } catch (err) {
+ toastError(err);
+ setLoading(false);
+ }
+ })();
+ }, []);
- useEffect(() => {
- const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
+ useEffect(() => {
+ const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
- socket.on("queue", data => {
- if (data.action === "update" || data.action === "create") {
- dispatch({ type: "UPDATE_QUEUES", payload: data.queue });
- }
+ socket.on("queue", (data) => {
+ if (data.action === "update" || data.action === "create") {
+ dispatch({ type: "UPDATE_QUEUES", payload: data.queue });
+ }
- if (data.action === "delete") {
- dispatch({ type: "DELETE_QUEUE", payload: data.queueId });
- }
- });
+ if (data.action === "delete") {
+ dispatch({ type: "DELETE_QUEUE", payload: data.queueId });
+ }
+ });
- return () => {
- socket.disconnect();
- };
- }, []);
+ return () => {
+ socket.disconnect();
+ };
+ }, []);
- const handleOpenQueueModal = () => {
- setQueueModalOpen(true);
- setSelectedQueue(null);
- };
+ const handleOpenQueueModal = () => {
+ setQueueModalOpen(true);
+ setSelectedQueue(null);
+ };
- const handleCloseQueueModal = () => {
- setQueueModalOpen(false);
- setSelectedQueue(null);
- };
+ const handleCloseQueueModal = () => {
+ setQueueModalOpen(false);
+ setSelectedQueue(null);
+ };
- const handleEditQueue = queue => {
- setSelectedQueue(queue);
- setQueueModalOpen(true);
- };
+ const handleEditQueue = (queue) => {
+ setSelectedQueue(queue);
+ setQueueModalOpen(true);
+ };
- const handleCloseConfirmationModal = () => {
- setConfirmModalOpen(false);
- setSelectedQueue(null);
- };
+ const handleCloseConfirmationModal = () => {
+ setConfirmModalOpen(false);
+ setSelectedQueue(null);
+ };
- const handleDeleteQueue = async queueId => {
- try {
- await api.delete(`/queue/${queueId}`);
- toast.success(i18n.t("Queue deleted successfully!"));
- } catch (err) {
- toastError(err);
- }
- setSelectedQueue(null);
- };
+ const handleDeleteQueue = async (queueId) => {
+ try {
+ await api.delete(`/queue/${queueId}`);
+ toast.success(i18n.t("Queue deleted successfully!"));
+ } catch (err) {
+ toastError(err);
+ }
+ setSelectedQueue(null);
+ };
- return (
-
- handleDeleteQueue(selectedQueue.id)}
- >
- {i18n.t("queues.confirmationModal.deleteMessage")}
-
-
-
- {i18n.t("queues.title")}
-
-
-
-
-
-
-
-
-
- {i18n.t("queues.table.name")}
-
-
- {i18n.t("queues.table.color")}
-
-
- {i18n.t("queues.table.greeting")}
-
-
- {i18n.t("queues.table.actions")}
-
-
-
-
- <>
- {queues.map(queue => (
-
- {queue.name}
-
-
-
-
-
-
-
-
- {queue.greetingMessage}
-
-
-
-
- handleEditQueue(queue)}
- >
-
-
+ return (
+
+ handleDeleteQueue(selectedQueue.id)}
+ >
+ {i18n.t("queues.confirmationModal.deleteMessage")}
+
+
+
+ {i18n.t("queues.title")}
+
+
+
+
+
+
+
+
+
+ {i18n.t("queues.table.name")}
+
+
+ {i18n.t("queues.table.color")}
+
+
+ {i18n.t("queues.table.greeting")}
+
+
+ {i18n.t("queues.table.actions")}
+
+
+
+
+ <>
+ {queues.map((queue) => (
+
+ {queue.name}
+
+
+
+
+
+
+
+
+ {queue.greetingMessage}
+
+
+
+
+ handleEditQueue(queue)}
+ >
+
+
- {
- setSelectedQueue(queue);
- setConfirmModalOpen(true);
- }}
- >
-
-
-
-
- ))}
- {loading && }
- >
-
-
-
-
- );
+ {
+ setSelectedQueue(queue);
+ setConfirmModalOpen(true);
+ }}
+ >
+
+
+
+
+ ))}
+ {loading && }
+ >
+
+
+
+
+ );
};
export default Queues;
diff --git a/frontend/src/pages/Tickets/index.js b/frontend/src/pages/Tickets/index.js
index 9e6ea20..80eb909 100644
--- a/frontend/src/pages/Tickets/index.js
+++ b/frontend/src/pages/Tickets/index.js
@@ -8,69 +8,98 @@ import TicketsManager from "../../components/TicketsManager/";
import Ticket from "../../components/Ticket/";
import { i18n } from "../../translate/i18n";
+import Hidden from "@material-ui/core/Hidden";
-const useStyles = makeStyles(theme => ({
- chatContainer: {
- flex: 1,
- // backgroundColor: "#eee",
- padding: theme.spacing(4),
- height: `calc(100% - 48px)`,
- overflowY: "hidden",
- },
+const useStyles = makeStyles((theme) => ({
+ chatContainer: {
+ flex: 1,
+ // // backgroundColor: "#eee",
+ // padding: theme.spacing(4),
+ height: `calc(100% - 48px)`,
+ overflowY: "hidden",
+ },
- chatPapper: {
- // backgroundColor: "red",
- display: "flex",
- height: "100%",
- },
+ chatPapper: {
+ // backgroundColor: "red",
+ display: "flex",
+ height: "100%",
+ },
- contactsWrapper: {
- display: "flex",
- height: "100%",
- flexDirection: "column",
- overflowY: "hidden",
- },
- messagessWrapper: {
- display: "flex",
- height: "100%",
- flexDirection: "column",
- },
- welcomeMsg: {
- backgroundColor: "#eee",
- display: "flex",
- justifyContent: "space-evenly",
- alignItems: "center",
- height: "100%",
- textAlign: "center",
- },
+ contactsWrapper: {
+ display: "flex",
+ height: "100%",
+ flexDirection: "column",
+ overflowY: "hidden",
+ },
+ contactsWrapperSmall: {
+ display: "flex",
+ height: "100%",
+ flexDirection: "column",
+ overflowY: "hidden",
+ [theme.breakpoints.down("sm")]: {
+ display: "none",
+ },
+ },
+ messagessWrapper: {
+ display: "flex",
+ height: "100%",
+ flexDirection: "column",
+ },
+ welcomeMsg: {
+ backgroundColor: "#eee",
+ display: "flex",
+ justifyContent: "space-evenly",
+ alignItems: "center",
+ height: "100%",
+ textAlign: "center",
+ borderRadius: 0,
+ },
+ ticketsManager: {},
+ ticketsManagerClosed: {
+ [theme.breakpoints.down("sm")]: {
+ display: "none",
+ },
+ },
}));
const Chat = () => {
- const classes = useStyles();
- const { ticketId } = useParams();
+ const classes = useStyles();
+ const { ticketId } = useParams();
- return (
-
-
-
-
-
-
-
- {ticketId ? (
- <>
-
- >
- ) : (
-
- {i18n.t("chat.noTicketMessage")}
-
- )}
-
-
-
-
- );
+ return (
+
+
+
+ {/* */}
+
+
+
+
+ {/* */}
+ {ticketId ? (
+ <>
+
+ >
+ ) : (
+
+
+ {/* */}
+ {i18n.t("chat.noTicketMessage")}
+
+
+ )}
+
+
+
+
+ );
};
export default Chat;
diff --git a/frontend/src/pages/Users/index.js b/frontend/src/pages/Users/index.js
index f4c8ae6..c7f5c1f 100644
--- a/frontend/src/pages/Users/index.js
+++ b/frontend/src/pages/Users/index.js
@@ -31,257 +31,257 @@ import ConfirmationModal from "../../components/ConfirmationModal";
import toastError from "../../errors/toastError";
const reducer = (state, action) => {
- if (action.type === "LOAD_USERS") {
- const users = action.payload;
- const newUsers = [];
+ if (action.type === "LOAD_USERS") {
+ const users = action.payload;
+ const newUsers = [];
- users.forEach(user => {
- const userIndex = state.findIndex(u => u.id === user.id);
- if (userIndex !== -1) {
- state[userIndex] = user;
- } else {
- newUsers.push(user);
- }
- });
+ users.forEach((user) => {
+ const userIndex = state.findIndex((u) => u.id === user.id);
+ if (userIndex !== -1) {
+ state[userIndex] = user;
+ } else {
+ newUsers.push(user);
+ }
+ });
- return [...state, ...newUsers];
- }
+ return [...state, ...newUsers];
+ }
- if (action.type === "UPDATE_USERS") {
- const user = action.payload;
- const userIndex = state.findIndex(u => u.id === user.id);
+ if (action.type === "UPDATE_USERS") {
+ const user = action.payload;
+ const userIndex = state.findIndex((u) => u.id === user.id);
- if (userIndex !== -1) {
- state[userIndex] = user;
- return [...state];
- } else {
- return [user, ...state];
- }
- }
+ if (userIndex !== -1) {
+ state[userIndex] = user;
+ return [...state];
+ } else {
+ return [user, ...state];
+ }
+ }
- if (action.type === "DELETE_USER") {
- const userId = action.payload;
+ if (action.type === "DELETE_USER") {
+ const userId = action.payload;
- const userIndex = state.findIndex(u => u.id === userId);
- if (userIndex !== -1) {
- state.splice(userIndex, 1);
- }
- return [...state];
- }
+ const userIndex = state.findIndex((u) => u.id === userId);
+ if (userIndex !== -1) {
+ state.splice(userIndex, 1);
+ }
+ return [...state];
+ }
- if (action.type === "RESET") {
- return [];
- }
+ if (action.type === "RESET") {
+ return [];
+ }
};
-const useStyles = makeStyles(theme => ({
- mainPaper: {
- flex: 1,
- padding: theme.spacing(1),
- overflowY: "scroll",
- ...theme.scrollbarStyles,
- },
+const useStyles = makeStyles((theme) => ({
+ mainPaper: {
+ flex: 1,
+ padding: theme.spacing(1),
+ overflowY: "scroll",
+ ...theme.scrollbarStyles,
+ },
}));
const Users = () => {
- const classes = useStyles();
+ const classes = useStyles();
- const [loading, setLoading] = useState(false);
- const [pageNumber, setPageNumber] = useState(1);
- const [hasMore, setHasMore] = useState(false);
- const [selectedUser, setSelectedUser] = useState(null);
- const [deletingUser, setDeletingUser] = useState(null);
- const [userModalOpen, setUserModalOpen] = useState(false);
- const [confirmModalOpen, setConfirmModalOpen] = useState(false);
- const [searchParam, setSearchParam] = useState("");
- const [users, dispatch] = useReducer(reducer, []);
+ const [loading, setLoading] = useState(false);
+ const [pageNumber, setPageNumber] = useState(1);
+ const [hasMore, setHasMore] = useState(false);
+ const [selectedUser, setSelectedUser] = useState(null);
+ const [deletingUser, setDeletingUser] = useState(null);
+ const [userModalOpen, setUserModalOpen] = useState(false);
+ const [confirmModalOpen, setConfirmModalOpen] = useState(false);
+ const [searchParam, setSearchParam] = useState("");
+ const [users, dispatch] = useReducer(reducer, []);
- useEffect(() => {
- dispatch({ type: "RESET" });
- setPageNumber(1);
- }, [searchParam]);
+ useEffect(() => {
+ dispatch({ type: "RESET" });
+ setPageNumber(1);
+ }, [searchParam]);
- useEffect(() => {
- setLoading(true);
- const delayDebounceFn = setTimeout(() => {
- const fetchUsers = async () => {
- try {
- const { data } = await api.get("/users/", {
- params: { searchParam, pageNumber },
- });
- dispatch({ type: "LOAD_USERS", payload: data.users });
- setHasMore(data.hasMore);
- setLoading(false);
- } catch (err) {
- toastError(err);
- }
- };
- fetchUsers();
- }, 500);
- return () => clearTimeout(delayDebounceFn);
- }, [searchParam, pageNumber]);
+ useEffect(() => {
+ setLoading(true);
+ const delayDebounceFn = setTimeout(() => {
+ const fetchUsers = async () => {
+ try {
+ const { data } = await api.get("/users/", {
+ params: { searchParam, pageNumber },
+ });
+ dispatch({ type: "LOAD_USERS", payload: data.users });
+ setHasMore(data.hasMore);
+ setLoading(false);
+ } catch (err) {
+ toastError(err);
+ }
+ };
+ fetchUsers();
+ }, 500);
+ return () => clearTimeout(delayDebounceFn);
+ }, [searchParam, pageNumber]);
- useEffect(() => {
- const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
+ useEffect(() => {
+ const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
- socket.on("user", data => {
- if (data.action === "update" || data.action === "create") {
- dispatch({ type: "UPDATE_USERS", payload: data.user });
- }
+ socket.on("user", (data) => {
+ if (data.action === "update" || data.action === "create") {
+ dispatch({ type: "UPDATE_USERS", payload: data.user });
+ }
- if (data.action === "delete") {
- dispatch({ type: "DELETE_USER", payload: +data.userId });
- }
- });
+ if (data.action === "delete") {
+ dispatch({ type: "DELETE_USER", payload: +data.userId });
+ }
+ });
- return () => {
- socket.disconnect();
- };
- }, []);
+ return () => {
+ socket.disconnect();
+ };
+ }, []);
- const handleOpenUserModal = () => {
- setSelectedUser(null);
- setUserModalOpen(true);
- };
+ const handleOpenUserModal = () => {
+ setSelectedUser(null);
+ setUserModalOpen(true);
+ };
- const handleCloseUserModal = () => {
- setSelectedUser(null);
- setUserModalOpen(false);
- };
+ const handleCloseUserModal = () => {
+ setSelectedUser(null);
+ setUserModalOpen(false);
+ };
- const handleSearch = event => {
- setSearchParam(event.target.value.toLowerCase());
- };
+ const handleSearch = (event) => {
+ setSearchParam(event.target.value.toLowerCase());
+ };
- const handleEditUser = user => {
- setSelectedUser(user);
- setUserModalOpen(true);
- };
+ const handleEditUser = (user) => {
+ setSelectedUser(user);
+ setUserModalOpen(true);
+ };
- const handleDeleteUser = async userId => {
- try {
- await api.delete(`/users/${userId}`);
- toast.success(i18n.t("users.toasts.deleted"));
- } catch (err) {
- toastError(err);
- }
- setDeletingUser(null);
- setSearchParam("");
- setPageNumber(1);
- };
+ const handleDeleteUser = async (userId) => {
+ try {
+ await api.delete(`/users/${userId}`);
+ toast.success(i18n.t("users.toasts.deleted"));
+ } catch (err) {
+ toastError(err);
+ }
+ setDeletingUser(null);
+ setSearchParam("");
+ setPageNumber(1);
+ };
- const loadMore = () => {
- setPageNumber(prevState => prevState + 1);
- };
+ const loadMore = () => {
+ setPageNumber((prevState) => prevState + 1);
+ };
- const handleScroll = e => {
- if (!hasMore || loading) return;
- const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
- if (scrollHeight - (scrollTop + 100) < clientHeight) {
- loadMore();
- }
- };
+ const handleScroll = (e) => {
+ if (!hasMore || loading) return;
+ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
+ if (scrollHeight - (scrollTop + 100) < clientHeight) {
+ loadMore();
+ }
+ };
- return (
-
- handleDeleteUser(deletingUser.id)}
- >
- {i18n.t("users.confirmationModal.deleteMessage")}
-
-
-
- {i18n.t("users.title")}
-
-
-
-
- ),
- }}
- />
-
-
-
-
-
-
-
- {i18n.t("users.table.name")}
-
- {i18n.t("users.table.email")}
-
-
- {i18n.t("users.table.profile")}
-
-
- {i18n.t("users.table.actions")}
-
-
-
-
- <>
- {users.map(user => (
-
- {user.name}
- {user.email}
- {user.profile}
-
- handleEditUser(user)}
- >
-
-
+ return (
+
+ handleDeleteUser(deletingUser.id)}
+ >
+ {i18n.t("users.confirmationModal.deleteMessage")}
+
+
+
+ {i18n.t("users.title")}
+
+
+
+
+ ),
+ }}
+ />
+
+
+
+
+
+
+
+ {i18n.t("users.table.name")}
+
+ {i18n.t("users.table.email")}
+
+
+ {i18n.t("users.table.profile")}
+
+
+ {i18n.t("users.table.actions")}
+
+
+
+
+ <>
+ {users.map((user) => (
+
+ {user.name}
+ {user.email}
+ {user.profile}
+
+ handleEditUser(user)}
+ >
+
+
- {
- setConfirmModalOpen(true);
- setDeletingUser(user);
- }}
- >
-
-
-
-
- ))}
- {loading && }
- >
-
-
-
-
- );
+ {
+ setConfirmModalOpen(true);
+ setDeletingUser(user);
+ }}
+ >
+
+
+
+
+ ))}
+ {loading && }
+ >
+
+
+
+
+ );
};
export default Users;
diff --git a/frontend/src/routes/Route.js b/frontend/src/routes/Route.js
index bf2a375..fab61b3 100644
--- a/frontend/src/routes/Route.js
+++ b/frontend/src/routes/Route.js
@@ -5,32 +5,32 @@ import { AuthContext } from "../context/Auth/AuthContext";
import BackdropLoading from "../components/BackdropLoading";
const Route = ({ component: Component, isPrivate = false, ...rest }) => {
- const { isAuth, loading } = useContext(AuthContext);
+ const { isAuth, loading } = useContext(AuthContext);
- if (!isAuth && isPrivate) {
- return (
- <>
- {loading && }
-
- >
- );
- }
+ if (!isAuth && isPrivate) {
+ return (
+ <>
+ {loading && }
+
+ >
+ );
+ }
- if (isAuth && !isPrivate) {
- return (
- <>
- {loading && }
- ;
- >
- );
- }
+ if (isAuth && !isPrivate) {
+ return (
+ <>
+ {loading && }
+ ;
+ >
+ );
+ }
- return (
- <>
- {loading && }
-
- >
- );
+ return (
+ <>
+ {loading && }
+
+ >
+ );
};
export default Route;