Home > database >  Property 'roleName' does not exist on type 'never'
Property 'roleName' does not exist on type 'never'

Time:12-30

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

// ** MUI Imports
import Box, { BoxProps } from '@mui/material/Box'
import Button from '@mui/material/Button'
import Drawer from '@mui/material/Drawer'
import FormControl from '@mui/material/FormControl'
import FormHelperText from '@mui/material/FormHelperText'
import IconButton from '@mui/material/IconButton'
import InputLabel from '@mui/material/InputLabel'
import MenuItem from '@mui/material/MenuItem'
import Select from '@mui/material/Select'
import { styled } from '@mui/material/styles'
import TextField from '@mui/material/TextField'
import Typography from '@mui/material/Typography'

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

// ** Icon Imports
import Icon from 'src/@core/components/icon'

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

// ** Actions Imports
import { addUser } from 'src/store/apps/user'

// ** Types Imports
import { AppDispatch, RootState } from 'src/store'
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
}

const showErrors = (field: string, valueLen: number, min: number) => {
  if (valueLen === 0) {
    return `${field} field is required`
  } else if (valueLen > 0 && valueLen < min) {
    return `${field} must be at least ${min} characters`
  } else {
    return ''
  }
}

const Header = styled(Box)<BoxProps>(({ theme }) => ({
  display: 'flex',
  alignItems: 'center',
  padding: theme.spacing(3, 4),
  justifyContent: 'space-between',
  backgroundColor: theme.palette.background.default
}))

const schema = yup.object().shape({
  emailId: yup.string().email().required(),
  mobileNumber: yup
    .string()
    .typeError('Mobile Number field is required')

    // .min(10, obj => showErrors('Contact Number', obj.value.length, obj.min))
    .required(),
  firstName: yup
    .string()

    // .min(3, obj => showErrors('First Name', obj.value.length, obj.min))
    .required(),
  middleName: yup.string(),

  // .min(3, obj => showErrors('First Name', obj.value.length, obj.min))
  lastName: yup
    .string()

    // .min(3, obj => showErrors('First Name', obj.value.length, obj.min))
    .required(),
  loginId: yup
    .string()

    // .min(3, obj => showErrors('Username', obj.value.length, obj.min))
    .required()
})

const defaultValues = {
  firstName: '',
  middleName: '',
  lastName: '',
  loginId: '',
  emailId: '',
  mobileNumber: ''
}

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

  // ** State
  const [plan, setPlan] = useState<string>('basic')
  const [roleId, setRoleId] = useState<string>('')
  const [reportsTo, setReporterTo] = useState<string>('')
  const [departmentId, setDepartmentId] = useState<string>('')
  const [designationId, setDesignationId] = useState<string>('')

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

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

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

  const onSubmit = (data: UserData) => {
    console.log({ ...data, roleId, reportsTo, departmentId, designationId })
    dispatch(addUser({ ...data, roleId, reportsTo, departmentId, designationId }))
    toggle()
    reset()
  }

  const handleClose = () => {
    setPlan('basic')

    // setRole('subscriber')
    // setValue('contact', Number(''))
    toggle()
    reset()
  }

  return (
    <Drawer
      open={open}
      anchor='right'
      variant='temporary'
      onClose={handleClose}
      ModalProps={{ keepMounted: true }}
      sx={{ '& .MuiDrawer-paper': { width: { xs: 600, sm: 450 } } }}
    >
      <Header>
        <Typography variant='h6'>Add User</Typography>
        <IconButton size='small' onClick={handleClose} sx={{ color: 'text.primary' }}>
          <Icon icon='mdi:close' fontSize={20} />
        </IconButton>
      </Header>
      <Box sx={{ p: 5 }}>
        <form onSubmit={handleSubmit(onSubmit)}>
          <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='John Doe'
                  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='johndoe'
                  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={({ field: { value, onChange } }) => (
                <TextField
                  type='text'
                  value={value}
                  label='Login ID'
                  onChange={onChange}
                  placeholder='123456'
                  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='[email protected]'
                  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)}
                />
              )}
            />
            {errors.mobileNumber && (
              <FormHelperText sx={{ color: 'error.main' }}>{errors.mobileNumber.message}</FormHelperText>
            )}
          </FormControl>

          <FormControl fullWidth sx={{ mb: 6 }}>
            <InputLabel id='department-select'>Department</InputLabel>
            <Select
              fullWidth
              value={departmentId}
              id='select-department'
              label='Select Department'
              labelId='department-select'
              onChange={e => setDepartmentId(e.target.value)}
              inputProps={{ placeholder: 'Select Department' }}
            >
              <MenuItem value=''>
                <em>Choose a Department</em>
              </MenuItem>
              {store.role.map(p => (
                <MenuItem key={p.id} value={p.roleName}>
                  {p.roleName}
                </MenuItem>
              ))}
            </Select>
            {/* {errors.departmentId && (
              <FormHelperText sx={{ color: 'error.main' }}>{errors.departmentId.message}</FormHelperText>
            )} */}
          </FormControl>
          <FormControl fullWidth sx={{ mb: 6 }}>
            <InputLabel id='designation-select'>Designation</InputLabel>
            <Select
              fullWidth
              value={designationId}
              id='select-designation'
              label='Select Designation'
              labelId='designation-select'
              onChange={e => setDesignationId(e.target.value)}
              inputProps={{ placeholder: 'Select Designation' }}
            >
              <MenuItem value=''>
                <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={{ mb: 6 }}>
            <InputLabel id='reportsTo-select'>Reporter</InputLabel>
            <Select
              fullWidth
              value={reportsTo}
              id='select-reporter'
              label='Select Reporter'
              labelId='reportsTo-select'
              onChange={e => setReporterTo(e.target.value)}
              inputProps={{ placeholder: 'Select Reporter' }}
            >
              <MenuItem value={1}>Reporter1</MenuItem>
              <MenuItem value={2}>Reporter2</MenuItem>
              <MenuItem value={3}>Reporter3</MenuItem>
              <MenuItem value={4}>Reporter4</MenuItem>
            </Select>
          </FormControl>
          <FormControl fullWidth sx={{ mb: 6 }}>
            <InputLabel id='role-select'>Role</InputLabel>
            <Select
              fullWidth
              value={roleId}
              labelId='role-select'
              inputProps={{ placeholder: 'Select Reporter' }}
              id='select-role'
              label='Select Role'
              onChange={e => setRoleId(e.target.value)}
            >
              <MenuItem value=''>
                <em>Choose a Role</em>
              </MenuItem>
              {store.role.map(p => (
                <MenuItem key={p.id} value={p.roleName}>
                  {p.roleName}
                </MenuItem>
              ))}
            </Select>
          </FormControl>
          <Box sx={{ display: 'flex', alignItems: 'center' }}>
            <Button size='large' type='submit' variant='contained' sx={{ mr: 3 }}>
              Submit
            </Button>
            <Button size='large' variant='outlined' color='secondary' onClick={handleClose}>
              Cancel
            </Button>
          </Box>
        </form>
      </Box>
    </Drawer>
  )
}

export default SidebarAddUser


error msg

The id, rolename which you are seeing in red lines are coming from the api data. I am not getting the thing that where I need to specify that the id and rolename is coming from the api. The same is happening for all the select elements. All the dropdowns are dynamic where, and id and rolename are coming from the api. Where I will specify the interface for the rolename, id, value, key which are dynamic

I need to know where I need to specify the interface for the api result data.

The file where the RootState is defined.

// ** Toolkit imports
import { configureStore } from '@reduxjs/toolkit'

// ** Reducers
import calendar from 'src/store/apps/calendar'
import chat from 'src/store/apps/chat'
import designation from 'src/store/apps/designation'
import email from 'src/store/apps/email'
import invoice from 'src/store/apps/invoice'
import permissions from 'src/store/apps/permissions'
import role from 'src/store/apps/role'
import user from 'src/store/apps/user'

export const store = configureStore({
  reducer: {
    user,
    role,
    designation,
    chat,
    email,
    invoice,
    calendar,
    permissions
  },
  middleware: getDefaultMiddleware =>
    getDefaultMiddleware({
      serializableCheck: false
    })
})

export type AppDispatch = typeof store.dispatch
export type RootState = ReturnType<typeof store.getState>

src/store/apps/role file. where the actions are written

// ** Redux Imports
import {
  createAsyncThunk,
  createSlice
} from '@reduxjs/toolkit'
import {
  Dispatch
} from 'redux'

// ** Axios Imports
import axios from 'axios'

interface RoleParams {
  //   id: number
  //   roleName: string
  //   description: string
  //   ipAddress: string
  //   createdOn: string
  //   updatedOn: string
  //   createdBy: string
  //   updatedBy: string
}

interface Redux {
  getState: any
  dispatch: Dispatch < any >
}

const demo_token =
  'xzy'

// ** Fetch Users
export const fetchRole = createAsyncThunk('appRoles/fetchRole', async(params: RoleParams) => {
  try {
    const response = await axios.get('http://consoleapi.xzy.com/api/Roles', {
      headers: {
        Authorization: `Bearer ${demo_token}`
      }
    })
    console.log(response.data)
    return response.data
  } catch (error) {
    console.error(error)
  }
})

// ** Add User
// export const addUser = createAsyncThunk(
//   'appUsers/addUser',
//   async (data: { [key: string]: number | string }, { getState, dispatch }: Redux) => {
//     const response = await axios.post(
//       'http://consoleapi.xzy.com/api/Account/AddUser',
//       {
//         data
//       },
//       {
//         headers: {
//           Authorization: `Bearer ${demo_token}`
//         }
//       }
//     )
//     dispatch(fetchData(getState().user.params))

//     return response.data
//   }
// )

// ** Delete User
// export const deleteUser = createAsyncThunk(
//   'appUsers/deleteUser',
//   async (id: number | string, { getState, dispatch }: Redux) => {
//     const response = await axios.delete('/apps/users/delete', {
//       data: id
//     })
//     dispatch(fetchData(getState().user.params))

//     return response.data
//   }
// )

export const appRolesSlice = createSlice({
  name: 'appRoles',
  initialState: {
    role: [],
    allRole: []
  },
  reducers: {},
  extraReducers: builder => {
    builder.addCase(fetchRole.fulfilled, (state, action) => {
      state.role = action.payload.data
      // state.total = action.payload.total
      // state.params = action.payload.params
      state.allRole = action.payload.data
    })
  }
})

export default appRolesSlice.reducer

CodePudding user response:

When you define an array in typescript, without any types or inferred types, it assumes the type of the array items to be never. So, you will have to give some type to your array.

interface Role {
  id: string;
  roleName: string;
}

export const appRolesSlice = createSlice({
  ...
  initialState: {
    role: [] as Array<Role>,
    allRole: []
  },
  ...
})

You need to do the same for allRole property.

  • Related