// ** 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='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)}
/>
)}
/>
{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
你看到的红线中的id和rolename来自API数据。我没有得到我需要指定id和rolename来自api的东西。同样的事情发生在所有的select元素上。所有的下拉列表都是动态的,其中id和rolename来自api。我将为动态的rolename,id,value,key指定接口
我需要知道我需要在哪里为API结果数据指定接口。
定义RootState的文件。
// ** 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文件。写入操作的位置
// ** 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
1条答案
按热度按时间uqzxnwby1#
当你在typescript中定义一个数组,没有任何类型或推断类型,它假设数组项的类型是
never
,所以你必须给你的数组给予一些类型。您需要对
allRole
属性执行相同的操作。