-
-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(manageUsers): manage users table & role update functionality add
- Loading branch information
Showing
1 changed file
with
152 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
import React, { useEffect, useState } from 'react'; | ||
import DataTable from '@/components/common/DataTable'; | ||
import { GetUserListService, UpdateUserRole } from '@/api/User'; | ||
import { useAppDispatch, useAppSelector } from '@/types/reduxTypes'; | ||
import AssetModules from '@/shared/AssetModules'; | ||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '@/components/common/Dropdown'; | ||
import { user_roles } from '@/types/enums'; | ||
import { CommonActions } from '@/store/slices/CommonSlice'; | ||
import Searchbar from '@/components/common/SearchBar'; | ||
import useDebouncedInput from '@/hooks/useDebouncedInput'; | ||
|
||
const VITE_API_URL = import.meta.env.VITE_API_URL; | ||
|
||
type roleType = 'READ_ONLY' | 'ADMIN' | 'MAPPER'; | ||
const roleLabel = { | ||
READ_ONLY: 'Read Only', | ||
MAPPER: 'Mapper', | ||
ADMIN: 'Admin', | ||
}; | ||
|
||
const ManageUsers = () => { | ||
const dispatch = useAppDispatch(); | ||
const userListLoading = useAppSelector((state) => state.user.userListLoading); | ||
const userList = useAppSelector((state) => state.user.userList); | ||
|
||
const updateRole = (id: number, currentRole: roleType, newRole: roleType) => { | ||
if (currentRole === newRole) { | ||
dispatch(CommonActions.SetSnackBar({ duration: 2000, open: true, message: 'Role up-to-date', variant: 'info' })); | ||
return; | ||
} | ||
dispatch(UpdateUserRole(`${VITE_API_URL}/users/${id}`, { role: newRole })); | ||
}; | ||
|
||
const userDatacolumns = [ | ||
{ | ||
header: 'Users', | ||
accessorKey: 'username', | ||
cell: ({ row }: any) => { | ||
return ( | ||
<div className="fmtm-flex fmtm-items-center fmtm-gap-2"> | ||
{!row?.original?.profile_img ? ( | ||
<div className="fmtm-w-[1.875rem] fmtm-h-[1.875rem] fmtm-rounded-full fmtm-bg-[#68707F] fmtm-flex fmtm-items-center fmtm-justify-center fmtm-cursor-default"> | ||
<p className="fmtm-text-white">{row?.original?.username[0]?.toUpperCase()}</p> | ||
</div> | ||
) : ( | ||
<img | ||
src={row?.original?.profile_img} | ||
className="fmtm-w-[1.875rem] fmtm-h-[1.875rem] fmtm-rounded-full" | ||
alt="profile image" | ||
/> | ||
)} | ||
<p>{row?.original?.username}</p> | ||
</div> | ||
); | ||
}, | ||
}, | ||
{ | ||
header: 'User ID', | ||
accessorKey: 'id', | ||
}, | ||
{ | ||
header: 'Role', | ||
accessorKey: 'role', | ||
}, | ||
{ | ||
header: 'Last Active', | ||
accessorKey: 'last_login_at', | ||
cell: ({ row }: any) => { | ||
const lastActive = row?.original?.last_login_at ? row?.original?.last_login_at?.split('T')[0] : 'N/A'; | ||
return <>{lastActive}</>; | ||
}, | ||
}, | ||
{ | ||
header: ' ', | ||
cell: ({ row }: any) => { | ||
const userId = row?.original?.id; | ||
const currentRole = row?.original?.role; | ||
return ( | ||
<> | ||
<DropdownMenu> | ||
<DropdownMenuTrigger className="fmtm-outline-none"> | ||
<AssetModules.ManageAccountsOutlinedIcon className="fmtm-cursor-pointer hover:fmtm-text-primaryRed" /> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent className="fmtm-z-[50] fmtm-bg-white" align="end"> | ||
{Object.keys(user_roles)?.map((role) => ( | ||
<DropdownMenuItem | ||
key={role} | ||
className="hover:fmtm-bg-red-50 fmtm-duration-200 fmtm-outline-none fmtm-py-1 fmtm-px-4 fmtm-cursor-pointer fmtm-rounded" | ||
onSelect={() => { | ||
updateRole(userId, currentRole as roleType, role as roleType); | ||
}} | ||
> | ||
{roleLabel[role]} | ||
</DropdownMenuItem> | ||
))} | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
</> | ||
); | ||
}, | ||
}, | ||
]; | ||
|
||
const [filter, setFilter] = useState({ search: '' }); | ||
|
||
const [pagination, setPagination] = useState({ | ||
pageIndex: 0, | ||
pageSize: 2, | ||
}); | ||
|
||
const [searchTextData, handleChangeData] = useDebouncedInput({ | ||
ms: 500, | ||
init: filter.search, | ||
onChange: (debouncedEvent) => setFilter((prev) => ({ ...prev, search: debouncedEvent.target.value })), | ||
}); | ||
|
||
useEffect(() => { | ||
dispatch( | ||
GetUserListService(`${VITE_API_URL}/users`, { | ||
results_per_page: 2, | ||
page: pagination.pageIndex + 1, | ||
...filter, | ||
}), | ||
); | ||
}, [filter, pagination, filter]); | ||
return ( | ||
<div className="fmtm-h-full fmtm-flex fmtm-flex-col"> | ||
<div className="fmtm-flex fmtm-items-center fmtm-justify-between"> | ||
<h4 className="fmtm-text-[1.25rem] fmtm-font-bold fmtm-text-[#2C3038]">Manage Users</h4> | ||
<Searchbar | ||
value={searchTextData} | ||
onChange={handleChangeData} | ||
wrapperStyle="!fmtm-w-[13rem]" | ||
className="!fmtm-py-0" | ||
placeholder="Search by username" | ||
isSmall | ||
/> | ||
</div> | ||
<p className="fmtm-text-grey-500 fmtm-mb-4">Total number of users: {userList?.pagination?.total}</p> | ||
<DataTable | ||
data={userList || []} | ||
columns={userDatacolumns} | ||
isLoading={userListLoading} | ||
pagination={{ pageIndex: pagination.pageIndex, pageSize: pagination.pageSize }} | ||
setPaginationPage={(page) => setPagination(page)} | ||
tableWrapperClassName="fmtm-flex-1" | ||
/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ManageUsers; |