diff --git a/backend/src/controllers/ReportController.ts b/backend/src/controllers/ReportController.ts index 56f5c80..4025384 100644 --- a/backend/src/controllers/ReportController.ts +++ b/backend/src/controllers/ReportController.ts @@ -5,7 +5,13 @@ import AppError from "../errors/AppError"; import ShowTicketReport from "../services/TicketServices/ShowTicketReport"; -export const reportUser = async (req: Request, res: Response): Promise => { +type IndexQuery = { + userId: string; + startDate: string; + endDate: string; + }; + +/*export const reportUser = async (req: Request, res: Response): Promise => { const { userId } = req.params; @@ -15,6 +21,22 @@ export const reportUser = async (req: Request, res: Response): Promise return res.status(200).json(test); +};*/ + + +export const reportUserByDateStartDateEnd = async (req: Request, res: Response): Promise => { + + const { userId, startDate, endDate } = req.query as IndexQuery + + console.log('******* Estrou no report') + console.log('******* userId: ', userId) + console.log('******* startDate: ', startDate) + console.log('******* endDate: ', endDate) + + const data_query = await ShowTicketReport(userId, startDate, endDate); + + return res.status(200).json(data_query); + }; /*export const reportAll = async (req: Request, res: Response): Promise => { diff --git a/backend/src/routes/reportRoutes.ts b/backend/src/routes/reportRoutes.ts index c05f6f4..e86ac41 100644 --- a/backend/src/routes/reportRoutes.ts +++ b/backend/src/routes/reportRoutes.ts @@ -7,7 +7,9 @@ import * as ReportController from "../controllers/ReportController"; const reportRoutes = express.Router(); -reportRoutes.get("/reports/:userId", /*isAuth,*/ ReportController.reportUser); +//reportRoutes.get("/reports/:userId", /*isAuth,*/ ReportController.reportUser); + +reportRoutes.get("/reports", /*isAuth,*/ ReportController.reportUserByDateStartDateEnd); //reportRoutes.get("/reports", /*isAuth,*/ ReportController.reportAll); diff --git a/backend/src/services/TicketServices/ShowTicketReport.ts b/backend/src/services/TicketServices/ShowTicketReport.ts index 8b83ade..527a5c6 100644 --- a/backend/src/services/TicketServices/ShowTicketReport.ts +++ b/backend/src/services/TicketServices/ShowTicketReport.ts @@ -7,7 +7,62 @@ import Queue from "../../models/Queue"; import Message from "../../models/Message"; import { userInfo } from "os"; -//Report by user +import { Op } from "sequelize"; + +import { Sequelize } from "sequelize"; +import moment from 'moment'; + +import { startOfDay, endOfDay, parseISO, getDate} from "date-fns"; + +//Report by user, startDate, endDate +const ShowTicketReport = async (id: string | number, startDate: string, endDate: string): Promise => { + + const ticket = await Ticket.findAll({ + where: { + userid: id, + //createdAt: { + // [Op.between]: [+new Date('2022-01-24').toISOString(), +new Date().toISOString()] + //}, + createdAt: { + [Op.gte]: startDate+' 00:00:00.000000', + [Op.lte]: endDate +' 23:59:59.999999' + } + + }, + + + attributes: ['id', 'status', 'createdAt', 'updatedAt'], + include: [ + { + model: Message, + required:true, + separate: true, + attributes: ['body', 'read', 'mediaType','fromMe', 'mediaUrl','createdAt'], + order: [ + ['createdAt', 'ASC'] + ] + }, + { + model: Contact, + attributes: ['name', 'number'] + }, + { + model: User, + attributes: ['name', 'email'] + }, + { + model: Queue, + attributes: ['name'] + }, + + ], + + }); + + + + +/*//Report by user const ShowTicketReport = async (id: string | number): Promise => { const ticket = await Ticket.findAll({ @@ -36,47 +91,10 @@ const ShowTicketReport = async (id: string | number): Promise => { attributes: ['name'] }, - ], - - + ], - }); - - - - - - /*const ticket = await Message.findAll({ - //raw: true, - where:{''}, - attributes: ['body', 'createdAt', 'ticketId'], - include: [ - { - model: Ticket, - attributes: ['contactid', 'userid', 'queueid', 'status'], - include:[ - { - model: Contact, - attributes: ['name', 'number'] - }, - { - model: User, - attributes: ['name', 'email'] - }, - { - model: Queue, - attributes: ['name'] - } - ], - }, - - ], - order: - ['ticketId', 'createdAt'] - }); */ - if (!ticket) { throw new AppError("ERR_NO_TICKET_FOUND", 404); } diff --git a/frontend/src/components/Report/DatePicker/index.js b/frontend/src/components/Report/DatePicker/index.js index b36b15a..5031bd9 100644 --- a/frontend/src/components/Report/DatePicker/index.js +++ b/frontend/src/components/Report/DatePicker/index.js @@ -12,11 +12,17 @@ import { MuiPickersUtilsProvider, } from '@material-ui/pickers'; + +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(new Date()); - props.func(selectedDate); + props.func(formatDateDatePicker(selectedDate)); return ( diff --git a/frontend/src/components/Report/MTable/data.js b/frontend/src/components/Report/MTable/data.js index 6cebce3..41a355d 100644 --- a/frontend/src/components/Report/MTable/data.js +++ b/frontend/src/components/Report/MTable/data.js @@ -1,6 +1,12 @@ import { gridDateTimeFormatter } from "@mui/x-data-grid"; + + + + + export const data = [ + { "id": 210, "status": "closed", @@ -109,5 +115,92 @@ export const data = [ "createdAt": "2022-01-18T20:26:04.360Z" } ] - } + }, + + { + "id":229, + "status":"closed", + "createdAt":"2022-01-24T13:20:01.000Z", + "updatedAt":"2022-01-24T13:21:02.000Z", + "contact":{ + "name":"Meu Numero Oi", + "number":"5517988325936" + }, + "user":{ + "name":"Administrador", + "email":"admin@whaticket.com" + }, + "queue":{ + "name":"Cancelamento ou Sugestões" + }, + "messages":[ + { + "mediaUrl":null, + "body":"Bom dia", + "read":true, + "mediaType":"chat", + "fromMe":false, + "createdAt":"2022-01-24T13:20:01.562Z" + }, + { + "mediaUrl":null, + "body":"‎HIT COMMUNICATIONS 🇧🇷\n\nBem vindo ao novo canal digital de atendimento ao cliente. Escolha uma opção do MENU abaixo 👇 e digite o número:\n*1* - Atendimento a Fornecedores\n*2* - Cancelamento ou Sugestões\n*3* - Cobrança\n*4* - Comercial\n*5* - Contas a Pagar\n*6* - Suporte Técnico\n", + "read":true, + "mediaType":"chat", + "fromMe":true, + "createdAt":"2022-01-24T13:20:04.674Z" + }, + { + "mediaUrl":null, + "body":"2", + "read":true, + "mediaType":"chat", + "fromMe":false, + "createdAt":"2022-01-24T13:20:08.617Z" + }, + { + "mediaUrl":null, + "body":"‎Olá, sou do Cancelamento ou Sugestões, vou te atender em alguns instantes!", + "read":true, + "mediaType":"chat", + "fromMe":true, + "createdAt":"2022-01-24T13:20:09.216Z" + }, + { + "mediaUrl":null, + "body":"Ok obrigado", + "read":true, + "mediaType":"chat", + "fromMe":false, + "createdAt":"2022-01-24T13:20:13.902Z" + }, + { + "mediaUrl":null, + "body":"*Administrador:*\nOlá bom dia como posso ajudar", + "read":true, + "mediaType":"chat", + "fromMe":true, + "createdAt":"2022-01-24T13:20:34.561Z" + }, + { + "mediaUrl":null, + "body":"Estou com problemas técnicos", + "read":true, + "mediaType":"chat", + "fromMe":false, + "createdAt":"2022-01-24T13:20:54.191Z" + }, + { + "mediaUrl":null, + "body":"*Administrador:*\nok", + "read":true, + "mediaType":"chat", + "fromMe":true, + "createdAt":"2022-01-24T13:20:57.847Z" + } + ], + "tableData":{ + "id":0 + } + } ] \ No newline at end of file diff --git a/frontend/src/components/Report/MTable/index.js b/frontend/src/components/Report/MTable/index.js index 1fc4c52..87e7364 100644 --- a/frontend/src/components/Report/MTable/index.js +++ b/frontend/src/components/Report/MTable/index.js @@ -4,21 +4,13 @@ import MaterialTable from 'material-table'; import Modal from '../Modal' import { render } from '@testing-library/react'; -import React from 'react'; -import { fontSize } from '@mui/system'; -import { FastField } from 'formik'; - +import React from 'react'; - -let child_columns = [ - { title: 'Atendente', field: 'user.name' } -]; - const MTable = (props) => { const [selectedRow, setSelectedRow] = useState(null); - console.log('rederizou....................') + console.log('rederizou....................: ',props.data) useEffect(() => { @@ -40,7 +32,7 @@ const MTable = (props) => { console.log(selectedRow.messages); setSelectedRow(selectedRow.tableData.id) - render() + render() //evt.stopPropagation() } @@ -66,4 +58,5 @@ const MTable = (props) => { }; - export default React.memo(MTable); \ No newline at end of file + + export default React.memo(MTable) \ No newline at end of file diff --git a/frontend/src/components/Report/SelectField/index.js b/frontend/src/components/Report/SelectField/index.js index 2c3992f..ce5bd3a 100644 --- a/frontend/src/components/Report/SelectField/index.js +++ b/frontend/src/components/Report/SelectField/index.js @@ -7,6 +7,8 @@ import TextField from '@mui/material/TextField'; const SelectTextFields = (props) => { const [currency, setCurrency] = React.useState('0'); + props.currencies.push({ value: '0', label: ''}) + props.func(currency); const handleChange = (event) => { @@ -15,7 +17,7 @@ const SelectTextFields = (props) => { return ( - { noValidate autoComplete="off" > - { + + 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 === "RESET") { + return []; + } + +} + + + const reducer = (state, action) => { + if (action.type === "LOAD_USERS") { const users = action.payload; const newUsers = []; @@ -36,6 +70,7 @@ const reducer = (state, action) => { } }; + function Item(props) { @@ -71,8 +106,6 @@ Item.propTypes = { }; - - let columnsData = [ { title: 'Atendente', field: 'user.name' }, @@ -97,7 +130,7 @@ let columnsData = [ ]; - const currencies = [ + /*const currencies = [ { value: '1', label: 'Adriano', @@ -119,7 +152,7 @@ let columnsData = [ label: '', }, - ]; + ];*/ @@ -132,25 +165,33 @@ const Report = () => { const [pageNumber, setPageNumber] = useState(1); const [users, dispatch] = useReducer(reducer, []); - const [tot, setTot] = useState(0) - const [columns, setColums] = useState(columnsData) - const [datePicker1, setDatePicker1] = useState(new Date()) - const [datePicker2, setDatePicker2] = useState(new Date()) + + + 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, []) + 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); @@ -158,41 +199,76 @@ const Report = () => { console.log(err); } }; + fetchUsers(); + }, 500); return () => clearTimeout(delayDebounceFn); }, [searchParam, pageNumber]); - function handleTot (){ - setTot(tot+1) + useEffect(() => { - console.log('Datepicker valeu: ',DatePicker1.data) - /* if(tot == 3){ - setColums(columns1) - } */ + setLoading(true); -} + const delayDebounceFn = setTimeout(() => { + + const fetchQueries = async () => { + try { + const dataQuery = await api.get("/reports/", {params: {userId, startDate, endDate },}); + + console.log('fffffffffffffffffffff query: ', dataQuery.data) + dispatchQ({ type: "LOAD_QUERY", payload: dataQuery.data }); + + setLoading(false); + + } catch (err) { + console.log(err); + } + }; + + fetchQueries(); + + }, 500); + return () => clearTimeout(delayDebounceFn); + + }, [userId, startDate, endDate]); + // Get from child 1 -const datePicker1Value = (data) => { - console.log(data); +const datePicker1Value = (data) => { + console.log('DATE1: ',(data)); setDatePicker1(data) } // Get from child 2 const datePicker2Value = (data) => { - console.log(data); + console.log('DATE2: ',(data)); setDatePicker2(data) } // Get from child 3 const textFieldSelectUser = (data) => { - console.log(data); + console.log('textField: ',data); setUser(data) } + +function handleQuery (){ + + console.log('startDate: ', startDate) + console.log('endDate: ', endDate) + console.log('userid: ', userId) + + /* if(tot == 3){ + setColums(columns1) + } */ + +} + +console.log('XXXXXXXXX: ', query) + return ( @@ -200,12 +276,16 @@ const textFieldSelectUser = (data) => { - + { + return {'value': obj.id, 'label': obj.name} + })}/> + + - + @@ -214,10 +294,10 @@ const textFieldSelectUser = (data) => { display: 'grid', }}> - - - - + + + + {/*