mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
feat: deleting user from dialog
This commit is contained in:
parent
3a4296f3bd
commit
ee0bdb0e4a
@ -20,4 +20,6 @@ export const UsersPageContext = createContext<UsersPageContextType>({
|
|||||||
setSearch: () => {},
|
setSearch: () => {},
|
||||||
editingUser: undefined,
|
editingUser: undefined,
|
||||||
setEditingUser: () => {},
|
setEditingUser: () => {},
|
||||||
|
deletingUser: undefined,
|
||||||
|
setDeletingUser: () => {},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Text, Badge, Link, Box, Flex } from '@chakra-ui/layout';
|
import { Text, Link, Box, Flex } from '@chakra-ui/layout';
|
||||||
import { Link as ReactRouterLink } from 'react-router-dom';
|
import { Link as ReactRouterLink } from 'react-router-dom';
|
||||||
import { MdVideoLibrary, MdGroup, MdThumbUp } from 'react-icons/md';
|
import { MdVideoLibrary, MdGroup, MdThumbUp } from 'react-icons/md';
|
||||||
import { UserCourseType } from 'interfaces';
|
import { UserCourseType } from 'interfaces';
|
||||||
|
import { Tag, TagLabel } from '@chakra-ui/react';
|
||||||
|
|
||||||
type CourseItemPropsType = {
|
type CourseItemPropsType = {
|
||||||
course: UserCourseType;
|
course: UserCourseType;
|
||||||
@ -15,11 +16,11 @@ const CourseItem: React.FC<CourseItemPropsType> = ({ course }) => {
|
|||||||
<Link as={ReactRouterLink} to={`course/${course.id}`} fontWeight='bold' fontSize='2xl'>
|
<Link as={ReactRouterLink} to={`course/${course.id}`} fontWeight='bold' fontSize='2xl'>
|
||||||
{course.title}
|
{course.title}
|
||||||
</Link>
|
</Link>
|
||||||
<Badge colorScheme='purple'>
|
<Link as={ReactRouterLink} to={`category/${course.category.id}`}>
|
||||||
<Link as={ReactRouterLink} to={`category/${course.category.id}`}>
|
<Tag colorScheme='purple' borderRadius='full'>
|
||||||
{course.category.title}
|
<TagLabel>{course.category.title}</TagLabel>
|
||||||
</Link>
|
</Tag>
|
||||||
</Badge>
|
</Link>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text>{course.description}</Text>
|
<Text>{course.description}</Text>
|
||||||
<Flex mt='5' alignItems='center'>
|
<Flex mt='5' alignItems='center'>
|
||||||
|
|||||||
@ -0,0 +1,98 @@
|
|||||||
|
import React, { useContext, useRef, useState } from 'react';
|
||||||
|
import {
|
||||||
|
AlertDialog,
|
||||||
|
AlertDialogBody,
|
||||||
|
AlertDialogFooter,
|
||||||
|
AlertDialogHeader,
|
||||||
|
AlertDialogContent,
|
||||||
|
AlertDialogOverlay,
|
||||||
|
Button,
|
||||||
|
} from '@chakra-ui/react';
|
||||||
|
import { UsersPageContext } from 'contexts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks
|
||||||
|
*/
|
||||||
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
|
import useIsMountedRef from 'hooks/useIsMountedRef';
|
||||||
|
import { useToast } from '@chakra-ui/react';
|
||||||
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
|
|
||||||
|
type DeleteUserDialogPropsType = {
|
||||||
|
onClose: () => void;
|
||||||
|
isOpen: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeleteUserDialog: React.FC<DeleteUserDialogPropsType> = ({ onClose, isOpen }) => {
|
||||||
|
const { userStore } = useRootStore();
|
||||||
|
const { deletingUser, setDeletingUser } = useContext(UsersPageContext);
|
||||||
|
const isMountedRef = useIsMountedRef();
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const cancelRef = useRef<HTMLButtonElement | null>(null);
|
||||||
|
const handleError = useErrorHandler();
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete user handler
|
||||||
|
*/
|
||||||
|
const onDelete = async (id: string) => {
|
||||||
|
try {
|
||||||
|
setIsLoading(true);
|
||||||
|
await userStore.deleteUser(id);
|
||||||
|
toast({ title: 'User deleted', status: 'info' });
|
||||||
|
onClose();
|
||||||
|
setDeletingUser(undefined);
|
||||||
|
} catch (error: any) {
|
||||||
|
if (error.response) {
|
||||||
|
toast({ title: error.message, status: 'error' });
|
||||||
|
} else {
|
||||||
|
handleError(error);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (isMountedRef.current) {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (deletingUser === undefined) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<AlertDialog isOpen={isOpen} leastDestructiveRef={cancelRef} onClose={onClose}>
|
||||||
|
<AlertDialogOverlay>
|
||||||
|
<AlertDialogContent>
|
||||||
|
<AlertDialogHeader fontSize='lg' fontWeight='bold'>
|
||||||
|
Confirm deleting
|
||||||
|
</AlertDialogHeader>
|
||||||
|
<AlertDialogBody>
|
||||||
|
The user named "{deletingUser.first_name} {deletingUser.last_name}" will be removed from the system.
|
||||||
|
</AlertDialogBody>
|
||||||
|
<AlertDialogFooter>
|
||||||
|
<Button
|
||||||
|
ref={cancelRef}
|
||||||
|
onClick={() => {
|
||||||
|
setDeletingUser(undefined);
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
colorScheme='red'
|
||||||
|
isLoading={isLoading}
|
||||||
|
loadingText='Deleting...'
|
||||||
|
onClick={() => onDelete(deletingUser.id)}
|
||||||
|
ml={3}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</AlertDialogFooter>
|
||||||
|
</AlertDialogContent>
|
||||||
|
</AlertDialogOverlay>
|
||||||
|
</AlertDialog>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteUserDialog;
|
||||||
3
src/pages/users/components/DeleteUserDialog/index.ts
Normal file
3
src/pages/users/components/DeleteUserDialog/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import DeleteUserDialog from './DeleteUserDialog';
|
||||||
|
|
||||||
|
export default DeleteUserDialog;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import React from 'react';
|
import React, { useContext } from 'react';
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
@ -9,6 +9,7 @@ import {
|
|||||||
ModalFooter,
|
ModalFooter,
|
||||||
FormControl,
|
FormControl,
|
||||||
FormLabel,
|
FormLabel,
|
||||||
|
FormHelperText,
|
||||||
Input,
|
Input,
|
||||||
Button,
|
Button,
|
||||||
Select,
|
Select,
|
||||||
@ -18,25 +19,58 @@ import {
|
|||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { AddIcon } from '@chakra-ui/icons';
|
import { AddIcon } from '@chakra-ui/icons';
|
||||||
import { MdModeEdit } from 'react-icons/md';
|
import { MdModeEdit } from 'react-icons/md';
|
||||||
|
import { yupResolver } from '@hookform/resolvers/yup';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Types
|
* Types
|
||||||
*/
|
*/
|
||||||
import { IUser } from 'interfaces';
|
|
||||||
import { UserRoleEnum } from 'enums';
|
import { UserRoleEnum } from 'enums';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hooks
|
||||||
|
*/
|
||||||
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
|
import UpdateUserSchema from './EditUserForm.validator';
|
||||||
|
import { UsersPageContext } from 'contexts';
|
||||||
|
|
||||||
|
type UpdateUserInputType = {
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
login: string;
|
||||||
|
email: string;
|
||||||
|
role: UserRoleEnum;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
type UpdateUserFormPropsType = {
|
type UpdateUserFormPropsType = {
|
||||||
user: IUser;
|
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOpen }) => {
|
const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ onClose, isOpen }) => {
|
||||||
|
const { editingUser, setEditingUser } = useContext(UsersPageContext);
|
||||||
|
const {
|
||||||
|
register,
|
||||||
|
handleSubmit,
|
||||||
|
reset,
|
||||||
|
formState: { errors },
|
||||||
|
} = useForm<UpdateUserInputType>({
|
||||||
|
resolver: yupResolver(UpdateUserSchema),
|
||||||
|
defaultValues: {
|
||||||
|
first_name: editingUser && editingUser.first_name,
|
||||||
|
last_name: editingUser && editingUser.last_name,
|
||||||
|
email: editingUser && editingUser.email,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit: SubmitHandler<UpdateUserInputType> = data => {
|
||||||
|
console.log(data);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onClose={onClose}>
|
<Modal isOpen={isOpen} onClose={onClose}>
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent>
|
<ModalContent>
|
||||||
<form>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<Flex alignItems='center'>
|
<Flex alignItems='center'>
|
||||||
<MdModeEdit />
|
<MdModeEdit />
|
||||||
@ -48,31 +82,43 @@ const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOp
|
|||||||
<ModalBody pb={6}>
|
<ModalBody pb={6}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<FormLabel>First name</FormLabel>
|
<FormLabel>First name</FormLabel>
|
||||||
<Input placeholder='First name' value={user.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' value={user.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>
|
||||||
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
<option value={UserRoleEnum.TEACHER}>Teacher</option>
|
||||||
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
<option value={UserRoleEnum.ADMIN}>Administrator</option>
|
||||||
</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 color={errors.password ? 'red' : 'gray.500'}>
|
||||||
|
{errors.password ? errors.password.message : 'Must be at least 6 characters.'}
|
||||||
|
</FormHelperText>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
|
|
||||||
@ -80,14 +126,22 @@ const UpdateUserForm: React.FC<UpdateUserFormPropsType> = ({ user, onClose, isOp
|
|||||||
<Button
|
<Button
|
||||||
type='submit'
|
type='submit'
|
||||||
variant='outline'
|
variant='outline'
|
||||||
mr={3}
|
mr={1}
|
||||||
colorScheme='blue'
|
colorScheme='blue'
|
||||||
loadingText='Creating...'
|
loadingText='Saving...'
|
||||||
leftIcon={<AddIcon />}
|
leftIcon={<AddIcon />}
|
||||||
>
|
>
|
||||||
Edit
|
Save
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
reset({});
|
||||||
|
setEditingUser(undefined);
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button onClick={onClose}>Cancel</Button>
|
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</form>
|
</form>
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import * as helpres from 'helpers';
|
import * as helpres from 'helpers';
|
||||||
import { Box, Flex, Avatar, Text, IconButton } from '@chakra-ui/react';
|
import { Box, Flex, Avatar, Text, IconButton } from '@chakra-ui/react';
|
||||||
import { MdMoreHoriz } from 'react-icons/md';
|
|
||||||
import UserBadge from 'components/UserBadge';
|
import UserBadge from 'components/UserBadge';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -14,13 +13,15 @@ import { UserRoleEnum } from 'enums';
|
|||||||
* Hooks
|
* Hooks
|
||||||
*/
|
*/
|
||||||
import { useRootStore } from 'hooks/useRootStore';
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
|
import { DeleteIcon, EditIcon } from '@chakra-ui/icons';
|
||||||
|
|
||||||
type UserItemPropsType = {
|
type UserItemPropsType = {
|
||||||
user: IUser;
|
user: IUser;
|
||||||
onEdit: (user: IUser) => void;
|
onEdit: (user: IUser) => void;
|
||||||
|
onDelete: (user: IUser) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const UserItem: React.FC<UserItemPropsType> = ({ user, onEdit }) => {
|
const UserItem: React.FC<UserItemPropsType> = ({ user, onEdit, onDelete }) => {
|
||||||
const {
|
const {
|
||||||
userStore: { me },
|
userStore: { me },
|
||||||
} = useRootStore();
|
} = useRootStore();
|
||||||
@ -60,9 +61,18 @@ const UserItem: React.FC<UserItemPropsType> = ({ user, onEdit }) => {
|
|||||||
<IconButton
|
<IconButton
|
||||||
disabled={isDisabledActions()}
|
disabled={isDisabledActions()}
|
||||||
onClick={() => onEdit(user)}
|
onClick={() => onEdit(user)}
|
||||||
aria-label='Actions'
|
aria-label='Edit'
|
||||||
variant='ghost'
|
variant='ghost'
|
||||||
icon={<MdMoreHoriz />}
|
mr={1}
|
||||||
|
icon={<EditIcon />}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
|
disabled={isDisabledActions()}
|
||||||
|
onClick={() => onDelete(user)}
|
||||||
|
colorScheme='red'
|
||||||
|
aria-label='Delete'
|
||||||
|
variant='ghost'
|
||||||
|
icon={<DeleteIcon />}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@ -3,6 +3,10 @@ import { observer } from 'mobx-react';
|
|||||||
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
import { ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons';
|
||||||
import { Flex, Box, Stack, Text } from '@chakra-ui/layout';
|
import { Flex, Box, Stack, Text } from '@chakra-ui/layout';
|
||||||
import { Button } from '@chakra-ui/button';
|
import { Button } from '@chakra-ui/button';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Components
|
||||||
|
*/
|
||||||
import UserItem from './UserItem';
|
import UserItem from './UserItem';
|
||||||
import EditUserForm from '../EditUserForm';
|
import EditUserForm from '../EditUserForm';
|
||||||
|
|
||||||
@ -24,16 +28,18 @@ import { useContext } from 'react';
|
|||||||
import { useRootStore } from 'hooks/useRootStore';
|
import { useRootStore } from 'hooks/useRootStore';
|
||||||
import { useDisclosure } from '@chakra-ui/hooks';
|
import { useDisclosure } from '@chakra-ui/hooks';
|
||||||
import { useErrorHandler } from 'react-error-boundary';
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
|
import DeleteUserDialog from '../DeleteUserDialog';
|
||||||
|
|
||||||
type UserListPropsType = { users: IUser[]; pagination: IPaginationMeta };
|
type UserListPropsType = { users: IUser[]; pagination: IPaginationMeta };
|
||||||
|
|
||||||
const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
|
const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
|
||||||
const { userStore } = useRootStore();
|
const { userStore } = useRootStore();
|
||||||
const { searchingRole, loading, setLoading, search, editingUser, setEditingUser } =
|
const { searchingRole, loading, setLoading, search, editingUser, setEditingUser, deletingUser, setDeletingUser } =
|
||||||
useContext<UsersPageContextType>(UsersPageContext);
|
useContext<UsersPageContextType>(UsersPageContext);
|
||||||
const handleError = useErrorHandler();
|
const handleError = useErrorHandler();
|
||||||
const pagesCount = Math.ceil(pagination.total / pagination.per_page);
|
const pagesCount = Math.ceil(pagination.total / pagination.per_page);
|
||||||
const { onOpen: onOpenEditModal, onClose: onCloseEditModal, isOpen: isOpenEditModal } = useDisclosure();
|
const { onOpen: onOpenEditModal, onClose: onCloseEditModal, isOpen: isOpenEditModal } = useDisclosure();
|
||||||
|
const { onOpen: onOpenDeleteDialog, onClose: onCloseDeleteDialog, isOpen: isOpenDeleteDialog } = useDisclosure();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle next page
|
* Handle next page
|
||||||
@ -75,6 +81,7 @@ const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Set editing state when click on edit button
|
* Set editing state when click on edit button
|
||||||
|
* and open editing user form modal
|
||||||
*/
|
*/
|
||||||
const onEditUser = (user: IUser) => {
|
const onEditUser = (user: IUser) => {
|
||||||
setEditingUser(user);
|
setEditingUser(user);
|
||||||
@ -82,11 +89,22 @@ const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
|
|||||||
console.log(`[LOG]: Editing user "${user.id}"`);
|
console.log(`[LOG]: Editing user "${user.id}"`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set deleting state when click on delete button
|
||||||
|
* and open delete user dialog
|
||||||
|
*/
|
||||||
|
const onDeleteUser = (user: IUser) => {
|
||||||
|
setDeletingUser(user);
|
||||||
|
onOpenDeleteDialog();
|
||||||
|
console.log(`[LOG]: Alert delete "${user.id}"`);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{pagination.total !== 0 ? (
|
{pagination.total !== 0 ? (
|
||||||
<>
|
<>
|
||||||
{editingUser && <EditUserForm user={editingUser} onClose={onCloseEditModal} isOpen={isOpenEditModal} />}
|
{editingUser && <EditUserForm onClose={onCloseEditModal} isOpen={isOpenEditModal} />}
|
||||||
|
{deletingUser && <DeleteUserDialog onClose={onCloseDeleteDialog} isOpen={isOpenDeleteDialog} />}
|
||||||
<Box>
|
<Box>
|
||||||
<Flex mt='7' p='0 10px' fontWeight='bold' alignItems='center' justifyContent='space-between'>
|
<Flex mt='7' p='0 10px' fontWeight='bold' alignItems='center' justifyContent='space-between'>
|
||||||
<Text>Total: ({pagination.total})</Text>
|
<Text>Total: ({pagination.total})</Text>
|
||||||
@ -99,7 +117,7 @@ const UserList: React.FC<UserListPropsType> = ({ users, pagination }) => {
|
|||||||
) : (
|
) : (
|
||||||
<Stack mt='4' spacing='2'>
|
<Stack mt='4' spacing='2'>
|
||||||
{users.map(user => (
|
{users.map(user => (
|
||||||
<UserItem key={user.id} user={user} onEdit={onEditUser} />
|
<UserItem key={user.id} user={user} onEdit={onEditUser} onDelete={onDeleteUser} />
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -44,7 +44,7 @@ const UsersPage: React.FC<IPageProps> = () => {
|
|||||||
<UsersPageContextProvider>
|
<UsersPageContextProvider>
|
||||||
<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 users on this page.</Text>
|
||||||
{userStore.users !== null && userStore.me !== 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'>
|
||||||
|
|||||||
@ -35,10 +35,22 @@ export const UsersPageContextProvider: React.FC = ({ children }) => {
|
|||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [search, setSearch] = useState<string | undefined>(undefined);
|
const [search, setSearch] = useState<string | undefined>(undefined);
|
||||||
const [editingUser, setEditingUser] = useState<IUser | undefined>(undefined);
|
const [editingUser, setEditingUser] = useState<IUser | undefined>(undefined);
|
||||||
|
const [deletingUser, setDeletingUser] = useState<IUser | undefined>(undefined);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UsersPageContext.Provider
|
<UsersPageContext.Provider
|
||||||
value={{ searchingRole, setSearchingRole, loading, setLoading, search, setSearch, editingUser, setEditingUser }}
|
value={{
|
||||||
|
searchingRole,
|
||||||
|
setSearchingRole,
|
||||||
|
loading,
|
||||||
|
setLoading,
|
||||||
|
search,
|
||||||
|
setSearch,
|
||||||
|
editingUser,
|
||||||
|
setEditingUser,
|
||||||
|
deletingUser,
|
||||||
|
setDeletingUser,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</UsersPageContext.Provider>
|
</UsersPageContext.Provider>
|
||||||
|
|||||||
@ -50,6 +50,11 @@ export default class UserService {
|
|||||||
return result.data;
|
return result.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async delete(id: string): Promise<IApiRespose<IUser>> {
|
||||||
|
const result = await this.api.delete(`v1/users/${id}`);
|
||||||
|
return result.data;
|
||||||
|
}
|
||||||
|
|
||||||
public async updateContacts(data: IUserContacts): Promise<IApiRespose<IUserContacts>> {
|
public async updateContacts(data: IUserContacts): Promise<IApiRespose<IUserContacts>> {
|
||||||
const result = await this.api.put('v1/me/contacts', helpers.removeEmptyValues(data));
|
const result = await this.api.put('v1/me/contacts', helpers.removeEmptyValues(data));
|
||||||
return result.data;
|
return result.data;
|
||||||
|
|||||||
@ -96,6 +96,24 @@ export default class UserStore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async deleteUser(id: string) {
|
||||||
|
try {
|
||||||
|
const result = await this.userService.delete(id);
|
||||||
|
|
||||||
|
console.log(`[${this.constructor.name}]: ${result.message}`, result);
|
||||||
|
|
||||||
|
runInAction(() => {
|
||||||
|
if (this.users !== null) {
|
||||||
|
this.users = this.users.filter(user => user.id !== id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (error: any) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update contacts of authorized user
|
* Update contacts of authorized user
|
||||||
*
|
*
|
||||||
|
|||||||
8
src/types/index.d.ts
vendored
8
src/types/index.d.ts
vendored
@ -62,8 +62,14 @@ export type UsersPageContextType = {
|
|||||||
setSearch: React.Dispatch<React.SetStateAction<string | undefined>>;
|
setSearch: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set editing user state when press on action button
|
* Set editing user state when press on edit button
|
||||||
*/
|
*/
|
||||||
editingUser: IUser | undefined;
|
editingUser: IUser | undefined;
|
||||||
setEditingUser: React.Dispatch<React.SetStateAction<IUser | undefined>>;
|
setEditingUser: React.Dispatch<React.SetStateAction<IUser | undefined>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set deliting user state when press on delete button
|
||||||
|
*/
|
||||||
|
deletingUser: IUser | undefined;
|
||||||
|
setDeletingUser: React.Dispatch<React.SetStateAction<IUser | undefined>>;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user