// ** 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