feat: add options to handle whatsapp session on frontend

This commit is contained in:
canove
2020-10-27 16:08:50 -03:00
parent 73cb08a557
commit e573656276
11 changed files with 408 additions and 84 deletions

View File

@@ -14,8 +14,19 @@ import {
Table,
TableHead,
Paper,
Tooltip,
Typography,
} from "@material-ui/core";
import { Edit, DeleteOutline, CheckCircle } from "@material-ui/icons";
import {
Edit,
CheckCircle,
SignalCellularConnectedNoInternet2Bar,
SignalCellularConnectedNoInternet0Bar,
Schedule,
SignalCellular4Bar,
CropFree,
DeleteOutline,
} from "@material-ui/icons";
import MainContainer from "../../components/MainContainer";
import MainHeader from "../../components/MainHeader";
@@ -26,6 +37,7 @@ import TableRowSkeleton from "../../components/TableRowSkeleton";
import api from "../../services/api";
import WhatsAppModal from "../../components/WhatsAppModal";
import ConfirmationModal from "../../components/ConfirmationModal";
import ButtonWithSpinner from "../../components/ButtonWithSpinner";
import QrcodeModal from "../../components/QrcodeModal";
import { i18n } from "../../translate/i18n";
@@ -56,6 +68,7 @@ const reducer = (state, action) => {
state[whatsAppIndex].status = whatsApp.status;
state[whatsAppIndex].updatedAt = whatsApp.updatedAt;
state[whatsAppIndex].qrcode = whatsApp.qrcode;
state[whatsAppIndex].retries = whatsApp.retries;
return [...state];
} else {
return [...state];
@@ -84,8 +97,47 @@ const useStyles = makeStyles(theme => ({
overflowY: "scroll",
...theme.scrollbarStyles,
},
customTableCell: {
display: "flex",
alignItems: "center",
justifyContent: "center",
},
tooltip: {
backgroundColor: "#f5f5f9",
color: "rgba(0, 0, 0, 0.87)",
fontSize: theme.typography.pxToRem(14),
border: "1px solid #dadde9",
maxWidth: 450,
},
tooltipPopper: {
textAlign: "center",
},
}));
const CustomToolTip = ({ title, content, children }) => {
const classes = useStyles();
return (
<Tooltip
arrow
classes={{
tooltip: classes.tooltip,
popper: classes.tooltipPopper,
}}
title={
<React.Fragment>
<Typography gutterBottom color="inherit">
{title}
</Typography>
{content && <Typography>{content}</Typography>}
</React.Fragment>
}
>
{children}
</Tooltip>
);
};
const Connections = () => {
const classes = useStyles();
@@ -94,15 +146,28 @@ const Connections = () => {
const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false);
const [qrModalOpen, setQrModalOpen] = useState(false);
const [selectedWhatsApp, setSelectedWhatsApp] = useState(null);
const [loading, setLoading] = useState(true);
const [confirmModalOpen, setConfirmModalOpen] = useState(false);
const [deletingWhatsApp, setDeletingWhatsApp] = useState(null);
const confirmationModalInitialState = {
action: "",
title: "",
message: "",
whatsAppId: "",
open: false,
};
const [confirmModalInfo, setConfirmModalInfo] = useState(
confirmationModalInitialState
);
useEffect(() => {
setLoading(true);
const fetchSession = async () => {
try {
const { data } = await api.get("/whatsapp/");
dispatch({ type: "LOAD_WHATSAPPS", payload: data });
setLoading(false);
} catch (err) {
setLoading(false);
const errorMsg = err.response?.data?.error;
if (errorMsg) {
if (i18n.exists(`backendErrors.${errorMsg}`)) {
@@ -144,19 +209,27 @@ const Connections = () => {
};
}, []);
// const handleDisconnectSession = async whatsAppId => {
// try {
// await api.put(`/whatsapp/whatsApp/${whatsAppId}`, {
// whatsApp: "",
// status: "pending",
// });
// } catch (err) {
// console.log(err);
// if (err.response && err.response.data && err.response.data.error) {
// toast.error(err.response.data.error);
// }
// }
// };
const handleStartWhatsAppSession = async whatsAppId => {
try {
await api.post(`/whatsappsession/${whatsAppId}`);
} catch (err) {
console.log(err);
if (err.response && err.response.data && err.response.data.error) {
toast.error(err.response.data.error);
}
}
};
const handleRequestNewQrCode = async whatsAppId => {
try {
await api.put(`/whatsappsession/${whatsAppId}`);
} catch (err) {
console.log(err);
if (err.response && err.response.data && err.response.data.error) {
toast.error(err.response.data.error);
}
}
};
const handleOpenWhatsAppModal = () => {
setSelectedWhatsApp(null);
@@ -183,51 +256,187 @@ const Connections = () => {
setWhatsAppModalOpen(true);
};
const handleDeleteWhatsApp = async whatsAppId => {
try {
await api.delete(`/whatsapp/${whatsAppId}`);
toast.success(i18n.t("connections.toasts.deleted"));
} catch (err) {
const errorMsg = err.response?.data?.error;
if (errorMsg) {
if (i18n.exists(`backendErrors.${errorMsg}`)) {
toast.error(i18n.t(`backendErrors.${errorMsg}`));
const renderActionButtons = whatsApp => {
return (
<>
{whatsApp.status === "qrcode" && (
<Button
size="small"
variant="contained"
color="primary"
onClick={() => handleOpenQrModal(whatsApp)}
>
{i18n.t("connections.buttons.qrcode")}
</Button>
)}
{whatsApp.status === "DISCONNECTED" && (
<>
<Button
size="small"
variant="outlined"
color="primary"
onClick={() => handleStartWhatsAppSession(whatsApp.id)}
>
{i18n.t("connections.buttons.tryAgain")}
</Button>{" "}
<Button
size="small"
variant="outlined"
color="secondary"
onClick={() => handleRequestNewQrCode(whatsApp.id)}
>
{i18n.t("connections.buttons.newQr")}
</Button>
</>
)}
{(whatsApp.status === "CONNECTED" ||
whatsApp.status === "PAIRING" ||
whatsApp.status === "TIMEOUT") && (
<Button
size="small"
variant="outlined"
color="secondary"
onClick={() => {
handleOpenConfirmationModal("disconnect", whatsApp.id);
}}
>
{i18n.t("connections.buttons.disconnect")}
</Button>
)}
{whatsApp.status === "OPENING" && (
<ButtonWithSpinner
size="small"
variant="outlined"
loading={true}
color="default"
>
{i18n.t("connections.buttons.connecting")}
</ButtonWithSpinner>
)}
</>
);
};
const renderStatusToolTips = whatsApp => {
return (
<div className={classes.customTableCell}>
{whatsApp.status === "DISCONNECTED" && (
<CustomToolTip
title={i18n.t("connections.toolTips.disconnected.title")}
content={i18n.t("connections.toolTips.disconnected.content")}
>
<SignalCellularConnectedNoInternet0Bar color="secondary" />
</CustomToolTip>
)}
{whatsApp.status === "OPENING" && (
<CustomToolTip title={i18n.t("connections.toolTips.opening.title")}>
<Schedule color="disabled" />
</CustomToolTip>
)}
{whatsApp.status === "qrcode" && (
<CustomToolTip
title={i18n.t("connections.toolTips.qrcode.title")}
content={i18n.t("connections.toolTips.qrcode.content")}
>
<CropFree />
</CustomToolTip>
)}
{whatsApp.status === "CONNECTED" && (
<CustomToolTip title={i18n.t("connections.toolTips.connected.title")}>
<SignalCellular4Bar style={{ color: green[500] }} />
</CustomToolTip>
)}
{(whatsApp.status === "TIMEOUT" || whatsApp.status === "PAIRING") && (
<CustomToolTip
title={i18n.t("connections.toolTips.timeout.title")}
content={i18n.t("connections.toolTips.timeout.content")}
>
<SignalCellularConnectedNoInternet2Bar color="secondary" />
</CustomToolTip>
)}
</div>
);
};
const handleOpenConfirmationModal = (action, whatsAppId) => {
if (action === "disconnect") {
setConfirmModalInfo({
action: action,
title: i18n.t("connections.confirmationModal.disconnectTitle"),
message: i18n.t("connections.confirmationModal.disconnectMessage"),
whatsAppId: whatsAppId,
});
}
if (action === "delete") {
setConfirmModalInfo({
action: action,
title: i18n.t("connections.confirmationModal.deleteTitle"),
message: i18n.t("connections.confirmationModal.deleteMessage"),
whatsAppId: whatsAppId,
});
}
setConfirmModalOpen(true);
};
const handleSubmitConfirmationModal = async () => {
if (confirmModalInfo.action === "disconnect") {
try {
await api.delete(`/whatsappsession/${confirmModalInfo.whatsAppId}`);
} catch (err) {
const errorMsg = err.response?.data?.error;
if (errorMsg) {
if (i18n.exists(`backendErrors.${errorMsg}`)) {
toast.error(i18n.t(`backendErrors.${errorMsg}`));
} else {
toast.error(err.response.data.error);
}
} else {
toast.error(err.response.data.error);
toast.error("Unknown error");
}
} else {
toast.error("Unknown error");
}
}
setDeletingWhatsApp(null);
if (confirmModalInfo.action === "delete") {
try {
await api.delete(`/whatsapp/${confirmModalInfo.whatsAppId}`);
toast.success(i18n.t("connections.toasts.deleted"));
} catch (err) {
const errorMsg = err.response?.data?.error;
if (errorMsg) {
if (i18n.exists(`backendErrors.${errorMsg}`)) {
toast.error(i18n.t(`backendErrors.${errorMsg}`));
} else {
toast.error(err.response.data.error);
}
} else {
toast.error("Unknown error");
}
}
}
setConfirmModalInfo(confirmationModalInitialState);
};
return (
<MainContainer>
<ConfirmationModal
title={
deletingWhatsApp &&
`${i18n.t("connections.confirmationModal.deleteTitle")} ${
deletingWhatsApp.name
}?`
}
title={confirmModalInfo.title}
open={confirmModalOpen}
setOpen={setConfirmModalOpen}
onConfirm={() => handleDeleteWhatsApp(deletingWhatsApp.id)}
onConfirm={handleSubmitConfirmationModal}
>
{i18n.t("connections.confirmationModal.deleteMessage")}
{confirmModalInfo.message}
</ConfirmationModal>
<QrcodeModal
open={qrModalOpen}
onClose={handleCloseQrModal}
whatsAppId={
selectedWhatsApp && !whatsAppModalOpen && selectedWhatsApp.id
}
whatsAppId={!whatsAppModalOpen && selectedWhatsApp?.id}
/>
<WhatsAppModal
open={whatsAppModalOpen}
onClose={handleCloseWhatsAppModal}
whatsAppId={selectedWhatsApp && !qrModalOpen && selectedWhatsApp.id}
whatsAppId={!qrModalOpen && selectedWhatsApp?.id}
/>
<MainHeader>
<Title>{i18n.t("connections.title")}</Title>
@@ -251,6 +460,9 @@ const Connections = () => {
<TableCell align="center">
{i18n.t("connections.table.status")}
</TableCell>
<TableCell align="center">
{i18n.t("connections.table.session")}
</TableCell>
<TableCell align="center">
{i18n.t("connections.table.lastUpdate")}
</TableCell>
@@ -263,35 +475,28 @@ const Connections = () => {
</TableRow>
</TableHead>
<TableBody>
{false ? (
{loading ? (
<TableRowSkeleton />
) : (
<>
{whatsApps &&
whatsApps.length > 0 &&
whatsApps.map((whatsApp, index) => (
{whatsApps?.length > 0 &&
whatsApps.map(whatsApp => (
<TableRow key={whatsApp.id}>
<TableCell align="center">{whatsApp.name}</TableCell>
<TableCell align="center">
{whatsApp.status === "qrcode" ? (
<Button
size="small"
variant="contained"
color="primary"
onClick={() => handleOpenQrModal(whatsApp)}
>
QR CODE
</Button>
) : (
whatsApp.status
)}
{renderStatusToolTips(whatsApp)}
</TableCell>
<TableCell align="center">
{renderActionButtons(whatsApp)}
</TableCell>
<TableCell align="center">
{format(parseISO(whatsApp.updatedAt), "dd/MM/yy HH:mm")}
</TableCell>
<TableCell align="center">
{whatsApp.isDefault && (
<CheckCircle style={{ color: green[500] }} />
<div className={classes.customTableCell}>
<CheckCircle style={{ color: green[500] }} />
</div>
)}
</TableCell>
<TableCell align="center">
@@ -305,8 +510,7 @@ const Connections = () => {
<IconButton
size="small"
onClick={e => {
setConfirmModalOpen(true);
setDeletingWhatsApp(whatsApp);
handleOpenConfirmationModal("delete", whatsApp.id);
}}
>
<DeleteOutline />