559 lines
22 KiB
JavaScript
559 lines
22 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
|
import {
|
|
makeStyles,
|
|
Paper,
|
|
Grid,
|
|
TextField,
|
|
Table,
|
|
TableHead,
|
|
TableBody,
|
|
TableCell,
|
|
TableRow,
|
|
IconButton,
|
|
FormControl,
|
|
InputLabel,
|
|
MenuItem,
|
|
Select
|
|
} from "@material-ui/core";
|
|
import { Formik, Form, Field } from 'formik';
|
|
import ButtonWithSpinner from "../ButtonWithSpinner";
|
|
import ConfirmationModal from "../ConfirmationModal";
|
|
|
|
import { Edit as EditIcon } from "@material-ui/icons";
|
|
|
|
import { toast } from "react-toastify";
|
|
import usePlans from "../../hooks/usePlans";
|
|
import { i18n } from "../../translate/i18n";
|
|
|
|
|
|
const useStyles = makeStyles(theme => ({
|
|
root: {
|
|
width: '100%'
|
|
},
|
|
mainPaper: {
|
|
width: '100%',
|
|
flex: 1,
|
|
padding: theme.spacing(2)
|
|
},
|
|
fullWidth: {
|
|
width: '100%'
|
|
},
|
|
tableContainer: {
|
|
width: '100%',
|
|
overflowX: "scroll",
|
|
...theme.scrollbarStyles
|
|
},
|
|
textfield: {
|
|
width: '100%'
|
|
},
|
|
textRight: {
|
|
textAlign: 'right'
|
|
},
|
|
row: {
|
|
paddingTop: theme.spacing(2),
|
|
paddingBottom: theme.spacing(2)
|
|
},
|
|
control: {
|
|
paddingRight: theme.spacing(1),
|
|
paddingLeft: theme.spacing(1)
|
|
},
|
|
buttonContainer: {
|
|
textAlign: 'right',
|
|
padding: theme.spacing(1)
|
|
}
|
|
}));
|
|
|
|
export function PlanManagerForm(props) {
|
|
const { onSubmit, onDelete, onCancel, initialValue, loading } = props;
|
|
const classes = useStyles()
|
|
|
|
const [record, setRecord] = useState({
|
|
name: '',
|
|
users: 0,
|
|
connections: 0,
|
|
queues: 0,
|
|
value: 0,
|
|
useCampaigns: true,
|
|
useSchedules: true,
|
|
useInternalChat: true,
|
|
useExternalApi: true,
|
|
useKanban: true,
|
|
useOpenAi: true,
|
|
useIntegrations: true,
|
|
});
|
|
|
|
useEffect(() => {
|
|
setRecord(initialValue)
|
|
}, [initialValue])
|
|
|
|
const handleSubmit = async (data) => {
|
|
onSubmit(data)
|
|
}
|
|
|
|
return (
|
|
<Formik
|
|
enableReinitialize
|
|
className={classes.fullWidth}
|
|
initialValues={record}
|
|
onSubmit={(values, { resetForm }) =>
|
|
setTimeout(() => {
|
|
handleSubmit(values)
|
|
resetForm()
|
|
}, 500)
|
|
}
|
|
>
|
|
{(values) => (
|
|
<Form className={classes.fullWidth}>
|
|
<Grid spacing={1} justifyContent="flex-start" container>
|
|
{/* NOME */}
|
|
<Grid xs={12} sm={6} md={2} item>
|
|
<Field
|
|
as={TextField}
|
|
label={i18n.t("plans.form.name")}
|
|
name="name"
|
|
variant="outlined"
|
|
className={classes.fullWidth}
|
|
margin="dense"
|
|
/>
|
|
</Grid>
|
|
|
|
{/* USUARIOS */}
|
|
<Grid xs={12} sm={6} md={1} item>
|
|
<Field
|
|
as={TextField}
|
|
label={i18n.t("plans.form.users")}
|
|
name="users"
|
|
variant="outlined"
|
|
className={classes.fullWidth}
|
|
margin="dense"
|
|
type="number"
|
|
/>
|
|
</Grid>
|
|
|
|
{/* CONEXOES */}
|
|
<Grid xs={12} sm={6} md={1} item>
|
|
<Field
|
|
as={TextField}
|
|
label={i18n.t("plans.form.connections")}
|
|
name="connections"
|
|
variant="outlined"
|
|
className={classes.fullWidth}
|
|
margin="dense"
|
|
type="number"
|
|
/>
|
|
</Grid>
|
|
|
|
{/* FILAS */}
|
|
<Grid xs={12} sm={6} md={1} item>
|
|
<Field
|
|
as={TextField}
|
|
label="Filas"
|
|
name="queues"
|
|
variant="outlined"
|
|
className={classes.fullWidth}
|
|
margin="dense"
|
|
type="number"
|
|
/>
|
|
</Grid>
|
|
|
|
{/* VALOR */}
|
|
<Grid xs={12} sm={6} md={1} item>
|
|
<Field
|
|
as={TextField}
|
|
label="Valor"
|
|
name="value"
|
|
variant="outlined"
|
|
className={classes.fullWidth}
|
|
margin="dense"
|
|
type="text"
|
|
/>
|
|
</Grid>
|
|
|
|
{/* CAMPANHAS */}
|
|
<Grid xs={12} sm={6} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useCampaigns-selection">{i18n.t("plans.form.campaigns")}</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useCampaigns-selection"
|
|
label={i18n.t("plans.form.campaigns")}
|
|
labelId="useCampaigns-selection-label"
|
|
name="useCampaigns"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* AGENDAMENTOS */}
|
|
<Grid xs={12} sm={8} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useSchedules-selection">{i18n.t("plans.form.schedules")}</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useSchedules-selection"
|
|
label={i18n.t("plans.form.schedules")}
|
|
labelId="useSchedules-selection-label"
|
|
name="useSchedules"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* CHAT INTERNO */}
|
|
<Grid xs={12} sm={8} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useInternalChat-selection">Chat Interno</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useInternalChat-selection"
|
|
label="Chat Interno"
|
|
labelId="useInternalChat-selection-label"
|
|
name="useInternalChat"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* API Externa */}
|
|
<Grid xs={12} sm={8} md={4} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useExternalApi-selection">API Externa</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useExternalApi-selection"
|
|
label="API Externa"
|
|
labelId="useExternalApi-selection-label"
|
|
name="useExternalApi"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* KANBAN */}
|
|
<Grid xs={12} sm={8} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useKanban-selection">Kanban</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useKanban-selection"
|
|
label="Kanban"
|
|
labelId="useKanban-selection-label"
|
|
name="useKanban"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* OPENAI */}
|
|
<Grid xs={12} sm={8} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useOpenAi-selection">Open.Ai</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useOpenAi-selection"
|
|
label="Talk.Ai"
|
|
labelId="useOpenAi-selection-label"
|
|
name="useOpenAi"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
|
|
{/* INTEGRACOES */}
|
|
<Grid xs={12} sm={8} md={2} item>
|
|
<FormControl margin="dense" variant="outlined" fullWidth>
|
|
<InputLabel htmlFor="useIntegrations-selection">Integrações</InputLabel>
|
|
<Field
|
|
as={Select}
|
|
id="useIntegrations-selection"
|
|
label="Integrações"
|
|
labelId="useIntegrations-selection-label"
|
|
name="useIntegrations"
|
|
margin="dense"
|
|
>
|
|
<MenuItem value={true}>{i18n.t("plans.form.enabled")}</MenuItem>
|
|
<MenuItem value={false}>{i18n.t("plans.form.disabled")}</MenuItem>
|
|
</Field>
|
|
</FormControl>
|
|
</Grid>
|
|
</Grid>
|
|
<Grid spacing={2} justifyContent="flex-end" container>
|
|
|
|
<Grid sm={3} md={2} item>
|
|
<ButtonWithSpinner className={classes.fullWidth} loading={loading} onClick={() => onCancel()} variant="contained">
|
|
{i18n.t("plans.form.clear")}
|
|
</ButtonWithSpinner>
|
|
</Grid>
|
|
{record.id !== undefined ? (
|
|
<Grid sm={3} md={2} item>
|
|
<ButtonWithSpinner className={classes.fullWidth} loading={loading} onClick={() => onDelete(record)} variant="contained" color="secondary">
|
|
{i18n.t("plans.form.delete")}
|
|
</ButtonWithSpinner>
|
|
</Grid>
|
|
) : null}
|
|
<Grid sm={3} md={2} item>
|
|
<ButtonWithSpinner className={classes.fullWidth} loading={loading} type="submit" variant="contained" color="primary">
|
|
{i18n.t("plans.form.save")}
|
|
</ButtonWithSpinner>
|
|
</Grid>
|
|
</Grid>
|
|
</Form>
|
|
)}
|
|
</Formik>
|
|
)
|
|
}
|
|
|
|
export function PlansManagerGrid(props) {
|
|
const { records, onSelect } = props
|
|
const classes = useStyles()
|
|
|
|
const renderCampaigns = (row) => {
|
|
return row.useCampaigns === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderSchedules = (row) => {
|
|
return row.useSchedules === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderInternalChat = (row) => {
|
|
return row.useInternalChat === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderExternalApi = (row) => {
|
|
return row.useExternalApi === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderKanban = (row) => {
|
|
return row.useKanban === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderOpenAi = (row) => {
|
|
return row.useOpenAi === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
const renderIntegrations = (row) => {
|
|
return row.useIntegrations === false ? `${i18n.t("plans.form.no")}` : `${i18n.t("plans.form.yes")}`;
|
|
};
|
|
|
|
return (
|
|
<Paper className={classes.tableContainer}>
|
|
<Table
|
|
className={classes.fullWidth}
|
|
// size="small"
|
|
padding="none"
|
|
aria-label="a dense table"
|
|
>
|
|
<TableHead>
|
|
<TableRow>
|
|
<TableCell align="center" style={{ width: '1%' }}>#</TableCell>
|
|
<TableCell align="left">{i18n.t("plans.form.name")}</TableCell>
|
|
<TableCell align="center">{i18n.t("plans.form.users")}</TableCell>
|
|
<TableCell align="center">{i18n.t("plans.form.connections")}</TableCell>
|
|
<TableCell align="center">Filas</TableCell>
|
|
<TableCell align="center">Valor</TableCell>
|
|
<TableCell align="center">{i18n.t("plans.form.campaigns")}</TableCell>
|
|
<TableCell align="center">{i18n.t("plans.form.schedules")}</TableCell>
|
|
<TableCell align="center">Chat Interno</TableCell>
|
|
<TableCell align="center">API Externa</TableCell>
|
|
<TableCell align="center">Kanban</TableCell>
|
|
<TableCell align="center">Open.Ai</TableCell>
|
|
<TableCell align="center">Integrações</TableCell>
|
|
</TableRow>
|
|
</TableHead>
|
|
<TableBody>
|
|
{records.map((row) => (
|
|
<TableRow key={row.id}>
|
|
<TableCell align="center" style={{ width: '1%' }}>
|
|
<IconButton onClick={() => onSelect(row)} aria-label="delete">
|
|
<EditIcon />
|
|
</IconButton>
|
|
</TableCell>
|
|
<TableCell align="left">{row.name || '-'}</TableCell>
|
|
<TableCell align="center">{row.users || '-'}</TableCell>
|
|
<TableCell align="center">{row.connections || '-'}</TableCell>
|
|
<TableCell align="center">{row.queues || '-'}</TableCell>
|
|
<TableCell align="center">{i18n.t("plans.form.money")} {row.value ? row.value.toLocaleString('pt-br', { minimumFractionDigits: 2 }) : '00.00'}</TableCell>
|
|
<TableCell align="center">{renderCampaigns(row)}</TableCell>
|
|
<TableCell align="center">{renderSchedules(row)}</TableCell>
|
|
<TableCell align="center">{renderInternalChat(row)}</TableCell>
|
|
<TableCell align="center">{renderExternalApi(row)}</TableCell>
|
|
<TableCell align="center">{renderKanban(row)}</TableCell>
|
|
<TableCell align="center">{renderOpenAi(row)}</TableCell>
|
|
<TableCell align="center">{renderIntegrations(row)}</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</Paper>
|
|
)
|
|
}
|
|
|
|
export default function PlansManager() {
|
|
const classes = useStyles()
|
|
const { list, save, update, remove } = usePlans()
|
|
|
|
const [showConfirmDialog, setShowConfirmDialog] = useState(false)
|
|
const [loading, setLoading] = useState(false)
|
|
const [records, setRecords] = useState([])
|
|
const [record, setRecord] = useState({
|
|
name: '',
|
|
users: 0,
|
|
connections: 0,
|
|
queues: 0,
|
|
value: 0,
|
|
useCampaigns: true,
|
|
useSchedules: true,
|
|
useInternalChat: true,
|
|
useExternalApi: true,
|
|
useKanban: true,
|
|
useOpenAi: true,
|
|
useIntegrations: true,
|
|
})
|
|
|
|
useEffect(() => {
|
|
async function fetchData() {
|
|
await loadPlans()
|
|
}
|
|
fetchData()
|
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
}, [record])
|
|
|
|
const loadPlans = async () => {
|
|
setLoading(true)
|
|
try {
|
|
const planList = await list()
|
|
setRecords(planList)
|
|
} catch (e) {
|
|
toast.error('Não foi possível carregar a lista de registros')
|
|
}
|
|
setLoading(false)
|
|
}
|
|
|
|
const handleSubmit = async (data) => {
|
|
setLoading(true)
|
|
console.log(data)
|
|
try {
|
|
if (data.id !== undefined) {
|
|
await update(data)
|
|
} else {
|
|
await save(data)
|
|
}
|
|
await loadPlans()
|
|
handleCancel()
|
|
toast.success('Operação realizada com sucesso!')
|
|
} catch (e) {
|
|
toast.error('Não foi possível realizar a operação. Verifique se já existe uma plano com o mesmo nome ou se os campos foram preenchidos corretamente')
|
|
}
|
|
setLoading(false)
|
|
}
|
|
|
|
const handleDelete = async () => {
|
|
setLoading(true)
|
|
try {
|
|
await remove(record.id)
|
|
await loadPlans()
|
|
handleCancel()
|
|
toast.success('Operação realizada com sucesso!')
|
|
} catch (e) {
|
|
toast.error('Não foi possível realizar a operação')
|
|
}
|
|
setLoading(false)
|
|
}
|
|
|
|
const handleOpenDeleteDialog = () => {
|
|
setShowConfirmDialog(true)
|
|
}
|
|
|
|
const handleCancel = () => {
|
|
setRecord({
|
|
id: undefined,
|
|
name: '',
|
|
users: 0,
|
|
connections: 0,
|
|
queues: 0,
|
|
value: 0,
|
|
useCampaigns: true,
|
|
useSchedules: true,
|
|
useInternalChat: true,
|
|
useExternalApi: true,
|
|
useKanban: true,
|
|
useOpenAi: true,
|
|
useIntegrations: true
|
|
})
|
|
}
|
|
|
|
const handleSelect = (data) => {
|
|
|
|
let useCampaigns = data.useCampaigns === false ? false : true
|
|
let useSchedules = data.useSchedules === false ? false : true
|
|
let useInternalChat = data.useInternalChat === false ? false : true
|
|
let useExternalApi = data.useExternalApi === false ? false : true
|
|
let useKanban = data.useKanban === false ? false : true
|
|
let useOpenAi = data.useOpenAi === false ? false : true
|
|
let useIntegrations = data.useIntegrations === false ? false : true
|
|
|
|
setRecord({
|
|
id: data.id,
|
|
name: data.name || '',
|
|
users: data.users || 0,
|
|
connections: data.connections || 0,
|
|
queues: data.queues || 0,
|
|
value: data.value?.toLocaleString('pt-br', { minimumFractionDigits: 0 }) || 0,
|
|
useCampaigns,
|
|
useSchedules,
|
|
useInternalChat,
|
|
useExternalApi,
|
|
useKanban,
|
|
useOpenAi,
|
|
useIntegrations
|
|
})
|
|
}
|
|
|
|
return (
|
|
<Paper className={classes.mainPaper} elevation={0}>
|
|
<Grid spacing={2} container>
|
|
<Grid xs={12} item>
|
|
<PlanManagerForm
|
|
initialValue={record}
|
|
onDelete={handleOpenDeleteDialog}
|
|
onSubmit={handleSubmit}
|
|
onCancel={handleCancel}
|
|
loading={loading}
|
|
/>
|
|
</Grid>
|
|
<Grid xs={12} item>
|
|
<PlansManagerGrid
|
|
records={records}
|
|
onSelect={handleSelect}
|
|
/>
|
|
</Grid>
|
|
</Grid>
|
|
<ConfirmationModal
|
|
title="Exclusão de Registro"
|
|
open={showConfirmDialog}
|
|
onClose={() => setShowConfirmDialog(false)}
|
|
onConfirm={() => handleDelete()}
|
|
>
|
|
Deseja realmente excluir esse registro?
|
|
</ConfirmationModal>
|
|
</Paper>
|
|
)
|
|
} |