Merge branch 'master' of github.com:AdrianoRobson/projeto-hit
commit
e5dff2a6d5
|
@ -20,12 +20,18 @@ import {
|
||||||
} from "../helpers/ContactsCache";
|
} from "../helpers/ContactsCache";
|
||||||
|
|
||||||
import { off } from "process";
|
import { off } from "process";
|
||||||
|
import GetContactService from "../services/ContactServices/GetContactService"
|
||||||
|
|
||||||
type IndexQuery = {
|
type IndexQuery = {
|
||||||
searchParam: string;
|
searchParam: string;
|
||||||
pageNumber: string;
|
pageNumber: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type IndexGetContactQuery = {
|
||||||
|
name: string;
|
||||||
|
number: string;
|
||||||
|
};
|
||||||
|
|
||||||
interface ExtraInfo {
|
interface ExtraInfo {
|
||||||
name: string;
|
name: string;
|
||||||
value: string;
|
value: string;
|
||||||
|
@ -84,6 +90,20 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
return res.json({ contacts, count, hasMore });
|
return res.json({ contacts, count, hasMore });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getContact = async (
|
||||||
|
req: Request,
|
||||||
|
res: Response
|
||||||
|
): Promise<Response> => {
|
||||||
|
const { name, number } = req.body as IndexGetContactQuery;
|
||||||
|
|
||||||
|
const contact = await GetContactService({
|
||||||
|
name,
|
||||||
|
number
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json(contact);
|
||||||
|
};
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
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(" ", "");
|
||||||
|
|
|
@ -97,7 +97,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = params.find((p: any) => p?.template_name);
|
const name = params.find((p: any) => p?.template_name);
|
||||||
const { language }: any = params.find((p: any) => p?.language);
|
const { language }: any = params?.find((p: any) => p?.language) || 'pt_BR'
|
||||||
|
|
||||||
const { template_name } = name;
|
const { template_name } = name;
|
||||||
|
|
||||||
|
@ -110,9 +110,10 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("TEMPLATE: ", template);
|
||||||
|
|
||||||
sendWhatsAppMessageOfficialAPI(ticket, body, null, template);
|
sendWhatsAppMessageOfficialAPI(ticket, body, null, template);
|
||||||
|
|
||||||
console.log("TEMPLATE: ", template);
|
|
||||||
return res.send();
|
return res.send();
|
||||||
}
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
|
|
|
@ -4,28 +4,19 @@ import { Request, Response } from "express";
|
||||||
import AppError from "../errors/AppError";
|
import AppError from "../errors/AppError";
|
||||||
import ShowTicketReport from "../services/TicketServices/ShowTicketReport";
|
import ShowTicketReport from "../services/TicketServices/ShowTicketReport";
|
||||||
import ShowMessageReport from "../services/MessageServices/ShowMessageReport";
|
import ShowMessageReport from "../services/MessageServices/ShowMessageReport";
|
||||||
|
|
||||||
import onlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService";
|
import onlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService";
|
||||||
import User from "../models/User";
|
import User from "../models/User";
|
||||||
import Queue from "../models/Queue";
|
import Queue from "../models/Queue";
|
||||||
import UserOnlineTime from "../models/UserOnlineTime";
|
import UserOnlineTime from "../models/UserOnlineTime";
|
||||||
|
|
||||||
import { Op, Sequelize, literal } from "sequelize";
|
import { Op, Sequelize, literal } from "sequelize";
|
||||||
import format from 'date-fns/format';
|
import format from "date-fns/format";
|
||||||
import ptBR from 'date-fns/locale/pt-BR';
|
import ptBR from "date-fns/locale/pt-BR";
|
||||||
import { splitDateTime } from "../helpers/SplitDateTime";
|
import { splitDateTime } from "../helpers/SplitDateTime";
|
||||||
import ListUserOnlineOffline from "../services/UserServices/ListUsersOnlineOfflineService";
|
import ListUserOnlineOffline from "../services/UserServices/ListUsersOnlineOfflineService";
|
||||||
import ListUserParamiterService from "../services/UserServices/ListUserParamiterService";
|
import ListUserParamiterService from "../services/UserServices/ListUserParamiterService";
|
||||||
|
|
||||||
import ShowUserServiceReport from "../services/UserServices/ShowUserServiceReport";
|
import ShowUserServiceReport from "../services/UserServices/ShowUserServiceReport";
|
||||||
|
|
||||||
import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue";
|
import CountTicketsByUserQueue from "../services/UserServices/CountTicketsByUserQueue";
|
||||||
|
|
||||||
import ShowQueuesByUser from "../services/UserServices/ShowQueuesByUser";
|
import ShowQueuesByUser from "../services/UserServices/ShowQueuesByUser";
|
||||||
|
|
||||||
|
|
||||||
// import { filter } from "bluebird";
|
|
||||||
|
|
||||||
import { getIO } from "../libs/socket";
|
import { getIO } from "../libs/socket";
|
||||||
import { Json } from "sequelize/types/lib/utils";
|
import { Json } from "sequelize/types/lib/utils";
|
||||||
|
|
||||||
|
@ -33,6 +24,8 @@ type IndexQuery = {
|
||||||
userId: string;
|
userId: string;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
|
createdOrUpdated: string;
|
||||||
|
queueId: string;
|
||||||
pageNumber: string;
|
pageNumber: string;
|
||||||
userQueues: [];
|
userQueues: [];
|
||||||
};
|
};
|
||||||
|
@ -40,11 +33,12 @@ type IndexQuery = {
|
||||||
type ReportOnQueue = {
|
type ReportOnQueue = {
|
||||||
userId: string;
|
userId: string;
|
||||||
identifier: string;
|
identifier: string;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
export const reportUserByDateStartDateEnd = async (req: Request, res: Response): Promise<Response> => {
|
|
||||||
|
|
||||||
|
export const reportUserByDateStartDateEnd = async (
|
||||||
|
req: Request,
|
||||||
|
res: Response
|
||||||
|
): Promise<Response> => {
|
||||||
if (
|
if (
|
||||||
req.user.profile !== "master" &&
|
req.user.profile !== "master" &&
|
||||||
req.user.profile !== "admin" &&
|
req.user.profile !== "admin" &&
|
||||||
|
@ -53,23 +47,55 @@ export const reportUserByDateStartDateEnd = async (req: Request, res: Response):
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { userId, startDate, endDate, pageNumber, userQueues } = req.query as IndexQuery
|
const {
|
||||||
|
userId,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
pageNumber,
|
||||||
|
userQueues,
|
||||||
|
createdOrUpdated,
|
||||||
|
queueId
|
||||||
|
} = req.query as IndexQuery;
|
||||||
|
|
||||||
console.log("userId, startDate, endDate, pageNumber: ", userId, startDate, endDate, pageNumber);
|
console.log(
|
||||||
|
"userId, startDate, endDate, pageNumber, userQueues, createdOrUpdated, queueId: ",
|
||||||
|
userId,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
pageNumber,
|
||||||
|
userQueues,
|
||||||
|
createdOrUpdated,
|
||||||
|
queueId
|
||||||
|
);
|
||||||
|
|
||||||
const { tickets, count, hasMore } = await ShowTicketReport({ userId, startDate, endDate, pageNumber });
|
// return res.status(200).json({ tickets:[], count:0, hasMore:false, queues:[] });
|
||||||
// console.log('kkkkkkkkkkkkkkkkkk tickets: ', JSON.stringify(tickets, null, 6))
|
|
||||||
|
|
||||||
return res.status(200).json({ tickets, count, hasMore });
|
const { tickets, count, hasMore } = await ShowTicketReport({
|
||||||
|
userId,
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
pageNumber,
|
||||||
|
createdOrUpdated,
|
||||||
|
queueId
|
||||||
|
});
|
||||||
|
|
||||||
|
const queues = await Queue.findAll({ attributes: ["id", "name"] });
|
||||||
|
|
||||||
|
return res.status(200).json({ tickets, count, hasMore, queues });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const reportUserService = async (
|
||||||
export const reportUserService = async (req: Request, res: Response): Promise<Response> => {
|
req: Request,
|
||||||
|
res: Response
|
||||||
if (req.user.profile !== "master" && req.user.profile !== "admin" && req.user.profile !=="supervisor") {
|
): Promise<Response> => {
|
||||||
|
if (
|
||||||
|
req.user.profile !== "master" &&
|
||||||
|
req.user.profile !== "admin" &&
|
||||||
|
req.user.profile !== "supervisor"
|
||||||
|
) {
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
const { userId, startDate, endDate } = req.query as IndexQuery
|
const { userId, startDate, endDate } = req.query as IndexQuery;
|
||||||
|
|
||||||
// let usersProfile = await ListUserParamiterService({ profile: 'user' })
|
// let usersProfile = await ListUserParamiterService({ profile: 'user' })
|
||||||
let usersProfile = await ListUserParamiterService({
|
let usersProfile = await ListUserParamiterService({
|
||||||
|
@ -77,55 +103,89 @@ export const reportUserService = async (req: Request, res: Response): Promise<Re
|
||||||
raw: true
|
raw: true
|
||||||
});
|
});
|
||||||
|
|
||||||
const sumUserOlineTime = await ShowUserServiceReport({ startDate, endDate, userId });
|
const sumUserOlineTime = await ShowUserServiceReport({
|
||||||
const closedByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'closed', userId });
|
startDate,
|
||||||
const openByUser = await ShowUserServiceReport({ startDate, endDate, ticketStatus: 'open', userId });
|
endDate,
|
||||||
|
userId
|
||||||
|
});
|
||||||
|
const closedByUser = await ShowUserServiceReport({
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
ticketStatus: "closed",
|
||||||
|
userId
|
||||||
|
});
|
||||||
|
const openByUser = await ShowUserServiceReport({
|
||||||
|
startDate,
|
||||||
|
endDate,
|
||||||
|
ticketStatus: "open",
|
||||||
|
userId
|
||||||
|
});
|
||||||
|
|
||||||
let dateTime = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR })))
|
let dateTime = splitDateTime(
|
||||||
const onlineUsers = await ListUserOnlineOffline({ date: dateTime.fullDate })
|
new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR }))
|
||||||
|
);
|
||||||
|
const onlineUsers = await ListUserOnlineOffline({ date: dateTime.fullDate });
|
||||||
|
|
||||||
const openByUserOnQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'open', clientChatStart: true })
|
const openByUserOnQueue = await CountTicketsByUserQueue({
|
||||||
const openByUserOutQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'open', clientChatStart: false })
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
|
status: "open",
|
||||||
|
clientChatStart: true
|
||||||
|
});
|
||||||
|
const openByUserOutQueue = await CountTicketsByUserQueue({
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
|
status: "open",
|
||||||
|
clientChatStart: false
|
||||||
|
});
|
||||||
|
|
||||||
const closedByUserOnQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'closed', clientChatStart: true })
|
const closedByUserOnQueue = await CountTicketsByUserQueue({
|
||||||
const closedUserOutQueue = await CountTicketsByUserQueue({ startDate: startDate, endDate: endDate, status: 'closed', clientChatStart: false })
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
|
status: "closed",
|
||||||
|
clientChatStart: true
|
||||||
|
});
|
||||||
|
const closedUserOutQueue = await CountTicketsByUserQueue({
|
||||||
|
startDate: startDate,
|
||||||
|
endDate: endDate,
|
||||||
|
status: "closed",
|
||||||
|
clientChatStart: false
|
||||||
|
});
|
||||||
|
|
||||||
// let openQueueInOut = openByUserOnQueue.concat(openByUserOutQueue)
|
// let openQueueInOut = openByUserOnQueue.concat(openByUserOutQueue)
|
||||||
// let closedQueueInOut = closedByUserOnQueue.concat(closedUserOutQueue)
|
// let closedQueueInOut = closedByUserOnQueue.concat(closedUserOutQueue)
|
||||||
|
|
||||||
|
const queuesByUser = await ShowQueuesByUser({ profile: "user" });
|
||||||
|
|
||||||
const queuesByUser = await ShowQueuesByUser({ profile: 'user' })
|
let openCloseOnQueue = openByUserOnQueue.concat(closedByUserOnQueue);
|
||||||
|
let openCloseOutQueue = openByUserOutQueue.concat(closedUserOutQueue);
|
||||||
let openCloseOnQueue = openByUserOnQueue.concat(closedByUserOnQueue)
|
|
||||||
let openCloseOutQueue = openByUserOutQueue.concat(closedUserOutQueue)
|
|
||||||
|
|
||||||
|
|
||||||
// console.log('onlineUsers: ',JSON.parse(JSON.stringify(onlineUsers)))
|
// console.log('onlineUsers: ',JSON.parse(JSON.stringify(onlineUsers)))
|
||||||
// console.log('sumUserOlineTime: ', JSON.parse(JSON.stringify(sumUserOlineTime)))
|
// console.log('sumUserOlineTime: ', JSON.parse(JSON.stringify(sumUserOlineTime)))
|
||||||
|
|
||||||
for (let i = 0; i < queuesByUser.length; i++) {
|
for (let i = 0; i < queuesByUser.length; i++) {
|
||||||
|
queuesByUser[i].countOpen = 0;
|
||||||
queuesByUser[i].countOpen = 0
|
queuesByUser[i].countClosed = 0;
|
||||||
queuesByUser[i].countClosed = 0
|
|
||||||
|
|
||||||
for (let x = 0; x < openCloseOnQueue.length; x++) {
|
for (let x = 0; x < openCloseOnQueue.length; x++) {
|
||||||
if ((queuesByUser[i].userId == openCloseOnQueue[x].userId) &&
|
if (
|
||||||
(queuesByUser[i].queueId == openCloseOnQueue[x].queueId && openCloseOnQueue[x].status == 'open')) {
|
queuesByUser[i].userId == openCloseOnQueue[x].userId &&
|
||||||
queuesByUser[i].countOpen = openCloseOnQueue[x].totAttendance
|
queuesByUser[i].queueId == openCloseOnQueue[x].queueId &&
|
||||||
}
|
openCloseOnQueue[x].status == "open"
|
||||||
else if ((queuesByUser[i].userId == openCloseOnQueue[x].userId) &&
|
) {
|
||||||
(queuesByUser[i].queueId == openCloseOnQueue[x].queueId && openCloseOnQueue[x].status == 'closed')) {
|
queuesByUser[i].countOpen = openCloseOnQueue[x].totAttendance;
|
||||||
queuesByUser[i].countClosed = openCloseOnQueue[x].totAttendance
|
} else if (
|
||||||
}
|
queuesByUser[i].userId == openCloseOnQueue[x].userId &&
|
||||||
|
queuesByUser[i].queueId == openCloseOnQueue[x].queueId &&
|
||||||
|
openCloseOnQueue[x].status == "closed"
|
||||||
|
) {
|
||||||
|
queuesByUser[i].countClosed = openCloseOnQueue[x].totAttendance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
usersProfile.map((user: any) => {
|
usersProfile.map((user: any) => {
|
||||||
|
let index = sumUserOlineTime.findIndex((e: any) => e.userId == user.id);
|
||||||
let index = sumUserOlineTime.findIndex((e: any) => e.userId == user.id)
|
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
user.sumOnlineTime = sumUserOlineTime[index];
|
user.sumOnlineTime = sumUserOlineTime[index];
|
||||||
|
@ -133,68 +193,67 @@ export const reportUserService = async (req: Request, res: Response): Promise<Re
|
||||||
// console.log('user.sumOlineTime: 'user.sumOnlineTime)
|
// console.log('user.sumOlineTime: 'user.sumOnlineTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
index = closedByUser.findIndex((e: any) => e.userId == user.id)
|
index = closedByUser.findIndex((e: any) => e.userId == user.id);
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
user.sumClosed = closedByUser[index];
|
user.sumClosed = closedByUser[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
index = openByUser.findIndex((e: any) => e.userId == user.id)
|
index = openByUser.findIndex((e: any) => e.userId == user.id);
|
||||||
|
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
user.sumOpen = openByUser[index]
|
user.sumOpen = openByUser[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// OPEN, CLOSED TICKETS STARTED BY USERS
|
// OPEN, CLOSED TICKETS STARTED BY USERS
|
||||||
let openClosedOutQueue = {}
|
let openClosedOutQueue = {};
|
||||||
let open = openCloseOutQueue.filter((e) => e.userId == user.id && e.status == 'open')
|
let open = openCloseOutQueue.filter(
|
||||||
let closed = openCloseOutQueue.filter((e) => e.userId == user.id && e.status == 'closed')
|
e => e.userId == user.id && e.status == "open"
|
||||||
|
);
|
||||||
|
let closed = openCloseOutQueue.filter(
|
||||||
|
e => e.userId == user.id && e.status == "closed"
|
||||||
|
);
|
||||||
|
|
||||||
openClosedOutQueue = {
|
openClosedOutQueue = {
|
||||||
...openClosedOutQueue,
|
...openClosedOutQueue,
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
countOpen: open && open.length > 0 ? open[0].totAttendance : 0,
|
countOpen: open && open.length > 0 ? open[0].totAttendance : 0,
|
||||||
countClosed: closed && closed.length > 0 ? closed[0].totAttendance : 0
|
countClosed: closed && closed.length > 0 ? closed[0].totAttendance : 0
|
||||||
}
|
|
||||||
|
|
||||||
user.openClosedOutQueue = openClosedOutQueue
|
|
||||||
|
|
||||||
|
|
||||||
// OPEN, CLOSED TICKETS STARTED BY CLIENTS
|
|
||||||
let openClosedInQueue = queuesByUser.filter((e) => e.userId == user.id)
|
|
||||||
|
|
||||||
if (openClosedInQueue && openClosedInQueue.length > 0) {
|
|
||||||
user.openClosedInQueue = openClosedInQueue
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
index = onlineUsers.findIndex((e: any) => e.userId == user.id)
|
|
||||||
|
|
||||||
if (index != -1) {
|
|
||||||
user.statusOnline = onlineUsers[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startDate.length > 0 && startDate.split('-').length == 3) {
|
|
||||||
let date = startDate.split('-')
|
|
||||||
user.startDate = `${date[2]}/${date[1]}/${date[0]}`
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endDate.length > 0 && endDate.split('-').length == 3) {
|
|
||||||
let date = endDate.split('-')
|
|
||||||
user.endDate = `${date[2]}/${date[1]}/${date[0]}`
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
return res.status(200).json({usersProfile: usersProfile});
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
user.openClosedOutQueue = openClosedOutQueue;
|
||||||
|
|
||||||
|
// OPEN, CLOSED TICKETS STARTED BY CLIENTS
|
||||||
|
let openClosedInQueue = queuesByUser.filter(e => e.userId == user.id);
|
||||||
|
|
||||||
export const reportMessagesUserByDateStartDateEnd = async (req: Request, res: Response): Promise<Response> => {
|
if (openClosedInQueue && openClosedInQueue.length > 0) {
|
||||||
|
user.openClosedInQueue = openClosedInQueue;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = onlineUsers.findIndex((e: any) => e.userId == user.id);
|
||||||
|
|
||||||
|
if (index != -1) {
|
||||||
|
user.statusOnline = onlineUsers[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startDate.length > 0 && startDate.split("-").length == 3) {
|
||||||
|
let date = startDate.split("-");
|
||||||
|
user.startDate = `${date[2]}/${date[1]}/${date[0]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endDate.length > 0 && endDate.split("-").length == 3) {
|
||||||
|
let date = endDate.split("-");
|
||||||
|
user.endDate = `${date[2]}/${date[1]}/${date[0]}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return res.status(200).json({ usersProfile: usersProfile });
|
||||||
|
};
|
||||||
|
|
||||||
|
export const reportMessagesUserByDateStartDateEnd = async (
|
||||||
|
req: Request,
|
||||||
|
res: Response
|
||||||
|
): Promise<Response> => {
|
||||||
if (
|
if (
|
||||||
req.user.profile !== "master" &&
|
req.user.profile !== "master" &&
|
||||||
req.user.profile !== "admin" &&
|
req.user.profile !== "admin" &&
|
||||||
|
@ -203,35 +262,32 @@ export const reportMessagesUserByDateStartDateEnd = async (req: Request, res: Re
|
||||||
throw new AppError("ERR_NO_PERMISSION", 403);
|
throw new AppError("ERR_NO_PERMISSION", 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { userId, startDate, endDate } = req.query as IndexQuery
|
const { userId, startDate, endDate } = req.query as IndexQuery;
|
||||||
|
|
||||||
let data_query_messages = await ShowMessageReport(userId, startDate, endDate);
|
let data_query_messages = await ShowMessageReport(userId, startDate, endDate);
|
||||||
|
|
||||||
for (var i = 0; i < data_query_messages.length; i++) {
|
for (var i = 0; i < data_query_messages.length; i++) {
|
||||||
|
|
||||||
if (data_query_messages[i].fromMe) {
|
if (data_query_messages[i].fromMe) {
|
||||||
data_query_messages[i].fromMe = 'Atendente'
|
data_query_messages[i].fromMe = "Atendente";
|
||||||
}
|
} else {
|
||||||
else {
|
data_query_messages[i].fromMe = "Cliente";
|
||||||
data_query_messages[i].fromMe = 'Cliente'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
data_query_messages[i].id = (i + 1)
|
data_query_messages[i].id = i + 1;
|
||||||
|
|
||||||
console.log('data_query_messages: ', data_query_messages[i])
|
console.log("data_query_messages: ", data_query_messages[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json(data_query_messages);
|
return res.status(200).json(data_query_messages);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const reportOnQueue = async (
|
||||||
|
req: Request,
|
||||||
export const reportOnQueue = async (req: Request, res: Response): Promise<Response> => {
|
res: Response
|
||||||
|
): Promise<Response> => {
|
||||||
// console.log(req.body)
|
// console.log(req.body)
|
||||||
|
|
||||||
const { adminId, identifier, queueStatus, file } = req.body
|
const { adminId, identifier, queueStatus, file } = req.body;
|
||||||
|
|
||||||
const io = getIO();
|
const io = getIO();
|
||||||
io.emit("queryOnQueueStatus", {
|
io.emit("queryOnQueueStatus", {
|
||||||
|
@ -244,10 +300,5 @@ export const reportOnQueue = async (req: Request, res: Response): Promise<Respon
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).json({ message: 'ok' })
|
return res.status(200).json({ message: "ok" });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -120,12 +120,21 @@ export const remoteTicketCreation = async (
|
||||||
const { contact_from, contact_to, msg, contact_name }: any = req.body;
|
const { contact_from, contact_to, msg, contact_name }: any = req.body;
|
||||||
|
|
||||||
const validate = ["contact_from", "contact_to", "msg"];
|
const validate = ["contact_from", "contact_to", "msg"];
|
||||||
|
const validateOnlyNumber = ["contact_from", "contact_to"];
|
||||||
|
|
||||||
for (let prop of validate) {
|
for (let prop of validate) {
|
||||||
if (!req.body[prop])
|
if (!req.body[prop])
|
||||||
return res
|
return res
|
||||||
.status(400)
|
.status(400)
|
||||||
.json({ error: `Property '${prop}' is undefined.` });
|
.json({ error: `Property '${prop}' is undefined.` });
|
||||||
|
|
||||||
|
if (validateOnlyNumber.includes(prop)) {
|
||||||
|
if (!/^\d+$/.test(req.body[prop])) {
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.json({ error: `The property '${prop}' must be a number` });
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const whatsapp = await Whatsapp.findOne({
|
const whatsapp = await Whatsapp.findOne({
|
||||||
|
@ -226,11 +235,11 @@ export const remoteTicketCreation = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected`
|
`REMOTE TICKET CREATION FROM ENDPOINT | STATUS: 500 | MSG: Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit`
|
||||||
);
|
);
|
||||||
return res
|
return res.status(500).json({
|
||||||
.status(500)
|
msg: `Whatsapp number ${contact_from} disconnected or it doesn't exist in omnihit`
|
||||||
.json({ msg: `Whatsapp number ${contact_from} disconnected` });
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
|
@ -99,7 +99,7 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// };
|
// };
|
||||||
|
|
||||||
export const all = async (req: Request, res: Response): Promise<Response> => {
|
export const all = async (req: Request, res: Response): Promise<Response> => {
|
||||||
const { userId, profile } = req.query as IndexQuery;
|
let { userId, profile }: any = req.query as IndexQuery;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
"userId: ",
|
"userId: ",
|
||||||
|
@ -111,6 +111,9 @@ export const all = async (req: Request, res: Response): Promise<Response> => {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") {
|
if (getSettingValue("queueTransferByWhatsappScope")?.value == "enabled") {
|
||||||
|
|
||||||
|
if (!userId) return res.json({ users: [], queues: [] });
|
||||||
|
|
||||||
const obj = await ListUserByWhatsappQueuesService(
|
const obj = await ListUserByWhatsappQueuesService(
|
||||||
userId,
|
userId,
|
||||||
'"admin", "user", "supervisor"'
|
'"admin", "user", "supervisor"'
|
||||||
|
|
|
@ -54,6 +54,7 @@ interface WhatsappData {
|
||||||
isDefault?: boolean;
|
isDefault?: boolean;
|
||||||
isOfficial?: boolean;
|
isOfficial?: boolean;
|
||||||
phoneNumberId?: string;
|
phoneNumberId?: string;
|
||||||
|
number?: string;
|
||||||
wabaId?: string;
|
wabaId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,7 +323,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
urlApi,
|
urlApi,
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId,
|
wabaId,
|
||||||
isOfficial
|
isOfficial,
|
||||||
|
number
|
||||||
}: WhatsappData = req.body;
|
}: WhatsappData = req.body;
|
||||||
|
|
||||||
if (req.user.profile !== "master") {
|
if (req.user.profile !== "master") {
|
||||||
|
@ -333,7 +335,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
urlApi,
|
urlApi,
|
||||||
isOfficial,
|
isOfficial,
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId
|
wabaId,
|
||||||
|
number
|
||||||
});
|
});
|
||||||
|
|
||||||
if (invalid) {
|
if (invalid) {
|
||||||
|
@ -346,6 +349,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
} else if (!isOfficial) {
|
} else if (!isOfficial) {
|
||||||
phoneNumberId = "";
|
phoneNumberId = "";
|
||||||
wabaId = "";
|
wabaId = "";
|
||||||
|
number = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
let invalidPhoneName = validatePhoneName(name);
|
let invalidPhoneName = validatePhoneName(name);
|
||||||
|
@ -365,7 +369,8 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||||
queueIds,
|
queueIds,
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId,
|
wabaId,
|
||||||
isOfficial
|
isOfficial,
|
||||||
|
number
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("whatsapp.id: ", whatsapp.id);
|
console.log("whatsapp.id: ", whatsapp.id);
|
||||||
|
@ -549,18 +554,22 @@ interface WhatsappDataValidate {
|
||||||
isOfficial?: boolean;
|
isOfficial?: boolean;
|
||||||
phoneNumberId?: string;
|
phoneNumberId?: string;
|
||||||
wabaId?: string;
|
wabaId?: string;
|
||||||
|
number?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkWhatsAppData = ({
|
const checkWhatsAppData = ({
|
||||||
urlApi,
|
urlApi,
|
||||||
isOfficial,
|
isOfficial,
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId
|
wabaId,
|
||||||
|
number
|
||||||
}: WhatsappDataValidate) => {
|
}: WhatsappDataValidate) => {
|
||||||
if (isOfficial && (!phoneNumberId || phoneNumberId.trim() == "")) {
|
if (isOfficial && (!phoneNumberId || phoneNumberId.trim() == "")) {
|
||||||
return { message: "Phone number Id is required!" };
|
return { message: "Phone number Id is required!" };
|
||||||
} else if (isOfficial && (!wabaId || wabaId.trim() == "")) {
|
} else if (isOfficial && (!wabaId || wabaId.trim() == "")) {
|
||||||
return { message: "WABA ID is required!" };
|
return { message: "WABA ID is required!" };
|
||||||
|
} else if (isOfficial && (!number || number.trim() == "")) {
|
||||||
|
return { message: "Phone number is required!" };
|
||||||
} else if (!isOfficial && (!urlApi || urlApi.trim() == "")) {
|
} else if (!isOfficial && (!urlApi || urlApi.trim() == "")) {
|
||||||
return { message: "urlApi is required!" };
|
return { message: "urlApi is required!" };
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ const CheckContactOpenTickets = async (
|
||||||
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") {
|
||||||
let whats = await ListWhatsAppsNumber(whatsappId);
|
let whats = await ListWhatsAppsNumber(whatsappId);
|
||||||
|
|
||||||
console.log("contactId: ", contactId, " | whatsappId: ", whatsappId);
|
// console.log("contactId: ", contactId, " | whatsappId: ", whatsappId);
|
||||||
|
|
||||||
console.log("WHATS: ", JSON.stringify(whats, null, 6));
|
// console.log("WHATS: ", JSON.stringify(whats, null, 6));
|
||||||
|
|
||||||
ticket = await Ticket.findOne({
|
ticket = await Ticket.findOne({
|
||||||
where: {
|
where: {
|
||||||
|
|
|
@ -17,6 +17,18 @@ export async function get(key: string) {
|
||||||
return JSON.parse(value);
|
return JSON.parse(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function clearAllKeys() {
|
||||||
|
// Retrieve all keys matching the pattern '*'
|
||||||
|
const keys = await redis.keys("user:*");
|
||||||
|
|
||||||
|
// If there are keys, delete them
|
||||||
|
if (keys.length > 0) {
|
||||||
|
console.log('keys: ', keys)
|
||||||
|
await redis.del(...keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function findByContain(
|
export async function findByContain(
|
||||||
key: string,
|
key: string,
|
||||||
keyName: string,
|
keyName: string,
|
||||||
|
|
|
@ -16,6 +16,8 @@ contactRoutes.get("/contacts/:contactId", isAuth, ContactController.show);
|
||||||
|
|
||||||
contactRoutes.post("/contacts", isAuth, ContactController.store);
|
contactRoutes.post("/contacts", isAuth, ContactController.store);
|
||||||
|
|
||||||
|
contactRoutes.post("/contact", isAuth, ContactController.getContact);
|
||||||
|
|
||||||
contactRoutes.put("/contacts/:contactId", isAuth, ContactController.update);
|
contactRoutes.put("/contacts/:contactId", isAuth, ContactController.update);
|
||||||
|
|
||||||
contactRoutes.delete("/contacts/:contactId", isAuth, ContactController.remove);
|
contactRoutes.delete("/contacts/:contactId", isAuth, ContactController.remove);
|
||||||
|
|
|
@ -5,7 +5,6 @@ import * as TicketController from "../controllers/TicketController";
|
||||||
|
|
||||||
const ticketRoutes = express.Router();
|
const ticketRoutes = express.Router();
|
||||||
|
|
||||||
|
|
||||||
// ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache);
|
// ticketRoutes.get("/tickets/cache", isAuth, TicketController.ticketsCache);
|
||||||
|
|
||||||
ticketRoutes.get("/tickets/count", isAuth, TicketController.count);
|
ticketRoutes.get("/tickets/count", isAuth, TicketController.count);
|
||||||
|
|
|
@ -23,7 +23,7 @@ import fs from "fs";
|
||||||
import dir from "path";
|
import dir from "path";
|
||||||
import { getSettingValue } from "./helpers/WhaticketSettings";
|
import { getSettingValue } from "./helpers/WhaticketSettings";
|
||||||
import loadSettings from "./helpers/LoadSettings";
|
import loadSettings from "./helpers/LoadSettings";
|
||||||
import { set } from "./helpers/RedisClient";
|
import { clearAllKeys, set } from "./helpers/RedisClient";
|
||||||
|
|
||||||
const server = app.listen(process.env.PORT, () => {
|
const server = app.listen(process.env.PORT, () => {
|
||||||
logger.info(`Server started on port: ${process.env.PORT}`);
|
logger.info(`Server started on port: ${process.env.PORT}`);
|
||||||
|
@ -44,6 +44,8 @@ gracefulShutdown(server);
|
||||||
(async () => {
|
(async () => {
|
||||||
console.log("os.tmpdir(): ", os.tmpdir());
|
console.log("os.tmpdir(): ", os.tmpdir());
|
||||||
|
|
||||||
|
await clearAllKeys();
|
||||||
|
|
||||||
const users = await User.findAll();
|
const users = await User.findAll();
|
||||||
|
|
||||||
for (const user of users) {
|
for (const user of users) {
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
import AppError from "../../errors/AppError";
|
||||||
|
import Contact from "../../models/Contact";
|
||||||
|
import CreateContactService from "./CreateContactService";
|
||||||
|
|
||||||
|
interface ExtraInfo {
|
||||||
|
name: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Request {
|
||||||
|
name: string;
|
||||||
|
number: string;
|
||||||
|
email?: string;
|
||||||
|
profilePicUrl?: string;
|
||||||
|
extraInfo?: ExtraInfo[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const GetContactService = async ({ name, number }: Request): Promise<Contact> => {
|
||||||
|
const numberExists = await Contact.findOne({
|
||||||
|
where: { number }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!numberExists) {
|
||||||
|
const contact = await CreateContactService({
|
||||||
|
name,
|
||||||
|
number,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (contact == null)
|
||||||
|
throw new AppError("CONTACT_NOT_FIND")
|
||||||
|
else
|
||||||
|
return contact
|
||||||
|
}
|
||||||
|
|
||||||
|
return numberExists
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GetContactService;
|
|
@ -61,11 +61,6 @@ const ListTicketsService = async ({
|
||||||
|
|
||||||
console.log('PAGE NUMBER TICKET: ', pageNumber)
|
console.log('PAGE NUMBER TICKET: ', pageNumber)
|
||||||
|
|
||||||
//TEST DEL
|
|
||||||
// const url = await getWbot(46)
|
|
||||||
// console.log('---------> URL: ', url)
|
|
||||||
//
|
|
||||||
|
|
||||||
if (pageNumber.trim().length == 0) {
|
if (pageNumber.trim().length == 0) {
|
||||||
pageNumber = '1'
|
pageNumber = '1'
|
||||||
}
|
}
|
||||||
|
@ -136,15 +131,14 @@ const ListTicketsService = async ({
|
||||||
whereCondition = { ...whereCondition, status };
|
whereCondition = { ...whereCondition, status };
|
||||||
|
|
||||||
|
|
||||||
if (unlimited === 'true' && status !== 'pending') {
|
if (unlimited === "current" && status !== "pending") {
|
||||||
|
|
||||||
whereCondition = {
|
whereCondition = {
|
||||||
...whereCondition,
|
...whereCondition,
|
||||||
createdAt: {
|
createdAt: {
|
||||||
[Op.gte]: dateToday.fullDate + ' 00:00:00.000000',
|
[Op.gte]: dateToday.fullDate + " 00:00:00.000000",
|
||||||
[Op.lte]: dateToday.fullDate + ' 23:59:59.999999'
|
[Op.lte]: dateToday.fullDate + " 23:59:59.999999"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -196,8 +190,8 @@ const ListTicketsService = async ({
|
||||||
|
|
||||||
if (
|
if (
|
||||||
userProfile.dataValues.profile != "admin" &&
|
userProfile.dataValues.profile != "admin" &&
|
||||||
userProfile.dataValues.profile != "master"
|
userProfile.dataValues.profile != "master" &&
|
||||||
// userProfile.dataValues.profile != "supervisor"
|
userProfile.dataValues.profile != "supervisor"
|
||||||
) {
|
) {
|
||||||
whereCondition = { ...whereCondition, userId };
|
whereCondition = { ...whereCondition, userId };
|
||||||
}
|
}
|
||||||
|
@ -224,9 +218,10 @@ const ListTicketsService = async ({
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const limit = unlimited === 'true' ? 100000 : 40;
|
const limit = unlimited === "current" || unlimited === "all" ? 100000 : 40;
|
||||||
const offset = limit * (+pageNumber - 1);
|
const offset = limit * (+pageNumber - 1);
|
||||||
|
|
||||||
|
console.log("kkkkkkkkk limit: ", limit);
|
||||||
|
|
||||||
const { count, rows: tickets } = await Ticket.findAndCountAll({
|
const { count, rows: tickets } = await Ticket.findAndCountAll({
|
||||||
where: whereCondition,
|
where: whereCondition,
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { userInfo } from "os";
|
||||||
import { Op, where } from "sequelize";
|
import { Op, where } from "sequelize";
|
||||||
|
|
||||||
import { Sequelize } from "sequelize";
|
import { Sequelize } from "sequelize";
|
||||||
import moment from 'moment';
|
import moment from "moment";
|
||||||
|
|
||||||
import { startOfDay, endOfDay, parseISO, getDate } from "date-fns";
|
import { startOfDay, endOfDay, parseISO, getDate } from "date-fns";
|
||||||
import { string } from "yup/lib/locale";
|
import { string } from "yup/lib/locale";
|
||||||
|
@ -20,10 +20,11 @@ interface Request {
|
||||||
userId: string | number;
|
userId: string | number;
|
||||||
startDate: string;
|
startDate: string;
|
||||||
endDate: string;
|
endDate: string;
|
||||||
|
createdOrUpdated?: string;
|
||||||
|
queueId?: string;
|
||||||
pageNumber?: string;
|
pageNumber?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Response {
|
interface Response {
|
||||||
tickets: Ticket[];
|
tickets: Ticket[];
|
||||||
count: number;
|
count: number;
|
||||||
|
@ -35,84 +36,119 @@ const ShowTicketReport = async ({
|
||||||
userId,
|
userId,
|
||||||
startDate,
|
startDate,
|
||||||
endDate,
|
endDate,
|
||||||
pageNumber = "1"
|
pageNumber = "1",
|
||||||
|
createdOrUpdated = "created",
|
||||||
|
queueId
|
||||||
}: Request): Promise<Response> => {
|
}: Request): Promise<Response> => {
|
||||||
|
let where_clause: any = {};
|
||||||
|
// let where_clause_msg: any = {};
|
||||||
|
|
||||||
let where_clause = {}
|
if (userId !== "0") {
|
||||||
|
where_clause.userid = userId;
|
||||||
|
}
|
||||||
|
|
||||||
if(userId=='0'){
|
if (createdOrUpdated === "updated") {
|
||||||
where_clause = {
|
where_clause = {
|
||||||
|
...where_clause,
|
||||||
updatedAt: {
|
updatedAt: {
|
||||||
[Op.gte]: startDate+' 00:00:00.000000',
|
[Op.gte]: startDate + " 00:00:00.000000",
|
||||||
[Op.lte]: endDate +' 23:59:59.999999'
|
[Op.lte]: endDate + " 23:59:59.999999"
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
where_clause = {
|
|
||||||
userid: userId,
|
|
||||||
updatedAt: {
|
|
||||||
[Op.gte]: startDate+' 00:00:00.000000',
|
|
||||||
[Op.lte]: endDate +' 23:59:59.999999'
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (createdOrUpdated === "created") {
|
||||||
|
where_clause = {
|
||||||
|
...where_clause,
|
||||||
|
createdAt: {
|
||||||
|
[Op.gte]: startDate + " 00:00:00.000000",
|
||||||
|
[Op.lte]: endDate + " 23:59:59.999999"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let { userid, ...where_clause_msg } = where_clause;
|
||||||
|
|
||||||
|
if (queueId) {
|
||||||
|
where_clause.queueId = queueId;
|
||||||
|
}
|
||||||
|
|
||||||
const limit = 40;
|
const limit = 40;
|
||||||
const offset = limit * (+pageNumber - 1);
|
const offset = limit * (+pageNumber - 1);
|
||||||
|
|
||||||
const { count, rows: tickets } = await Ticket.findAndCountAll({
|
const { count, rows: tickets } = await Ticket.findAndCountAll({
|
||||||
|
|
||||||
where: where_clause,
|
where: where_clause,
|
||||||
limit,
|
limit,
|
||||||
offset,
|
offset,
|
||||||
//attributes: ['id', 'status', 'createdAt', 'updatedAt'],
|
|
||||||
|
|
||||||
attributes: ['id', 'status', 'statusChatEnd', [Sequelize.fn("DATE_FORMAT",Sequelize.col("Ticket.createdAt"),"%d/%m/%Y %H:%i:%s"),"createdAt"],
|
attributes: [
|
||||||
[Sequelize.fn("DATE_FORMAT",Sequelize.col("Ticket.updatedAt"),"%d/%m/%Y %H:%i:%s"),"updatedAt"]],
|
"id",
|
||||||
|
"status",
|
||||||
|
"statusChatEnd",
|
||||||
|
[
|
||||||
|
Sequelize.fn(
|
||||||
|
"DATE_FORMAT",
|
||||||
|
Sequelize.col("Ticket.createdAt"),
|
||||||
|
"%d/%m/%Y %H:%i:%s"
|
||||||
|
),
|
||||||
|
"createdAt"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
Sequelize.fn(
|
||||||
|
"DATE_FORMAT",
|
||||||
|
Sequelize.col("Ticket.updatedAt"),
|
||||||
|
"%d/%m/%Y %H:%i:%s"
|
||||||
|
),
|
||||||
|
"updatedAt"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Message,
|
model: Message,
|
||||||
required: true,
|
required: true,
|
||||||
separate: true,
|
separate: true,
|
||||||
|
where: where_clause_msg ,
|
||||||
|
|
||||||
// attributes: ['body', 'read', 'mediaType','fromMe', 'mediaUrl','createdAt'],
|
attributes: [
|
||||||
|
"body",
|
||||||
attributes: ['body', 'read', 'mediaType','fromMe', 'mediaUrl', [Sequelize.fn("DATE_FORMAT",Sequelize.col("createdAt"),"%d/%m/%Y %H:%i:%s"),"createdAt"]],
|
"read",
|
||||||
|
"mediaType",
|
||||||
order: [
|
"fromMe",
|
||||||
['createdAt', 'ASC']
|
"mediaUrl",
|
||||||
|
[
|
||||||
|
Sequelize.fn(
|
||||||
|
"DATE_FORMAT",
|
||||||
|
Sequelize.col("createdAt"),
|
||||||
|
"%d/%m/%Y %H:%i:%s"
|
||||||
|
),
|
||||||
|
"createdAt"
|
||||||
]
|
]
|
||||||
|
],
|
||||||
|
order: [["createdAt", "ASC"]]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: Contact,
|
model: Contact,
|
||||||
attributes: ['name', 'number']
|
attributes: ["name", "number"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: User,
|
model: User,
|
||||||
attributes: ['name', 'email']
|
attributes: ["name", "email"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: Queue,
|
model: Queue,
|
||||||
attributes: ['name']
|
attributes: ["name"]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
model: Whatsapp,
|
model: Whatsapp,
|
||||||
attributes: ['name']
|
attributes: ["name"]
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
|
order: [["updatedAt", "DESC"]]
|
||||||
order: [
|
|
||||||
['id', 'ASC']
|
|
||||||
]
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const hasMore = count > offset + tickets.length;
|
const hasMore = count > offset + tickets.length;
|
||||||
|
|
||||||
|
|
||||||
if (!tickets) {
|
if (!tickets) {
|
||||||
throw new AppError("ERR_NO_TICKET_FOUND", 404);
|
throw new AppError("ERR_NO_TICKET_FOUND", 404);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Op, Sequelize } from "sequelize";
|
||||||
import Queue from "../../models/Queue";
|
import Queue from "../../models/Queue";
|
||||||
import User from "../../models/User";
|
import User from "../../models/User";
|
||||||
import UserQueue from "../../models/UserQueue";
|
import UserQueue from "../../models/UserQueue";
|
||||||
import { List } from "whatsapp-web.js"
|
import { List } from "whatsapp-web.js";
|
||||||
|
|
||||||
interface Request {
|
interface Request {
|
||||||
userId?: string | number;
|
userId?: string | number;
|
||||||
|
@ -12,7 +12,13 @@ interface Request {
|
||||||
userIds?: string | number;
|
userIds?: string | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListUser = async ({ profile, userId, raw, userIds, profiles }: Request): Promise<User[]> => {
|
const ListUser = async ({
|
||||||
|
profile,
|
||||||
|
userId,
|
||||||
|
raw,
|
||||||
|
userIds,
|
||||||
|
profiles
|
||||||
|
}: Request): Promise<User[]> => {
|
||||||
let where_clause = {};
|
let where_clause = {};
|
||||||
|
|
||||||
if (userId && profile) {
|
if (userId && profile) {
|
||||||
|
@ -47,7 +53,7 @@ const ListUser = async ({ profile, userId, raw, userIds, profiles }: Request): P
|
||||||
],
|
],
|
||||||
|
|
||||||
order: [["id", "ASC"]],
|
order: [["id", "ASC"]],
|
||||||
group: ["User.id"]
|
group: userIds ? undefined : ["User.id"]
|
||||||
});
|
});
|
||||||
|
|
||||||
return users;
|
return users;
|
||||||
|
|
|
@ -98,6 +98,7 @@ import FindOrCreateTicketServiceBot from "../TicketServices/FindOrCreateTicketSe
|
||||||
import ShowTicketService from "../TicketServices/ShowTicketService";
|
import ShowTicketService from "../TicketServices/ShowTicketService";
|
||||||
import ShowQueuesByUser from "../UserServices/ShowQueuesByUser";
|
import ShowQueuesByUser from "../UserServices/ShowQueuesByUser";
|
||||||
import ListWhatsappQueuesByUserQueue from "../UserServices/ListWhatsappQueuesByUserQueue";
|
import ListWhatsappQueuesByUserQueue from "../UserServices/ListWhatsappQueuesByUserQueue";
|
||||||
|
import CreateContactService from "../ContactServices/CreateContactService"
|
||||||
|
|
||||||
var lst: any[] = getWhatsappIds();
|
var lst: any[] = getWhatsappIds();
|
||||||
|
|
||||||
|
@ -479,6 +480,7 @@ const isValidMsg = (msg: any): boolean => {
|
||||||
msg.type === "image" ||
|
msg.type === "image" ||
|
||||||
msg.type === "document" ||
|
msg.type === "document" ||
|
||||||
msg.type === "vcard" ||
|
msg.type === "vcard" ||
|
||||||
|
// msg.type === "multi_vcard" ||
|
||||||
msg.type === "sticker"
|
msg.type === "sticker"
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
|
@ -497,7 +499,12 @@ const queuesOutBot = async (wbot: Session, botId: string | number) => {
|
||||||
return { queues, greetingMessage };
|
return { queues, greetingMessage };
|
||||||
};
|
};
|
||||||
|
|
||||||
const transferTicket = async (queueName: any, wbot: any, ticket: Ticket) => {
|
const transferTicket = async (
|
||||||
|
queueName: any,
|
||||||
|
wbot: any,
|
||||||
|
ticket: Ticket,
|
||||||
|
sendGreetingMessage?: boolean
|
||||||
|
) => {
|
||||||
const botInfo = await BotIsOnQueue("botqueue");
|
const botInfo = await BotIsOnQueue("botqueue");
|
||||||
|
|
||||||
console.log("kkkkkkkkkkkkkkkkkkkkk queueName: ", queueName);
|
console.log("kkkkkkkkkkkkkkkkkkkkk queueName: ", queueName);
|
||||||
|
@ -519,16 +526,24 @@ const transferTicket = async (queueName: any, wbot: any, ticket: Ticket) => {
|
||||||
queue = queues[queueName];
|
queue = queues[queueName];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queue) await botTransferTicket(queue, ticket);
|
if (queue) await botTransferTicket(queue, ticket, sendGreetingMessage);
|
||||||
};
|
};
|
||||||
|
|
||||||
const botTransferTicket = async (queues: Queue, ticket: Ticket) => {
|
const botTransferTicket = async (
|
||||||
|
queues: Queue,
|
||||||
|
ticket: Ticket,
|
||||||
|
sendGreetingMessage?: boolean
|
||||||
|
) => {
|
||||||
await ticket.update({ userId: null });
|
await ticket.update({ userId: null });
|
||||||
|
|
||||||
await UpdateTicketService({
|
await UpdateTicketService({
|
||||||
ticketData: { status: "pending", queueId: queues.id },
|
ticketData: { status: "pending", queueId: queues.id },
|
||||||
ticketId: ticket.id
|
ticketId: ticket.id
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (sendGreetingMessage && queues?.greetingMessage?.length > 0) {
|
||||||
|
botSendMessage(ticket, queues.greetingMessage);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const botTransferTicketToUser = async (
|
const botTransferTicketToUser = async (
|
||||||
|
@ -630,7 +645,13 @@ const handleMessage = async (
|
||||||
// media messages sent from me from cell phone, first comes with "hasMedia = false" and type = "image/ptt/etc"
|
// media messages sent from me from cell phone, first comes with "hasMedia = false" and type = "image/ptt/etc"
|
||||||
// in this case, return and let this message be handled by "media_uploaded" event, when it will have "hasMedia = true"
|
// in this case, return and let this message be handled by "media_uploaded" event, when it will have "hasMedia = true"
|
||||||
|
|
||||||
if (!msg.hasMedia && msg.type !== "chat" && msg.type !== "vcard") return;
|
if (
|
||||||
|
!msg.hasMedia &&
|
||||||
|
msg.type !== "chat" &&
|
||||||
|
msg.type !== "vcard" &&
|
||||||
|
msg.type !== "multi_vcard"
|
||||||
|
)
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
console.log(`\n <<<<<<<<<< RECEIVING MESSAGE:
|
console.log(`\n <<<<<<<<<< RECEIVING MESSAGE:
|
||||||
Parcial msg and msgContact info:
|
Parcial msg and msgContact info:
|
||||||
|
@ -759,12 +780,54 @@ const handleMessage = async (
|
||||||
await verifyQueue(wbot, msg, ticket, contact);
|
await verifyQueue(wbot, msg, ticket, contact);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (msg.type === "vcard") {
|
||||||
|
try {
|
||||||
|
const array = msg.body.split("\n");
|
||||||
|
const obj = [];
|
||||||
|
let contact = "";
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
const v = array[index];
|
||||||
|
const values = v.split(":");
|
||||||
|
for (let ind = 0; ind < values.length; ind++) {
|
||||||
|
if (values[ind].indexOf("+") !== -1) {
|
||||||
|
obj.push({ number: values[ind] });
|
||||||
|
}
|
||||||
|
if (values[ind].indexOf("FN") !== -1) {
|
||||||
|
contact = values[ind + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for await (const ob of obj) {
|
||||||
|
const cont = await CreateContactService({
|
||||||
|
name: contact,
|
||||||
|
number: ob.number.replace(/\D/g, "")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const botInfo = await BotIsOnQueue("botqueue");
|
||||||
|
|
||||||
// Transfer to agent
|
// Transfer to agent
|
||||||
if (!msg.fromMe) {
|
// O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente
|
||||||
|
if (
|
||||||
|
!msg.fromMe &&
|
||||||
|
((ticket.status == "open" &&
|
||||||
|
botInfo &&
|
||||||
|
ticket.userId == +botInfo.userIdBot) ||
|
||||||
|
ticket.status == "pending" ||
|
||||||
|
ticket.status == "queueChoice")
|
||||||
|
) {
|
||||||
const filteredUsers = await findByContain("user:*", "name", msg?.body);
|
const filteredUsers = await findByContain("user:*", "name", msg?.body);
|
||||||
|
|
||||||
|
|
||||||
if (filteredUsers && filteredUsers.length > 0) {
|
if (filteredUsers && filteredUsers.length > 0) {
|
||||||
|
if (botInfo.isOnQueue) {
|
||||||
|
transferTicket(filteredUsers[0].name, wbot, ticket, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const whatsappQueues = await ListWhatsappQueuesByUserQueue(
|
const whatsappQueues = await ListWhatsappQueuesByUserQueue(
|
||||||
+filteredUsers[0].id
|
+filteredUsers[0].id
|
||||||
);
|
);
|
||||||
|
@ -791,12 +854,6 @@ const handleMessage = async (
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
|
|
||||||
// O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente
|
|
||||||
|
|
||||||
//Habilitar esse caso queira usar o bot
|
|
||||||
const botInfo = await BotIsOnQueue("botqueue");
|
|
||||||
// const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 };
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
botInfo.isOnQueue &&
|
botInfo.isOnQueue &&
|
||||||
!msg.fromMe &&
|
!msg.fromMe &&
|
||||||
|
@ -844,11 +901,6 @@ const handleMessage = async (
|
||||||
menuMsg?.transferToQueue &&
|
menuMsg?.transferToQueue &&
|
||||||
menuMsg.transferToQueue.trim().length > 0
|
menuMsg.transferToQueue.trim().length > 0
|
||||||
) {
|
) {
|
||||||
console.log(
|
|
||||||
"YYYYYYYYYYYYYYYYYYYY menuMsg.transferToQueue: ",
|
|
||||||
menuMsg.transferToQueue
|
|
||||||
);
|
|
||||||
|
|
||||||
transferTicket(menuMsg.transferToQueue.trim(), wbot, ticket);
|
transferTicket(menuMsg.transferToQueue.trim(), wbot, ticket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ interface Request {
|
||||||
phoneNumberId?: string;
|
phoneNumberId?: string;
|
||||||
wabaId?: string;
|
wabaId?: string;
|
||||||
isOfficial?: boolean;
|
isOfficial?: boolean;
|
||||||
|
number?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Response {
|
interface Response {
|
||||||
|
@ -34,7 +35,8 @@ const CreateWhatsAppService = async ({
|
||||||
isDefault = false,
|
isDefault = false,
|
||||||
isOfficial = false,
|
isOfficial = false,
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId
|
wabaId,
|
||||||
|
number
|
||||||
}: Request): Promise<Response> => {
|
}: Request): Promise<Response> => {
|
||||||
try {
|
try {
|
||||||
const schema = Yup.object().shape({
|
const schema = Yup.object().shape({
|
||||||
|
@ -98,6 +100,7 @@ const CreateWhatsAppService = async ({
|
||||||
phoneNumberId,
|
phoneNumberId,
|
||||||
wabaId,
|
wabaId,
|
||||||
isOfficial,
|
isOfficial,
|
||||||
|
number,
|
||||||
classification
|
classification
|
||||||
},
|
},
|
||||||
{ include: ["queues"] }
|
{ include: ["queues"] }
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
import { Button } from "@material-ui/core";
|
||||||
|
import React, { useRef } from "react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
const LS_NAME = 'audioMessageRate';
|
||||||
|
|
||||||
|
export default function({url}) {
|
||||||
|
const audioRef = useRef(null);
|
||||||
|
const [audioRate, setAudioRate] = useState( parseFloat(localStorage.getItem(LS_NAME) || "1") );
|
||||||
|
const [showButtonRate, setShowButtonRate] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
audioRef.current.playbackRate = audioRate;
|
||||||
|
localStorage.setItem(LS_NAME, audioRate);
|
||||||
|
}, [audioRate]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
audioRef.current.onplaying = () => {
|
||||||
|
setShowButtonRate(true);
|
||||||
|
};
|
||||||
|
audioRef.current.onpause = () => {
|
||||||
|
setShowButtonRate(false);
|
||||||
|
};
|
||||||
|
audioRef.current.onended = () => {
|
||||||
|
setShowButtonRate(false);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const toogleRate = () => {
|
||||||
|
let newRate = null;
|
||||||
|
|
||||||
|
switch(audioRate) {
|
||||||
|
case 0.5:
|
||||||
|
newRate = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
newRate = 1.5;
|
||||||
|
break;
|
||||||
|
case 1.5:
|
||||||
|
newRate = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
newRate = 0.5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
newRate = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setAudioRate(newRate);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<audio ref={audioRef} controls>
|
||||||
|
<source src={url} type="audio/ogg"></source>
|
||||||
|
</audio>
|
||||||
|
{showButtonRate && <Button style={{marginLeft: "5px", marginTop: "-45px"}} onClick={toogleRate}>{audioRate}x</Button>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React, { useEffect } from 'react';
|
||||||
|
import toastError from "../../errors/toastError";
|
||||||
|
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import Grid from "@material-ui/core/Grid";
|
||||||
|
|
||||||
|
import { Button, Divider, } from "@material-ui/core";
|
||||||
|
|
||||||
|
const LocationPreview = ({ image, link, description }) => {
|
||||||
|
useEffect(() => {}, [image, link, description]);
|
||||||
|
|
||||||
|
const handleLocation = async() => {
|
||||||
|
try {
|
||||||
|
window.open(link);
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{
|
||||||
|
minWidth: "250px",
|
||||||
|
}}>
|
||||||
|
<div>
|
||||||
|
<div style={{ float: "left" }}>
|
||||||
|
<img src={image} onClick={handleLocation} style={{ width: "100px" }} />
|
||||||
|
</div>
|
||||||
|
{ description && (
|
||||||
|
<div style={{ display: "flex", flexWrap: "wrap" }}>
|
||||||
|
<Typography style={{ marginTop: "12px", marginLeft: "15px", marginRight: "15px", float: "left" }} variant="subtitle1" color="primary" gutterBottom>
|
||||||
|
<div dangerouslySetInnerHTML={{ __html: description.replace('\\n', '<br />') }}></div>
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div style={{ display: "block", content: "", clear: "both" }}></div>
|
||||||
|
<div>
|
||||||
|
<Divider />
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
onClick={handleLocation}
|
||||||
|
disabled={!link}
|
||||||
|
>Visualizar</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LocationPreview;
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React from "react"
|
||||||
import Markdown from "markdown-to-jsx";
|
import Markdown from "markdown-to-jsx"
|
||||||
|
|
||||||
const elements = [
|
const elements = [
|
||||||
"a",
|
"a",
|
||||||
|
@ -139,25 +139,32 @@ const elements = [
|
||||||
"svg",
|
"svg",
|
||||||
"text",
|
"text",
|
||||||
"tspan",
|
"tspan",
|
||||||
];
|
]
|
||||||
|
|
||||||
const allowedElements = ["a", "b", "strong", "em", "u", "code", "del"];
|
const allowedElements = ["a", "b", "strong", "em", "u", "code", "del"]
|
||||||
|
|
||||||
const CustomLink = ({ children, ...props }) => (
|
const CustomLink = ({ children, ...props }) => (
|
||||||
<a {...props} target="_blank" rel="noopener noreferrer">
|
<a {...props} target="_blank" rel="noopener noreferrer">
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
);
|
)
|
||||||
|
|
||||||
const MarkdownWrapper = ({ children }) => {
|
const MarkdownWrapper = ({ children }) => {
|
||||||
const boldRegex = /\*(.*?)\*/g;
|
const boldRegex = /\*(.*?)\*/g
|
||||||
const tildaRegex = /~(.*?)~/g;
|
const tildaRegex = /~(.*?)~/g
|
||||||
|
|
||||||
|
if (children && children.includes('BEGIN:VCARD'))
|
||||||
|
//children = "Diga olá ao seu novo contato clicando em *conversar*!";
|
||||||
|
children = null
|
||||||
|
|
||||||
|
if (children && children.includes('data:image/'))
|
||||||
|
children = null
|
||||||
|
|
||||||
if (children && boldRegex.test(children)) {
|
if (children && boldRegex.test(children)) {
|
||||||
children = children.replace(boldRegex, "**$1**");
|
children = children.replace(boldRegex, "**$1**")
|
||||||
}
|
}
|
||||||
if (children && tildaRegex.test(children)) {
|
if (children && tildaRegex.test(children)) {
|
||||||
children = children.replace(tildaRegex, "~~$1~~");
|
children = children.replace(tildaRegex, "~~$1~~")
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = React.useMemo(() => {
|
const options = React.useMemo(() => {
|
||||||
|
@ -167,20 +174,20 @@ const MarkdownWrapper = ({ children }) => {
|
||||||
overrides: {
|
overrides: {
|
||||||
a: { component: CustomLink },
|
a: { component: CustomLink },
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
if (!allowedElements.includes(element)) {
|
if (!allowedElements.includes(element)) {
|
||||||
markdownOptions.overrides[element] = el => el.children || null;
|
markdownOptions.overrides[element] = el => el.children || null
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return markdownOptions;
|
return markdownOptions
|
||||||
}, []);
|
}, [])
|
||||||
|
|
||||||
if (!children) return null;
|
if (!children) return null
|
||||||
|
|
||||||
return <Markdown options={options}>{children}</Markdown>;
|
return <Markdown options={options}>{children}</Markdown>
|
||||||
};
|
}
|
||||||
|
|
||||||
export default MarkdownWrapper;
|
export default MarkdownWrapper
|
|
@ -350,6 +350,8 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
console.log('kkkkkkkkkkkkkkkkkkk message: ', message)
|
||||||
|
|
||||||
const { data } = await api.post(`/messages/${ticketId}`, message)
|
const { data } = await api.post(`/messages/${ticketId}`, message)
|
||||||
setParams(null)
|
setParams(null)
|
||||||
if (data && data?.data && Array.isArray(data.data)) {
|
if (data && data?.data && Array.isArray(data.data)) {
|
||||||
|
@ -371,7 +373,11 @@ const MessageInput = ({ ticketStatus }) => {
|
||||||
|
|
||||||
if (!params) return
|
if (!params) return
|
||||||
|
|
||||||
const body_params = params.find(p => p?.type === 'BODY')
|
const body_params = params?.find(p => p?.type === 'BODY')
|
||||||
|
|
||||||
|
console.log('------------> body_params: ', body_params)
|
||||||
|
|
||||||
|
if(!body_params) return
|
||||||
|
|
||||||
let { text } = body_params
|
let { text } = body_params
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,11 @@ import {
|
||||||
} from "@material-ui/icons";
|
} from "@material-ui/icons";
|
||||||
|
|
||||||
import MarkdownWrapper from "../MarkdownWrapper";
|
import MarkdownWrapper from "../MarkdownWrapper";
|
||||||
|
import VcardPreview from "../VcardPreview";
|
||||||
|
import LocationPreview from "../LocationPreview";
|
||||||
|
import Audio from "../Audio";
|
||||||
|
|
||||||
|
|
||||||
import ModalImageCors from "../ModalImageCors";
|
import ModalImageCors from "../ModalImageCors";
|
||||||
import MessageOptionsMenu from "../MessageOptionsMenu";
|
import MessageOptionsMenu from "../MessageOptionsMenu";
|
||||||
import whatsBackground from "../../assets/wa-background.png";
|
import whatsBackground from "../../assets/wa-background.png";
|
||||||
|
@ -488,27 +493,109 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const checkMessageMedia = (message) => {
|
||||||
|
// if (message.mediaType === "image") {
|
||||||
|
// return <ModalImageCors imageUrl={message.mediaUrl} />;
|
||||||
|
// }
|
||||||
|
// if (message.mediaType === "audio") {
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <audio controls>
|
||||||
|
// <source src={message.mediaUrl} type="audio/ogg"></source>
|
||||||
|
// </audio>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (message.mediaType === "video") {
|
||||||
|
// return (
|
||||||
|
// <video
|
||||||
|
// className={classes.messageMedia}
|
||||||
|
// src={message.mediaUrl}
|
||||||
|
// controls
|
||||||
|
// />
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <div className={classes.downloadMedia}>
|
||||||
|
// <Button
|
||||||
|
// startIcon={<GetApp />}
|
||||||
|
// color="primary"
|
||||||
|
// variant="outlined"
|
||||||
|
// target="_blank"
|
||||||
|
// href={message.mediaUrl}
|
||||||
|
// >
|
||||||
|
// Download
|
||||||
|
// </Button>
|
||||||
|
// </div>
|
||||||
|
// <Divider />
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
const checkMessageMedia = (message) => {
|
const checkMessageMedia = (message) => {
|
||||||
if (message.mediaType === "image") {
|
if (message.mediaType === "location" && message.body.split('|').length >= 2) {
|
||||||
return <ModalImageCors imageUrl={message.mediaUrl} />;
|
let locationParts = message.body.split('|')
|
||||||
}
|
let imageLocation = locationParts[0]
|
||||||
if (message.mediaType === "audio") {
|
let linkLocation = locationParts[1]
|
||||||
|
|
||||||
|
let descriptionLocation = null
|
||||||
|
|
||||||
|
if (locationParts.length > 2)
|
||||||
|
descriptionLocation = message.body.split('|')[2]
|
||||||
|
|
||||||
|
return <LocationPreview image={imageLocation} link={linkLocation} description={descriptionLocation} />
|
||||||
|
}
|
||||||
|
else if (message.mediaType === "vcard") {
|
||||||
|
//console.log("vcard")
|
||||||
|
//console.log(message)
|
||||||
|
let array = message.body.split("\n")
|
||||||
|
let obj = []
|
||||||
|
let contact = ""
|
||||||
|
for (let index = 0; index < array.length; index++) {
|
||||||
|
const v = array[index]
|
||||||
|
let values = v.split(":")
|
||||||
|
for (let ind = 0; ind < values.length; ind++) {
|
||||||
|
if (values[ind].indexOf("+") !== -1) {
|
||||||
|
obj.push({ number: values[ind] })
|
||||||
|
}
|
||||||
|
if (values[ind].indexOf("FN") !== -1) {
|
||||||
|
contact = values[ind + 1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <VcardPreview contact={contact} numbers={obj[0]?.number} />
|
||||||
|
}
|
||||||
|
/*else if (message.mediaType === "multi_vcard") {
|
||||||
|
console.log("multi_vcard")
|
||||||
|
console.log(message)
|
||||||
|
|
||||||
|
if(message.body !== null && message.body !== "") {
|
||||||
|
let newBody = JSON.parse(message.body)
|
||||||
return (
|
return (
|
||||||
<audio controls>
|
<>
|
||||||
<source src={message.mediaUrl} type="audio/ogg"></source>
|
{
|
||||||
</audio>
|
newBody.map(v => (
|
||||||
);
|
<VcardPreview contact={v.name} numbers={v.number} />
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
</>
|
||||||
if (message.mediaType === "video") {
|
)
|
||||||
|
} else return (<></>)
|
||||||
|
}*/
|
||||||
|
else if (/^.*\.(jpe?g|png|gif)?$/i.exec(message.mediaUrl) && message.mediaType === "image") {
|
||||||
|
return <ModalImageCors imageUrl={message.mediaUrl} />
|
||||||
|
} else if (message.mediaType === "audio") {
|
||||||
|
return <Audio url={message.mediaUrl} />
|
||||||
|
} else if (message.mediaType === "video") {
|
||||||
return (
|
return (
|
||||||
<video
|
<video
|
||||||
className={classes.messageMedia}
|
className={classes.messageMedia}
|
||||||
src={message.mediaUrl}
|
src={message.mediaUrl}
|
||||||
controls
|
controls
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -525,7 +612,7 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
</div>
|
</div>
|
||||||
<Divider />
|
<Divider />
|
||||||
</>
|
</>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -643,6 +730,88 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// const renderMessages = () => {
|
||||||
|
// if (messagesList.length > 0) {
|
||||||
|
// const viewMessagesList = messagesList.map((message, index) => {
|
||||||
|
// if (!message.fromMe) {
|
||||||
|
// return (
|
||||||
|
// <React.Fragment key={message.id}>
|
||||||
|
// {renderDailyTimestamps(message, index)}
|
||||||
|
// {renderMessageDivider(message, index)}
|
||||||
|
// <div className={classes.messageLeft}>
|
||||||
|
// <IconButton
|
||||||
|
// variant="contained"
|
||||||
|
// size="small"
|
||||||
|
// id="messageActionsButton"
|
||||||
|
// disabled={message.isDeleted}
|
||||||
|
// className={classes.messageActionsButton}
|
||||||
|
// onClick={(e) => handleOpenMessageOptionsMenu(e, message)}
|
||||||
|
// >
|
||||||
|
// <ExpandMore />
|
||||||
|
// </IconButton>
|
||||||
|
// {isGroup && (
|
||||||
|
// <span className={classes.messageContactName}>
|
||||||
|
// {message.contact?.name}
|
||||||
|
// </span>
|
||||||
|
// )}
|
||||||
|
// {message.mediaUrl && checkMessageMedia(message)}
|
||||||
|
// <div className={classes.textContentItem}>
|
||||||
|
// {message.quotedMsg && renderQuotedMessage(message)}
|
||||||
|
// <MarkdownWrapper>{message.body}</MarkdownWrapper>
|
||||||
|
// <span className={classes.timestamp}>
|
||||||
|
// {format(parseISO(message.createdAt), "HH:mm")}
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </React.Fragment>
|
||||||
|
// );
|
||||||
|
// } else {
|
||||||
|
// return (
|
||||||
|
// <React.Fragment key={message.id}>
|
||||||
|
// {renderDailyTimestamps(message, index)}
|
||||||
|
// {renderMessageDivider(message, index)}
|
||||||
|
// <div className={classes.messageRight}>
|
||||||
|
// <IconButton
|
||||||
|
// variant="contained"
|
||||||
|
// size="small"
|
||||||
|
// id="messageActionsButton"
|
||||||
|
// disabled={message.isDeleted}
|
||||||
|
// className={classes.messageActionsButton}
|
||||||
|
// onClick={(e) => handleOpenMessageOptionsMenu(e, message)}
|
||||||
|
// >
|
||||||
|
// <ExpandMore />
|
||||||
|
// </IconButton>
|
||||||
|
// {message.mediaUrl && checkMessageMedia(message)}
|
||||||
|
// <div
|
||||||
|
// className={clsx(classes.textContentItem, {
|
||||||
|
// [classes.textContentItemDeleted]: message.isDeleted,
|
||||||
|
// })}
|
||||||
|
// >
|
||||||
|
// {message.isDeleted && (
|
||||||
|
// <Block
|
||||||
|
// color="disabled"
|
||||||
|
// fontSize="small"
|
||||||
|
// className={classes.deletedIcon}
|
||||||
|
// />
|
||||||
|
// )}
|
||||||
|
// {message.quotedMsg && renderQuotedMessage(message)}
|
||||||
|
// <MarkdownWrapper>{message.body}</MarkdownWrapper>
|
||||||
|
// <span className={classes.timestamp}>
|
||||||
|
// {format(parseISO(message.createdAt), "HH:mm")}
|
||||||
|
// {renderMessageAck(message)}
|
||||||
|
// </span>
|
||||||
|
// </div>
|
||||||
|
// </div>
|
||||||
|
// </React.Fragment>
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// return viewMessagesList;
|
||||||
|
// } else {
|
||||||
|
// return <div>Say hello to your new contact!</div>;
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
const renderMessages = () => {
|
const renderMessages = () => {
|
||||||
if (messagesList.length > 0) {
|
if (messagesList.length > 0) {
|
||||||
const viewMessagesList = messagesList.map((message, index) => {
|
const viewMessagesList = messagesList.map((message, index) => {
|
||||||
|
@ -667,7 +836,9 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
{message.contact?.name}
|
{message.contact?.name}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{message.mediaUrl && checkMessageMedia(message)}
|
{(message.mediaUrl || message.mediaType === "location" || message.mediaType === "vcard"
|
||||||
|
//|| message.mediaType === "multi_vcard"
|
||||||
|
) && checkMessageMedia(message)}
|
||||||
<div className={classes.textContentItem}>
|
<div className={classes.textContentItem}>
|
||||||
{message.quotedMsg && renderQuotedMessage(message)}
|
{message.quotedMsg && renderQuotedMessage(message)}
|
||||||
<MarkdownWrapper>{message.body}</MarkdownWrapper>
|
<MarkdownWrapper>{message.body}</MarkdownWrapper>
|
||||||
|
@ -677,7 +848,7 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<React.Fragment key={message.id}>
|
<React.Fragment key={message.id}>
|
||||||
|
@ -694,7 +865,9 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
>
|
>
|
||||||
<ExpandMore />
|
<ExpandMore />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
{message.mediaUrl && checkMessageMedia(message)}
|
{(message.mediaUrl || message.mediaType === "location" || message.mediaType === "vcard"
|
||||||
|
//|| message.mediaType === "multi_vcard"
|
||||||
|
) && checkMessageMedia(message)}
|
||||||
<div
|
<div
|
||||||
className={clsx(classes.textContentItem, {
|
className={clsx(classes.textContentItem, {
|
||||||
[classes.textContentItemDeleted]: message.isDeleted,
|
[classes.textContentItemDeleted]: message.isDeleted,
|
||||||
|
@ -716,12 +889,12 @@ const MessagesList = ({ ticketId, isGroup }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
return viewMessagesList;
|
return viewMessagesList
|
||||||
} else {
|
} else {
|
||||||
return <div>Say hello to your new contact!</div>;
|
return <div>Say hello to your new contact!</div>
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ const ModalTemplate = ({ templates, modal_header, func }) => {
|
||||||
|
|
||||||
templates = [{}, ...templates]
|
templates = [{}, ...templates]
|
||||||
|
|
||||||
|
// console.log('TEMPLATES: ', templates)
|
||||||
|
|
||||||
const [open, setOpen] = useState(true)
|
const [open, setOpen] = useState(true)
|
||||||
const [scroll, /*setScroll*/] = useState('body')
|
const [scroll, /*setScroll*/] = useState('body')
|
||||||
const [templateId, setTemplateId] = useState(null)
|
const [templateId, setTemplateId] = useState(null)
|
||||||
|
@ -34,7 +36,25 @@ const ModalTemplate = ({ templates, modal_header, func }) => {
|
||||||
const handleChatEnd = () => {
|
const handleChatEnd = () => {
|
||||||
|
|
||||||
console.log('PARAMS TO SEND TO MESSAGE INPUT: ', params)
|
console.log('PARAMS TO SEND TO MESSAGE INPUT: ', params)
|
||||||
|
console.log('templateComponents: ', templateComponents)
|
||||||
|
|
||||||
|
if (params && params.length === 1) {
|
||||||
|
|
||||||
|
const bodyObject = templateComponents.find(obj => obj?.type === 'BODY')
|
||||||
|
|
||||||
|
if (bodyObject) {
|
||||||
|
const { text } = bodyObject
|
||||||
|
func([...params, {
|
||||||
|
"type": "BODY",
|
||||||
|
"text": text,
|
||||||
|
"language": "pt_BR",
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
func(params)
|
func(params)
|
||||||
|
}
|
||||||
|
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +147,9 @@ const ModalTemplate = ({ templates, modal_header, func }) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log('---------> PARAMS: ', params)
|
console.log('---------> PARAMS: ', params)
|
||||||
}, [params])
|
console.log('---------> templateComponents: ', templateComponents)
|
||||||
|
|
||||||
|
}, [params, templateComponents])
|
||||||
|
|
||||||
const dinamicTextField = (replicateItems, func, type, text, language) => {
|
const dinamicTextField = (replicateItems, func, type, text, language) => {
|
||||||
|
|
||||||
|
@ -204,7 +226,7 @@ const ModalTemplate = ({ templates, modal_header, func }) => {
|
||||||
{text &&
|
{text &&
|
||||||
<div style={{ margin: 0, padding: 0, 'marginBottom': '15px' }}>
|
<div style={{ margin: 0, padding: 0, 'marginBottom': '15px' }}>
|
||||||
<p style={{ margin: 0, padding: 0, fontSize: 12 }}>{text}</p>
|
<p style={{ margin: 0, padding: 0, fontSize: 12 }}>{text}</p>
|
||||||
{type && (type === 'BODY') && dinamicTextField(body_params.length, handleTextChange, type, text, language)}
|
{type && (type === 'BODY') && body_params && dinamicTextField(body_params.length, handleTextChange, type, text, language)}
|
||||||
</div>}
|
</div>}
|
||||||
{buttons && <div>{buttons.map((b) => {
|
{buttons && <div>{buttons.map((b) => {
|
||||||
const { type, text, url } = b
|
const { type, text, url } = b
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import React, { useState, useEffect, useReducer, useContext } from "react";
|
import React, { useState, useEffect, useReducer, useContext } from "react"
|
||||||
|
|
||||||
|
|
||||||
import openSocket from "socket.io-client";
|
import openSocket from "socket.io-client"
|
||||||
|
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles"
|
||||||
import List from "@material-ui/core/List";
|
import List from "@material-ui/core/List"
|
||||||
import Paper from "@material-ui/core/Paper";
|
import Paper from "@material-ui/core/Paper"
|
||||||
|
|
||||||
import TicketListItem from "../TicketListItem";
|
import TicketListItem from "../TicketListItem"
|
||||||
import TicketsListSkeleton from "../TicketsListSkeleton";
|
import TicketsListSkeleton from "../TicketsListSkeleton"
|
||||||
|
|
||||||
import useTickets from "../../hooks/useTickets";
|
import useTickets from "../../hooks/useTickets"
|
||||||
import { i18n } from "../../translate/i18n";
|
import { i18n } from "../../translate/i18n"
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
|
|
||||||
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket";
|
import { SearchTicketContext } from "../../context/SearchTicket/SearchTicket"
|
||||||
|
|
||||||
const useStyles = makeStyles(theme => ({
|
const useStyles = makeStyles(theme => ({
|
||||||
ticketsListWrapper: {
|
ticketsListWrapper: {
|
||||||
|
@ -73,64 +73,64 @@ const useStyles = makeStyles(theme => ({
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
}));
|
}))
|
||||||
|
|
||||||
const reducer = (state, action) => {
|
const reducer = (state, action) => {
|
||||||
if (action.type === "LOAD_TICKETS") {
|
if (action.type === "LOAD_TICKETS") {
|
||||||
const newTickets = action.payload;
|
const newTickets = action.payload
|
||||||
|
|
||||||
|
|
||||||
newTickets.forEach(ticket => {
|
newTickets.forEach(ticket => {
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex] = ticket;
|
state[ticketIndex] = ticket
|
||||||
if (+ticket.unreadMessages > 0) {
|
if (+ticket.unreadMessages > 0) {
|
||||||
state.unshift(state.splice(ticketIndex, 1)[0]);
|
state.unshift(state.splice(ticketIndex, 1)[0])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state.push(ticket);
|
state.push(ticket)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "RESET_UNREAD") {
|
if (action.type === "RESET_UNREAD") {
|
||||||
const ticketId = action.payload;
|
const ticketId = action.payload
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => +t.id === +ticketId);
|
const ticketIndex = state.findIndex(t => +t.id === +ticketId)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex].unreadMessages = 0;
|
state[ticketIndex].unreadMessages = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "UPDATE_TICKET") {
|
if (action.type === "UPDATE_TICKET") {
|
||||||
const ticket = action.payload;
|
const ticket = action.payload
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
|
||||||
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex] = ticket;
|
state[ticketIndex] = ticket
|
||||||
} else {
|
} else {
|
||||||
state.unshift(ticket);
|
state.unshift(ticket)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") {
|
if (action.type === "UPDATE_TICKET_UNREAD_MESSAGES") {
|
||||||
|
|
||||||
const message = action.payload.message
|
const message = action.payload.message
|
||||||
|
|
||||||
const ticket = action.payload.ticket;
|
const ticket = action.payload.ticket
|
||||||
|
|
||||||
const ticketIndex = state.findIndex(t => +t.id === +ticket.id);
|
const ticketIndex = state.findIndex(t => +t.id === +ticket.id)
|
||||||
|
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
|
|
||||||
|
@ -142,55 +142,55 @@ const reducer = (state, action) => {
|
||||||
ticket.unreadMessages += 1
|
ticket.unreadMessages += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
state[ticketIndex] = ticket;
|
state[ticketIndex] = ticket
|
||||||
state.unshift(state.splice(ticketIndex, 1)[0]);
|
state.unshift(state.splice(ticketIndex, 1)[0])
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
state.unshift(ticket);
|
state.unshift(ticket)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "UPDATE_TICKET_CONTACT") {
|
if (action.type === "UPDATE_TICKET_CONTACT") {
|
||||||
const contact = action.payload;
|
const contact = action.payload
|
||||||
const ticketIndex = state.findIndex(t => +t.contactId === +contact.id);
|
const ticketIndex = state.findIndex(t => +t.contactId === +contact.id)
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state[ticketIndex].contact = contact;
|
state[ticketIndex].contact = contact
|
||||||
}
|
}
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "DELETE_TICKET") {
|
if (action.type === "DELETE_TICKET") {
|
||||||
const ticketId = action.payload;
|
const ticketId = action.payload
|
||||||
const ticketIndex = state.findIndex(t => +t.id === +ticketId);
|
const ticketIndex = state.findIndex(t => +t.id === +ticketId)
|
||||||
if (ticketIndex !== -1) {
|
if (ticketIndex !== -1) {
|
||||||
state.splice(ticketIndex, 1);
|
state.splice(ticketIndex, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return [...state];
|
return [...state]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action.type === "RESET") {
|
if (action.type === "RESET") {
|
||||||
return [];
|
return []
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
const TicketsList = (props) => {
|
const TicketsList = (props) => {
|
||||||
const { status, searchParam, searchParamContent, showAll, selectedQueueIds, updateCount, style, tab } = props;
|
const { status, searchParam, searchParamContent, showAll, selectedQueueIds, updateCount, style, tab } = props
|
||||||
const classes = useStyles();
|
const classes = useStyles()
|
||||||
const [pageNumber, setPageNumber] = useState(1);
|
const [pageNumber, setPageNumber] = useState(1)
|
||||||
const [ticketsList, dispatch] = useReducer(reducer, []);
|
const [ticketsList, dispatch] = useReducer(reducer, [])
|
||||||
const { user } = useContext(AuthContext);
|
const { user } = useContext(AuthContext)
|
||||||
|
|
||||||
const { searchTicket } = useContext(SearchTicketContext)
|
const { searchTicket } = useContext(SearchTicketContext)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
dispatch({ type: "RESET" });
|
dispatch({ type: "RESET" })
|
||||||
setPageNumber(1);
|
setPageNumber(1)
|
||||||
|
|
||||||
}, [status, searchParam, searchParamContent, showAll, selectedQueueIds, searchTicket]);
|
}, [status, searchParam, searchParamContent, showAll, selectedQueueIds, searchTicket])
|
||||||
|
|
||||||
const { tickets, hasMore, loading } = useTickets({
|
const { tickets, hasMore, loading } = useTickets({
|
||||||
pageNumber,
|
pageNumber,
|
||||||
|
@ -199,12 +199,13 @@ const TicketsList = (props) => {
|
||||||
status,
|
status,
|
||||||
showAll,
|
showAll,
|
||||||
queueIds: JSON.stringify(selectedQueueIds),
|
queueIds: JSON.stringify(selectedQueueIds),
|
||||||
tab
|
tab,
|
||||||
});
|
unlimited: status === 'open' ? "all" : "false"
|
||||||
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
if (!status && !searchParam) return;
|
if (!status && !searchParam) return
|
||||||
|
|
||||||
// if (searchParam) {
|
// if (searchParam) {
|
||||||
//
|
//
|
||||||
|
@ -217,31 +218,31 @@ const TicketsList = (props) => {
|
||||||
dispatch({ type: "RESET" })
|
dispatch({ type: "RESET" })
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ type: "LOAD_TICKETS", payload: tickets, });
|
dispatch({ type: "LOAD_TICKETS", payload: tickets, })
|
||||||
|
|
||||||
}, [tickets, status, searchParam, pageNumber]);
|
}, [tickets, status, searchParam, pageNumber])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
// if (tab=='search')return
|
// if (tab=='search')return
|
||||||
|
|
||||||
const socket = openSocket(process.env.REACT_APP_BACKEND_URL);
|
const socket = openSocket(process.env.REACT_APP_BACKEND_URL)
|
||||||
|
|
||||||
const shouldUpdateTicket = ticket =>
|
const shouldUpdateTicket = ticket =>
|
||||||
(!ticket.userId || ticket.userId === user?.id || showAll) &&
|
(!ticket.userId || ticket.userId === user?.id || showAll) &&
|
||||||
(!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1);
|
(!ticket.queueId || selectedQueueIds.indexOf(ticket.queueId) > -1)
|
||||||
|
|
||||||
const notBelongsToUserQueues = ticket =>
|
const notBelongsToUserQueues = ticket =>
|
||||||
ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1;
|
ticket.queueId && selectedQueueIds.indexOf(ticket.queueId) === -1
|
||||||
|
|
||||||
socket.on("connect", () => {
|
socket.on("connect", () => {
|
||||||
if (status) {
|
if (status) {
|
||||||
socket.emit("joinTickets", status);
|
socket.emit("joinTickets", status)
|
||||||
} else {
|
} else {
|
||||||
socket.emit("joinNotification");
|
socket.emit("joinNotification")
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -254,7 +255,7 @@ const TicketsList = (props) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "RESET_UNREAD",
|
type: "RESET_UNREAD",
|
||||||
payload: data.ticketId,
|
payload: data.ticketId,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
|
if (data.action === "update" && shouldUpdateTicket(data.ticket)) {
|
||||||
|
@ -264,17 +265,17 @@ const TicketsList = (props) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE_TICKET",
|
type: "UPDATE_TICKET",
|
||||||
payload: data.ticket,
|
payload: data.ticket,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "update" && notBelongsToUserQueues(data.ticket)) {
|
if (data.action === "update" && notBelongsToUserQueues(data.ticket)) {
|
||||||
dispatch({ type: "DELETE_TICKET", payload: data.ticket.id });
|
dispatch({ type: "DELETE_TICKET", payload: data.ticket.id })
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.action === "delete") {
|
if (data.action === "delete") {
|
||||||
dispatch({ type: "DELETE_TICKET", payload: data.ticketId });
|
dispatch({ type: "DELETE_TICKET", payload: data.ticketId })
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
|
|
||||||
socket.on("appMessage", data => {
|
socket.on("appMessage", data => {
|
||||||
|
@ -287,51 +288,49 @@ const TicketsList = (props) => {
|
||||||
type: "UPDATE_TICKET_UNREAD_MESSAGES",
|
type: "UPDATE_TICKET_UNREAD_MESSAGES",
|
||||||
// payload: data.ticket,
|
// payload: data.ticket,
|
||||||
payload: data,
|
payload: data,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
socket.on("contact", data => {
|
socket.on("contact", data => {
|
||||||
if (data.action === "update") {
|
if (data.action === "update") {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "UPDATE_TICKET_CONTACT",
|
type: "UPDATE_TICKET_CONTACT",
|
||||||
payload: data.contact,
|
payload: data.contact,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.disconnect();
|
socket.disconnect()
|
||||||
};
|
}
|
||||||
}, [status, showAll, user, selectedQueueIds, tab]);
|
}, [status, showAll, user, selectedQueueIds, tab])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (typeof updateCount === "function") {
|
if (typeof updateCount === "function") {
|
||||||
updateCount(ticketsList.length);
|
updateCount(ticketsList.length)
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [ticketsList]);
|
}, [ticketsList])
|
||||||
|
|
||||||
const loadMore = () => {
|
const loadMore = () => {
|
||||||
setPageNumber(prevState => prevState + 1);
|
setPageNumber(prevState => prevState + 1)
|
||||||
};
|
}
|
||||||
|
|
||||||
const handleScroll = e => {
|
const handleScroll = e => {
|
||||||
|
|
||||||
if (!hasMore || loading) return;
|
if (!hasMore || loading) return
|
||||||
|
|
||||||
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
|
const { scrollTop, scrollHeight, clientHeight } = e.currentTarget
|
||||||
|
|
||||||
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
if (scrollHeight - (scrollTop + 100) < clientHeight) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loadMore();
|
loadMore()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper className={classes.ticketsListWrapper} style={style}>
|
<Paper className={classes.ticketsListWrapper} style={style}>
|
||||||
|
@ -363,7 +362,7 @@ const TicketsList = (props) => {
|
||||||
</List>
|
</List>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Paper>
|
</Paper>
|
||||||
);
|
)
|
||||||
};
|
}
|
||||||
|
|
||||||
export default TicketsList;
|
export default TicketsList
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
import React, { useEffect, useState, useContext } from 'react';
|
||||||
|
import { useHistory } from "react-router-dom";
|
||||||
|
import toastError from "../../errors/toastError";
|
||||||
|
import api from "../../services/api";
|
||||||
|
|
||||||
|
import Avatar from "@material-ui/core/Avatar";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import Grid from "@material-ui/core/Grid";
|
||||||
|
|
||||||
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
|
|
||||||
|
import { Button, Divider, } from "@material-ui/core";
|
||||||
|
|
||||||
|
const VcardPreview = ({ contact, numbers }) => {
|
||||||
|
const history = useHistory();
|
||||||
|
const { user } = useContext(AuthContext);
|
||||||
|
|
||||||
|
const [selectedContact, setContact] = useState({
|
||||||
|
name: "",
|
||||||
|
number: 0,
|
||||||
|
profilePicUrl: ""
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
const fetchContacts = async () => {
|
||||||
|
try {
|
||||||
|
let contactObj = {
|
||||||
|
name: contact,
|
||||||
|
// number: numbers.replace(/\D/g, ""),
|
||||||
|
number: numbers !== undefined && numbers.replace(/\D/g, ""),
|
||||||
|
email: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data } = await api.post("/contact", contactObj);
|
||||||
|
setContact(data)
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
toastError(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchContacts();
|
||||||
|
}, 500);
|
||||||
|
return () => clearTimeout(delayDebounceFn);
|
||||||
|
}, [contact, numbers]);
|
||||||
|
|
||||||
|
const handleNewChat = async () => {
|
||||||
|
try {
|
||||||
|
const { data: ticket } = await api.post("/tickets", {
|
||||||
|
contactId: selectedContact.id,
|
||||||
|
userId: user.id,
|
||||||
|
status: "open",
|
||||||
|
});
|
||||||
|
history.push(`/tickets/${ticket.id}`);
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div style={{
|
||||||
|
minWidth: "250px",
|
||||||
|
}}>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item xs={2}>
|
||||||
|
<Avatar src={selectedContact.profilePicUrl} />
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={9}>
|
||||||
|
<Typography style={{ marginTop: "12px", marginLeft: "10px" }} variant="subtitle1" color="primary" gutterBottom>
|
||||||
|
{selectedContact.name}
|
||||||
|
</Typography>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<Divider />
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
color="primary"
|
||||||
|
onClick={handleNewChat}
|
||||||
|
disabled={!selectedContact.number}
|
||||||
|
>Conversar</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default VcardPreview;
|
|
@ -70,6 +70,7 @@ const WhatsAppModal = ({ open, onClose, whatsAppId, whatsAppOfficial }) => {
|
||||||
farewellMessage: '',
|
farewellMessage: '',
|
||||||
isDefault: false,
|
isDefault: false,
|
||||||
isOfficial: false,
|
isOfficial: false,
|
||||||
|
number: '',
|
||||||
phoneNumberId: '',
|
phoneNumberId: '',
|
||||||
wabaId: ''
|
wabaId: ''
|
||||||
}
|
}
|
||||||
|
@ -109,6 +110,7 @@ const WhatsAppModal = ({ open, onClose, whatsAppId, whatsAppOfficial }) => {
|
||||||
if (!isOfficial) {
|
if (!isOfficial) {
|
||||||
values.phoneNumberId = ''
|
values.phoneNumberId = ''
|
||||||
values.wabaId = ''
|
values.wabaId = ''
|
||||||
|
values.number = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -276,6 +278,18 @@ const WhatsAppModal = ({ open, onClose, whatsAppId, whatsAppOfficial }) => {
|
||||||
margin="dense"
|
margin="dense"
|
||||||
className={classes.textField}
|
className={classes.textField}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<Field
|
||||||
|
as={TextField}
|
||||||
|
label="Phone number"
|
||||||
|
autoFocus
|
||||||
|
name="number"
|
||||||
|
error={touched.name && Boolean(errors.name)}
|
||||||
|
helperText={touched.name && errors.name}
|
||||||
|
variant="outlined"
|
||||||
|
margin="dense"
|
||||||
|
className={classes.textField}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ const Chart = (props) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
const date = useRef(new Date().toISOString());
|
const date = useRef(new Date().toISOString());
|
||||||
let { tickets } = useTickets({ date: date.current, unlimited: "true" });
|
let { tickets } = useTickets({ date: date.current, unlimited: "current" });
|
||||||
|
|
||||||
const [chartData, setChartData] = useState([
|
const [chartData, setChartData] = useState([
|
||||||
{ time: "08:00", amount: 0 },
|
{ time: "08:00", amount: 0 },
|
||||||
|
|
|
@ -9,6 +9,10 @@ import PropTypes from 'prop-types'
|
||||||
import Box from '@mui/material/Box'
|
import Box from '@mui/material/Box'
|
||||||
import { AuthContext } from "../../context/Auth/AuthContext"
|
import { AuthContext } from "../../context/Auth/AuthContext"
|
||||||
import { Can } from "../../components/Can"
|
import { Can } from "../../components/Can"
|
||||||
|
import FormControlLabel from "@mui/material/FormControlLabel"
|
||||||
|
import Checkbox from '@mui/material/Checkbox'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import { Button } from "@material-ui/core"
|
import { Button } from "@material-ui/core"
|
||||||
|
|
||||||
|
@ -25,6 +29,9 @@ import openSocket from "socket.io-client"
|
||||||
|
|
||||||
import { i18n } from "../../translate/i18n"
|
import { i18n } from "../../translate/i18n"
|
||||||
|
|
||||||
|
import Switch from '@mui/material/Switch'
|
||||||
|
|
||||||
|
const label = { inputProps: { 'aria-label': 'Size switch demo' } }
|
||||||
|
|
||||||
const report = [{ 'value': '1', 'label': 'Atendimento por atendentes' }, { 'value': '2', 'label': 'Usuários online/offline' }]
|
const report = [{ 'value': '1', 'label': 'Atendimento por atendentes' }, { 'value': '2', 'label': 'Usuários online/offline' }]
|
||||||
|
|
||||||
|
@ -48,9 +55,13 @@ const reducerQ = (state, action) => {
|
||||||
|
|
||||||
if (action.type === 'LOAD_QUERY') {
|
if (action.type === 'LOAD_QUERY') {
|
||||||
|
|
||||||
const queries = action.payload
|
let queries = action.payload
|
||||||
const newQueries = []
|
const newQueries = []
|
||||||
|
|
||||||
|
if (queries?.hasOwnProperty('usersProfile')) {
|
||||||
|
queries = queries.usersProfile
|
||||||
|
}
|
||||||
|
|
||||||
queries.forEach((query) => {
|
queries.forEach((query) => {
|
||||||
|
|
||||||
const queryIndex = state.findIndex((q) => q.id === query.id)
|
const queryIndex = state.findIndex((q) => q.id === query.id)
|
||||||
|
@ -282,6 +293,10 @@ const Report = () => {
|
||||||
|
|
||||||
const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined)
|
const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined)
|
||||||
const [csvFile, setCsvFile] = useState()
|
const [csvFile, setCsvFile] = useState()
|
||||||
|
const [selectedValue, setSelectedValue] = useState('created')
|
||||||
|
const [checked, setChecked] = useState(true)
|
||||||
|
const [queues, setQueues] = useState([])
|
||||||
|
const [queueId, setQueue] = useState(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
dispatch({ type: "RESET" })
|
dispatch({ type: "RESET" })
|
||||||
|
@ -332,22 +347,23 @@ const Report = () => {
|
||||||
|
|
||||||
// const { data } = await api.get("/reports/", { params: { userId: userId ? userId : 0, startDate: convertAndFormatDate(startDate), endDate: convertAndFormatDate(endDate), pageNumber: pageNumberTickets }, })
|
// const { data } = await api.get("/reports/", { params: { userId: userId ? userId : 0, startDate: convertAndFormatDate(startDate), endDate: convertAndFormatDate(endDate), pageNumber: pageNumberTickets }, })
|
||||||
|
|
||||||
const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets }, userQueues: userA.queues})
|
const { data } = await api.get("/reports/", { params: { userId, startDate, endDate, pageNumber: pageNumberTickets, createdOrUpdated: selectedValue, queueId }, userQueues: userA.queues })
|
||||||
|
|
||||||
let ticketsQueue = data.tickets;
|
let ticketsQueue = data.tickets
|
||||||
let userQueues = userA.queues;
|
let userQueues = userA.queues
|
||||||
let filterQueuesTickets = [];
|
let filterQueuesTickets = []
|
||||||
if (userQueues.length > 1) {
|
if (userQueues.length > 1) {
|
||||||
filterQueuesTickets = ticketsQueue.filter(ticket => userQueues.some(queue => queue?.name === ticket?.queue?.name));
|
filterQueuesTickets = ticketsQueue.filter(ticket => userQueues.some(queue => queue?.name === ticket?.queue?.name))
|
||||||
} else if (userQueues.length > 0) {
|
} else if (userQueues.length > 0) {
|
||||||
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name);
|
filterQueuesTickets = ticketsQueue.filter(ticket => ticket?.queue?.name === userQueues[0]?.name)
|
||||||
}
|
}
|
||||||
data.tickets = filterQueuesTickets;
|
data.tickets = filterQueuesTickets
|
||||||
dispatchQ({ type: "LOAD_QUERY", payload: data.tickets })
|
dispatchQ({ type: "LOAD_QUERY", payload: data.tickets })
|
||||||
|
|
||||||
setHasMore(data.hasMore)
|
setHasMore(data.hasMore)
|
||||||
setTotalCountTickets(data.count)
|
setTotalCountTickets(data.count)
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
|
setQueues(data.queues)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -370,9 +386,13 @@ const Report = () => {
|
||||||
}, 500)
|
}, 500)
|
||||||
return () => clearTimeout(delayDebounceFn)
|
return () => clearTimeout(delayDebounceFn)
|
||||||
|
|
||||||
}, [userId, startDate, endDate, reportOption, pageNumberTickets, totalCountTickets])
|
}, [userId, queueId, checked, startDate, endDate, reportOption, pageNumberTickets, totalCountTickets, selectedValue])
|
||||||
|
|
||||||
|
|
||||||
|
const handleCheckBoxChange = (value) => {
|
||||||
|
setSelectedValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
// Get from child 1
|
// Get from child 1
|
||||||
const datePicker1Value = (data) => {
|
const datePicker1Value = (data) => {
|
||||||
|
|
||||||
|
@ -387,18 +407,23 @@ const Report = () => {
|
||||||
|
|
||||||
// Get from child 3
|
// Get from child 3
|
||||||
const textFieldSelectUser = (data) => {
|
const textFieldSelectUser = (data) => {
|
||||||
|
setQueue(null)
|
||||||
setUser(data)
|
setUser(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const textFieldSelectQueue = (data) => {
|
||||||
|
setUser(0)
|
||||||
|
setQueue(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get from report option
|
// Get from report option
|
||||||
const reportValue = (data) => {
|
const reportValue = (data) => {
|
||||||
|
if (data === '2') {
|
||||||
|
setChecked(true)
|
||||||
|
}
|
||||||
setReport(data)
|
setReport(data)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -490,6 +515,7 @@ const Report = () => {
|
||||||
identifier: 'csv'
|
identifier: 'csv'
|
||||||
},
|
},
|
||||||
query_params: {
|
query_params: {
|
||||||
|
queueId: queueId,
|
||||||
userId: userId,
|
userId: userId,
|
||||||
startDate: startDate,
|
startDate: startDate,
|
||||||
endDate: endDate
|
endDate: endDate
|
||||||
|
@ -567,7 +593,7 @@ const Report = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}, [reportOption, startDate, endDate, userId, userA])
|
}, [reportOption, startDate, endDate, userId, queueId, checked, userA, selectedValue])
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -657,6 +683,10 @@ const Report = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleChange = (event) => {
|
||||||
|
setChecked(event.target.checked)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<Can
|
<Can
|
||||||
|
@ -665,16 +695,67 @@ const Report = () => {
|
||||||
yes={() => (
|
yes={() => (
|
||||||
|
|
||||||
<MainContainer>
|
<MainContainer>
|
||||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
|
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 2fr) repeat(2, 1fr)', gap: '8px' }}>
|
||||||
|
|
||||||
<Item><SelectField func={textFieldSelectUser} emptyField={true} header={i18n.t("reports.user")} currencies={users.map((obj) => {
|
<Box sx={{ display: 'flex', flexDirection: 'column', padding: '10px 0', alignItems: 'center', }}>
|
||||||
|
|
||||||
|
{checked ?
|
||||||
|
<SelectField
|
||||||
|
func={textFieldSelectUser}
|
||||||
|
emptyField={true}
|
||||||
|
header={i18n.t("reports.user")}
|
||||||
|
currencies={users.map((obj) => {
|
||||||
return { 'value': obj.id, 'label': obj.name }
|
return { 'value': obj.id, 'label': obj.name }
|
||||||
})} /></Item>
|
})} /> :
|
||||||
|
<SelectField
|
||||||
|
func={textFieldSelectQueue}
|
||||||
|
emptyField={true}
|
||||||
|
header={'Filas'}
|
||||||
|
currencies={queues.map((obj) => {
|
||||||
|
return { 'value': obj.id, 'label': obj.name }
|
||||||
|
})} />
|
||||||
|
}
|
||||||
|
|
||||||
<Item><DatePicker1 func={datePicker1Value} minDate={false} startEmpty={false} title={i18n.t("reports.dateStart")} /></Item>
|
{reportOption === '1' &&
|
||||||
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={i18n.t("reports.dateEnd")} /></Item>
|
<div>
|
||||||
|
<label>
|
||||||
|
Filas
|
||||||
|
<Switch
|
||||||
|
checked={checked}
|
||||||
|
onChange={handleChange}
|
||||||
|
inputProps={{ 'aria-label': 'controlled' }}
|
||||||
|
/>
|
||||||
|
Usuarios
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<Item sx={{ display: 'grid', gridColumn: '4 / 5', }}>
|
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
|
||||||
|
<DatePicker1 func={datePicker1Value} minDate={false} startEmpty={false} title={i18n.t("reports.dateStart")} />
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={i18n.t("reports.dateEnd")} /></Box>
|
||||||
|
|
||||||
|
{reportOption === '1' ?
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', padding: '10px 0', }}>
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Checkbox checked={selectedValue === 'created'} onChange={() => handleCheckBoxChange('created')} />}
|
||||||
|
label="Criado"
|
||||||
|
/>
|
||||||
|
<FormControlLabel
|
||||||
|
control={<Checkbox checked={selectedValue === 'updated'} onChange={() => handleCheckBoxChange('updated')} />}
|
||||||
|
label="Atualizado"
|
||||||
|
/>
|
||||||
|
</Box> :
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', padding: '10px 0', }}>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
|
|
||||||
|
<Box sx={{ display: 'flex', flexDirection: 'column', padding: '10px 0', gap: '8px', width: '100px', alignItems: 'center' }}>
|
||||||
|
|
||||||
<ReportModal currencies={reporList} func={reportValue} reportOption={reportOption} />
|
<ReportModal currencies={reporList} func={reportValue} reportOption={reportOption} />
|
||||||
|
|
||||||
|
@ -688,7 +769,7 @@ const Report = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</Item>
|
</Box>
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
@ -701,7 +782,6 @@ const Report = () => {
|
||||||
{reportOption === '1' &&
|
{reportOption === '1' &&
|
||||||
|
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<MTable data={query}
|
<MTable data={query}
|
||||||
columns={userA.profile !== 'supervisor' ? columnsData : columnsDataSuper}
|
columns={userA.profile !== 'supervisor' ? columnsData : columnsDataSuper}
|
||||||
hasChild={true}
|
hasChild={true}
|
||||||
|
@ -710,7 +790,6 @@ const Report = () => {
|
||||||
handleScroll={handleScroll}
|
handleScroll={handleScroll}
|
||||||
|
|
||||||
table_title={i18n.t("reports.listTitles.title1_1")} />
|
table_title={i18n.t("reports.listTitles.title1_1")} />
|
||||||
|
|
||||||
</>
|
</>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue