mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 10:19:22 +03:00
feat: register create user form
This commit is contained in:
parent
7bb1141af2
commit
5f04242d88
@ -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();
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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,6 +70,7 @@ const CreateUserModal: React.FC = () => {
|
|||||||
<Modal isOpen={isOpen} onClose={onClose}>
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<Flex alignItems='center'>
|
<Flex alignItems='center'>
|
||||||
<MdSupervisorAccount />
|
<MdSupervisorAccount />
|
||||||
@ -52,41 +82,59 @@ const CreateUserModal: React.FC = () => {
|
|||||||
<ModalBody pb={6}>
|
<ModalBody pb={6}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>First name</FormLabel>
|
<FormLabel>First name</FormLabel>
|
||||||
<Input placeholder='First name' />
|
<Input
|
||||||
|
placeholder='First name'
|
||||||
|
{...register('first_name')}
|
||||||
|
isInvalid={errors.first_name ? true : false}
|
||||||
|
/>
|
||||||
|
{errors.first_name ? (
|
||||||
|
<FormHelperText color='red.500'>{errors.first_name.message}</FormHelperText>
|
||||||
|
) : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={4}>
|
<FormControl mt={4}>
|
||||||
<FormLabel>Last name</FormLabel>
|
<FormLabel>Last name</FormLabel>
|
||||||
<Input placeholder='Last name' />
|
<Input placeholder='Last name' {...register('last_name')} isInvalid={errors.last_name ? true : false} />
|
||||||
|
{errors.last_name ? <FormHelperText color='red.500'>{errors.last_name.message}</FormHelperText> : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={4}>
|
<FormControl mt={4}>
|
||||||
<FormLabel>Login</FormLabel>
|
<FormLabel>Login</FormLabel>
|
||||||
<Input placeholder='e.g student893' />
|
<Input placeholder='e.g student893' {...register('login')} isInvalid={errors.login ? true : false} />
|
||||||
|
{errors.login ? <FormHelperText color='red.500'>{errors.login.message}</FormHelperText> : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={4}>
|
<FormControl mt={4}>
|
||||||
<FormLabel>Email</FormLabel>
|
<FormLabel>Email</FormLabel>
|
||||||
<Input placeholder='example@email.com' />
|
<Input placeholder='example@email.com' {...register('email')} isInvalid={errors.email ? true : false} />
|
||||||
|
{errors.email ? <FormHelperText color='red.500'>{errors.email.message}</FormHelperText> : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={4}>
|
<FormControl mt={4}>
|
||||||
<FormLabel>Role</FormLabel>
|
<FormLabel>Role</FormLabel>
|
||||||
<Select w='full' mr='2'>
|
<Select w='full' mr='2' {...register('role')} isInvalid={errors.role ? true : false}>
|
||||||
<option value={UserRoleEnum.STUDENT}>Student</option>
|
<option value={UserRoleEnum.STUDENT}>Student</option>
|
||||||
|
{me.isAdmin ? (
|
||||||
|
<>
|
||||||
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
||||||
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
</Select>
|
</Select>
|
||||||
|
{errors.role ? <FormHelperText color='red.500'>{errors.role.message}</FormHelperText> : null}
|
||||||
</FormControl>
|
</FormControl>
|
||||||
<FormControl mt={4}>
|
<FormControl mt={4}>
|
||||||
<FormLabel>Password</FormLabel>
|
<FormLabel>Password</FormLabel>
|
||||||
<Input placeholder='******' />
|
<Input placeholder='******' {...register('password')} isInvalid={errors.password ? true : false} />
|
||||||
<FormHelperText>Must be at least 6 characters</FormHelperText>
|
<FormHelperText color={errors.password ? 'red' : 'gray.500'}>
|
||||||
|
{errors.password ? errors.password.message : 'Must be at least 6 characters.'}
|
||||||
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</ModalBody>
|
</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>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -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.'),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
@ -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]),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user