263 lines
6.1 KiB
JavaScript
263 lines
6.1 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import { useState, useEffect } from 'react'
|
|
import axios from 'axios'
|
|
import { useMediaQuery } from 'react-responsive'
|
|
import {
|
|
Form,
|
|
Input,
|
|
Button,
|
|
Typography,
|
|
Flex,
|
|
Steps,
|
|
Descriptions,
|
|
Divider
|
|
} from 'antd'
|
|
import { useMessageContext } from '../../context/MessageContext'
|
|
|
|
import config from '../../../../config'
|
|
|
|
const { Title } = Typography
|
|
|
|
const initialNewUserForm = {
|
|
username: '',
|
|
name: '',
|
|
firstName: '',
|
|
lastName: '',
|
|
email: ''
|
|
}
|
|
|
|
const NewUser = ({ onOk, reset }) => {
|
|
const { showError } = useMessageContext()
|
|
const [newUserLoading, setNewUserLoading] = useState(false)
|
|
const [currentStep, setCurrentStep] = useState(0)
|
|
const [nextEnabled, setNextEnabled] = useState(false)
|
|
const [newUserForm] = Form.useForm()
|
|
const [newUserFormValues, setNewUserFormValues] = useState(initialNewUserForm)
|
|
const isMobile = useMediaQuery({ maxWidth: 768 })
|
|
|
|
const newUserFormUpdateValues = Form.useWatch([], newUserForm)
|
|
|
|
useEffect(() => {
|
|
newUserForm
|
|
.validateFields({
|
|
validateOnly: true
|
|
})
|
|
.then(() => setNextEnabled(true))
|
|
.catch(() => setNextEnabled(false))
|
|
}, [newUserForm, newUserFormUpdateValues])
|
|
|
|
const summaryItems = [
|
|
{
|
|
key: 'username',
|
|
label: 'Username',
|
|
children: newUserFormValues.username
|
|
},
|
|
{
|
|
key: 'name',
|
|
label: 'Full Name',
|
|
children: newUserFormValues.name || 'n/a'
|
|
},
|
|
{
|
|
key: 'firstName',
|
|
label: 'First Name',
|
|
children: newUserFormValues.firstName || 'n/a'
|
|
},
|
|
{
|
|
key: 'lastName',
|
|
label: 'Last Name',
|
|
children: newUserFormValues.lastName || 'n/a'
|
|
},
|
|
{
|
|
key: 'email',
|
|
label: 'Email',
|
|
children: newUserFormValues.email || 'n/a'
|
|
}
|
|
]
|
|
|
|
useEffect(() => {
|
|
if (reset) {
|
|
newUserForm.resetFields()
|
|
}
|
|
}, [reset, newUserForm])
|
|
|
|
const handleNewUser = async () => {
|
|
setNewUserLoading(true)
|
|
try {
|
|
await axios.post(`${config.backendUrl}/users`, newUserFormValues, {
|
|
withCredentials: true
|
|
})
|
|
onOk()
|
|
} catch (error) {
|
|
showError('Error creating new user: ' + error.message)
|
|
} finally {
|
|
setNewUserLoading(false)
|
|
}
|
|
}
|
|
|
|
const steps = [
|
|
{
|
|
title: 'Details',
|
|
key: 'details',
|
|
content: (
|
|
<>
|
|
<Form.Item
|
|
label='Username'
|
|
name='username'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter a username.'
|
|
},
|
|
{
|
|
min: 3,
|
|
message: 'Username must be at least 3 characters.'
|
|
}
|
|
]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label='Full Name'
|
|
name='name'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter a full name.'
|
|
}
|
|
]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label='First Name'
|
|
name='firstName'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter a first name.'
|
|
}
|
|
]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label='Last Name'
|
|
name='lastName'
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter a last name.'
|
|
}
|
|
]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
<Form.Item
|
|
label='Email'
|
|
name='email'
|
|
style={{ marginBottom: 8 }}
|
|
rules={[
|
|
{
|
|
required: true,
|
|
message: 'Please enter an email address.'
|
|
},
|
|
{
|
|
type: 'email',
|
|
message: 'Please enter a valid email address.'
|
|
}
|
|
]}
|
|
>
|
|
<Input />
|
|
</Form.Item>
|
|
</>
|
|
)
|
|
},
|
|
{
|
|
title: 'Summary',
|
|
key: 'summary',
|
|
content: <Descriptions column={1} items={summaryItems} size={'small'} />
|
|
}
|
|
]
|
|
|
|
return (
|
|
<Flex gap='middle'>
|
|
{!isMobile && (
|
|
<div style={{ minWidth: '160px' }}>
|
|
<Steps
|
|
current={currentStep}
|
|
items={steps}
|
|
direction='vertical'
|
|
style={{ width: 'fit-content' }}
|
|
/>
|
|
</div>
|
|
)}
|
|
|
|
{!isMobile && <Divider type='vertical' style={{ height: 'unset' }} />}
|
|
|
|
<Flex vertical gap='middle' style={{ flexGrow: 1 }}>
|
|
<Title level={2} style={{ marginTop: 0, marginBottom: 4 }}>
|
|
New User
|
|
</Title>
|
|
<Form
|
|
name='basic'
|
|
autoComplete='off'
|
|
form={newUserForm}
|
|
onFinish={handleNewUser}
|
|
onValuesChange={(changedValues) =>
|
|
setNewUserFormValues((prevValues) => ({
|
|
...prevValues,
|
|
...changedValues
|
|
}))
|
|
}
|
|
initialValues={initialNewUserForm}
|
|
>
|
|
<div style={{ minHeight: '260px' }}>{steps[currentStep].content}</div>
|
|
</Form>
|
|
|
|
<Flex justify='end'>
|
|
<Button
|
|
style={{ margin: '0 8px' }}
|
|
onClick={() => {
|
|
setCurrentStep((prev) => prev - 1)
|
|
setNextEnabled(true)
|
|
}}
|
|
disabled={currentStep === 0}
|
|
>
|
|
Previous
|
|
</Button>
|
|
|
|
{currentStep < steps.length - 1 ? (
|
|
<Button
|
|
type='primary'
|
|
disabled={!nextEnabled}
|
|
onClick={() => {
|
|
setCurrentStep((prev) => prev + 1)
|
|
setNextEnabled(false)
|
|
}}
|
|
>
|
|
Next
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
type='primary'
|
|
loading={newUserLoading}
|
|
onClick={() => {
|
|
newUserForm.submit()
|
|
}}
|
|
>
|
|
Done
|
|
</Button>
|
|
)}
|
|
</Flex>
|
|
</Flex>
|
|
</Flex>
|
|
)
|
|
}
|
|
|
|
NewUser.propTypes = {
|
|
onOk: PropTypes.func.isRequired,
|
|
reset: PropTypes.bool
|
|
}
|
|
|
|
export default NewUser
|