Adição da função deletar para os lembretes
parent
25e3e5dde1
commit
7020d15c70
|
@ -1,8 +1,35 @@
|
||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
|
import AppError from "../errors/AppError";
|
||||||
|
|
||||||
import DeleteSchedulingNotifyService from "../services/SchedulingNotifyServices/DeleteSchedulingNotifyService";
|
import DeleteSchedulingNotifyService from "../services/SchedulingNotifyServices/DeleteSchedulingNotifyService";
|
||||||
|
import ListSchedulingNotifyContactService from "../services/SchedulingNotifyServices/ListSchedulingNotifyContactService";
|
||||||
|
|
||||||
|
|
||||||
|
// const test = await ListSchedulingNotifyContactService('5517988310949','2022-03-18','2022-03-19');
|
||||||
|
// const test = await ListSchedulingNotifyContactService('','2022-03-18','2022-03-19');
|
||||||
|
// const test = await ListSchedulingNotifyContactService('5517988310949');
|
||||||
|
// console.log('$$$$$$$$$$$$$$$$$$$$$$$$$$ test:\n', test)
|
||||||
|
|
||||||
|
|
||||||
|
type IndexQuery = {
|
||||||
|
contactNumber: string;
|
||||||
|
startDate: string;
|
||||||
|
endDate: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export const reportScheduleNotifyByDateStartDateEnd = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
|
const { contactNumber, startDate, endDate } = req.query as IndexQuery
|
||||||
|
|
||||||
|
const data_query = await ListSchedulingNotifyContactService(contactNumber, startDate, endDate);
|
||||||
|
|
||||||
|
console.group('DATA QUERY SCHEDULE:\n',data_query)
|
||||||
|
|
||||||
|
return res.status(200).json(data_query);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
export const remove = async ( req: Request, res: Response ): Promise<Response> => {
|
export const remove = async ( req: Request, res: Response ): Promise<Response> => {
|
||||||
|
|
||||||
console.log('EEEEEEEEEEEEEEEEEEEEEEEEEEE')
|
console.log('EEEEEEEEEEEEEEEEEEEEEEEEEEE')
|
||||||
|
@ -13,3 +40,4 @@ export const remove = async ( req: Request, res: Response ): Promise<Response> =
|
||||||
|
|
||||||
return res.status(200).send();
|
return res.status(200).send();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ export const show = async (req: Request, res: Response): Promise<Response> => {
|
||||||
|
|
||||||
const { schedules, count, hasMore } = await ListScheduleService({ searchParam: "", pageNumber: "1" });
|
const { schedules, count, hasMore } = await ListScheduleService({ searchParam: "", pageNumber: "1" });
|
||||||
|
|
||||||
|
|
||||||
//////////////////
|
//////////////////
|
||||||
const schedulesContact = await ListSchedulingNotifyContactService(contact.contact.number);
|
const schedulesContact = await ListSchedulingNotifyContactService(contact.contact.number);
|
||||||
/////////////////
|
/////////////////
|
||||||
|
|
|
@ -7,4 +7,6 @@ const schedulingNotifiyRoutes = Router();
|
||||||
|
|
||||||
schedulingNotifiyRoutes.delete("/schedule/:scheduleId", isAuth, SchedulingNotifyController.remove);
|
schedulingNotifiyRoutes.delete("/schedule/:scheduleId", isAuth, SchedulingNotifyController.remove);
|
||||||
|
|
||||||
|
schedulingNotifiyRoutes.get("/schedules", isAuth, SchedulingNotifyController.reportScheduleNotifyByDateStartDateEnd);
|
||||||
|
|
||||||
export default schedulingNotifiyRoutes;
|
export default schedulingNotifiyRoutes;
|
||||||
|
|
|
@ -4,11 +4,114 @@ import SchedulingNotify from "../../models/SchedulingNotify";
|
||||||
import { Op, where, Sequelize } from "sequelize";
|
import { Op, where, Sequelize } from "sequelize";
|
||||||
import AppError from "../../errors/AppError";
|
import AppError from "../../errors/AppError";
|
||||||
|
|
||||||
const ListSchedulingNotifyContactService = async (contactNumber: string): Promise<SchedulingNotify[]> => {
|
const ListSchedulingNotifyContactService = async (contactNumber: string = '', startDate: string='', endDate: string=''): Promise<SchedulingNotify[]> => {
|
||||||
|
|
||||||
|
|
||||||
|
let where_clause = {}
|
||||||
|
let where_clause_notify = {}
|
||||||
|
|
||||||
|
let nameNumber = {
|
||||||
|
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
name: Sequelize.where(
|
||||||
|
Sequelize.fn("LOWER", Sequelize.col("name")),
|
||||||
|
"LIKE",
|
||||||
|
`%${contactNumber.toLowerCase().trim()}%`
|
||||||
|
)
|
||||||
|
},
|
||||||
|
{ number: { [Op.like]: `%${contactNumber.toLowerCase().trim()}%` } }
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (contactNumber.trim().length>0 && startDate.trim().length>0 && endDate.trim().length>0){
|
||||||
|
|
||||||
|
where_clause = nameNumber
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (contactNumber.trim().length==0 && startDate.trim().length>0 && endDate.trim().length>0){
|
||||||
|
|
||||||
|
where_clause = {}
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (contactNumber.trim().length==0 && startDate.trim().length>0 && endDate.trim().length==0){
|
||||||
|
|
||||||
|
where_clause = {}
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: startDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (contactNumber.trim().length==0 && startDate.trim().length==0 && endDate.trim().length>0){
|
||||||
|
|
||||||
|
where_clause = {}
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: endDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (contactNumber.trim().length>0 && startDate.trim().length>0 && endDate.trim().length==0){
|
||||||
|
|
||||||
|
where_clause = nameNumber
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: startDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: startDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (contactNumber.trim().length>0 && startDate.trim().length==0 && endDate.trim().length>0){
|
||||||
|
|
||||||
|
where_clause = nameNumber
|
||||||
|
|
||||||
|
where_clause_notify = {
|
||||||
|
schedulingTime: {
|
||||||
|
[Op.gte]: endDate+' 00:00:00.000000',
|
||||||
|
[Op.lte]: endDate +' 23:59:59.999999'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(contactNumber.trim().length>0){
|
||||||
|
|
||||||
|
where_clause = nameNumber
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const ticket = await SchedulingNotify.findAll({
|
const ticket = await SchedulingNotify.findAll({
|
||||||
|
|
||||||
|
raw: true,
|
||||||
|
where: where_clause_notify,
|
||||||
|
|
||||||
attributes:['id', [Sequelize.fn("DATE_FORMAT",Sequelize.col("schedulingDate"),"%d/%m/%Y %H:%i:%s"),"schedulingDate"],
|
attributes:['id', [Sequelize.fn("DATE_FORMAT",Sequelize.col("schedulingDate"),"%d/%m/%Y %H:%i:%s"),"schedulingDate"],
|
||||||
[Sequelize.fn("DATE_FORMAT",Sequelize.col("schedulingTime"),"%d/%m/%Y %H:%i:%s"),"schedulingTime"], 'message'],
|
[Sequelize.fn("DATE_FORMAT",Sequelize.col("schedulingTime"),"%d/%m/%Y %H:%i:%s"),"schedulingTime"], 'message'],
|
||||||
|
|
||||||
|
@ -20,10 +123,8 @@ const ListSchedulingNotifyContactService = async (contactNumber: string): Promis
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Contact,
|
model: Contact,
|
||||||
where:{
|
where: where_clause,
|
||||||
number: contactNumber,
|
attributes: ['name', 'number', 'profilePicUrl']
|
||||||
},
|
|
||||||
attributes: ['name', 'number']
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -28,7 +28,8 @@ import {
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
|
|
||||||
import { DeleteOutline } from "@material-ui/icons";
|
import { DeleteOutline } from "@material-ui/icons";
|
||||||
import { toast } from "react-toastify"; import api from "../../../services/api";
|
import { toast } from "react-toastify";
|
||||||
|
import api from "../../../services/api";
|
||||||
import toastError from "../../../errors/toastError";
|
import toastError from "../../../errors/toastError";
|
||||||
import ConfirmationModal from "../../ConfirmationModal";
|
import ConfirmationModal from "../../ConfirmationModal";
|
||||||
|
|
||||||
|
@ -337,7 +338,7 @@ const handleChange = (event) => {
|
||||||
|
|
||||||
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}>
|
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}>
|
||||||
|
|
||||||
<Item><DatePicker func={datePickerValue} minDate = {true} title={'Data do lembrete'}/></Item>
|
<Item><DatePicker func={datePickerValue} minDate={true} startEmpty={true} title={'Data do lembrete'}/></Item>
|
||||||
|
|
||||||
<Item><TimerPickerSelect func={timerPickerValue} title={'Hora do lembrete'}/></Item>
|
<Item><TimerPickerSelect func={timerPickerValue} title={'Hora do lembrete'}/></Item>
|
||||||
|
|
||||||
|
@ -351,7 +352,7 @@ const handleChange = (event) => {
|
||||||
aria-label="minimum height"
|
aria-label="minimum height"
|
||||||
minRows={3}
|
minRows={3}
|
||||||
value={textArea1}
|
value={textArea1}
|
||||||
placeholder={'Mensagem para lembrar cliente'}
|
placeholder={'Mensagem de envio para cliente'}
|
||||||
onChange={ handleChange}
|
onChange={ handleChange}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
/>
|
/>
|
||||||
|
@ -375,7 +376,7 @@ const handleChange = (event) => {
|
||||||
>
|
>
|
||||||
<span>Deseja realmente deletar esse Lembrete? </span>
|
<span>Deseja realmente deletar esse Lembrete? </span>
|
||||||
</ConfirmationModal>
|
</ConfirmationModal>
|
||||||
<span>Lembrete</span>
|
<span>Lembretes</span>
|
||||||
<Paper variant="outlined">
|
<Paper variant="outlined">
|
||||||
<Table size="small">
|
<Table size="small">
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,28 @@ function formatDateDatePicker(data){
|
||||||
}
|
}
|
||||||
|
|
||||||
function ResponsiveDatePickers(props) {
|
function ResponsiveDatePickers(props) {
|
||||||
const [selectedDate, handleDateChange] = useState(new Date());
|
const [selectedDate, handleDateChange] = useState(props.startEmpty? null : new Date());
|
||||||
|
|
||||||
// props.func(formatDateDatePicker(selectedDate));
|
|
||||||
|
//////////////////////////
|
||||||
|
useEffect(() => {
|
||||||
|
if (props.reset) {
|
||||||
|
handleDateChange(null)
|
||||||
|
props.setReset(false)
|
||||||
|
}
|
||||||
|
}, [props.reset, props.setReset, props])
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
|
||||||
|
|
||||||
|
if( !selectedDate ){
|
||||||
|
props.func('');
|
||||||
|
}
|
||||||
|
else{
|
||||||
props.func(formatDateDatePicker(selectedDate));
|
props.func(formatDateDatePicker(selectedDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}, [selectedDate, props])
|
}, [selectedDate, props])
|
||||||
|
|
||||||
|
@ -37,7 +52,8 @@ function ResponsiveDatePickers(props) {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
|
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
|
||||||
<KeyboardDatePicker
|
<KeyboardDatePicker
|
||||||
autoOk
|
// autoOk
|
||||||
|
|
||||||
variant="inline"
|
variant="inline"
|
||||||
inputVariant="outlined"
|
inputVariant="outlined"
|
||||||
label={props.title}
|
label={props.title}
|
||||||
|
@ -46,6 +62,7 @@ function ResponsiveDatePickers(props) {
|
||||||
value={selectedDate}
|
value={selectedDate}
|
||||||
InputAdornmentProps={{ position: "start" }}
|
InputAdornmentProps={{ position: "start" }}
|
||||||
onChange={date => handleDateChange(date)}
|
onChange={date => handleDateChange(date)}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</MuiPickersUtilsProvider>
|
</MuiPickersUtilsProvider>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
|
||||||
|
|
||||||
|
import React, { Fragment, useState, useEffect } from "react";
|
||||||
|
|
||||||
|
|
||||||
|
import DateFnsUtils from '@date-io/date-fns'; // choose your lib
|
||||||
|
import {
|
||||||
|
KeyboardDatePicker,
|
||||||
|
MuiPickersUtilsProvider,
|
||||||
|
} from '@material-ui/pickers';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import ptBrLocale from "date-fns/locale/pt-BR";
|
||||||
|
|
||||||
|
|
||||||
|
function formatDateDatePicker(data){
|
||||||
|
return String(new Date(data).getFullYear())+'-'+
|
||||||
|
String(new Date(data).getMonth() + 1).padStart(2,'0')+'-'+
|
||||||
|
String(new Date(data).getDate()).padStart(2,'0')
|
||||||
|
}
|
||||||
|
|
||||||
|
function ResponsiveDatePickers(props) {
|
||||||
|
const [selectedDate, handleDateChange] = useState(null);
|
||||||
|
|
||||||
|
// props.func(formatDateDatePicker(selectedDate));
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
|
||||||
|
if( !selectedDate ){
|
||||||
|
props.func('');
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
props.func(formatDateDatePicker(selectedDate));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}, [selectedDate, props])
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
|
||||||
|
<KeyboardDatePicker
|
||||||
|
// autoOk
|
||||||
|
|
||||||
|
variant="inline"
|
||||||
|
inputVariant="outlined"
|
||||||
|
label={props.title}
|
||||||
|
minDate={props.minDate? new Date() : false}
|
||||||
|
format="dd/MM/yyyy"
|
||||||
|
value={selectedDate}
|
||||||
|
InputAdornmentProps={{ position: "start" }}
|
||||||
|
onChange={date => handleDateChange(date)}
|
||||||
|
/>
|
||||||
|
</MuiPickersUtilsProvider>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResponsiveDatePickers;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*import * as React from 'react';
|
||||||
|
import TextField from '@mui/material/TextField';
|
||||||
|
import AdapterDateFns from '@mui/lab/AdapterDateFns';
|
||||||
|
import LocalizationProvider from '@mui/lab/LocalizationProvider';
|
||||||
|
import DesktopDatePicker from '@mui/lab/DesktopDatePicker';
|
||||||
|
import Stack from '@mui/material/Stack';
|
||||||
|
|
||||||
|
const ResponsiveDatePickers = (props) => {
|
||||||
|
|
||||||
|
const [value, setValue] = React.useState(new Date());
|
||||||
|
|
||||||
|
props.func(value);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LocalizationProvider dateAdapter={AdapterDateFns}>
|
||||||
|
<Stack spacing={1}>
|
||||||
|
<DesktopDatePicker
|
||||||
|
label={props.title}
|
||||||
|
|
||||||
|
value={value}
|
||||||
|
minDate={new Date('2017-01-01')}
|
||||||
|
onChange={(newValue) => {setValue(newValue)}}
|
||||||
|
renderInput={(params) => <TextField {...params} />}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</LocalizationProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ResponsiveDatePickers*/
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
import { useState, useEffect} from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import MaterialTable from 'material-table';
|
import MaterialTable from 'material-table';
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import { render } from '@testing-library/react';
|
import { render } from '@testing-library/react';
|
||||||
|
@ -12,20 +12,20 @@ const MTable = (props) => {
|
||||||
|
|
||||||
|
|
||||||
//const dataLoad = props.data.map((dt) => { return { ...dt }});
|
//const dataLoad = props.data.map((dt) => { return { ...dt }});
|
||||||
const dataLoad = props.data.map(({user, ...others})=>({...others, 'user': user ? user : {name: 'Aguardando atendente', email:''}}));
|
const dataLoad = props.data.map(({ user, ...others }) => ({ ...others, 'user': user ? user : { name: 'Aguardando atendente', email: '' } }));
|
||||||
|
|
||||||
const columnsLoad = props.columns.map((column) => { return { ...column }});
|
const columnsLoad = props.columns.map((column) => { return { ...column } });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
||||||
console.log(`You have clicked the button ${selectedRow} times`)
|
console.log(`You have clicked the button ${selectedRow} times`)
|
||||||
|
|
||||||
},[selectedRow]);
|
}, [selectedRow]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
||||||
<MaterialTable
|
<MaterialTable
|
||||||
title= {props.table_title}
|
title={props.table_title}
|
||||||
columns={columnsLoad}
|
columns={columnsLoad}
|
||||||
data={dataLoad}
|
data={dataLoad}
|
||||||
|
|
||||||
|
@ -33,17 +33,21 @@ const MTable = (props) => {
|
||||||
|
|
||||||
onRowClick={(evt, selectedRow) => {
|
onRowClick={(evt, selectedRow) => {
|
||||||
|
|
||||||
|
if(props.removeClickRow){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
console.log(selectedRow.tableData.id);
|
console.log(selectedRow.tableData.id);
|
||||||
console.log(selectedRow);
|
console.log(selectedRow);
|
||||||
console.log(selectedRow.messages);
|
console.log(selectedRow.messages);
|
||||||
setSelectedRow(selectedRow.tableData.id)
|
setSelectedRow(selectedRow.tableData.id)
|
||||||
|
|
||||||
if(props.hasChild) {
|
if (props.hasChild) {
|
||||||
render(<Modal data={selectedRow.messages}
|
render(<Modal data={selectedRow.messages}
|
||||||
hasChild={false}
|
hasChild={false}
|
||||||
modal_header={'Chat do atendimento pelo Whatsapp'}
|
modal_header={'Chat do atendimento pelo Whatsapp'}
|
||||||
user={selectedRow.user.name}
|
user={selectedRow.user.name}
|
||||||
clientContactNumber={selectedRow.contact.number}/>)
|
clientContactNumber={selectedRow.contact.number} />)
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('props.hasChild: ', props.hasChild)
|
console.log('props.hasChild: ', props.hasChild)
|
||||||
|
@ -57,7 +61,7 @@ const MTable = (props) => {
|
||||||
selection: false,
|
selection: false,
|
||||||
paging: false,
|
paging: false,
|
||||||
padding: 'dense',
|
padding: 'dense',
|
||||||
sorting: true ? props.hasChild: false,
|
sorting: true ? props.hasChild : false,
|
||||||
//loadingType: 'linear',
|
//loadingType: 'linear',
|
||||||
searchFieldStyle: {
|
searchFieldStyle: {
|
||||||
width: 300,
|
width: 300,
|
||||||
|
@ -71,7 +75,7 @@ const MTable = (props) => {
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export default React.memo(MTable)
|
export default React.memo(MTable)
|
|
@ -10,6 +10,8 @@ import { Badge } from "@material-ui/core";
|
||||||
import DashboardOutlinedIcon from "@material-ui/icons/DashboardOutlined";
|
import DashboardOutlinedIcon from "@material-ui/icons/DashboardOutlined";
|
||||||
|
|
||||||
import ReportOutlinedIcon from "@material-ui/icons/ReportOutlined";
|
import ReportOutlinedIcon from "@material-ui/icons/ReportOutlined";
|
||||||
|
import SendOutlined from '@material-ui/icons/SendOutlined';
|
||||||
|
|
||||||
//import ReportOutlined from "@bit/mui-org.material-ui-icons.report-outlined";
|
//import ReportOutlined from "@bit/mui-org.material-ui-icons.report-outlined";
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,6 +91,11 @@ const MainListItems = (props) => {
|
||||||
to="/contacts"
|
to="/contacts"
|
||||||
primary={i18n.t("mainDrawer.listItems.contacts")}
|
primary={i18n.t("mainDrawer.listItems.contacts")}
|
||||||
icon={<ContactPhoneOutlinedIcon />}
|
icon={<ContactPhoneOutlinedIcon />}
|
||||||
|
/>
|
||||||
|
<ListItemLink
|
||||||
|
to="/schedulesReminder"
|
||||||
|
primary="Lembretes"
|
||||||
|
icon={<SendOutlined />}
|
||||||
/>
|
/>
|
||||||
<ListItemLink
|
<ListItemLink
|
||||||
to="/quickAnswers"
|
to="/quickAnswers"
|
||||||
|
|
|
@ -266,8 +266,8 @@ const textFieldSelectUser = (data) => {
|
||||||
return {'value': obj.id, 'label': obj.name}
|
return {'value': obj.id, 'label': obj.name}
|
||||||
})}/></Item>
|
})}/></Item>
|
||||||
|
|
||||||
<Item><DatePicker1 func={datePicker1Value} minDate={false} title={'Data inicio'}/></Item>
|
<Item><DatePicker1 func={datePicker1Value} minDate={false} startEmpty={false} title={'Data inicio'}/></Item>
|
||||||
<Item><DatePicker2 func={datePicker2Value} minDate={false} title={'Data fim'}/></Item>
|
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={false} title={'Data fim'}/></Item>
|
||||||
|
|
||||||
<Item sx={{ gridColumn: '4 / 5' }}>
|
<Item sx={{ gridColumn: '4 / 5' }}>
|
||||||
{/* <Button size="small" variant="contained" onClick={()=>{handleQuery()}}>GO</Button>*/}
|
{/* <Button size="small" variant="contained" onClick={()=>{handleQuery()}}>GO</Button>*/}
|
||||||
|
@ -283,6 +283,7 @@ const textFieldSelectUser = (data) => {
|
||||||
<MTable data={query}
|
<MTable data={query}
|
||||||
columns={columnsData}
|
columns={columnsData}
|
||||||
hasChild={true}
|
hasChild={true}
|
||||||
|
removeClickRow={false}
|
||||||
table_title={'Relatório de atendimento por atendentes'}/>
|
table_title={'Relatório de atendimento por atendentes'}/>
|
||||||
</Item>
|
</Item>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,427 @@
|
||||||
|
import React, { useState, useEffect, useReducer, useContext} from "react";
|
||||||
|
import MainContainer from "../../components/MainContainer";
|
||||||
|
import api from "../../services/api";
|
||||||
|
import SelectField from "../../components/Report/SelectField";
|
||||||
|
//import { data } from '../../components/Report/MTable/data';
|
||||||
|
import DatePicker1 from '../../components/Report/DatePicker'
|
||||||
|
import DatePicker2 from '../../components/Report/DatePicker'
|
||||||
|
//import { Button } from "@material-ui/core";
|
||||||
|
import MTable from "../../components/Report/MTable";
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import { AuthContext } from "../../context/Auth/AuthContext";
|
||||||
|
import { Can } from "../../components/Can";
|
||||||
|
|
||||||
|
import SearchIcon from "@material-ui/icons/Search";
|
||||||
|
import TextField from "@material-ui/core/TextField";
|
||||||
|
import InputAdornment from "@material-ui/core/InputAdornment";
|
||||||
|
import Button from "@material-ui/core/Button";
|
||||||
|
|
||||||
|
import MaterialTable from 'material-table';
|
||||||
|
|
||||||
|
import Delete from '@material-ui/icons/Delete';
|
||||||
|
import Edit from '@material-ui/icons/Edit';
|
||||||
|
import Save from '@material-ui/icons/Save';
|
||||||
|
|
||||||
|
import {
|
||||||
|
IconButton,
|
||||||
|
Paper,
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
} from "@material-ui/core";
|
||||||
|
|
||||||
|
import { DeleteOutline } from "@material-ui/icons";
|
||||||
|
import { toast } from "react-toastify";
|
||||||
|
import toastError from "../../errors/toastError";
|
||||||
|
import ConfirmationModal from "../../components/ConfirmationModal";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const reducerQ = (state, action) =>{
|
||||||
|
|
||||||
|
if(action.type === 'LOAD_QUERY'){
|
||||||
|
|
||||||
|
console.log('----------------action.payload: ', action.payload)
|
||||||
|
const queries = action.payload
|
||||||
|
const newQueries = []
|
||||||
|
|
||||||
|
queries.forEach((query) => {
|
||||||
|
|
||||||
|
const queryIndex = state.findIndex((q) => q.id === query.id)
|
||||||
|
|
||||||
|
if(queryIndex !== -1){
|
||||||
|
state[queryIndex] = query
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
newQueries.push(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
return [...state, ...newQueries]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === "DELETE_SCHEDULE") {
|
||||||
|
const scheduleId = action.payload;
|
||||||
|
|
||||||
|
const scheduleIndex = state.findIndex((q) => q.id === scheduleId);
|
||||||
|
if (scheduleIndex !== -1) {
|
||||||
|
state.splice(scheduleIndex, 1);
|
||||||
|
}
|
||||||
|
return [...state];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (action.type === "RESET") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const reducer = (state, action) => {
|
||||||
|
|
||||||
|
if (action.type === "LOAD_USERS") {
|
||||||
|
const users = action.payload;
|
||||||
|
const newUsers = [];
|
||||||
|
|
||||||
|
users.forEach((user) => {
|
||||||
|
const userIndex = state.findIndex((u) => u.id === user.id);
|
||||||
|
if (userIndex !== -1) {
|
||||||
|
state[userIndex] = user;
|
||||||
|
} else {
|
||||||
|
newUsers.push(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return [...state, ...newUsers];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action.type === "RESET") {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function 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,
|
||||||
|
]),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let columnsData = [
|
||||||
|
|
||||||
|
{ title: 'Foto', field: 'ticket.contact.profilePicUrl', render: rowData => <img src={rowData['ticket.contact.profilePicUrl']} style={{width: 40, borderRadius: '50%'}}/> },
|
||||||
|
|
||||||
|
{ title: 'Nome', field: 'ticket.contact.name' },
|
||||||
|
{ title: 'Contato', field: 'ticket.contact.number' },
|
||||||
|
{ title: 'schedulingTime', field: 'schedulingTime' },
|
||||||
|
{ title: 'schedulingDate', field: 'schedulingDate' },
|
||||||
|
{ title: 'message', field: 'message' },
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const SchedulesReminder = () => {
|
||||||
|
|
||||||
|
const { user: userA } = useContext(AuthContext);
|
||||||
|
|
||||||
|
//--------
|
||||||
|
const [searchParam] = useState("");
|
||||||
|
//const [loading, setLoading] = useState(false);
|
||||||
|
//const [hasMore, setHasMore] = useState(false);
|
||||||
|
const [pageNumber, setPageNumber] = useState(1);
|
||||||
|
const [users, dispatch] = useReducer(reducer, []);
|
||||||
|
//const [columns, setColums] = useState([])
|
||||||
|
const [startDate, setDatePicker1] = useState(new Date())
|
||||||
|
const [endDate, setDatePicker2] = useState(new Date())
|
||||||
|
const [userId, setUser] = useState(null)
|
||||||
|
const [query, dispatchQ] = useReducer(reducerQ, [])
|
||||||
|
const [contactNumber, setContactNumber] = useState("");
|
||||||
|
|
||||||
|
const [resetChild, setReset] = useState(false)
|
||||||
|
|
||||||
|
const [selectedSchedule, setSelectedSchedule] = useState(null);
|
||||||
|
const [confirmModalOpen, setConfirmModalOpen] = useState(false);
|
||||||
|
const [dataRows, setData] = useState([]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch({ type: "RESET" });
|
||||||
|
dispatchQ({ type: "RESET" })
|
||||||
|
|
||||||
|
setPageNumber(1);
|
||||||
|
}, [searchParam]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//setLoading(true);
|
||||||
|
|
||||||
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
|
||||||
|
const fetchUsers = async () => {
|
||||||
|
try {
|
||||||
|
const { data } = await api.get("/users/", {
|
||||||
|
params: { searchParam, pageNumber },
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({ type: "LOAD_USERS", payload: data.users });
|
||||||
|
//setHasMore(data.hasMore);
|
||||||
|
//setLoading(false);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchUsers();
|
||||||
|
|
||||||
|
}, 500);
|
||||||
|
return () => clearTimeout(delayDebounceFn);
|
||||||
|
}, [searchParam, pageNumber]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
|
||||||
|
setData(query)
|
||||||
|
|
||||||
|
}, [query])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
//setLoading(true);
|
||||||
|
|
||||||
|
const delayDebounceFn = setTimeout(() => {
|
||||||
|
|
||||||
|
const fetchQueries = async () => {
|
||||||
|
try {
|
||||||
|
|
||||||
|
const dataQuery = await api.get("/schedules/", {params: {contactNumber, startDate, endDate },});
|
||||||
|
|
||||||
|
dispatchQ({ type: "RESET" })
|
||||||
|
dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data });
|
||||||
|
|
||||||
|
//setLoading(false);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fetchQueries();
|
||||||
|
|
||||||
|
}, 500);
|
||||||
|
return () => clearTimeout(delayDebounceFn);
|
||||||
|
|
||||||
|
}, [contactNumber, startDate, endDate]);
|
||||||
|
|
||||||
|
|
||||||
|
// Get from child 1
|
||||||
|
const datePicker1Value = (data) => {
|
||||||
|
console.log('DATE1: ',(data));
|
||||||
|
setDatePicker1(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get from child 2
|
||||||
|
const datePicker2Value = (data) => {
|
||||||
|
console.log('DATE2: ',(data));
|
||||||
|
setDatePicker2(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get from child 3
|
||||||
|
const textFieldSelectUser = (data) => {
|
||||||
|
console.log('textField: ',data);
|
||||||
|
setUser(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = (event) => {
|
||||||
|
setContactNumber(event.target.value.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
|
||||||
|
setContactNumber('')
|
||||||
|
|
||||||
|
setReset(true)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseConfirmationModal = () => {
|
||||||
|
setConfirmModalOpen(false);
|
||||||
|
setSelectedSchedule(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleDeleteRows = (id) => {
|
||||||
|
|
||||||
|
let _data = [...dataRows];
|
||||||
|
|
||||||
|
_data.forEach(rd => {
|
||||||
|
_data = _data.filter(t => t.id !== id);
|
||||||
|
});
|
||||||
|
setData(_data);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const handleDeleteSchedule = async (scheduleId) => {
|
||||||
|
try {
|
||||||
|
await api.delete(`/schedule/${scheduleId}`);
|
||||||
|
toast.success(("Lembrete deletado com sucesso!"));
|
||||||
|
handleDeleteRows(scheduleId)
|
||||||
|
} catch (err) {
|
||||||
|
toastError(err);
|
||||||
|
}
|
||||||
|
setSelectedSchedule(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
|
||||||
|
|
||||||
|
<MainContainer>
|
||||||
|
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
|
||||||
|
|
||||||
|
<Item>
|
||||||
|
<TextField
|
||||||
|
placeholder='Numero/Nome...'
|
||||||
|
type="search"
|
||||||
|
value={contactNumber}
|
||||||
|
onChange={handleSearch}
|
||||||
|
InputProps={{
|
||||||
|
startAdornment: (
|
||||||
|
<InputAdornment position="start">
|
||||||
|
<SearchIcon style={{ color: "gray" }} />
|
||||||
|
</InputAdornment>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Item>
|
||||||
|
|
||||||
|
{/* <Item>
|
||||||
|
<SelectField func={textFieldSelectUser} emptyField={true} header={'Usuário'} currencies={users.map((obj)=>{
|
||||||
|
return {'value': obj.id, 'label': obj.name}
|
||||||
|
})}/>
|
||||||
|
|
||||||
|
</Item> */}
|
||||||
|
|
||||||
|
<Item><DatePicker1 func={datePicker1Value} minDate={false} startEmpty={true} reset={resetChild} setReset={setReset} title={'Data inicio'}/></Item>
|
||||||
|
<Item><DatePicker2 func={datePicker2Value} minDate={false} startEmpty={true} reset={resetChild} setReset={setReset} title={'Data fim'}/></Item>
|
||||||
|
|
||||||
|
<Item sx={{ gridColumn: '4 / 5' }}>
|
||||||
|
{/* <Button size="small" variant="contained" onClick={()=>{handleQuery()}}>GO</Button>*/}
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={(e) => handleClear()}
|
||||||
|
>
|
||||||
|
{"CLEAR"}
|
||||||
|
</Button>
|
||||||
|
</Item>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<Box sx={{
|
||||||
|
display: 'grid',
|
||||||
|
}}>
|
||||||
|
|
||||||
|
<Item sx={{ gridColumn: '1', gridRow: 'span 1' }}>
|
||||||
|
|
||||||
|
{/* <MTable data={query}
|
||||||
|
columns={columnsData}
|
||||||
|
removeClickRow={true}
|
||||||
|
hasChild={true}
|
||||||
|
table_title={'Lembretes/Agendamentos'}/> */}
|
||||||
|
|
||||||
|
<ConfirmationModal
|
||||||
|
title={selectedSchedule && `Deletar lembrete do dia ${selectedSchedule.schedulingTime.split(' ')[0]} ${selectedSchedule.schedulingTime.split(' ')[1]} ?`}
|
||||||
|
open={confirmModalOpen}
|
||||||
|
onClose={handleCloseConfirmationModal}
|
||||||
|
onConfirm={() => handleDeleteSchedule(selectedSchedule.id)}
|
||||||
|
>
|
||||||
|
<span>Deseja realmente deletar esse Lembrete? </span>
|
||||||
|
</ConfirmationModal>
|
||||||
|
|
||||||
|
<MaterialTable
|
||||||
|
title="Lembretes/Agendamentos"
|
||||||
|
columns={columnsData}
|
||||||
|
data={dataRows}
|
||||||
|
// icons={tableIcons}
|
||||||
|
|
||||||
|
actions={[
|
||||||
|
{
|
||||||
|
icon: Edit,
|
||||||
|
tooltip: 'Editar',
|
||||||
|
onClick: (event, rowData) => console.log("You saved ",rowData)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: Delete,
|
||||||
|
tooltip: 'Deletar',
|
||||||
|
onClick: (event, rowData) => {
|
||||||
|
console.log("You want to delete ",rowData)
|
||||||
|
setSelectedSchedule(rowData);
|
||||||
|
setConfirmModalOpen(true);
|
||||||
|
}
|
||||||
|
// onClick: handleDeleteRows
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
|
||||||
|
options={{
|
||||||
|
search: true,
|
||||||
|
selection: false,
|
||||||
|
paging: false,
|
||||||
|
padding: 'dense',
|
||||||
|
sorting: true,
|
||||||
|
//loadingType: 'linear',
|
||||||
|
searchFieldStyle: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
</Item>
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
</MainContainer>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SchedulesReminder;
|
|
@ -6,6 +6,7 @@ import LoggedInLayout from "../layout";
|
||||||
import Dashboard from "../pages/Dashboard/";
|
import Dashboard from "../pages/Dashboard/";
|
||||||
|
|
||||||
import Report from "../pages/Report/";
|
import Report from "../pages/Report/";
|
||||||
|
import SchedulesReminder from "../pages/SchedulesReminder/";
|
||||||
|
|
||||||
import Tickets from "../pages/Tickets/";
|
import Tickets from "../pages/Tickets/";
|
||||||
import Signup from "../pages/Signup/";
|
import Signup from "../pages/Signup/";
|
||||||
|
@ -20,7 +21,6 @@ import { AuthProvider } from "../context/Auth/AuthContext";
|
||||||
import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext";
|
import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext";
|
||||||
import Route from "./Route";
|
import Route from "./Route";
|
||||||
|
|
||||||
//import { Report } from "@material-ui/icons";
|
|
||||||
|
|
||||||
//console.log('---AuthProvider: ',AuthProvider)
|
//console.log('---AuthProvider: ',AuthProvider)
|
||||||
|
|
||||||
|
@ -61,6 +61,10 @@ const Routes = () => {
|
||||||
|
|
||||||
|
|
||||||
<Route exact path="/contacts" component={Contacts} isPrivate />
|
<Route exact path="/contacts" component={Contacts} isPrivate />
|
||||||
|
|
||||||
|
<Route exact path="/schedulesReminder" component={SchedulesReminder} isPrivate />
|
||||||
|
|
||||||
|
|
||||||
<Route exact path="/users" component={Users} isPrivate />
|
<Route exact path="/users" component={Users} isPrivate />
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
|
|
Loading…
Reference in New Issue