| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- import React, { useState, useEffect, useRef } from "react";
- import * as Yup from "yup";
- import { Formik, FieldArray, Form, Field } from "formik";
- import { toast } from "react-toastify";
- import { makeStyles } from "@material-ui/core/styles";
- import { green } from "@material-ui/core/colors";
- import Button from "@material-ui/core/Button";
- import TextField from "@material-ui/core/TextField";
- import Dialog from "@material-ui/core/Dialog";
- import DialogActions from "@material-ui/core/DialogActions";
- import DialogContent from "@material-ui/core/DialogContent";
- import DialogTitle from "@material-ui/core/DialogTitle";
- import Typography from "@material-ui/core/Typography";
- import IconButton from "@material-ui/core/IconButton";
- import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline";
- import CircularProgress from "@material-ui/core/CircularProgress";
- import { i18n } from "../../translate/i18n";
- import api from "../../services/api";
- import toastError from "../../errors/toastError";
- import InputMask from 'react-input-mask';
- const useStyles = makeStyles(theme => ({
- root: {
- display: "flex",
- flexWrap: "wrap",
- },
- textField: {
- marginRight: theme.spacing(1),
- flex: 1,
- },
- extraAttr: {
- display: "flex",
- justifyContent: "center",
- alignItems: "center",
- },
- btnWrapper: {
- position: "relative",
- },
- buttonProgress: {
- color: green[500],
- position: "absolute",
- top: "50%",
- left: "50%",
- marginTop: -12,
- marginLeft: -12,
- },
- }));
- const MaskedTextField = ({ field, form, ...props }) => {
- return (
- <InputMask {...field} {...props}>
- {(inputProps) => <TextField {...inputProps} />}
- </InputMask>
- );
- };
- const ContactSchema = Yup.object().shape({
- name: Yup.string()
- .min(2, i18n.t("contactModal.formErrors.name.short"))
- .max(50, i18n.t("contactModal.formErrors.name.long"))
- .required(i18n.t("contactModal.formErrors.name.required")),
- number: Yup.string().min(8,
- i18n.t("contactModal.formErrors.phone.short")).max(50,
- i18n.t("contactModal.formErrors.phone.long")),
- email: Yup.string().email(i18n.t("contactModal.formErrors.email.invalid")),
- });
- const ContactModal = ({ open, onClose, contactId, initialValues, onSave }) => {
- const classes = useStyles();
- const isMounted = useRef(true);
- const initialState = {
- name: "",
- number: "",
- email: "",
- };
- const [contact, setContact] = useState(initialState);
- useEffect(() => {
- return () => {
- isMounted.current = false;
- };
- }, []);
- useEffect(() => {
- const fetchContact = async () => {
- if (initialValues) {
- setContact(prevState => {
- return { ...prevState, ...initialValues };
- });
- }
- if (!contactId) return;
- try {
- const { data } = await api.get(`/contacts/${contactId}`);
- if (isMounted.current) {
- console.log(data)
- setContact({
- ...data,
- number: data.number,
- });
- }
- } catch (err) {
- toastError(err);
- }
- };
- fetchContact();
- }, [contactId, open, initialValues]);
- const handleClose = () => {
- onClose();
- setContact(initialState);
- };
- const handleSaveContact = async values => {
- try {
- if (contactId) {
- await api.put(`/contacts/${contactId}`, values);
- handleClose();
- } else {
- const { data } = await api.post("/contacts", values);
- if (onSave) {
- onSave(data);
- }
- handleClose();
- }
- toast.success(i18n.t("contactModal.success"));
- } catch (e) {
- toastError(e);
- }
- };
- return (
- <div className={classes.root}>
- <Dialog open={open} onClose={handleClose} maxWidth="lg" scroll="paper">
- <DialogTitle id="form-dialog-title">
- {contactId
- ? `${i18n.t("contactModal.title.edit")}`
- : `${i18n.t("contactModal.title.add")}`}
- </DialogTitle>
- <Formik
- initialValues={contact}
- enableReinitialize={true}
- validationSchema={ContactSchema}
- onSubmit={(values, actions) => {
- setTimeout(() => {
- handleSaveContact(values);
- actions.setSubmitting(false);
- }, 400);
- }}
- >
- {({ values, errors, touched, isSubmitting }) => (
- <Form>
- <DialogContent dividers>
- <Typography variant="subtitle1" gutterBottom>
- {i18n.t("contactModal.form.mainInfo")}
- </Typography>
- <Field
- as={TextField}
- label={i18n.t("contactModal.form.name")}
- name="name"
- autoFocus
- error={touched.name && Boolean(errors.name)}
- helperText={touched.name && errors.name}
- variant="outlined"
- margin="dense"
- className={classes.textField}
- />
- <Field
- as={TextField}
- name="number"
- label={i18n.t("contactModal.form.number")}
- error={touched.number && Boolean(errors.number)}
- helperText={touched.number && errors.number}
- placeholder=""
- variant="outlined"
- margin="dense"
- />
- <div>
- <Field
- as={TextField}
- label={i18n.t("contactModal.form.email")}
- name="email"
- error={touched.email && Boolean(errors.email)}
- helperText={touched.email && errors.email}
- placeholder="Email address"
- fullWidth
- margin="dense"
- variant="outlined"
- />
- </div>
- <Typography
- style={{ marginBottom: 8, marginTop: 12 }}
- variant="subtitle1"
- >
- {i18n.t("contactModal.form.whatsapp")} {contact?.whatsapp ? contact?.whatsapp.name : ""}
- </Typography>
- <Typography
- style={{ marginBottom: 8, marginTop: 12 }}
- variant="subtitle1"
- >
- {i18n.t("contactModal.form.extraInfo")}
- </Typography>
- <FieldArray name="extraInfo">
- {({ push, remove }) => (
- <>
- {values.extraInfo &&
- values.extraInfo.length > 0 &&
- values.extraInfo.map((info, index) => (
- <div
- className={classes.extraAttr}
- key={`${index}-info`}
- >
- <Field
- as={TextField}
- label={i18n.t("contactModal.form.extraName")}
- name={`extraInfo[${index}].name`}
- variant="outlined"
- margin="dense"
- className={classes.textField}
- />
- <Field
- as={TextField}
- label={i18n.t("contactModal.form.extraValue")}
- name={`extraInfo[${index}].value`}
- variant="outlined"
- margin="dense"
- className={classes.textField}
- />
- <IconButton
- size="small"
- onClick={() => remove(index)}
- >
- <DeleteOutlineIcon />
- </IconButton>
- </div>
- ))}
- <div className={classes.extraAttr}>
- <Button
- style={{ flex: 1, marginTop: 8 }}
- variant="outlined"
- color="primary"
- onClick={() => push({ name: "", value: "" })}
- >
- {`+ ${i18n.t("contactModal.buttons.addExtraInfo")}`}
- </Button>
- </div>
- </>
- )}
- </FieldArray>
- </DialogContent>
- <DialogActions>
- <Button
- onClick={handleClose}
- color="secondary"
- disabled={isSubmitting}
- variant="outlined"
- >
- {i18n.t("contactModal.buttons.cancel")}
- </Button>
- <Button
- type="submit"
- color="primary"
- disabled={isSubmitting}
- variant="contained"
- className={classes.btnWrapper}
- >
- {contactId
- ? `${i18n.t("contactModal.buttons.okEdit")}`
- : `${i18n.t("contactModal.buttons.okAdd")}`}
- {isSubmitting && (
- <CircularProgress
- size={24}
- className={classes.buttonProgress}
- />
- )}
- </Button>
- </DialogActions>
- </Form>
- )}
- </Formik>
- </Dialog>
- </div>
- );
- };
- export default ContactModal;
|