git commit -m "feat: Implement online/offline status handling and enhance ticket creation"

adriano 2024-01-22 15:52:30 -03:00
parent 605e4035b9
commit 52619bfd26
9 changed files with 263 additions and 374 deletions

View File

@ -8,18 +8,19 @@ import ShowContactService from "../services/ContactServices/ShowContactService";
import UpdateContactService from "../services/ContactServices/UpdateContactService"; import UpdateContactService from "../services/ContactServices/UpdateContactService";
import DeleteContactService from "../services/ContactServices/DeleteContactService"; import DeleteContactService from "../services/ContactServices/DeleteContactService";
import CheckContactNumber from "../services/WbotServices/CheckNumber" import CheckContactNumber from "../services/WbotServices/CheckNumber";
import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact";
import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl";
import AppError from "../errors/AppError"; import AppError from "../errors/AppError";
import {
import { searchContactCache, insertContactsCache, escapeCharCache } from '../helpers/ContactsCache' searchContactCache,
insertContactsCache,
escapeCharCache
} from "../helpers/ContactsCache";
import { off } from "process"; import { off } from "process";
type IndexQuery = { type IndexQuery = {
searchParam: string; searchParam: string;
pageNumber: string; pageNumber: string;
@ -39,42 +40,46 @@ interface ContactData {
export const index = async (req: Request, res: Response): Promise<Response> => { export const index = async (req: Request, res: Response): Promise<Response> => {
let { searchParam, pageNumber } = req.query as IndexQuery; let { searchParam, pageNumber } = req.query as IndexQuery;
console.log('PAGE NUMBER CONTACT: ', pageNumber) console.log("PAGE NUMBER CONTACT: ", pageNumber);
if (pageNumber === undefined || pageNumber.trim().length == 0) { if (pageNumber === undefined || pageNumber.trim().length == 0) {
pageNumber = '1' pageNumber = "1";
} }
// TEST DEL // TEST DEL
if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) { if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) {
try { try {
const offset = 20 * (+pageNumber - 1); const offset = 20 * (+pageNumber - 1);
searchParam = searchParam.replace(/\s+/g, ' ').trim().toLowerCase(); searchParam = searchParam.replace(/\s+/g, " ").trim().toLowerCase();
const data = await searchContactCache(searchParam, offset, 20) const data = await searchContactCache(searchParam, offset, 20);
if (data) { if (data) {
console.log("QUERY CONTACTS FROM CACHE SEARCH PARAM: ", searchParam);
console.log('QUERY CONTACTS FROM CACHE SEARCH PARAM: ', searchParam) console.log("QUERY CONTACTS FROM CACHE QUERY LENGTH: ", data.length);
console.log('QUERY CONTACTS FROM CACHE QUERY LENGTH: ', data.length) return res.json({
contacts: data,
return res.json({ contacts: data, count: data.length, hasMore: data.length > 0 ? true : false }); count: data.length,
hasMore: data.length > 0 ? true : false
});
} }
} catch (error) { } catch (error) {
console.log('There was an error on search ContactController.ts search cache: ', error) console.log(
"There was an error on search ContactController.ts search cache: ",
error
);
} }
} }
console.log('QUERY CONTACTS FROM DATABASE SEARCH PARAM: ', searchParam) console.log("QUERY CONTACTS FROM DATABASE SEARCH PARAM: ", searchParam);
const { contacts, count, hasMore } = await ListContactsService({ searchParam, pageNumber }); const { contacts, count, hasMore } = await ListContactsService({
searchParam,
pageNumber
});
return res.json({ contacts, count, hasMore }); return res.json({ contacts, count, hasMore });
}; };
@ -83,6 +88,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
const newContact: ContactData = req.body; const newContact: ContactData = req.body;
newContact.number = newContact.number.replace("-", "").replace(" ", ""); newContact.number = newContact.number.replace("-", "").replace(" ", "");
throw new AppError("ERR_NO_ADD_CONTACT");
const schema = Yup.object().shape({ const schema = Yup.object().shape({
name: Yup.string().required(), name: Yup.string().required(),
number: Yup.string() number: Yup.string()
@ -109,25 +116,24 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
const profilePicUrl = await GetProfilePicUrl(validNumber); const profilePicUrl = await GetProfilePicUrl(validNumber);
console.log('xxxxxxxxxxx profilePicUrl: ', profilePicUrl) console.log("xxxxxxxxxxx profilePicUrl: ", profilePicUrl);
// console.log(`newContact.name: ${newContact.name}\n // console.log(`newContact.name: ${newContact.name}\n
// newContact.number: ${newContact.number}\n // newContact.number: ${newContact.number}\n
// newContact.email: ${newContact.email}\n // newContact.email: ${newContact.email}\n
// newContact.extraInfo: ${newContact.extraInfo}`) // newContact.extraInfo: ${newContact.extraInfo}`)
let name = newContact.name let name = newContact.name;
let number = validNumber let number = validNumber;
let email = newContact.email let email = newContact.email;
let extraInfo = newContact.extraInfo let extraInfo = newContact.extraInfo;
const contact = await CreateContactService({ const contact = await CreateContactService({
name, name,
number, number,
email, email,
profilePicUrl: profilePicUrl, profilePicUrl: profilePicUrl,
extraInfo, extraInfo
}); });
const io = getIO(); const io = getIO();
@ -155,8 +161,10 @@ export const update = async (
const schema = Yup.object().shape({ const schema = Yup.object().shape({
name: Yup.string(), name: Yup.string(),
number: Yup.string() number: Yup.string().matches(
.matches(/^\d+$/, "Invalid number format. Only numbers is allowed.") /^\d+$/,
"Invalid number format. Only numbers is allowed."
)
// .matches(/^55\d+$/, "The number must start with 55.") // .matches(/^55\d+$/, "The number must start with 55.")
}); });
@ -200,13 +208,14 @@ export const remove = async (
return res.status(200).json({ message: "Contact deleted" }); return res.status(200).json({ message: "Contact deleted" });
}; };
export const contacsBulkInsertOnQueue = async (
req: Request,
export const contacsBulkInsertOnQueue = async (req: Request, res: Response): Promise<Response> => { res: Response
): Promise<Response> => {
// console.log('THE BODY: ', req.body) // console.log('THE BODY: ', req.body)
const { adminId, identifier, queueStatus, file, contacts_inserted } = req.body const { adminId, identifier, queueStatus, file, contacts_inserted } =
req.body;
const io = getIO(); const io = getIO();
io.emit("contactsBulkInsertOnQueueStatus", { io.emit("contactsBulkInsertOnQueueStatus", {
@ -219,24 +228,19 @@ export const contacsBulkInsertOnQueue = async (req: Request, res: Response): Pro
} }
}); });
if (process.env.CACHE && contacts_inserted) { if (process.env.CACHE && contacts_inserted) {
await insertContactsCache(contacts_inserted);
await insertContactsCache(contacts_inserted)
} }
return res.status(200).json({ message: 'ok' }) return res.status(200).json({ message: "ok" });
}; };
function addStartPhoneNumber(phoneNumber: string) { function addStartPhoneNumber(phoneNumber: string) {
const regex = /^55/; const regex = /^55/;
if (!regex.test(phoneNumber)) { if (!regex.test(phoneNumber)) {
phoneNumber = '55' + phoneNumber; phoneNumber = "55" + phoneNumber;
} }
return phoneNumber return phoneNumber;
} }

View File

@ -5,6 +5,8 @@ import AuthUserService from "../services/UserServices/AuthUserService";
import { SendRefreshToken } from "../helpers/SendRefreshToken"; import { SendRefreshToken } from "../helpers/SendRefreshToken";
import { RefreshTokenService } from "../services/AuthServices/RefreshTokenService"; import { RefreshTokenService } from "../services/AuthServices/RefreshTokenService";
import createOrUpdateOnlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService";
export const store = async (req: Request, res: Response): Promise<Response> => { export const store = async (req: Request, res: Response): Promise<Response> => {
const { email, password } = req.body; const { email, password } = req.body;
@ -13,6 +15,13 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
password password
}); });
console.log("serializedUser.id: ", serializedUser.id);
const userOnline = await createOrUpdateOnlineUserService({
userId: serializedUser.id,
status: "online"
});
SendRefreshToken(res, refreshToken); SendRefreshToken(res, refreshToken);
return res.status(200).json({ return res.status(200).json({
@ -47,5 +56,11 @@ export const remove = async (
): Promise<Response> => { ): Promise<Response> => {
res.clearCookie("jrt"); res.clearCookie("jrt");
const { userId } = req.params;
const userOnline = await createOrUpdateOnlineUserService({
userId,
status: "offline"
});
return res.send(); return res.send();
}; };

View File

@ -108,7 +108,7 @@ const monitor = async () => {
el.onlineTime = userOnline.onlineTime el.onlineTime = userOnline.onlineTime
el.updatedAt = userOnline.updatedAt, el.updatedAt = userOnline.updatedAt,
console.log(' * CREATED OR UPDATED USER TO ONLINE: ', userOnline.userId) console.log('* CREATED OR UPDATED USER TO ONLINE: ', userOnline.userId)
lstOnline.push({ 'id': el.id, 'status': 'online' }) lstOnline.push({ 'id': el.id, 'status': 'online' })
} }

View File

@ -47,12 +47,6 @@ export const initIO = (httpServer: Server): SocketIO => {
io.on("connection", socket => { io.on("connection", socket => {
logger.info("Client Connected"); logger.info("Client Connected");
socket.on("joinWhatsSession", (whatsappId: string) => { socket.on("joinWhatsSession", (whatsappId: string) => {
logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`); logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`);
socket.join(`session_${whatsappId}`); socket.join(`session_${whatsappId}`);
@ -82,15 +76,6 @@ export const initIO = (httpServer: Server): SocketIO => {
}); });
socket.on("online", (userId: any) => { socket.on("online", (userId: any) => {
// console.log('userId: ', userId) // console.log('userId: ', userId)
@ -179,6 +164,8 @@ export const initIO = (httpServer: Server): SocketIO => {
e.try += 1 e.try += 1
console.log("try.......: ", e.try);
if (e.try > 1) { if (e.try > 1) {
e.status = 'waiting...' e.status = 'waiting...'
} }

View File

@ -11,6 +11,6 @@ authRoutes.post("/login", SessionController.store);
authRoutes.post("/refresh_token", SessionController.update); authRoutes.post("/refresh_token", SessionController.update);
authRoutes.delete("/logout", isAuth, SessionController.remove); authRoutes.delete("/logout/:userId", isAuth, SessionController.remove);
export default authRoutes; export default authRoutes;

View File

@ -1,26 +1,26 @@
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react"
import * as Yup from "yup"; import * as Yup from "yup"
import { Formik, FieldArray, Form, Field } from "formik"; import { Formik, FieldArray, Form, Field } from "formik"
import { toast } from "react-toastify"; import { toast } from "react-toastify"
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles"
import { green } from "@material-ui/core/colors"; import { green } from "@material-ui/core/colors"
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 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"
import DialogTitle from "@material-ui/core/DialogTitle"; import DialogTitle from "@material-ui/core/DialogTitle"
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography"
import IconButton from "@material-ui/core/IconButton"; import IconButton from "@material-ui/core/IconButton"
import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"
import CircularProgress from "@material-ui/core/CircularProgress"; import CircularProgress from "@material-ui/core/CircularProgress"
import { i18n } from "../../translate/i18n"; import { i18n } from "../../translate/i18n"
import api from "../../services/api"; import api from "../../services/api"
import toastError from "../../errors/toastError"; import toastError from "../../errors/toastError"
const useStyles = makeStyles(theme => ({ const useStyles = makeStyles(theme => ({
root: { root: {
@ -50,7 +50,7 @@ const useStyles = makeStyles(theme => ({
marginTop: -12, marginTop: -12,
marginLeft: -12, marginLeft: -12,
}, },
})); }))
const ContactSchema = Yup.object().shape({ const ContactSchema = Yup.object().shape({
name: Yup.string() name: Yup.string()
@ -63,29 +63,29 @@ const ContactSchema = Yup.object().shape({
.max(50, "Too Long!"), .max(50, "Too Long!"),
// email: Yup.string().email("Invalid email"), // email: Yup.string().email("Invalid email"),
}); })
const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => { const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
const classes = useStyles(); const classes = useStyles()
const isMounted = useRef(true); const isMounted = useRef(true)
const initialState = { const initialState = {
name: "", name: "",
number: "", number: "",
email: "", email: "",
}; }
const [contact, setContact] = useState(initialState); const [contact, setContact] = useState(initialState)
const [phone, setPhone] = useState('') const [phone, setPhone] = useState('')
useEffect(() => { useEffect(() => {
return () => { return () => {
isMounted.current = false; isMounted.current = false
}; }
}, []); }, [])
// useEffect(() => { // useEffect(() => {
// console.log('1 Contact: ', contact) // console.log('1 Contact: ', contact)
@ -103,64 +103,66 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
const fetchContact = async () => { const fetchContact = async () => {
if (initialValues) { if (initialValues) {
if (initialValues?.number)
setPhone(initialValues.number)
setContact(prevState => { setContact(prevState => {
return { ...prevState, ...initialValues }; return { ...prevState, ...initialValues }
}); })
} }
if (!contactId) return; if (!contactId) return
try { try {
const { data } = await api.get(`/contacts/${contactId}`); const { data } = await api.get(`/contacts/${contactId}`)
if (isMounted.current) { if (isMounted.current) {
setPhone(data.number) setPhone(data.number)
setContact(data); setContact(data)
} }
} catch (err) { } catch (err) {
toastError(err); toastError(err)
} }
}; }
fetchContact(); fetchContact()
}, [contactId, open, initialValues]); }, [contactId, open, initialValues])
const handleClose = () => { const handleClose = () => {
onClose(); onClose()
setContact(initialState); console.log('INITIAL STATE: ', initialState)
}; setContact(initialState)
}
const handleSaveContact = async values => { const handleSaveContact = async values => {
values = { ...values, number: phone }; values = { ...values, number: phone }
console.log('submit values', values)
try { try {
if (contactId) { if (contactId) {
await api.put(`/contacts/${contactId}`, values); await api.put(`/contacts/${contactId}`, values)
handleClose(); handleClose()
} else { } else {
const { data } = await api.post("/contacts", values); const { data } = await api.post("/contacts", values)
if (onSave) { if (onSave) {
onSave(data); onSave(data)
} }
handleClose(); handleClose()
} }
toast.success(i18n.t("contactModal.success")); toast.success(i18n.t("contactModal.success"))
} catch (err) { } catch (err) {
toastError(err); toastError(err)
} }
}; }
const handleChange = (event) => { const handleChange = (event) => {
const regex = /^[0-9\b]+$/; // Regular expression to match only numbers const regex = /^[0-9\b]+$/ // Regular expression to match only numbers
setPhone(event.target.value); setPhone(event.target.value)
setTimeout(() => { setTimeout(() => {
@ -174,9 +176,9 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
setPhone(newValue) setPhone(newValue)
}, 100); }, 100)
}; }
return ( return (
<div className={classes.root}> <div className={classes.root}>
@ -192,12 +194,12 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
validationSchema={ContactSchema} validationSchema={ContactSchema}
onSubmit={(values, actions) => { onSubmit={(values, actions) => {
setTimeout(() => { setTimeout(() => {
handleSaveContact(values); handleSaveContact(values)
actions.setSubmitting(false); actions.setSubmitting(false)
}, 400); }, 400)
}} }}
> >
{({ values, errors, touched, isSubmitting }) => ( {({ values, errors, touched, isSubmitting, resetForm }) => (
<Form> <Form>
<DialogContent dividers> <DialogContent dividers>
<Typography variant="subtitle1" gutterBottom> <Typography variant="subtitle1" gutterBottom>
@ -298,7 +300,9 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button <Button
onClick={handleClose} onClick={()=>{
handleClose()
}}
color="secondary" color="secondary"
disabled={isSubmitting} disabled={isSubmitting}
variant="outlined" variant="outlined"
@ -328,7 +332,7 @@ const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
</Formik> </Formik>
</Dialog> </Dialog>
</div> </div>
); )
}; }
export default ContactModal; export default ContactModal

View File

@ -1,256 +1,154 @@
import React, { useState, useEffect, useContext } from "react"; import React, { useState, useEffect, useContext } from "react"
import { useHistory } from "react-router-dom"; 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 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"
import DialogTitle from "@material-ui/core/DialogTitle"; import DialogTitle from "@material-ui/core/DialogTitle"
// import Autocomplete, { import Autocomplete, {
// createFilterOptions, createFilterOptions,
// } from "@material-ui/lab/Autocomplete"; } from "@material-ui/lab/Autocomplete"
// import CircularProgress from "@material-ui/core/CircularProgress"; import CircularProgress from "@material-ui/core/CircularProgress"
import { i18n } from "../../translate/i18n"; import { i18n } from "../../translate/i18n"
import api from "../../services/api"; import api from "../../services/api"
import ButtonWithSpinner from "../ButtonWithSpinner"; import ButtonWithSpinner from "../ButtonWithSpinner"
import ContactModal from "../ContactModal"; import ContactModal from "../ContactModal"
import toastError from "../../errors/toastError"; import toastError from "../../errors/toastError"
import { AuthContext } from "../../context/Auth/AuthContext"; import { AuthContext } from "../../context/Auth/AuthContext"
// const filter = createFilterOptions({ const filter = createFilterOptions({
// trim: true, trim: true,
// }); })
const NewTicketModal = ({ modalOpen, onClose }) => { const NewTicketModal = ({ modalOpen, onClose }) => {
const history = useHistory(); const history = useHistory()
// const [options, setOptions] = useState([]); const [options, setOptions] = useState([])
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false)
const [searchParam, setSearchParam] = useState(""); const [searchParam, setSearchParam] = useState("")
const [selectedContact, setSelectedContact] = useState(null); const [selectedContact, setSelectedContact] = useState(null)
// const [newContact, setNewContact] = useState({}); const [newContact, setNewContact] = useState({})
const [contactModalOpen, setContactModalOpen] = useState(false); const [contactModalOpen, setContactModalOpen] = useState(false)
const { user } = useContext(AuthContext); const { user } = useContext(AuthContext)
useEffect(() => { useEffect(() => {
if (!modalOpen || searchParam.length < 3) {
setLoading(false)
const regex = /^[0-9\b]+$/; // Regular expression to match only numbers return
if (searchParam && !searchParam.match(regex)) return
if (searchParam && searchParam.length > 9) {
setSelectedContact({})
}
else {
setSelectedContact(null)
} }
setLoading(true)
const delayDebounceFn = setTimeout(() => {
const fetchContacts = async () => {
try {
const { data } = await api.get("contacts", {
params: { searchParam },
})
setOptions(data.contacts)
setLoading(false)
} catch (err) {
setLoading(false)
toastError(err)
}
}
if (!modalOpen || searchParam.length < 5) { fetchContacts()
setLoading(false); }, 500)
return; return () => clearTimeout(delayDebounceFn)
} }, [searchParam, modalOpen])
// setLoading(true);
// const delayDebounceFn = setTimeout(() => {
// const fetchContacts = async () => {
// try {
// const { data } = await api.get("contacts", {
// params: { searchParam },
// });
// // console.log('data.contacts: ', data.contacts)
// setOptions(data.contacts);
// setLoading(false);
// } catch (err) {
// setLoading(false);
// toastError(err);
// }
// };
// fetchContacts();
// }, 500);
// return () => clearTimeout(delayDebounceFn);
}, [searchParam, modalOpen]);
const handleClose = () => { const handleClose = () => {
onClose(); onClose()
setSearchParam(""); setSearchParam("")
setSelectedContact(null); setSelectedContact(null)
}; }
const handleSaveTicket = async contactId => { const handleSaveTicket = async contactId => {
if (!contactId) return
setLoading(true)
try { try {
const { data: data0 } = await api.get("/contacts/", { params: { searchParam, pageNumber: "1" }, });
if (data0 && data0.contacts.length > 0) {
console.log('-----> data: ', data0.contacts[0].id)
contactId = data0.contacts[0].id
}
else {
console.log('NO CONTACT whith this searchParam: ', searchParam)
const values = {
name: searchParam,
number: searchParam,
};
const { data: data1 } = await api.post("/contacts", values);
console.log('data1: ', data1)
contactId = data1.id
}
const { data: ticket } = await api.post("/tickets", { const { data: ticket } = await api.post("/tickets", {
contactId: contactId, contactId: contactId,
userId: user.id, userId: user.id,
status: "open", status: "open",
}); })
history.push(`/tickets/${ticket.id}`)
window.location.reload();
history.push(`/tickets/${ticket.id}`);
window.location.reload();
setLoading(false);
handleClose();
} catch (err) { } catch (err) {
setLoading(false); toastError(err)
toastError(err);
} }
setLoading(false)
handleClose()
}
// if (!contactId) return;
// setLoading(true);
// try {
// const { data: ticket } = await api.post("/tickets", {
// contactId: contactId,
// userId: user.id,
// status: "open",
// });
// window.location.reload();
// history.push(`/tickets/${ticket.id}`);
// window.location.reload();
// } catch (err) {
// toastError(err);
// }
};
const handleChange = (number) => {
const regex = /^[0-9\b]+$/; // Regular expression to match only numbers
setSearchParam(number)
setTimeout(() => {
let newValue = ''
for (const char of number) {
// console.log('char: ', char)
if (char.match(regex)) {
newValue += char
}
}
// console.log('newValue: ', newValue)
setSearchParam(newValue)
}, 30);
};
// const handleSelectOption = (e, newValue) => { // const handleSelectOption = (e, newValue) => {
// if (newValue?.number) { // if (newValue?.number) {
// setSelectedContact(newValue)
// console.log('newValue: ', newValue)
// setSelectedContact(newValue);
// } else if (newValue?.name) { // } else if (newValue?.name) {
// setNewContact({ name: newValue.name })
// // console.log('newValue?.name: ', newValue?.name) // setContactModalOpen(true)
// const regex = /^[0-9\b]+$/; // Regular expression to match only numbers
// if (newValue.name.match(regex)) {
// console.log('==========> newValue.name', newValue.name)
// setNewContact({ name: newValue.name, number: newValue.name });
// }
// else {
// setNewContact({ name: newValue.name });
// setContactModalOpen(true);
// }
// } // }
// }; // }
const handleSelectOption = (e, newValue) => {
if (newValue?.number) {
setSelectedContact(newValue)
} else if (newValue?.name) {
if (/^-?\d+(\.\d+)?$/.test(newValue?.name)){
setNewContact({ number: newValue.name })
}
else{
setNewContact({ name: newValue.name })
}
setContactModalOpen(true)
}
}
const handleCloseContactModal = () => { const handleCloseContactModal = () => {
setContactModalOpen(false); setContactModalOpen(false)
}; }
const handleAddNewContactTicket = contact => { const handleAddNewContactTicket = contact => {
handleSaveTicket(contact.id); handleSaveTicket(contact.id)
}; }
// const createAddContactOption = (filterOptions, params) => { const createAddContactOption = (filterOptions, params) => {
// const filtered = filter(filterOptions, params); const filtered = filter(filterOptions, params)
// if (params.inputValue !== "" && !loading && searchParam.length >= 3) { if (params.inputValue !== "" && !loading && searchParam.length >= 3) {
// filtered.push({ filtered.push({
// name: `${params.inputValue}`, name: `${params.inputValue}`,
// }); })
// } }
// return filtered; return filtered
// }; }
// const renderOption = option => { const renderOption = option => {
// if (option.number) { if (option.number) {
// return `${option.name} - ${option.number}`; return `${option.name} - ${option.number}`
// } else { } else {
// return `${i18n.t("newTicketModal.add")} ${option.name}`; return `${i18n.t("newTicketModal.add")} ${option.name}`
// } }
// }; }
// const renderOptionLabel = option => { const renderOptionLabel = option => {
// if (option.number) { if (option.number) {
// return `${option.name} - ${option.number}`; return `${option.name} - ${option.number}`
// } else { } else {
// return `${option.name}`; return `${option.name}`
// } }
// }; }
return ( return (
<> <>
<ContactModal <ContactModal
open={contactModalOpen} open={contactModalOpen}
// initialValues={newContact} initialValues={newContact}
onClose={handleCloseContactModal} onClose={handleCloseContactModal}
onSave={handleAddNewContactTicket} onSave={handleAddNewContactTicket}
></ContactModal> ></ContactModal>
@ -258,29 +156,7 @@ const NewTicketModal = ({ modalOpen, onClose }) => {
<DialogTitle id="form-dialog-title"> <DialogTitle id="form-dialog-title">
{i18n.t("newTicketModal.title")} {i18n.t("newTicketModal.title")}
</DialogTitle> </DialogTitle>
<DialogContent dividers> <DialogContent dividers>
<TextField
label={i18n.t("newTicketModal.fieldLabel")}
variant="outlined"
autoFocus
value={searchParam}
onChange={e => handleChange(e.target.value)}
// onChange={e => setSearchParam(e.target.value)}
onKeyPress={e => {
if (loading || !selectedContact) return;
else if (e.key === "Enter") {
handleSaveTicket(selectedContact.id);
}
}}
/>
</DialogContent>
{/* <DialogContent dividers>
<Autocomplete <Autocomplete
options={options} options={options}
loading={loading} loading={loading}
@ -301,9 +177,9 @@ const NewTicketModal = ({ modalOpen, onClose }) => {
autoFocus autoFocus
onChange={e => setSearchParam(e.target.value)} onChange={e => setSearchParam(e.target.value)}
onKeyPress={e => { onKeyPress={e => {
if (loading || !selectedContact) return; if (loading || !selectedContact) return
else if (e.key === "Enter") { else if (e.key === "Enter") {
handleSaveTicket(selectedContact.id); handleSaveTicket(selectedContact.id)
} }
}} }}
InputProps={{ InputProps={{
@ -320,7 +196,7 @@ const NewTicketModal = ({ modalOpen, onClose }) => {
/> />
)} )}
/> />
</DialogContent> */} </DialogContent>
<DialogActions> <DialogActions>
<Button <Button
onClick={handleClose} onClick={handleClose}
@ -343,7 +219,7 @@ const NewTicketModal = ({ modalOpen, onClose }) => {
</DialogActions> </DialogActions>
</Dialog> </Dialog>
</> </>
); )
}; }
export default NewTicketModal; export default NewTicketModal

View File

@ -105,8 +105,10 @@ const useAuth = () => {
const handleLogout = async () => { const handleLogout = async () => {
setLoading(true); setLoading(true);
console.log('USER: ', user)
try { try {
await api.delete("/auth/logout"); await api.delete(`/auth/logout/${user.id}`);
setIsAuth(false); setIsAuth(false);
setUser({}); setUser({});
localStorage.removeItem("token"); localStorage.removeItem("token");

View File

@ -280,7 +280,7 @@ const messages = {
}, },
newTicketModal: { newTicketModal: {
title: "Criar Ticket", title: "Criar Ticket",
fieldLabel: "Digite o numero para criar um ticket", fieldLabel: "Digite o numero/nome para criar um ticket",
add: "Adicionar", add: "Adicionar",
buttons: { buttons: {
ok: "Salvar", ok: "Salvar",
@ -491,6 +491,7 @@ const messages = {
"A criação do usuário foi desabilitada pelo administrador.", "A criação do usuário foi desabilitada pelo administrador.",
ERR_NO_PERMISSION: "Você não tem permissão para acessar este recurso.", ERR_NO_PERMISSION: "Você não tem permissão para acessar este recurso.",
ERR_DUPLICATED_CONTACT: "Já existe um contato com este número.", ERR_DUPLICATED_CONTACT: "Já existe um contato com este número.",
ERR_NO_ADD_CONTACT: "Não é permitido adicionar um novo contado na agenda.",
ERR_NO_SETTING_FOUND: "Nenhuma configuração encontrada com este ID.", ERR_NO_SETTING_FOUND: "Nenhuma configuração encontrada com este ID.",
ERR_NO_CONTACT_FOUND: "Nenhum contato encontrado com este ID.", ERR_NO_CONTACT_FOUND: "Nenhum contato encontrado com este ID.",
ERR_NO_TICKET_FOUND: "Nenhum tíquete encontrado com este ID.", ERR_NO_TICKET_FOUND: "Nenhum tíquete encontrado com este ID.",