diff --git a/dashboard/src/components/DeleteUserModal.tsx b/dashboard/src/components/DeleteUserModal.tsx new file mode 100644 index 0000000..c9e5ac8 --- /dev/null +++ b/dashboard/src/components/DeleteUserModal.tsx @@ -0,0 +1,112 @@ +import React from 'react'; +import { + Button, + Center, + Flex, + MenuItem, + Modal, + ModalBody, + ModalCloseButton, + ModalContent, + ModalFooter, + ModalHeader, + ModalOverlay, + useDisclosure, + Text, + useToast, +} from '@chakra-ui/react'; +import { useClient } from 'urql'; +import { FaRegTrashAlt } from 'react-icons/fa'; +import { DeleteUser } from '../graphql/mutation'; +import { capitalizeFirstLetter } from '../utils'; + +interface userDataTypes { + id: string; + email: string; +} + +const DeleteUserModal = ({ + user, + updateUserList, +}: { + user: userDataTypes; + updateUserList: Function; +}) => { + const client = useClient(); + const toast = useToast(); + const { isOpen, onOpen, onClose } = useDisclosure(); + const [userData, setUserData] = React.useState({ + id: '', + email: '', + }); + React.useEffect(() => { + setUserData(user); + }, []); + const deleteHandler = async () => { + const res = await client + .mutation(DeleteUser, { params: { email: userData.email } }) + .toPromise(); + if (res.error) { + toast({ + title: capitalizeFirstLetter(res.error.message), + isClosable: true, + status: 'error', + position: 'bottom-right', + }); + + return; + } else if (res.data?._delete_user) { + toast({ + title: capitalizeFirstLetter(res.data?._delete_user.message), + isClosable: true, + status: 'success', + position: 'bottom-right', + }); + } + onClose(); + updateUserList(); + }; + return ( + <> + Delete User + + + + Delete User + + + Are you sure? + + + User {user.email} will be deleted permanently! + + + + + + + + + + + ); +}; + +export default DeleteUserModal; diff --git a/dashboard/src/graphql/mutation/index.ts b/dashboard/src/graphql/mutation/index.ts index 8eb652e..9736a01 100644 --- a/dashboard/src/graphql/mutation/index.ts +++ b/dashboard/src/graphql/mutation/index.ts @@ -23,9 +23,7 @@ export const AdminLogout = ` `; export const UpdateEnvVariables = ` - mutation updateEnvVariables( - $params: UpdateEnvInput! - ) { + mutation updateEnvVariables($params: UpdateEnvInput!) { _update_env(params: $params) { message } @@ -33,11 +31,17 @@ export const UpdateEnvVariables = ` `; export const UpdateUser = ` - mutation updateUser( - $params: UpdateUserInput! - ) { + mutation updateUser($params: UpdateUserInput!) { _update_user(params: $params) { id } } `; + +export const DeleteUser = ` + mutation deleteUser($params: DeleteUserInput!) { + _delete_user(params: $params) { + message + } + } +`; diff --git a/dashboard/src/pages/Users.tsx b/dashboard/src/pages/Users.tsx index ef4d86a..e632a5c 100644 --- a/dashboard/src/pages/Users.tsx +++ b/dashboard/src/pages/Users.tsx @@ -28,6 +28,7 @@ import { MenuList, MenuItem, useToast, + Spinner, } from '@chakra-ui/react'; import { FaAngleLeft, @@ -40,6 +41,7 @@ import { import { UserDetailsQuery } from '../graphql/queries'; import { UpdateUser } from '../graphql/mutation'; import EditUserModal from '../components/EditUserModal'; +import DeleteUserModal from '../components/DeleteUserModal'; interface paginationPropTypes { limit: number; @@ -98,7 +100,9 @@ export default function Users() { maxPages: 1, }); const [userList, setUserList] = React.useState([]); + const [loading, setLoading] = React.useState(false); const updateUserList = async () => { + setLoading(true); const { data } = await client .query(UserDetailsQuery, { params: { @@ -112,9 +116,21 @@ export default function Users() { if (data?._users) { const { pagination, users } = data._users; const maxPages = getMaxPages(pagination); - setPaginationProps({ ...paginationProps, ...pagination, maxPages }); - setUserList(users); + if (users && users.length > 0) { + setPaginationProps({ ...paginationProps, ...pagination, maxPages }); + setUserList(users); + } else { + if (paginationProps.page !== 1) { + setPaginationProps({ + ...paginationProps, + ...pagination, + maxPages, + page: 1, + }); + } + } } + setLoading(false); }; React.useEffect(() => { updateUserList(); @@ -162,208 +178,216 @@ export default function Users() { Users - {userList.length > 0 ? ( - - - - - - - - - - - - - {userList.map((user: userDataTypes) => { - const { email_verified, created_at, ...rest }: any = user; - return ( - - - - - - -
EmailCreated AtSignup MethodsRolesVerifiedActions
{user.email} - {dayjs(user.created_at * 1000).format('MMM DD, YYYY')} - {user.signup_methods}{user.roles.join(', ')} - - {user.email_verified.toString()} - - - - - - - Menu - - - - - - - {!user.email_verified && ( - userVerificationHandler(user)} + {!loading ? ( + userList.length > 0 ? ( + + + + + + + + + + + {userList.map((user: userDataTypes) => { + const { email_verified, created_at, ...rest }: any = user; + return ( + + + + + - - ); - })} - - {paginationProps.maxPages > 1 && ( - - - - - + + Menu + + + + + + {!user.email_verified && ( + userVerificationHandler(user)} + > + Verify User + + )} + + + + + + + ); + })} + + {(paginationProps.maxPages > 1 || paginationProps.total >= 5) && ( + + + + + + paginationHandler({ + page: 1, + }) + } + isDisabled={paginationProps.page <= 1} + mr={4} + icon={} + /> + + + + paginationHandler({ + page: paginationProps.page - 1, + }) + } + isDisabled={paginationProps.page <= 1} + icon={} + /> + + + + + Page{' '} + + {paginationProps.page} + {' '} + of{' '} + + {paginationProps.maxPages} + + + + Go to page:{' '} + + paginationHandler({ + page: parseInt(value), + }) + } + value={paginationProps.page} + > + + + + + + + + + + + + + paginationHandler({ + page: paginationProps.page + 1, + }) + } + isDisabled={ + paginationProps.page >= paginationProps.maxPages + } + icon={} + /> + + + + paginationHandler({ + page: paginationProps.maxPages, + }) + } + isDisabled={ + paginationProps.page >= paginationProps.maxPages + } + ml={4} + icon={} + /> + - - - - - paginationHandler({ - page: paginationProps.page + 1, - }) - } - isDisabled={ - paginationProps.page >= paginationProps.maxPages - } - icon={} - /> - - - - paginationHandler({ - page: paginationProps.maxPages, - }) - } - isDisabled={ - paginationProps.page >= paginationProps.maxPages - } - ml={4} - icon={} - /> - - - - - )} -
EmailCreated AtVerifiedActions
{user.email}{dayjs(user.created_at).format('MMM DD, YYYY')} + + {user.email_verified.toString()} + + + + + - Verify User - - )} - - -
- ) : ( - -
- -
- + )} +
+ ) : ( + - No Data - - +
+ +
+ + No Data + + + ) + ) : ( +
+ +
)} );