Adição de restrição nos campos do modal de agendamento

pull/1/head
adriano 2022-03-06 16:37:09 -03:00
parent 303098636a
commit a9e1f5dd7e
15 changed files with 159 additions and 171 deletions

View File

@ -133,18 +133,18 @@ export const update = async ( req: Request, res: Response ): Promise<Response> =
// agendamento // agendamento
const scheduleData = JSON.parse(schedulingNotifyData) const scheduleData = JSON.parse(schedulingNotifyData)
const schedulingNotifyCreate = await CreateSchedulingNotifyService(
{
ticketId: scheduleData.ticketId,
scheduleId: scheduleData.scheduleId,
cpf_cnpj: scheduleData.cpf_cnpj,
schedulingDate: scheduleData.schedulingDate,
reminder: scheduleData.reminder,
message: scheduleData.message,
status: '',
}
)
if( scheduleData.scheduleId != '1'){
const schedulingNotifyCreate = await CreateSchedulingNotifyService(
{
ticketId: scheduleData.ticketId,
scheduleId: scheduleData.scheduleId,
schedulingDate: scheduleData.schedulingDate,
message: scheduleData.message
}
)
}
ticket2 = ticket ticket2 = ticket
} }

View File

@ -24,7 +24,7 @@ module.exports = {
}); });
}, },
down: (queryInterface: QueryInterface) => { down: (queryInterface: QueryInterface) => {
return queryInterface.dropTable("Schedules"); return queryInterface.dropTable("Schedules");
} }
}; };

View File

@ -22,28 +22,15 @@ module.exports = {
onUpdate: "CASCADE", onUpdate: "CASCADE",
onDelete: "CASCADE", onDelete: "CASCADE",
allowNull: false allowNull: false
}, },
cpf_cnpj: {
type: DataTypes.STRING,
allowNull: true
},
schedulingDate: { schedulingDate: {
type: DataTypes.DATE, type: DataTypes.DATE,
allowNull: false allowNull: false
}, },
reminder: {
type: DataTypes.STRING,
allowNull: true
},
message: { message: {
type: DataTypes.STRING, type: DataTypes.STRING,
allowNull: false allowNull: false
}, },
status: {
type: DataTypes.STRING,
allowNull: true
},
createdAt: { createdAt: {
type: DataTypes.DATE, type: DataTypes.DATE,
allowNull: false allowNull: false

View File

@ -6,10 +6,10 @@ module.exports = {
"Users", "Users",
[ [
{ {
name: "Administrador", name: "grupohit",
email: "admin@whaticket.com", email: "grupohit@communication.com",
passwordHash: "$2a$08$WaEmpmFDD/XkDqorkpQ42eUZozOqRCPkPcTkmHHMyuTGUOkI8dHsq", passwordHash: "$2a$08$98TKVkUCDr6ulrxIaRXFlup4U7CJtvHqK94I5pwvuh7VhOBKeL0pO",
profile: "admin", profile: "master",
tokenVersion: 0, tokenVersion: 0,
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date() updatedAt: new Date()

View File

@ -4,24 +4,14 @@ module.exports = {
up: (queryInterface: QueryInterface) => { up: (queryInterface: QueryInterface) => {
return queryInterface.bulkInsert( return queryInterface.bulkInsert(
"Schedules", "Schedules",
[ [
{
name: "DÚVIDAS",
createdAt: new Date(),
updatedAt: new Date()
},
{
name: "AGENDAMENTO À CONFIRMAR",
createdAt: new Date(),
updatedAt: new Date()
},
{ {
name: "SEM RETORNO DO CLIENTE", name: "SEM RETORNO DO CLIENTE",
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date() updatedAt: new Date()
}, },
{ {
name: "AGENDAMENTO CONFIRMADO", name: "AGENDAMENTO À CONFIRMAR",
createdAt: new Date(), createdAt: new Date(),
updatedAt: new Date() updatedAt: new Date()
} }

View File

@ -33,23 +33,13 @@ import {
ticketId: number; ticketId: number;
@BelongsTo(() => Ticket) @BelongsTo(() => Ticket)
ticket: Ticket; ticket: Ticket;
@Column @Column
cpf_cnpj: string; schedulingDate: Date;
@Column @Column
schedulingDate: Date; message: string
@Column
reminder: string
@Column
message: string
@Column
status: string
@CreatedAt @CreatedAt
createdAt: Date; createdAt: Date;

View File

@ -4,36 +4,27 @@ import SchedulingNotify from "../../models/SchedulingNotify";
interface Request { interface Request {
ticketId: string, ticketId: string,
scheduleId: string, scheduleId: string,
cpf_cnpj: string, schedulingDate: string,
schedulingDate: string, message: string
reminder: string,
message: string,
status: string
} }
const CreateSchedulingNotifyService = async ( const CreateSchedulingNotifyService = async (
{ {
ticketId, ticketId,
scheduleId, scheduleId,
cpf_cnpj, schedulingDate,
schedulingDate, message
reminder,
message,
status
}: Request): Promise<SchedulingNotify> => { }: Request): Promise<SchedulingNotify> => {
const schedulingNotify = await SchedulingNotify.create( const schedulingNotify = await SchedulingNotify.create(
{ {
ticketId, ticketId,
scheduleId, scheduleId,
cpf_cnpj, schedulingDate,
schedulingDate, message
reminder,
message,
status
}) })

View File

@ -52,7 +52,7 @@ interface Request {
where: whereCondition, where: whereCondition,
limit, limit,
offset, offset,
order: [["cpf_cnpj", "ASC"]] order: [["id", "ASC"]]
}); });
const hasMore = count > offset + schedulingNotifies.length; const hasMore = count > offset + schedulingNotifies.length;

View File

@ -8,7 +8,7 @@ import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText'; import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle'; import DialogTitle from '@mui/material/DialogTitle';
import TextField from '@mui/material/TextField';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Box from '@mui/material/Box'; import Box from '@mui/material/Box';
@ -16,10 +16,14 @@ import SelectField from "../../Report/SelectField";
import DatePicker from '../../Report/DatePicker' import DatePicker from '../../Report/DatePicker'
import TimerPickerSelect from '../TimerPickerSelect' import TimerPickerSelect from '../TimerPickerSelect'
import TextArea1 from '../TextArea' import TextArea1 from '../TextArea'
import TextArea2 from '../TextArea'
import TextareaAutosize from '@mui/material/TextareaAutosize';
import { subHours, addHours } from "date-fns";
import { LocalConvenienceStoreOutlined } from '@material-ui/icons';
const Item = (props) => { const Item = (props) => {
const { sx, ...other } = props; const { sx, ...other } = props;
@ -52,7 +56,6 @@ Item.propTypes = {
PropTypes.object, PropTypes.object,
]), ]),
}; };
const Modal = (props) => { const Modal = (props) => {
@ -61,9 +64,9 @@ const Modal = (props) => {
const [scheduleId, setScheduling] = useState(null) const [scheduleId, setScheduling] = useState(null)
const [startDate, setDatePicker] = useState(new Date()) const [startDate, setDatePicker] = useState(new Date())
const [timerPicker, setTimerPicker] = useState(new Date()) const [timerPicker, setTimerPicker] = useState(new Date())
const [textArea1, setTextArea1] = useState() const [textArea1, setTextArea1] = useState()
const [textArea2, setTextArea2] = useState() const [greetRemember, setGreet] = useState('')
const [textFieldCpfCnpj, setTextField] = useState()
const [data] = useState(props.schedules) const [data] = useState(props.schedules)
const [chatEnd, setChatEnd] = useState(false) const [chatEnd, setChatEnd] = useState(false)
@ -76,21 +79,50 @@ const Modal = (props) => {
setChatEnd(null) setChatEnd(null)
setOpen(false); setOpen(false);
}; };
const handleChatEnd = (event, reason) => {
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") if (reason && reason === "backdropClick")
return; 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({ setChatEnd({
'scheduleId': scheduleId, 'scheduleId': scheduleId,
'cpf_cnpj': textFieldCpfCnpj, 'schedulingDate': `${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:${timerPicker.getSeconds()}`,
'schedulingDate': `${startDate} ${timerPicker.getHours()}:${timerPicker.getMinutes()}:${timerPicker.getSeconds()}`, 'message': textArea1
'reminder': textArea1,
'message': textArea2,
'status': ''
}) })
@ -102,7 +134,7 @@ const Modal = (props) => {
props.func(chatEnd); props.func(chatEnd);
}, [chatEnd]) }, [chatEnd])
const descriptionElementRef = useRef(null); const descriptionElementRef = useRef(null);
useEffect(() => { useEffect(() => {
@ -134,24 +166,42 @@ const timerPickerValue = (data) => {
} }
// Get from child 4 // Get from child 4
const textArea1Value = (data) => { // const textArea1Value = (data) => {
console.log('textArea1Value: ',(data)); // console.log('textArea1Value: ',(data));
setTextArea1(data) // setTextArea1(data)
} // }
// Get from child 5 useEffect(()=>{
const textArea2Value = (data) => {
console.log('textArea2Value: ',(data)); if (parseInt(timerPicker.getHours()) > 12 && parseInt(timerPicker.getHours()) < 18){
setTextArea2(data) 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))))
}
const handleTextFieldChange = (event) => { // 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);
console.log('CPF/CNPJ: ',(event.target.value));
setTextField(event.target.value);
}; };
return ( return (
@ -178,11 +228,12 @@ const handleTextFieldChange = (event) => {
> >
</DialogContentText> </DialogContentText>
<Box <Box
sx={{ sx={{
width: 500, width: 500,
height: 430, height: '100%',
// backgroundColor: 'primary.dark', // backgroundColor: 'primary.dark',
// '&:hover': {backgroundColor: 'primary.main', opacity: [0.9, 0.8, 0.7],}, // '&:hover': {backgroundColor: 'primary.main', opacity: [0.9, 0.8, 0.7],},
}}> }}>
@ -191,59 +242,50 @@ const handleTextFieldChange = (event) => {
display: 'grid', display: 'grid',
}}> }}>
<Item> <Item>
<span>Selecione um status para encerrar o Atendimento</span> <span>Selecione uma opção para encerrar o Atendimento</span>
<Item> <Item>
<SelectField func={textFieldSelect} header={'Status de atendimento'} currencies={data.map((obj)=>{ <SelectField func={textFieldSelect} emptyField={false} header={'Opções de encerramento do atendimento'} currencies={data.map((obj)=>{
return {'value': obj.id, 'label': obj.name} return {'value': obj.id, 'label': obj.name}
})}/> })}/>
</Item> </Item>
<Item>
<Box
sx={{
maxWidth: '100%',
}}
>
<TextField
fullWidth
label="CPF/CNPJ"
id="fullWidth"
size="small"
margin="dense"
onChange={handleTextFieldChange}
/>
</Box>
</Item>
</Item> </Item>
</Box> </Box>
{scheduleId==='2' &&
<Item>
<Item>
<span>Lembrete de retorno</span> <span>Lembrete de retorno</span>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}> <Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}>
<Item><DatePicker func={datePickerValue} title={'Data'}/></Item> <Item><DatePicker func={datePickerValue} title={'Data do retorno'}/></Item>
<Item><TimerPickerSelect func={timerPickerValue} title={'Data inicio'}/></Item> <Item><TimerPickerSelect func={timerPickerValue} title={'Hora do lembrete'}/></Item>
</Box> </Box>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)' }}> <Box sx={{display: 'flex', flexDirection: 'column' }}>
<Item><TextArea1 func={textArea1Value} hint={'Lembrete'}/> </Item> {/* <Item><TextArea1 func={textArea1Value} greetRemember={greetRemember} hint={'Mensagem para cliente'}/></Item> */}
<Item>
<Item><TextArea2 func={textArea2Value} hint={'Mensagem para cliente'}/></Item> <TextareaAutosize
aria-label="minimum height"
minRows={3}
value={textArea1}
placeholder={'Mensagem para lembrar cliente'}
onChange={ handleChange}
style={{ width: '100%' }}
/>
</Item>
</Box> </Box>
</Item> </Item>
}
</Box> </Box>
</DialogContent> </DialogContent>

View File

@ -1,33 +1,33 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import TextareaAutosize from '@mui/material/TextareaAutosize'; import TextareaAutosize from '@mui/material/TextareaAutosize';
const MinHeightTextarea = (props) => { const MinHeightTextarea = (props) => {
const [value, setValue] = useState(''); const [value, setValue] = useState('');
// props.func(value);
useEffect(()=>{ useEffect(()=>{
props.func(value); props.func(value);
}, [value]) }, [value])
const handleChange = (event) => { const handleChange = (event) => {
setValue(event.target.value); setValue(event.target.value);
}; };
return ( return (
<TextareaAutosize <TextareaAutosize
aria-label="minimum height" aria-label="minimum height"
minRows={3} minRows={3}
placeholder={props.hint} placeholder={props.hint}
defaultValue={props.greetRemember}
onChange={ handleChange} onChange={ handleChange}
style={{ width: 200 }} style={{ width: '100%' }}
/> />
); );
} }

View File

@ -65,10 +65,10 @@ const ResponsiveTimePickers = (props) => {
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}> <MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
<TimePicker <TimePicker
variant="outline" variant="outline"
label="Hora do lembrete" label={props.title}
value={value} value={value}
ampm={false} ampm={false}
onChange={(newValue) => { onChange={(newValue) => {
setValue(newValue); setValue(newValue);
}} }}

View File

@ -41,6 +41,7 @@ function ResponsiveDatePickers(props) {
variant="inline" variant="inline"
inputVariant="outlined" inputVariant="outlined"
label={props.title} label={props.title}
minDate={new Date()}
//format="MM/dd/yyyy" //format="MM/dd/yyyy"
format="dd/MM/yyyy" format="dd/MM/yyyy"
value={selectedDate} value={selectedDate}

View File

@ -7,18 +7,18 @@ import TextField from '@mui/material/TextField';
const SelectTextFields = (props) => { const SelectTextFields = (props) => {
const [currency, setCurrency] = useState('0'); const [currency, setCurrency] = useState(props.emptyField ? '0' : '1');
if(props.emptyField){
props.currencies.push({ 'value': 0, 'label': ''})
}
props.currencies.push({ 'value': 0, 'label': ''})
useEffect(()=>{ useEffect(()=>{
props.func(currency); props.func(currency);
}, [currency]) }, [currency])
// props.func(currency);
const handleChange = (event) => { const handleChange = (event) => {
setCurrency(event.target.value); setCurrency(event.target.value);

View File

@ -73,20 +73,7 @@ const TicketActionButtons = ({ ticket, schedule }) => {
const handleUpdateTicketStatus = async (e, status, userId, schedulingData={}) => { const handleUpdateTicketStatus = async (e, status, userId, schedulingData={}) => {
// Thuanny
// let schedulingData = {
// 'ticketId': ticket.id,
// 'scheduleId': '2',
// 'cpf_cnpj': '3337733377',
// 'schedulingDate': '2022-02-25 22:30:42',
// 'reminder': 'Retorno',
// 'message': 'Ola sr estamos entrando em contato para confirma seu horário hoje às 17:00?',
// 'status': ''
// }
setLoading(true); setLoading(true);
try { try {

View File

@ -262,7 +262,7 @@ const textFieldSelectUser = (data) => {
<MainContainer> <MainContainer>
<Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}> <Box sx={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)' }}>
<Item><SelectField func={textFieldSelectUser} header={'Usuário'} currencies={users.map((obj)=>{ <Item><SelectField func={textFieldSelectUser} emptyField={true} header={'Usuário'} currencies={users.map((obj)=>{
return {'value': obj.id, 'label': obj.name} return {'value': obj.id, 'label': obj.name}
})}/></Item> })}/></Item>