1
// ** React Imports
import { FocusEvent, useEffect } from 'react'

// ** MUI Imports
import Box from '@mui/material/Box'

import Button from '@mui/material/Button'
import Dialog from '@mui/material/Dialog'
import DialogActions from '@mui/material/DialogActions'
import DialogContent from '@mui/material/DialogContent'
import DialogTitle from '@mui/material/DialogTitle'

import FormControl from '@mui/material/FormControl'
import FormHelperText from '@mui/material/FormHelperText'
import InputLabel from '@mui/material/InputLabel'
import MenuItem from '@mui/material/MenuItem'
import Select from '@mui/material/Select'
import TextField from '@mui/material/TextField'

// ** Third Party Imports
import { yupResolver } from '@hookform/resolvers/yup'
import { Controller, useForm } from 'react-hook-form'
import * as yup from 'yup'

// ** Icon Imports

// ** Store Imports
import { useDispatch, useSelector } from 'react-redux'

// ** Actions Imports

// ** Types Imports
import { AppDispatch, RootState } from 'src/store'
import { fetchDepartment } from 'src/store/apps/department'
import { fetchDesignation } from 'src/store/apps/designation'
import { fetchRole } from 'src/store/apps/role'

interface SidebarAddUserType {
  open: boolean
  toggle: () => void
}

interface UserData {
  firstName: string
  middleName: string
  lastName: string
  loginId: string
  emailId: string
  mobileNumber: string
  roleId: number
  reportsTo: number
  designationId: number
  departmentId: number
}

const phoneRegExp =
  /^((\\+[1-9]{1,4}[ \\-]*)|(\\([0-9]{2,3}\\)[ \\-]*)|([0-9]{2,4})[ \\-]*)*?[0-9]{3,4}?[ \\-]*[0-9]{3,4}?$/
const noSpecialCharRegExp = /^[^*|\":<>[\]{}`\\()';@&$-.,~!#%_=+/ ]+$/
const noSpecialCharRegExp2 = /^[^*|\":<>[\]{}`\\()';@&$-.,~!#%_=+/ 1234567890]+$/

const schema = yup.object().shape({
  emailId: yup
    .string()
    .email('EmailId is not valid !')
    .required('EmailId field is required !')
    .max(30, 'Must be exactly 30 chars')
    .min(10, 'Must be atleast 10 chars'),
  firstName: yup
    .string()
    .required('First Name field is required !')
    .matches(noSpecialCharRegExp2, 'Only alphabets are allowed in first name !')
    .max(15, 'Must be exactly 15 chars')
    .min(3, 'Must be atleast 3 chars'),
  lastName: yup
    .string()
    .required('Last Name field is required !')
    .matches(noSpecialCharRegExp2, 'Only alphabets are allowed in last name !')
    .max(15, 'Must be exactly 15 chars')
    .min(3, 'Must be atleast 3 chars'),
  loginId: yup
    .string()
    .required('LoginId field is required !')
    .matches(noSpecialCharRegExp, 'No special characters, space and numbers are allowed !')
    .max(15, 'Must be exactly 15 chars')
    .min(5, 'Must be atleast 5 chars'),
  mobileNumber: yup
    .string()
    .required('Mobile number is required !')
    .matches(phoneRegExp, 'Mobile number is not valid !')
    .min(10, 'Mobile number must be of 10 digits !')
    .max(10, 'Mobile number must be of 10 digits !'),
  roleId: yup.number().required('Role is required !').min(1, 'Role is required !'),
  reportsTo: yup.number().required('Reporting to is required !').min(1, 'Reporting to is required !'),
  designationId: yup.number().required('Designation is required !').min(1, 'Designation is required !'),
  departmentId: yup.number().required('Department is required !').min(1, 'Department is required !')
})

const defaultValues = {
  firstName: '',
  middleName: '',
  lastName: '',
  loginId: '',
  emailId: '',
  mobileNumber: '',
  roleId: 0,
  reportsTo: 0,
  designationId: 0,
  departmentId: 0
}

const SidebarAddUser = (props: SidebarAddUserType) => {
  // ** Props
  const { open, toggle } = props

  // ** Hooks
  const dispatch = useDispatch<AppDispatch>()
  const store = useSelector((state: RootState) => state.role)
  const allUsers = useSelector((state: RootState) => state.user)
  const designations = useSelector((state: RootState) => state.designation)
  const departments = useSelector((state: RootState) => state.department)

  useEffect(() => {
    dispatch(fetchRole())
    dispatch(fetchDesignation())
    dispatch(fetchDepartment())
  }, [dispatch])

  const {
    reset,
    control,
    handleSubmit,
    formState: { errors, isValid, isSubmitting },
    setError
  } = useForm({
    defaultValues,
    mode: 'onChange',
    resolver: yupResolver(schema)
  })

  const onSubmit = (data: UserData) => {
    // dispatch(addUser({ ...data }))
    console.log({ ...data })
    handleClose()
  }

  const handleClose = () => {
    toggle()
    reset()
  }

  const handleCheckExisting = (e: FocusEvent<HTMLInputElement | HTMLTextAreaElement, Element>, checkField: string) => {
    allUsers.data.find((singleUser: any) => {
      return singleUser.loginId == e.target.value
    })
    setError('loginId', { type: 'manual', message: 'hheeyyy there is an error' })
  }

  return (
    <Dialog open={open} onClose={handleClose} sx={{ '& .MuiDrawer-paper': { width: { xs: 600, sm: 450 } } }}>
      <DialogTitle>Add User</DialogTitle>
      <DialogContent>
        <Box sx={{ p: 5 }}>
          <form onSubmit={handleSubmit(onSubmit)} id='myform'>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='firstName'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <TextField
                    value={value}
                    label='First Name'
                    onChange={onChange}
                    placeholder=''
                    error={Boolean(errors.firstName)}
                  />
                )}
              />
              {errors.firstName && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.firstName.message}</FormHelperText>
              )}
            </FormControl>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='middleName'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <TextField
                    value={value}
                    label='Middle Name'
                    onChange={onChange}
                    placeholder=''
                    error={Boolean(errors.middleName)}
                  />
                )}
              />
              {errors.middleName && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.middleName.message}</FormHelperText>
              )}
            </FormControl>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='lastName'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <TextField
                    value={value}
                    label='Last Name'
                    onChange={onChange}
                    placeholder=''
                    error={Boolean(errors.lastName)}
                  />
                )}
              />
              {errors.lastName && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.lastName.message}</FormHelperText>
              )}
            </FormControl>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='loginId'
                control={control}
                rules={{ required: true }}
                render={props => (
                  <TextField
                    type='text'
                    value={props.field.value}
                    label='Login ID'
                    onChange={(value): void => {
                      props.field.onChange(value)
                    }}
                    onBlur={(value): void => {
                      handleCheckExisting(value, 'loginId')
                    }}
                    placeholder=''
                    error={Boolean(errors.loginId)}
                  />
                )}
              />
              {errors.loginId && <FormHelperText sx={{ color: 'error.main' }}>{errors.loginId.message}</FormHelperText>}
            </FormControl>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='emailId'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <TextField
                    value={value}
                    label='Email Id'
                    onChange={onChange}
                    placeholder='abc@gmail.com'
                    error={Boolean(errors.emailId)}
                  />
                )}
              />
              {errors.emailId && <FormHelperText sx={{ color: 'error.main' }}>{errors.emailId.message}</FormHelperText>}
            </FormControl>
            <FormControl fullWidth sx={{ mb: 6 }}>
              <Controller
                name='mobileNumber'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <TextField
                    value={value}
                    label='Mobile Number'
                    onChange={onChange}
                    placeholder='9874561230'
                    error={Boolean(errors.mobileNumber)}
                    type='number'
                  />
                )}
              />
              {errors.mobileNumber && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.mobileNumber.message}</FormHelperText>
              )}
            </FormControl>

            <FormControl fullWidth sx={{ width: '32.5vw', mb: 6 }}>
              <InputLabel id='department-select'>Department</InputLabel>
              <Controller
                name='departmentId'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <Select
                    label='Department'
                    value={value}
                    onChange={onChange}
                    labelId='department-select'
                    error={Boolean(errors.departmentId)}
                  >
                    <MenuItem value={0}>
                      <em>Choose a Department</em>
                    </MenuItem>
                    {departments.department.map(p => (
                      <MenuItem key={p.key} value={p.key}>
                        {p.value}
                      </MenuItem>
                    ))}
                  </Select>
                )}
              />
              {errors.departmentId && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.departmentId.message}</FormHelperText>
              )}
            </FormControl>

            <FormControl fullWidth sx={{ width: '32.5vw', mb: 6 }}>
              <InputLabel id='designation-select'>Designation</InputLabel>
              <Controller
                name='designationId'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <Select
                    label='Designation'
                    value={value}
                    onChange={onChange}
                    labelId='designation-select'
                    error={Boolean(errors.designationId)}
                  >
                    <MenuItem value={0}>
                      <em>Choose a designation</em>
                    </MenuItem>
                    {designations.allDesignations.map(p => (
                      <MenuItem key={p.key} value={p.key}>
                        {p.value}
                      </MenuItem>
                    ))}
                  </Select>
                )}
              />
              {errors.designationId && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.designationId.message}</FormHelperText>
              )}
            </FormControl>

            <FormControl fullWidth sx={{ width: '32.5vw', mb: 6 }}>
              <InputLabel id='reportsTo-select'>Reports to</InputLabel>
              <Controller
                name='reportsTo'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <Select
                    label='Reports to'
                    value={value}
                    onChange={onChange}
                    labelId='reportsTo-select'
                    error={Boolean(errors.reportsTo)}
                  >
                    <MenuItem value={0}>
                      <em>Choose a reporter</em>
                    </MenuItem>
                    <MenuItem value={1}>Reporter1</MenuItem>
                    <MenuItem value={2}>Reporter2</MenuItem>
                    <MenuItem value={3}>Reporter3</MenuItem>
                  </Select>
                )}
              />
              {errors.reportsTo && (
                <FormHelperText sx={{ color: 'error.main' }}>{errors.reportsTo.message}</FormHelperText>
              )}
            </FormControl>

            <FormControl fullWidth sx={{ width: '32.5vw', mb: 6 }}>
              <InputLabel id='role-select'>Role</InputLabel>
              <Controller
                name='roleId'
                control={control}
                rules={{ required: true }}
                render={({ field: { value, onChange } }) => (
                  <Select
                    label='Role'
                    value={value}
                    onChange={onChange}
                    labelId='role-select'
                    error={Boolean(errors.roleId)}
                  >
                    <MenuItem value={0}>
                      <em>Choose a role</em>
                    </MenuItem>
                    {store.role.map(p => (
                      <MenuItem key={p.roleId} value={p.roleId}>
                        {p.roleName}
                      </MenuItem>
                    ))}
                  </Select>
                )}
              />
              {errors.roleId && <FormHelperText sx={{ color: 'error.main' }}>{errors.roleId.message}</FormHelperText>}
            </FormControl>
          </form>
        </Box>
      </DialogContent>
      <DialogActions>
        <Button onClick={handleClose}>Cancel</Button>
        <Button form='myform' type='submit'>
          Submit
        </Button>
      </DialogActions>
    </Dialog>
  )
}

export default SidebarAddUser

Here the file where i am using useform and mui to handle form validation and form submittion. But you can see that in loginId and calling one external function to perform some checks and return true or false and also there i am using setError to genereate a error for that field. Error is generated and can can be seen correctly. but its not stopping the form from submitting which i dont want

So i want to stop the form from submitting when there is custom error using seterror function and let the submit happen only when that condition is fulfilled. all the condition is written inside that handleCheckExisting function handleCheckExisting which return a object or undefine, according to that i want to seterror and if there is undefined then i will be able to submit the form. if there is one object as return form handleCheckExisting then, i will generate a error and stop the form from submitting

Olivier Tassinari
  • 8,238
  • 4
  • 23
  • 23

0 Answers0