Initial commit
This commit is contained in:
@@ -0,0 +1,559 @@
|
||||
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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user