feat: register create user form

This commit is contained in:
Sergey Yarkov 2021-09-20 22:05:29 +03:00
parent 7bb1141af2
commit 5f04242d88
6 changed files with 114 additions and 51 deletions

View File

@ -12,7 +12,11 @@ const UserBadge: React.FC<{ roles: IUserRole[] }> = ({ roles }) => {
if (userHasRoles(roles, [UserRoleEnum.ADMIN])) return { name: 'Administrator', color: 'purple' }; if (userHasRoles(roles, [UserRoleEnum.ADMIN])) return { name: 'Administrator', color: 'purple' };
if (userHasRoles(roles, [UserRoleEnum.TEACHER])) return { name: 'Teacher', color: 'orange' }; if (userHasRoles(roles, [UserRoleEnum.TEACHER])) return { name: 'Teacher', color: 'orange' };
if (userHasRoles(roles, [UserRoleEnum.STUDENT])) return { name: 'Student', color: 'blue' }; if (userHasRoles(roles, [UserRoleEnum.STUDENT])) return { name: 'Student', color: 'blue' };
if (roles.length === 0) return { name: 'Guest', color: 'gray' };
/**
* The user has no roles
*/
return { name: 'Guest', color: 'gray' };
}; };
const role = getCurrentRole(); const role = getCurrentRole();

View File

@ -94,6 +94,9 @@ export interface IMe extends IUser {
* does not have the STUDENT role * does not have the STUDENT role
*/ */
courses?: UserCourseType[]; courses?: UserCourseType[];
isAdmin: boolean;
isTeacher: boolean;
isStudent: boolean;
} }
export interface IUserContacts { export interface IUserContacts {

View File

@ -19,19 +19,48 @@ import {
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { AddIcon } from '@chakra-ui/icons'; import { AddIcon } from '@chakra-ui/icons';
import { MdSupervisorAccount } from 'react-icons/md'; import { MdSupervisorAccount } from 'react-icons/md';
import { yupResolver } from '@hookform/resolvers/yup';
import { SubmitHandler } from 'react-hook-form';
import CreateUserSchema from './CreateUserModal.validator';
/** /**
* Types * Types
*/ */
import { IMe } from 'interfaces';
import { UserRoleEnum } from 'enums'; import { UserRoleEnum } from 'enums';
/** /**
* Hooks * Hooks
*/ */
import { useDisclosure } from '@chakra-ui/hooks'; import { useDisclosure } from '@chakra-ui/hooks';
import { useForm } from 'react-hook-form';
const CreateUserModal: React.FC = () => { type CreateUserModalPropsType = {
me: IMe;
};
type CreateUserInputType = {
first_name: string;
last_name: string;
login: string;
email: string;
role: UserRoleEnum;
password: string;
};
const CreateUserModal: React.FC<CreateUserModalPropsType> = ({ me }) => {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const {
register,
handleSubmit,
formState: { errors },
} = useForm<CreateUserInputType>({
resolver: yupResolver(CreateUserSchema),
});
const onSubmit: SubmitHandler<CreateUserInputType> = data => {
console.log(data);
};
return ( return (
<> <>
@ -41,52 +70,71 @@ const CreateUserModal: React.FC = () => {
<Modal isOpen={isOpen} onClose={onClose}> <Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay /> <ModalOverlay />
<ModalContent> <ModalContent>
<ModalHeader> <form onSubmit={handleSubmit(onSubmit)}>
<Flex alignItems='center'> <ModalHeader>
<MdSupervisorAccount /> <Flex alignItems='center'>
<Text ml={2}>Create new user</Text> <MdSupervisorAccount />
</Flex> <Text ml={2}>Create new user</Text>
</ModalHeader> </Flex>
<ModalCloseButton /> </ModalHeader>
<Divider /> <ModalCloseButton />
<ModalBody pb={6}> <Divider />
<FormControl> <ModalBody pb={6}>
<FormLabel>First name</FormLabel> <FormControl>
<Input placeholder='First name' /> <FormLabel>First name</FormLabel>
</FormControl> <Input
<FormControl mt={4}> placeholder='First name'
<FormLabel>Last name</FormLabel> {...register('first_name')}
<Input placeholder='Last name' /> isInvalid={errors.first_name ? true : false}
</FormControl> />
<FormControl mt={4}> {errors.first_name ? (
<FormLabel>Login</FormLabel> <FormHelperText color='red.500'>{errors.first_name.message}</FormHelperText>
<Input placeholder='e.g student893' /> ) : null}
</FormControl> </FormControl>
<FormControl mt={4}> <FormControl mt={4}>
<FormLabel>Email</FormLabel> <FormLabel>Last name</FormLabel>
<Input placeholder='example@email.com' /> <Input placeholder='Last name' {...register('last_name')} isInvalid={errors.last_name ? true : false} />
</FormControl> {errors.last_name ? <FormHelperText color='red.500'>{errors.last_name.message}</FormHelperText> : null}
<FormControl mt={4}> </FormControl>
<FormLabel>Role</FormLabel> <FormControl mt={4}>
<Select w='full' mr='2'> <FormLabel>Login</FormLabel>
<option value={UserRoleEnum.STUDENT}>Student</option> <Input placeholder='e.g student893' {...register('login')} isInvalid={errors.login ? true : false} />
<option value={UserRoleEnum.TEACHER}>Teacher</option> {errors.login ? <FormHelperText color='red.500'>{errors.login.message}</FormHelperText> : null}
<option value={UserRoleEnum.ADMIN}>Administrator</option> </FormControl>
</Select> <FormControl mt={4}>
</FormControl> <FormLabel>Email</FormLabel>
<FormControl mt={4}> <Input placeholder='example@email.com' {...register('email')} isInvalid={errors.email ? true : false} />
<FormLabel>Password</FormLabel> {errors.email ? <FormHelperText color='red.500'>{errors.email.message}</FormHelperText> : null}
<Input placeholder='******' /> </FormControl>
<FormHelperText>Must be at least 6 characters</FormHelperText> <FormControl mt={4}>
</FormControl> <FormLabel>Role</FormLabel>
</ModalBody> <Select w='full' mr='2' {...register('role')} isInvalid={errors.role ? true : false}>
<option value={UserRoleEnum.STUDENT}>Student</option>
{me.isAdmin ? (
<>
<option value={UserRoleEnum.TEACHER}>Teacher</option>
<option value={UserRoleEnum.ADMIN}>Administrator</option>
</>
) : null}
</Select>
{errors.role ? <FormHelperText color='red.500'>{errors.role.message}</FormHelperText> : null}
</FormControl>
<FormControl mt={4}>
<FormLabel>Password</FormLabel>
<Input placeholder='******' {...register('password')} isInvalid={errors.password ? true : false} />
<FormHelperText color={errors.password ? 'red' : 'gray.500'}>
{errors.password ? errors.password.message : 'Must be at least 6 characters.'}
</FormHelperText>
</FormControl>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button variant='outline' mr={3} colorScheme='blue' leftIcon={<AddIcon />}> <Button type='submit' variant='outline' mr={3} colorScheme='blue' leftIcon={<AddIcon />}>
Create Create
</Button> </Button>
<Button onClick={onClose}>Cancel</Button> <Button onClick={onClose}>Cancel</Button>
</ModalFooter> </ModalFooter>
</form>
</ModalContent> </ModalContent>
</Modal> </Modal>
</> </>

View File

@ -5,8 +5,11 @@ const CreateUserSchema = yup.object().shape({
first_name: yup.string().required('First field name is required'), first_name: yup.string().required('First field name is required'),
last_name: yup.string().required('Last field name is required'), last_name: yup.string().required('Last field name is required'),
login: yup.string().required('Login field is required'), login: yup.string().required('Login field is required'),
email: yup.string().required('Email field is required'), email: yup.string().email('Email is invalid').required('Email field is required'),
role: yup.mixed<UserRoleEnum>().required('Role field is required').oneOf(Object.values(UserRoleEnum)), role: yup
.mixed<UserRoleEnum>()
.required('Role field is required')
.oneOf(Object.values(UserRoleEnum), `Available roles: ${Object.keys(UserRoleEnum).join(', ')}`),
password: yup.string().required('Password field is required').min(6, 'Password must be at least 6 characters.'), password: yup.string().required('Password field is required').min(6, 'Password must be at least 6 characters.'),
}); });

View File

@ -49,12 +49,12 @@ const UsersPage: React.FC<IPageProps> = ({ title }) => {
<Box h='100%'> <Box h='100%'>
<Heading as='h1'>User management</Heading> <Heading as='h1'>User management</Heading>
<Text mt='2'>You can add or delete your users on this page.</Text> <Text mt='2'>You can add or delete your users on this page.</Text>
{userStore.users !== null && userStore.pagination !== undefined ? ( {userStore.users !== null && userStore.me !== null && userStore.pagination !== undefined ? (
<Flex mt='5' flexDir='column' h='full'> <Flex mt='5' flexDir='column' h='full'>
<Flex justifyContent='space-between' sx={{ gap: '10px' }} flexWrap='wrap'> <Flex justifyContent='space-between' sx={{ gap: '10px' }} flexWrap='wrap'>
<UserSearch /> <UserSearch />
<Flex sx={{ gap: '10px' }}> <Flex sx={{ gap: '10px' }}>
<CreateUserModal /> <CreateUserModal me={userStore.me} />
<Button variant='outline' colorScheme='green' leftIcon={<FaFileExcel />}> <Button variant='outline' colorScheme='green' leftIcon={<FaFileExcel />}>
Import Import
</Button> </Button>

View File

@ -1,6 +1,7 @@
import { AxiosInstance } from 'axios'; import { AxiosInstance } from 'axios';
import { makeAutoObservable, runInAction } from 'mobx'; import { makeAutoObservable, runInAction } from 'mobx';
import { IUser, IUserContacts, IMe, IPaginationMeta } from 'interfaces'; import { IUser, IUserContacts, IMe, IPaginationMeta } from 'interfaces';
import * as helpers from 'helpers';
/** /**
* Services * Services
@ -11,6 +12,7 @@ import UserService, { FetchUsersParamsType } from 'services/UserService';
* Stores * Stores
*/ */
import RootStore from './RootStore'; import RootStore from './RootStore';
import { UserRoleEnum } from 'enums';
export default class UserStore { export default class UserStore {
public root: RootStore; public root: RootStore;
@ -64,6 +66,9 @@ export default class UserStore {
roles, roles,
contacts, contacts,
courses, courses,
isAdmin: helpers.userContainRoles(roles, [UserRoleEnum.ADMIN]),
isTeacher: helpers.userContainRoles(roles, [UserRoleEnum.TEACHER]),
isStudent: helpers.userContainRoles(roles, [UserRoleEnum.STUDENT]),
}; };
}); });