Correção de conflito no merge
commit
b5ec63b02c
|
@ -10,7 +10,7 @@ import "./database";
|
|||
import uploadConfig from "./config/upload";
|
||||
import AppError from "./errors/AppError";
|
||||
import routes from "./routes";
|
||||
import { logger } from "./utils/logger";
|
||||
import { logger } from "./utils/logger";
|
||||
|
||||
Sentry.init({ dsn: process.env.SENTRY_DSN });
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
const { ticketId } = req.params;
|
||||
const { body, quotedMsg }: MessageData = req.body;
|
||||
const medias = req.files as Express.Multer.File[];
|
||||
|
||||
|
||||
const ticket = await ShowTicketService(ticketId);
|
||||
|
||||
SetTicketMessagesAsRead(ticket);
|
||||
|
@ -51,6 +51,9 @@ export const store = async (req: Request, res: Response): Promise<Response> => {
|
|||
})
|
||||
);
|
||||
} else {
|
||||
|
||||
console.log('------- quotedMsg: ', quotedMsg)
|
||||
|
||||
await SendWhatsAppMessage({ body, ticket, quotedMsg });
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ import UpdateTicketService from "../services/TicketServices/UpdateTicketService"
|
|||
import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage";
|
||||
import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService";
|
||||
|
||||
import CreateSchedulingNotifyService from "../services/SchedulingNotifyServices/CreateSchedulingNotifyService";
|
||||
|
||||
|
||||
|
||||
|
||||
type IndexQuery = {
|
||||
|
@ -29,6 +32,7 @@ interface TicketData {
|
|||
}
|
||||
|
||||
|
||||
import ListScheduleService from "../services/ScheduleService/ListScheduleService";
|
||||
|
||||
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||
const {
|
||||
|
@ -66,6 +70,11 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
|||
export const store = async (req: Request, res: Response): Promise<Response> => {
|
||||
const { contactId, status, userId }: TicketData = req.body;
|
||||
|
||||
// naty
|
||||
// console.log(
|
||||
// `contactId: ${contactId} \n| status: ${status} \n| userId: ${userId}`
|
||||
// )
|
||||
|
||||
const ticket = await CreateTicketService({ contactId, status, userId });
|
||||
|
||||
const io = getIO();
|
||||
|
@ -83,37 +92,109 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
|||
|
||||
const contact = await ShowTicketService(ticketId);
|
||||
|
||||
//console.log('------- contact: ',JSON.stringify(contact))
|
||||
const { schedules, count, hasMore } = await ListScheduleService({ searchParam: "", pageNumber: "1" });
|
||||
|
||||
return res.status(200).json(contact);
|
||||
// return res.status(200).json(contact);
|
||||
|
||||
return res.status(200).json({contact, schedules});
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
): Promise<Response> => {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export const update = async ( req: Request, res: Response ): Promise<Response> => {
|
||||
|
||||
const { ticketId } = req.params;
|
||||
const ticketData: TicketData = req.body;
|
||||
|
||||
const { ticket } = await UpdateTicketService({
|
||||
ticketData,
|
||||
ticketId
|
||||
});
|
||||
let ticket2 = {}
|
||||
|
||||
if(req.body['status'] === "closed"){
|
||||
|
||||
if (ticket.status === "closed") {
|
||||
const {status, userId, schedulingNotifyData} = req.body;
|
||||
|
||||
const { ticket } = await UpdateTicketService({
|
||||
ticketData:{'status': status, 'userId': userId},
|
||||
ticketId
|
||||
});
|
||||
|
||||
|
||||
///////////////////////////////
|
||||
const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
||||
|
||||
const { farewellMessage } = whatsapp;
|
||||
|
||||
if (farewellMessage) {
|
||||
await SendWhatsAppMessage({ body: farewellMessage, ticket });
|
||||
}
|
||||
///////////////////////////////
|
||||
|
||||
// agendamento
|
||||
const scheduleData = JSON.parse(schedulingNotifyData)
|
||||
|
||||
if( scheduleData.scheduleId != '1'){
|
||||
const schedulingNotifyCreate = await CreateSchedulingNotifyService(
|
||||
{
|
||||
ticketId: scheduleData.ticketId,
|
||||
scheduleId: scheduleData.scheduleId,
|
||||
schedulingDate: scheduleData.schedulingDate,
|
||||
message: scheduleData.message
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
ticket2 = ticket
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
const ticketData: TicketData = req.body;
|
||||
|
||||
return res.status(200).json(ticket);
|
||||
const { ticket } = await UpdateTicketService({
|
||||
ticketData,
|
||||
ticketId
|
||||
});
|
||||
|
||||
ticket2 = ticket
|
||||
|
||||
}
|
||||
|
||||
return res.status(200).json(ticket2);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// export const update = async (
|
||||
// req: Request,
|
||||
// res: Response
|
||||
// ): Promise<Response> => {
|
||||
// const { ticketId } = req.params;
|
||||
// const ticketData: TicketData = req.body;
|
||||
|
||||
// const { ticket } = await UpdateTicketService({
|
||||
// ticketData,
|
||||
// ticketId
|
||||
// });
|
||||
|
||||
// if (ticket.status === "closed") {
|
||||
// const whatsapp = await ShowWhatsAppService(ticket.whatsappId);
|
||||
|
||||
// const { farewellMessage } = whatsapp;
|
||||
|
||||
// if (farewellMessage) {
|
||||
// await SendWhatsAppMessage({ body: farewellMessage, ticket });
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// return res.status(200).json(ticket);
|
||||
// };
|
||||
|
||||
export const remove = async (
|
||||
req: Request,
|
||||
res: Response
|
||||
|
|
|
@ -11,6 +11,10 @@ import WhatsappQueue from "../models/WhatsappQueue";
|
|||
import UserQueue from "../models/UserQueue";
|
||||
import QuickAnswer from "../models/QuickAnswer";
|
||||
|
||||
import SchedulingNotify from "../models/SchedulingNotify";
|
||||
import Schedule from "../models/Schedule";
|
||||
|
||||
|
||||
// eslint-disable-next-line
|
||||
const dbConfig = require("../config/database");
|
||||
// import dbConfig from "../config/database";
|
||||
|
@ -28,7 +32,10 @@ const models = [
|
|||
Queue,
|
||||
WhatsappQueue,
|
||||
UserQueue,
|
||||
QuickAnswer
|
||||
QuickAnswer,
|
||||
|
||||
SchedulingNotify,
|
||||
Schedule,
|
||||
];
|
||||
|
||||
sequelize.addModels(models);
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
import { QueryInterface, DataTypes } from "sequelize";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.createTable("Schedules", {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
name: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.dropTable("Schedules");
|
||||
}
|
||||
};
|
|
@ -0,0 +1,48 @@
|
|||
import { QueryInterface, DataTypes } from "sequelize";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.createTable("SchedulingNotifies", {
|
||||
id: {
|
||||
type: DataTypes.INTEGER,
|
||||
autoIncrement: true,
|
||||
primaryKey: true,
|
||||
allowNull: false
|
||||
},
|
||||
scheduleId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: { model: "Schedules", key: "id" },
|
||||
onUpdate: "CASCADE",
|
||||
onDelete: "CASCADE",
|
||||
allowNull: false
|
||||
},
|
||||
ticketId: {
|
||||
type: DataTypes.INTEGER,
|
||||
references: { model: "Tickets", key: "id" },
|
||||
onUpdate: "CASCADE",
|
||||
onDelete: "CASCADE",
|
||||
allowNull: false
|
||||
},
|
||||
schedulingDate: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
},
|
||||
message: {
|
||||
type: DataTypes.STRING,
|
||||
allowNull: false
|
||||
},
|
||||
createdAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
},
|
||||
updatedAt: {
|
||||
type: DataTypes.DATE,
|
||||
allowNull: false
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.dropTable("SchedulingNotifies");
|
||||
}
|
||||
};
|
|
@ -6,10 +6,10 @@ module.exports = {
|
|||
"Users",
|
||||
[
|
||||
{
|
||||
name: "Administrador",
|
||||
email: "admin@whaticket.com",
|
||||
passwordHash: "$2a$08$WaEmpmFDD/XkDqorkpQ42eUZozOqRCPkPcTkmHHMyuTGUOkI8dHsq",
|
||||
profile: "admin",
|
||||
name: "grupohit",
|
||||
email: "grupohit@communication.com",
|
||||
passwordHash: "$2a$08$98TKVkUCDr6ulrxIaRXFlup4U7CJtvHqK94I5pwvuh7VhOBKeL0pO",
|
||||
profile: "master",
|
||||
tokenVersion: 0,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
import { QueryInterface } from "sequelize";
|
||||
|
||||
module.exports = {
|
||||
up: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.bulkInsert(
|
||||
"Schedules",
|
||||
[
|
||||
{
|
||||
name: "SEM RETORNO DO CLIENTE",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
},
|
||||
{
|
||||
name: "AGENDAMENTO À CONFIRMAR",
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
}
|
||||
],
|
||||
{}
|
||||
);
|
||||
},
|
||||
|
||||
down: (queryInterface: QueryInterface) => {
|
||||
return queryInterface.bulkDelete("Schedules", {});
|
||||
}
|
||||
};
|
|
@ -0,0 +1,76 @@
|
|||
import SetTicketMessagesAsRead from "../helpers/SetTicketMessagesAsRead";
|
||||
import ShowTicketService from "../services/TicketServices/ShowTicketService";
|
||||
import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage";
|
||||
|
||||
import ListSchedulingNotifyService from "../services/SchedulingNotifyServices/ListSchedulingNotifyService";
|
||||
import DeleteSchedulingNotifyService from "../services/SchedulingNotifyServices/DeleteSchedulingNotifyService";
|
||||
|
||||
let countTest: number = 0
|
||||
let scheduler_monitor:any;
|
||||
|
||||
// const test = async () => {
|
||||
|
||||
// const ticket = await ShowTicketService('336');
|
||||
|
||||
// SetTicketMessagesAsRead(ticket);
|
||||
|
||||
// await SendWhatsAppMessage({ body: 'Olá Sr Adriano, estamos entrando em contato para confirmar seu retorno hoje', ticket });
|
||||
|
||||
// }
|
||||
|
||||
|
||||
const monitor = async () => {
|
||||
countTest += 1
|
||||
console.log(`${countTest}`)
|
||||
|
||||
|
||||
let date = new Date()
|
||||
|
||||
let day = date.getDate().toString().padStart(2, '0');
|
||||
let month = (date.getMonth()+1).toString().padStart(2, '0');
|
||||
let year = date.getFullYear();
|
||||
|
||||
let hour = date.getHours()
|
||||
let minute = date.getMinutes()
|
||||
|
||||
let fullDate = `${year}-${month}-${day}`;
|
||||
let dateParm = `${fullDate} ${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}:00`
|
||||
|
||||
console.log(dateParm);
|
||||
|
||||
|
||||
const { schedulingNotifies, count, hasMore } = await ListSchedulingNotifyService({ searchParam: dateParm, pageNumber: "1" });
|
||||
|
||||
if(schedulingNotifies.length){
|
||||
|
||||
const ticket = await ShowTicketService(schedulingNotifies[0].ticketId);
|
||||
|
||||
SetTicketMessagesAsRead(ticket);
|
||||
|
||||
await SendWhatsAppMessage({
|
||||
body: schedulingNotifies[0].message, ticket
|
||||
});
|
||||
|
||||
DeleteSchedulingNotifyService(schedulingNotifies[0].id)
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const startSchedulingMonitor =async (mileseconds: number) => {
|
||||
|
||||
scheduler_monitor = setInterval(monitor, mileseconds)
|
||||
|
||||
}
|
||||
|
||||
|
||||
export const stopSchedulingMonitor =async ( ) => {
|
||||
|
||||
clearInterval(scheduler_monitor)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import {
|
||||
Table,
|
||||
AutoIncrement,
|
||||
Column,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
Model,
|
||||
PrimaryKey,
|
||||
HasMany
|
||||
} from "sequelize-typescript";
|
||||
|
||||
import SchedulingNotify from "./SchedulingNotify";
|
||||
|
||||
@Table
|
||||
class Schedule extends Model<Schedule> {
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column
|
||||
id: number;
|
||||
|
||||
@Column
|
||||
name: string;
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date;
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date;
|
||||
|
||||
@HasMany(() => SchedulingNotify)
|
||||
SchedulingNotifies: SchedulingNotify[];
|
||||
}
|
||||
|
||||
export default Schedule;
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
import {
|
||||
Table,
|
||||
AutoIncrement,
|
||||
Column,
|
||||
CreatedAt,
|
||||
UpdatedAt,
|
||||
Model,
|
||||
PrimaryKey,
|
||||
ForeignKey,
|
||||
BelongsTo
|
||||
} from "sequelize-typescript";
|
||||
|
||||
import Schedule from "./Schedule";
|
||||
import Ticket from "./Ticket";
|
||||
|
||||
@Table
|
||||
class SchedulingNotify extends Model<SchedulingNotify> {
|
||||
@PrimaryKey
|
||||
@AutoIncrement
|
||||
@Column
|
||||
id: number;
|
||||
|
||||
@ForeignKey(() => Schedule)
|
||||
@Column
|
||||
scheduleId: number;
|
||||
|
||||
@BelongsTo(() => Schedule)
|
||||
schedule: Schedule;
|
||||
|
||||
|
||||
@ForeignKey(() => Ticket)
|
||||
@Column
|
||||
ticketId: number;
|
||||
|
||||
@BelongsTo(() => Ticket)
|
||||
ticket: Ticket;
|
||||
|
||||
@Column
|
||||
schedulingDate: Date;
|
||||
|
||||
@Column
|
||||
message: string
|
||||
|
||||
@CreatedAt
|
||||
createdAt: Date;
|
||||
|
||||
@UpdatedAt
|
||||
updatedAt: Date;
|
||||
}
|
||||
|
||||
export default SchedulingNotify;
|
||||
|
|
@ -8,6 +8,7 @@ import {
|
|||
ForeignKey,
|
||||
BelongsTo,
|
||||
HasMany,
|
||||
HasOne,
|
||||
AutoIncrement,
|
||||
Default
|
||||
} from "sequelize-typescript";
|
||||
|
@ -18,6 +19,8 @@ import Queue from "./Queue";
|
|||
import User from "./User";
|
||||
import Whatsapp from "./Whatsapp";
|
||||
|
||||
import SchedulingNotify from "./SchedulingNotify";
|
||||
|
||||
@Table
|
||||
class Ticket extends Model<Ticket> {
|
||||
@PrimaryKey
|
||||
|
@ -74,6 +77,9 @@ class Ticket extends Model<Ticket> {
|
|||
|
||||
@HasMany(() => Message)
|
||||
messages: Message[];
|
||||
|
||||
@HasOne(() => SchedulingNotify)
|
||||
schedulingNotify: SchedulingNotify
|
||||
}
|
||||
|
||||
export default Ticket;
|
||||
|
|
|
@ -11,12 +11,7 @@ const upload = multer(uploadConfig);
|
|||
|
||||
messageRoutes.get("/messages/:ticketId", isAuth, MessageController.index);
|
||||
|
||||
messageRoutes.post(
|
||||
"/messages/:ticketId",
|
||||
isAuth,
|
||||
upload.array("medias"),
|
||||
MessageController.store
|
||||
);
|
||||
messageRoutes.post("/messages/:ticketId", isAuth, upload.array("medias"), MessageController.store);
|
||||
|
||||
messageRoutes.delete("/messages/:messageId", isAuth, MessageController.remove);
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import { initIO } from "./libs/socket";
|
|||
import { logger } from "./utils/logger";
|
||||
import { StartAllWhatsAppsSessions } from "./services/WbotServices/StartAllWhatsAppsSessions";
|
||||
|
||||
import { startSchedulingMonitor } from "./helpers/SchedulingNotifySendMessage"
|
||||
|
||||
const server = app.listen(process.env.PORT, () => {
|
||||
logger.info(`Server started on port: ${process.env.PORT}`);
|
||||
});
|
||||
|
@ -11,3 +13,5 @@ const server = app.listen(process.env.PORT, () => {
|
|||
initIO(server);
|
||||
StartAllWhatsAppsSessions();
|
||||
gracefulShutdown(server);
|
||||
|
||||
startSchedulingMonitor(5000)
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { Sequelize } from "sequelize";
|
||||
import Schedule from "../../models/Schedule";
|
||||
|
||||
interface Request {
|
||||
searchParam?: string;
|
||||
pageNumber?: string;
|
||||
}
|
||||
|
||||
interface Response {
|
||||
schedules: Schedule[];
|
||||
count: number;
|
||||
hasMore: boolean;
|
||||
}
|
||||
|
||||
const ListSchedulingService = async ({
|
||||
searchParam = "",
|
||||
pageNumber = "1"
|
||||
}: Request): Promise<Response> => {
|
||||
const whereCondition = {
|
||||
message: Sequelize.where(
|
||||
Sequelize.fn("LOWER", Sequelize.col("name")), "LIKE", `%${searchParam.toLowerCase().trim()}%`)
|
||||
};
|
||||
const limit = 20;
|
||||
const offset = limit * (+pageNumber - 1);
|
||||
|
||||
const { count, rows: schedules } = await Schedule.findAndCountAll({
|
||||
where: whereCondition,
|
||||
attributes: ['id', 'name'],
|
||||
limit,
|
||||
offset,
|
||||
order: [["id", "ASC"]]
|
||||
});
|
||||
|
||||
const hasMore = count > offset + schedules.length;
|
||||
|
||||
return {
|
||||
schedules,
|
||||
count,
|
||||
hasMore
|
||||
};
|
||||
};
|
||||
|
||||
export default ListSchedulingService;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
import AppError from "../../errors/AppError";
|
||||
import SchedulingNotify from "../../models/SchedulingNotify";
|
||||
|
||||
|
||||
interface Request {
|
||||
ticketId: string,
|
||||
scheduleId: string,
|
||||
schedulingDate: string,
|
||||
message: string
|
||||
}
|
||||
|
||||
|
||||
const CreateSchedulingNotifyService = async (
|
||||
{
|
||||
ticketId,
|
||||
scheduleId,
|
||||
schedulingDate,
|
||||
message
|
||||
|
||||
}: Request): Promise<SchedulingNotify> => {
|
||||
|
||||
const schedulingNotify = await SchedulingNotify.create(
|
||||
{
|
||||
ticketId,
|
||||
scheduleId,
|
||||
schedulingDate,
|
||||
message
|
||||
|
||||
})
|
||||
|
||||
return schedulingNotify
|
||||
}
|
||||
|
||||
export default CreateSchedulingNotifyService
|
|
@ -0,0 +1,17 @@
|
|||
import AppError from "../../errors/AppError";
|
||||
import SchedulingNotify from "../../models/SchedulingNotify";
|
||||
|
||||
|
||||
const DeleteSchedulingNotifyService = async (id: string | number): Promise<void> => {
|
||||
const schedulingNotify = await SchedulingNotify.findOne({
|
||||
where: { id }
|
||||
});
|
||||
|
||||
if (!schedulingNotify) {
|
||||
throw new AppError("ERR_NO_SCHEDULING_NOTIFY_FOUND", 404);
|
||||
}
|
||||
|
||||
await schedulingNotify.destroy();
|
||||
};
|
||||
|
||||
export default DeleteSchedulingNotifyService;
|
|
@ -0,0 +1,68 @@
|
|||
import { Op, Sequelize } from "sequelize";
|
||||
import SchedulingNotify from "../../models/SchedulingNotify";
|
||||
|
||||
interface Request {
|
||||
searchParam?: string;
|
||||
pageNumber?: string;
|
||||
}
|
||||
|
||||
interface Response {
|
||||
schedulingNotifies: SchedulingNotify[];
|
||||
count: number;
|
||||
hasMore: boolean;
|
||||
}
|
||||
|
||||
const ListSchedulingNotifyService = async ({
|
||||
searchParam = "",
|
||||
pageNumber = "1"
|
||||
}: Request): Promise<Response> => {
|
||||
// const whereCondition = {
|
||||
// message: Sequelize.where(
|
||||
|
||||
// Sequelize.fn("date", Sequelize.col("schedulingDate")), `${searchParam.toLowerCase().trim()}`,
|
||||
|
||||
// ),
|
||||
|
||||
// };
|
||||
|
||||
let date = searchParam.split(' ')[0]
|
||||
let hour = searchParam.split(' ')[1].split(':')[0]
|
||||
let minute = searchParam.split(' ')[1].split(':')[1]
|
||||
|
||||
const whereCondition = {
|
||||
[Op.and]: [
|
||||
{
|
||||
"$schedulingDate$": Sequelize.where(Sequelize.fn("date", Sequelize.col("schedulingDate")), `${date.trim()}`)
|
||||
},
|
||||
{
|
||||
"$schedulingDate$": Sequelize.where(Sequelize.fn("hour", Sequelize.col("schedulingDate")), `${hour.trim()}`)
|
||||
},
|
||||
{
|
||||
"$schedulingDate$": Sequelize.where(Sequelize.fn("minute", Sequelize.col("schedulingDate")), `${minute.trim()}`)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
const limit = 1;
|
||||
const offset = limit * (+pageNumber - 1);
|
||||
|
||||
const { count, rows: schedulingNotifies } = await SchedulingNotify.findAndCountAll({
|
||||
raw: true,
|
||||
where: whereCondition,
|
||||
limit,
|
||||
offset,
|
||||
order: [["id", "ASC"]]
|
||||
});
|
||||
|
||||
const hasMore = count > offset + schedulingNotifies.length;
|
||||
|
||||
return {
|
||||
schedulingNotifies,
|
||||
count,
|
||||
hasMore
|
||||
};
|
||||
};
|
||||
|
||||
export default ListSchedulingNotifyService;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import AppError from "../../errors/AppError";
|
||||
import SchedulingNotify from "../../models/SchedulingNotify";
|
||||
|
||||
const ShowSchedulingNotifyService = async (id: string): Promise<SchedulingNotify> => {
|
||||
|
||||
const schedulingNotify = await SchedulingNotify.findByPk(id);
|
||||
|
||||
if (!schedulingNotify) {
|
||||
throw new AppError("ERR_NO_SCHEDULING_NOTIFY_FOUND", 404);
|
||||
}
|
||||
|
||||
return schedulingNotify;
|
||||
};
|
||||
|
||||
export default ShowSchedulingNotifyService;
|
|
@ -0,0 +1,39 @@
|
|||
import AppError from "../../errors/AppError";
|
||||
import SchedulingNotify from "../../models/SchedulingNotify";
|
||||
|
||||
|
||||
interface SchedulingData {
|
||||
name?: string
|
||||
}
|
||||
|
||||
interface Request {
|
||||
schedulingData: SchedulingData
|
||||
schedulingDataId: string
|
||||
}
|
||||
|
||||
const UpdateSchedulingNotify = async ({
|
||||
schedulingData,
|
||||
schedulingDataId
|
||||
|
||||
}: Request): Promise<SchedulingNotify> => {
|
||||
const { name } = schedulingData;
|
||||
|
||||
const updateScheduling = await SchedulingNotify.findOne({
|
||||
where: { id: schedulingDataId },
|
||||
attributes: ["id", "name"]
|
||||
});
|
||||
|
||||
if (!updateScheduling) {
|
||||
//console.log('NOT FOUND SCHEDULING NOTIFY')
|
||||
throw new AppError("ERR_NO_SCHEDULING_NOTIFY_FOUND", 404);
|
||||
}
|
||||
await updateScheduling.update({ name });
|
||||
|
||||
await updateScheduling.reload({
|
||||
attributes: ["id", "name"]
|
||||
});
|
||||
|
||||
return updateScheduling;
|
||||
};
|
||||
|
||||
export default UpdateSchedulingNotify;
|
|
@ -5,8 +5,8 @@
|
|||
"dependencies": {
|
||||
"@date-io/date-fns": "^1.3.13",
|
||||
"@emotion/react": "^11.7.1",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@material-ui/core": "^4.11.0",
|
||||
"@emotion/styled": "^11.6.0",
|
||||
"@material-ui/core": "^4.12.1",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.56",
|
||||
"@material-ui/pickers": "^3.3.10",
|
||||
|
|
|
@ -0,0 +1,306 @@
|
|||
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import Button from '@mui/material/Button';
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogActions from '@mui/material/DialogActions';
|
||||
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DialogContentText from '@mui/material/DialogContentText';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import Box from '@mui/material/Box';
|
||||
|
||||
import SelectField from "../../Report/SelectField";
|
||||
import DatePicker from '../../Report/DatePicker'
|
||||
|
||||
import TimerPickerSelect from '../TimerPickerSelect'
|
||||
import TextArea1 from '../TextArea'
|
||||
|
||||
|
||||
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
||||
|
||||
import { subHours, addHours } from "date-fns";
|
||||
import { LocalConvenienceStoreOutlined } from '@material-ui/icons';
|
||||
|
||||
const Item = (props) => {
|
||||
|
||||
const { sx, ...other } = props;
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
bgcolor: (theme) => (theme.palette.mode === 'dark' ? '#101010' : '#fff'),
|
||||
color: (theme) => (theme.palette.mode === 'dark' ? 'grey.300' : 'grey.800'),
|
||||
border: '1px solid',
|
||||
borderColor: (theme) =>
|
||||
theme.palette.mode === 'dark' ? 'grey.800' : 'grey.300',
|
||||
p: 1,
|
||||
m: 1,
|
||||
borderRadius: 2,
|
||||
fontSize: '0.875rem',
|
||||
fontWeight: '700',
|
||||
...sx,
|
||||
}}
|
||||
{...other}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Item.propTypes = {
|
||||
sx: PropTypes.oneOfType([
|
||||
PropTypes.arrayOf(
|
||||
PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool]),
|
||||
),
|
||||
PropTypes.func,
|
||||
PropTypes.object,
|
||||
]),
|
||||
};
|
||||
|
||||
|
||||
const Modal = (props) => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const [scroll, /*setScroll*/] = useState('body');
|
||||
const [scheduleId, setScheduling] = useState(null)
|
||||
const [startDate, setDatePicker] = useState(new Date())
|
||||
const [timerPicker, setTimerPicker] = useState(new Date())
|
||||
const [textArea1, setTextArea1] = useState()
|
||||
const [greetRemember, setGreet] = useState('')
|
||||
|
||||
|
||||
const [data] = useState(props.schedules)
|
||||
const [chatEnd, setChatEnd] = useState(false)
|
||||
|
||||
const handleCancel = (event, reason) => {
|
||||
|
||||
if (reason && reason === "backdropClick")
|
||||
return;
|
||||
|
||||
setChatEnd(null)
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
|
||||
function greetMessageSchedule(scheduleDate){
|
||||
return `podemos confirmar sua consulta agendada para hoje às ${scheduleDate}?`
|
||||
}
|
||||
|
||||
function formatedTimeHour(timer){
|
||||
return `${timer.getHours().toString().padStart(2, '0')}:${timer.getMinutes().toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
const handleChatEnd = (event, reason) => {
|
||||
|
||||
|
||||
if (reason && reason === "backdropClick")
|
||||
return;
|
||||
|
||||
if (scheduleId === '1'){
|
||||
}
|
||||
else if(textArea1.trim().length<10){
|
||||
alert('Mensagem muito curta!\nMínimo 10 caracteres.')
|
||||
return
|
||||
}
|
||||
else if((new Date(timerPicker).getHours() > 16 && new Date(timerPicker).getMinutes() > 0) ||
|
||||
(new Date(timerPicker).getHours() < 7)){
|
||||
alert('Horário comercial inválido!\n Selecione um horário de lembrete válido entre às 07:00 e 17:00')
|
||||
return
|
||||
}
|
||||
else if((new Date(startDate).toISOString().slice(0, 10) === new Date().toISOString().slice(0, 10))){
|
||||
|
||||
if(((new Date(timerPicker).getHours() == new Date().getHours()) &&
|
||||
(new Date(timerPicker).getMinutes() <= new Date().getMinutes())) ||
|
||||
(new Date(timerPicker).getHours() < new Date().getHours())
|
||||
){
|
||||
alert('Para agendamentos do dia, é necessário que o horário do lembrete seja maior que o horário atual!')
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setChatEnd({
|
||||
|
||||
'scheduleId': scheduleId,
|
||||
'schedulingDate': `${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:${timerPicker.getSeconds()}`,
|
||||
'message': textArea1
|
||||
|
||||
})
|
||||
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
props.func(chatEnd);
|
||||
|
||||
}, [chatEnd])
|
||||
|
||||
|
||||
const descriptionElementRef = useRef(null);
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
const { current: descriptionElement } = descriptionElementRef;
|
||||
if (descriptionElement !== null) {
|
||||
descriptionElement.focus();
|
||||
}
|
||||
}
|
||||
}, [open]);
|
||||
|
||||
|
||||
// Get from child 1
|
||||
const textFieldSelect = (data) => {
|
||||
console.log('textFieldSelect: ',data);
|
||||
setScheduling(data)
|
||||
}
|
||||
|
||||
// Get from child 2
|
||||
const datePickerValue = (data) => {
|
||||
console.log('datePickerValue: ',(data));
|
||||
setDatePicker(data)
|
||||
}
|
||||
|
||||
// Get from child 3
|
||||
const timerPickerValue = (data) => {
|
||||
console.log('timerPickerValue: ',(data));
|
||||
setTimerPicker(data)
|
||||
}
|
||||
|
||||
// Get from child 4
|
||||
// const textArea1Value = (data) => {
|
||||
// console.log('textArea1Value: ',(data));
|
||||
// setTextArea1(data)
|
||||
// }
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
if (parseInt(timerPicker.getHours()) > 12 && parseInt(timerPicker.getHours()) < 18){
|
||||
setTextArea1('Boa tarde, '+greetMessageSchedule( formatedTimeHour(addHours(new Date(timerPicker), 1))))
|
||||
}
|
||||
else if(parseInt(timerPicker.getHours()) < 12){
|
||||
setTextArea1('Bom dia, '+greetMessageSchedule( formatedTimeHour(addHours(new Date(timerPicker), 1))))
|
||||
}
|
||||
else if(parseInt(timerPicker.getHours()) > 18){
|
||||
|
||||
setTextArea1('Boa noite, '+greetMessageSchedule( formatedTimeHour(addHours(new Date(timerPicker), 1))))
|
||||
}
|
||||
|
||||
|
||||
|
||||
// console.log(
|
||||
// 'addHours(new Date(timerPicker), 1): ', addHours(new Date(timerPicker), 1).getHours(),
|
||||
// '\naddHours(new Date(timerPicker), 1): ', addHours(new Date(timerPicker), 1).getMinutes()
|
||||
|
||||
// )
|
||||
|
||||
|
||||
|
||||
},[timerPicker])
|
||||
|
||||
|
||||
const handleChange = (event) => {
|
||||
|
||||
setTextArea1(event.target.value);
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
|
||||
<Dialog
|
||||
open={open}
|
||||
onClose={handleCancel}
|
||||
// fullWidth={true}
|
||||
// maxWidth={true}
|
||||
disableEscapeKeyDown
|
||||
|
||||
scroll={scroll}
|
||||
aria-labelledby="scroll-dialog-title"
|
||||
aria-describedby="scroll-dialog-description"
|
||||
>
|
||||
|
||||
<DialogTitle id="scroll-dialog-title">{props.modal_header}</DialogTitle>
|
||||
<DialogContent dividers={scroll === 'body'}>
|
||||
|
||||
<DialogContentText
|
||||
id="scroll-dialog-description"
|
||||
ref={descriptionElementRef}
|
||||
tabIndex={-1}
|
||||
>
|
||||
|
||||
</DialogContentText>
|
||||
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
width: 500,
|
||||
height: '100%',
|
||||
// backgroundColor: 'primary.dark',
|
||||
// '&:hover': {backgroundColor: 'primary.main', opacity: [0.9, 0.8, 0.7],},
|
||||
}}>
|
||||
|
||||
<Box sx={{
|
||||
display: 'grid',
|
||||
}}>
|
||||
<Item>
|
||||
<span>Selecione uma opção para encerrar o Atendimento</span>
|
||||
|
||||
<Item>
|
||||
<SelectField func={textFieldSelect} emptyField={false} header={'Opções de encerramento do atendimento'} currencies={data.map((obj)=>{
|
||||
return {'value': obj.id, 'label': obj.name}
|
||||
})}/>
|
||||
</Item>
|
||||
|
||||
</Item>
|
||||
|
||||
</Box>
|
||||
|
||||
{scheduleId==='2' &&
|
||||
|
||||
<Item>
|
||||
|
||||
<span>Lembrete de retorno</span>
|
||||
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}>
|
||||
|
||||
<Item><DatePicker func={datePickerValue} title={'Data do retorno'}/></Item>
|
||||
|
||||
<Item><TimerPickerSelect func={timerPickerValue} title={'Hora do lembrete'}/></Item>
|
||||
|
||||
</Box>
|
||||
|
||||
|
||||
<Box sx={{display: 'flex', flexDirection: 'column' }}>
|
||||
|
||||
{/* <Item><TextArea1 func={textArea1Value} greetRemember={greetRemember} hint={'Mensagem para cliente'}/></Item> */}
|
||||
<Item>
|
||||
<TextareaAutosize
|
||||
aria-label="minimum height"
|
||||
minRows={3}
|
||||
value={textArea1}
|
||||
placeholder={'Mensagem para lembrar cliente'}
|
||||
onChange={ handleChange}
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
</Item>
|
||||
</Box>
|
||||
|
||||
</Item>
|
||||
}
|
||||
|
||||
</Box>
|
||||
</DialogContent>
|
||||
|
||||
|
||||
<DialogActions>
|
||||
<div style={{marginRight:'50px'}}>
|
||||
<Button onClick={handleCancel}>Cancelar</Button>
|
||||
</div>
|
||||
<Button onClick={handleChatEnd}>Ok</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default Modal
|
|
@ -0,0 +1,35 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import TextareaAutosize from '@mui/material/TextareaAutosize';
|
||||
|
||||
const MinHeightTextarea = (props) => {
|
||||
|
||||
const [value, setValue] = useState('');
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
props.func(value);
|
||||
|
||||
}, [value])
|
||||
|
||||
const handleChange = (event) => {
|
||||
|
||||
setValue(event.target.value);
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<TextareaAutosize
|
||||
aria-label="minimum height"
|
||||
minRows={3}
|
||||
placeholder={props.hint}
|
||||
|
||||
defaultValue={props.greetRemember}
|
||||
|
||||
onChange={ handleChange}
|
||||
|
||||
style={{ width: '100%' }}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default MinHeightTextarea;
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
|
||||
|
||||
// import React, { useState } from "react";
|
||||
// import { DateTimePicker, KeyboardDateTimePicker } from "@material-ui/pickers";
|
||||
|
||||
// function InlineDateTimePickerDemo(props) {
|
||||
// const [selectedDate, handleDateChange] = useState(new Date("2018-01-01T00:00:00.000Z"));
|
||||
|
||||
// return (
|
||||
// <>
|
||||
// <DateTimePicker
|
||||
// variant="inline"
|
||||
// label="Basic example"
|
||||
// value={selectedDate}
|
||||
// onChange={handleDateChange}
|
||||
// />
|
||||
|
||||
// <KeyboardDateTimePicker
|
||||
// variant="inline"
|
||||
// ampm={false}
|
||||
// label="With keyboard"
|
||||
// value={selectedDate}
|
||||
// onChange={handleDateChange}
|
||||
// onError={console.log}
|
||||
// disablePast
|
||||
// format="yyyy/MM/dd HH:mm"
|
||||
// />
|
||||
// </>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default InlineDateTimePickerDemo;
|
||||
|
||||
|
||||
|
||||
import React, { Fragment, useState, useEffect } from "react";
|
||||
// import TextField from '@mui/material/TextField';
|
||||
import DateFnsUtils from '@date-io/date-fns';
|
||||
|
||||
import {
|
||||
TimePicker,
|
||||
MuiPickersUtilsProvider,
|
||||
} from '@material-ui/pickers';
|
||||
|
||||
|
||||
import ptBrLocale from "date-fns/locale/pt-BR";
|
||||
|
||||
|
||||
const ResponsiveTimePickers = (props) => {
|
||||
|
||||
const [value, setValue] = useState(new Date());
|
||||
|
||||
// props.func(value);
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
props.func(value);
|
||||
|
||||
}, [value])
|
||||
|
||||
return (
|
||||
|
||||
<Fragment>
|
||||
|
||||
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
|
||||
<TimePicker
|
||||
variant="outline"
|
||||
label={props.title}
|
||||
value={value}
|
||||
ampm={false}
|
||||
onChange={(newValue) => {
|
||||
setValue(newValue);
|
||||
}}
|
||||
// Ativar se necessario
|
||||
// renderInput={(params) => <TextField {...params} />}
|
||||
|
||||
/>
|
||||
</MuiPickersUtilsProvider>
|
||||
|
||||
</Fragment>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default ResponsiveTimePickers
|
|
@ -585,7 +585,8 @@ const MessageInput = ({ ticketStatus }) => {
|
|||
: i18n.t("messagesInput.placeholderClosed")
|
||||
}
|
||||
multiline
|
||||
rowsMax={5}
|
||||
// rowsMax={5}
|
||||
maxRows={5}
|
||||
value={inputMessage}
|
||||
onChange={handleChangeInput}
|
||||
disabled={recording || loading || ticketStatus !== "open"}
|
||||
|
|
|
@ -190,7 +190,8 @@ const NotificationsPopOver = () => {
|
|||
<>
|
||||
<IconButton
|
||||
onClick={handleClick}
|
||||
buttonRef={anchorEl}
|
||||
// buttonRef={anchorEl}
|
||||
ref={anchorEl}
|
||||
aria-label="Open Notifications"
|
||||
color="inherit"
|
||||
>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
|
||||
|
||||
import React, { Fragment, useState } from "react";
|
||||
import React, { Fragment, useState, useEffect } from "react";
|
||||
|
||||
|
||||
import DateFnsUtils from '@date-io/date-fns'; // choose your lib
|
||||
|
@ -24,7 +24,13 @@ function formatDateDatePicker(data){
|
|||
function ResponsiveDatePickers(props) {
|
||||
const [selectedDate, handleDateChange] = useState(new Date());
|
||||
|
||||
props.func(formatDateDatePicker(selectedDate));
|
||||
// props.func(formatDateDatePicker(selectedDate));
|
||||
|
||||
useEffect(()=>{
|
||||
|
||||
props.func(formatDateDatePicker(selectedDate));
|
||||
|
||||
}, [selectedDate])
|
||||
|
||||
return (
|
||||
|
||||
|
@ -35,6 +41,7 @@ function ResponsiveDatePickers(props) {
|
|||
variant="inline"
|
||||
inputVariant="outlined"
|
||||
label={props.title}
|
||||
minDate={new Date()}
|
||||
//format="MM/dd/yyyy"
|
||||
format="dd/MM/yyyy"
|
||||
value={selectedDate}
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
import * as React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import Box from '@mui/material/Box';
|
||||
import TextField from '@mui/material/TextField';
|
||||
|
||||
|
||||
|
||||
const SelectTextFields = (props) => {
|
||||
const [currency, setCurrency] = React.useState('0');
|
||||
|
||||
props.currencies.push({ value: '0', label: ''})
|
||||
const [currency, setCurrency] = useState(props.emptyField ? '0' : '1');
|
||||
|
||||
if(props.emptyField){
|
||||
props.currencies.push({ 'value': 0, 'label': ''})
|
||||
}
|
||||
|
||||
|
||||
props.func(currency);
|
||||
useEffect(()=>{
|
||||
|
||||
props.func(currency);
|
||||
|
||||
}, [currency])
|
||||
|
||||
const handleChange = (event) => {
|
||||
setCurrency(event.target.value);
|
||||
|
@ -17,50 +26,54 @@ const SelectTextFields = (props) => {
|
|||
|
||||
|
||||
|
||||
return (
|
||||
return (
|
||||
|
||||
<Box
|
||||
component="form"
|
||||
sx={{
|
||||
"&:hover": {
|
||||
"&& fieldset": {
|
||||
border: "1px solid black"
|
||||
}
|
||||
},
|
||||
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& .MuiTextField-root': { m: 1, width: '30ch' },}}
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
>
|
||||
<TextField
|
||||
id="outlined-select-currency-native"
|
||||
margin="dense"
|
||||
size="small"
|
||||
select
|
||||
label="Usuário"
|
||||
value={currency}
|
||||
onChange={handleChange}
|
||||
SelectProps={{
|
||||
native: true,
|
||||
}}
|
||||
//helperText="Please select your currency"
|
||||
<Box
|
||||
component="form"
|
||||
sx={{
|
||||
"&:hover": {
|
||||
"&& fieldset": {
|
||||
border: "1px solid black"
|
||||
}
|
||||
},
|
||||
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
'& .MuiTextField-root': { m: 1, },}
|
||||
}
|
||||
noValidate
|
||||
autoComplete="off"
|
||||
>
|
||||
{props.currencies.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</TextField>
|
||||
<TextField
|
||||
id="outlined-select-currency-native"
|
||||
margin="dense"
|
||||
size="small"
|
||||
select
|
||||
label={props.header}
|
||||
value={currency}
|
||||
onChange={handleChange}
|
||||
SelectProps={{
|
||||
native: true,
|
||||
}}
|
||||
// helperText="Please select your currency"
|
||||
>
|
||||
|
||||
{props.currencies.map((option, index) => (
|
||||
<option key={index} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
|
||||
</Box>
|
||||
</TextField>
|
||||
|
||||
|
||||
</Box>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
export default SelectTextFields
|
||||
export default SelectTextFields
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -83,15 +83,26 @@ const Ticket = () => {
|
|||
const [contact, setContact] = useState({});
|
||||
const [ticket, setTicket] = useState({});
|
||||
|
||||
const [schedule, setSchedule] = useState({})
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
const delayDebounceFn = setTimeout(() => {
|
||||
const fetchTicket = async () => {
|
||||
try {
|
||||
|
||||
// maria julia
|
||||
|
||||
const { data } = await api.get("/tickets/" + ticketId);
|
||||
|
||||
setContact(data.contact);
|
||||
setTicket(data);
|
||||
// setContact(data.contact);
|
||||
// setTicket(data);
|
||||
|
||||
setContact(data.contact.contact);
|
||||
setTicket(data.contact);
|
||||
|
||||
setSchedule(data.schedules)
|
||||
|
||||
setLoading(false);
|
||||
} catch (err) {
|
||||
setLoading(false);
|
||||
|
@ -161,7 +172,7 @@ const Ticket = () => {
|
|||
/>
|
||||
</div>
|
||||
<div className={classes.ticketActionButtons}>
|
||||
<TicketActionButtons ticket={ticket} />
|
||||
<TicketActionButtons ticket={ticket} schedule={schedule}/>
|
||||
</div>
|
||||
</TicketHeader>
|
||||
<ReplyMessageProvider>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useContext, useState } from "react";
|
||||
import React, { useContext, useState, useEffect } from "react";
|
||||
import { useHistory } from "react-router-dom";
|
||||
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
|
@ -12,6 +12,9 @@ import ButtonWithSpinner from "../ButtonWithSpinner";
|
|||
import toastError from "../../errors/toastError";
|
||||
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||
|
||||
import Modal from "../ChatEnd/ModalChatEnd";
|
||||
import { render } from '@testing-library/react';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
actionButtons: {
|
||||
marginRight: 6,
|
||||
|
@ -24,7 +27,7 @@ const useStyles = makeStyles(theme => ({
|
|||
},
|
||||
}));
|
||||
|
||||
const TicketActionButtons = ({ ticket }) => {
|
||||
const TicketActionButtons = ({ ticket, schedule }) => {
|
||||
const classes = useStyles();
|
||||
const history = useHistory();
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
|
@ -32,6 +35,8 @@ const TicketActionButtons = ({ ticket }) => {
|
|||
const ticketOptionsMenuOpen = Boolean(anchorEl);
|
||||
const { user } = useContext(AuthContext);
|
||||
|
||||
const [chatEnd, setChatEnd] = useState(null)
|
||||
|
||||
const handleOpenTicketOptionsMenu = e => {
|
||||
setAnchorEl(e.currentTarget);
|
||||
};
|
||||
|
@ -40,26 +45,71 @@ const TicketActionButtons = ({ ticket }) => {
|
|||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleUpdateTicketStatus = async (e, status, userId) => {
|
||||
|
||||
|
||||
const chatEndVal = (data) => {
|
||||
|
||||
if(data){
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
await api.put(`/tickets/${ticket.id}`, {
|
||||
status: status,
|
||||
userId: userId || null,
|
||||
});
|
||||
data = {...data, 'ticketId': ticket.id}
|
||||
|
||||
console.log('ChatEnd: ',(data));
|
||||
|
||||
setLoading(false);
|
||||
if (status === "open") {
|
||||
history.push(`/tickets/${ticket.id}`);
|
||||
} else {
|
||||
history.push("/tickets");
|
||||
}
|
||||
} catch (err) {
|
||||
setLoading(false);
|
||||
toastError(err);
|
||||
handleUpdateTicketStatus(null, "closed", user?.id, data)
|
||||
|
||||
}
|
||||
|
||||
setChatEnd(data)
|
||||
}
|
||||
|
||||
|
||||
const handleModal = (/*status, userId*/) => {
|
||||
|
||||
render(<Modal
|
||||
modal_header={'Finalização de Atendimento'}
|
||||
func={chatEndVal}
|
||||
schedules={schedule}
|
||||
/>)
|
||||
|
||||
};
|
||||
|
||||
|
||||
const handleUpdateTicketStatus = async (e, status, userId, schedulingData={}) => {
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
|
||||
if(status==='closed'){
|
||||
|
||||
await api.put(`/tickets/${ticket.id}`, {
|
||||
status: status,
|
||||
userId: userId || null,
|
||||
schedulingNotifyData: JSON.stringify(schedulingData)
|
||||
});
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
await api.put(`/tickets/${ticket.id}`, {
|
||||
status: status,
|
||||
userId: userId || null
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
if (status === "open") {
|
||||
history.push(`/tickets/${ticket.id}`);
|
||||
} else {
|
||||
history.push("/tickets");
|
||||
}
|
||||
} catch (err) {
|
||||
setLoading(false);
|
||||
toastError(err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -90,7 +140,13 @@ const TicketActionButtons = ({ ticket }) => {
|
|||
size="small"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={e => handleUpdateTicketStatus(e, "closed", user?.id)}
|
||||
onClick={e => {
|
||||
|
||||
|
||||
handleModal()
|
||||
// handleUpdateTicketStatus(e, "closed", user?.id)
|
||||
|
||||
}}
|
||||
>
|
||||
{i18n.t("messagesList.header.buttons.resolve")}
|
||||
</ButtonWithSpinner>
|
||||
|
|
|
@ -262,7 +262,7 @@ const textFieldSelectUser = (data) => {
|
|||
<MainContainer>
|
||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
|
||||
|
||||
<Item><SelectField func={textFieldSelectUser} currencies={users.map((obj)=>{
|
||||
<Item><SelectField func={textFieldSelectUser} emptyField={true} header={'Usuário'} currencies={users.map((obj)=>{
|
||||
return {'value': obj.id, 'label': obj.name}
|
||||
})}/></Item>
|
||||
|
||||
|
|
Loading…
Reference in New Issue