diff --git a/src/pages/profile/containers/UpdatePasswordContainer/UpdatePasswordForm/UpdatePasswordForm.tsx b/src/pages/profile/containers/UpdatePasswordContainer/UpdatePasswordForm/UpdatePasswordForm.tsx index 248cfdc..f4b9b96 100644 --- a/src/pages/profile/containers/UpdatePasswordContainer/UpdatePasswordForm/UpdatePasswordForm.tsx +++ b/src/pages/profile/containers/UpdatePasswordContainer/UpdatePasswordForm/UpdatePasswordForm.tsx @@ -1,4 +1,4 @@ -import React, { useContext } from 'react'; +import React, { useContext, useState } from 'react'; import { useRootStore } from 'hooks/useRootStore'; import { Box, Stack } from '@chakra-ui/layout'; import { FormControl, FormLabel, FormHelperText } from '@chakra-ui/form-control'; @@ -10,6 +10,7 @@ import UpdatePasswordSchema from './UpdatePasswordForm.validator'; import { useToast } from '@chakra-ui/toast'; import { useErrorHandler } from 'react-error-boundary'; import { ProfilePageViewContext } from 'contexts'; +import useIsMountedRef from 'hooks/useIsMountedRef'; type UpdatePasswordInputType = { old_password: string; @@ -23,6 +24,8 @@ type UpdatePasswordInputType = { const UpdatePasswordForm: React.FC = () => { const { setStatusPageView } = useContext(ProfilePageViewContext); const { userStore } = useRootStore(); + const isMountedRef = useIsMountedRef(); + const [loading, setLoading] = useState(false); const { handleSubmit, register, @@ -38,10 +41,11 @@ const UpdatePasswordForm: React.FC = () => { const onSubmit: SubmitHandler = async ({ old_password, new_password, confirm_password }) => { try { + setLoading(true); await userStore.updateCurrentUserPassword(old_password, new_password); toast({ title: 'Password changed.', status: 'success' }); reset(); - setStatusPageView('default'); + setStatusPageView({ status: 'default' }); } catch (error: any) { if (error.response) { if (error.response.status === 401) { @@ -54,6 +58,10 @@ const UpdatePasswordForm: React.FC = () => { } else { handleError(error); } + } finally { + if (isMountedRef.current) { + setLoading(false); + } } }; @@ -102,7 +110,15 @@ const UpdatePasswordForm: React.FC = () => { - diff --git a/src/pages/users/components/CreateUserModal/CreateUserModal.tsx b/src/pages/users/components/CreateUserModal/CreateUserModal.tsx new file mode 100644 index 0000000..05ab71c --- /dev/null +++ b/src/pages/users/components/CreateUserModal/CreateUserModal.tsx @@ -0,0 +1,96 @@ +import React from 'react'; +import { + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalCloseButton, + ModalBody, + ModalFooter, + FormControl, + FormLabel, + FormHelperText, + Input, + Button, + Select, + Flex, + Text, + Divider, +} from '@chakra-ui/react'; +import { AddIcon } from '@chakra-ui/icons'; +import { MdSupervisorAccount } from 'react-icons/md'; + +/** + * Types + */ +import { UserRoleEnum } from 'enums'; + +/** + * Hooks + */ +import { useDisclosure } from '@chakra-ui/hooks'; + +const CreateUserModal: React.FC = () => { + const { isOpen, onOpen, onClose } = useDisclosure(); + + return ( + <> + + + + + + + + Create new user + + + + + + + First name + + + + Last name + + + + Login + + + + Email + + + + Role + + + + Password + + Must be at least 6 characters + + + + + + + + + + + ); +}; + +export default CreateUserModal; diff --git a/src/pages/users/components/CreateUserModal/CreateUserModal.validator.ts b/src/pages/users/components/CreateUserModal/CreateUserModal.validator.ts new file mode 100644 index 0000000..b6830c1 --- /dev/null +++ b/src/pages/users/components/CreateUserModal/CreateUserModal.validator.ts @@ -0,0 +1,13 @@ +import yup from 'schema'; +import { UserRoleEnum } from 'enums'; + +const CreateUserSchema = yup.object().shape({ + first_name: yup.string().required('First field name is required'), + last_name: yup.string().required('Last field name is required'), + login: yup.string().required('Login field is required'), + email: yup.string().required('Email field is required'), + role: yup.mixed().required('Role field is required').oneOf(Object.values(UserRoleEnum)), + password: yup.string().required('Password field is required').min(6, 'Password must be at least 6 characters.'), +}); + +export default CreateUserSchema; diff --git a/src/pages/users/components/CreateUserModal/index.ts b/src/pages/users/components/CreateUserModal/index.ts new file mode 100644 index 0000000..acf6db5 --- /dev/null +++ b/src/pages/users/components/CreateUserModal/index.ts @@ -0,0 +1,3 @@ +import CreateUserModal from './CreateUserModal'; + +export default CreateUserModal; diff --git a/src/pages/users/components/UserList/UserList.tsx b/src/pages/users/components/UserList/UserList.tsx index 8f54628..2f1749a 100644 --- a/src/pages/users/components/UserList/UserList.tsx +++ b/src/pages/users/components/UserList/UserList.tsx @@ -73,7 +73,7 @@ const UserList: React.FC = ({ users, pagination }) => { )} - + Page {pagination.current_page} of {pagesCount} diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx index 1073123..563a470 100644 --- a/src/pages/users/index.tsx +++ b/src/pages/users/index.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useState } from 'react'; import { observer } from 'mobx-react'; import { Box, Flex, Button, Heading, Text } from '@chakra-ui/react'; -import { AddIcon } from '@chakra-ui/icons'; import { FaFileExcel } from 'react-icons/fa'; /** @@ -28,6 +27,7 @@ import { useLocation } from 'react-router'; * Context */ import { UsersPageContext } from 'contexts'; +import CreateUserModal from './components/CreateUserModal'; /** * Users Page @@ -46,23 +46,21 @@ const UsersPage: React.FC = ({ title }) => { return ( - + User management You can add or delete your users on this page. - {userStore.users !== null ? ( + {userStore.users !== null && userStore.pagination !== undefined ? ( - + - {userStore.pagination && } + ) : ( diff --git a/src/services/UserService.ts b/src/services/UserService.ts index aa30566..d7ebe4c 100644 --- a/src/services/UserService.ts +++ b/src/services/UserService.ts @@ -18,7 +18,7 @@ export default class UserService { } public async fetchAll(params?: FetchUsersParamsType): Promise> { - const { page = 1, limit = 1, role, search } = params || {}; + const { page = 1, limit = 6, role, search } = params || {}; const result = await this.api.get('/v1/users', { params: { page,