| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- 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={i18n.t("plans.form.queues")}
- 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={i18n.t("plans.form.value")}
- 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">{i18n.t("plans.form.internalChat")}</InputLabel>
- <Field
- as={Select}
- id="useInternalChat-selection"
- label={i18n.t("plans.form.internalChat")}
- 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">{i18n.t("plans.form.externalApi")}</InputLabel>
- <Field
- as={Select}
- id="useExternalApi-selection"
- label={i18n.t("plans.form.externalApi")}
- 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">{i18n.t("plans.form.kanban")}</InputLabel>
- <Field
- as={Select}
- id="useKanban-selection"
- label={i18n.t("plans.form.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">
- {i18n.t("plans.form.integrations")}
- </InputLabel>
- <Field
- as={Select}
- id="useIntegrations-selection"
- label={i18n.t("plans.form.integrations")}
- 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">{i18n.t("plans.form.queues")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.value")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.campaigns")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.schedules")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.internalChat")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.externalApi")}</TableCell>
- <TableCell align="center">{i18n.t("plans.form.kanban")}</TableCell>
- <TableCell align="center">Open.Ai</TableCell>
- <TableCell align="center">{i18n.t("plans.form.integrations")}</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(i18n.t("plans.toasts.errorList"))
- }
- 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(i18n.t("plans.toasts.success"))
- } catch (e) {
- toast.error(i18n.t("plans.toasts.error"))
- }
- setLoading(false)
- }
- const handleDelete = async () => {
- setLoading(true)
- try {
- await remove(record.id)
- await loadPlans()
- handleCancel()
- toast.success(i18n.t("plans.toasts.success"))
- } catch (e) {
- toast.error(i18n.t("plans.toasts.errorOperation"))
- }
- 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={i18n.t("plans.confirm.title")}
- open={showConfirmDialog}
- onClose={() => setShowConfirmDialog(false)}
- onConfirm={() => handleDelete()}
- >
- {i18n.t("plans.confirm.message")}
- </ConfirmationModal>
- </Paper>
- )
- }
|