feat: users pagination

This commit is contained in:
IlyaDoronin 2024-03-07 15:44:44 +03:00
parent 8978081198
commit 13ec627b31
6 changed files with 287 additions and 95 deletions

@ -1,70 +0,0 @@
import { makeRequest } from "@frontend/kitui";
import { parseAxiosError } from "@root/utils/parse-error";
import type { UserType } from "@root/api/roles";
type RegisteredUsersResponse = {
tatalPages: number;
users: UserType[];
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/user";
export const getUserInfo = async (
id: string
): Promise<[UserType | null, string?]> => {
try {
const userInfoResponse = await makeRequest<never, UserType>({
url: `${baseUrl}/${id}`,
method: "GET",
useToken: true,
});
return [userInfoResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка получения информации о пользователе. ${error}`];
}
};
export const getRegisteredUsers = async (): Promise<
[RegisteredUsersResponse | null, string?]
> => {
try {
const registeredUsersResponse = await makeRequest<
never,
RegisteredUsersResponse
>({
method: "get",
url: baseUrl + "/",
});
return [registeredUsersResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении пользователей. ${error}`];
}
};
export const getManagersList = async (): Promise<
[RegisteredUsersResponse | null, string?]
> => {
try {
const managersListResponse = await makeRequest<
never,
RegisteredUsersResponse
>({
method: "get",
url: baseUrl + "/",
});
return [managersListResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении менеджеров. ${error}`];
}
};

89
src/api/user/requests.ts Normal file

@ -0,0 +1,89 @@
import { makeRequest } from "@frontend/kitui";
import { parseAxiosError } from "@root/utils/parse-error";
import type { UserType } from "@root/api/roles";
export type RegisteredUsersResponse = {
totalPages: number;
users: UserType[];
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/user";
const getUserInfo = async (id: string): Promise<[UserType | null, string?]> => {
try {
const userInfoResponse = await makeRequest<never, UserType>({
url: `${baseUrl}/${id}`,
method: "GET",
useToken: true,
});
return [userInfoResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка получения информации о пользователе. ${error}`];
}
};
const getUserList = async (
page = 1,
limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => {
try {
const userResponse = await makeRequest<never, RegisteredUsersResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
});
return [userResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении пользователей. ${error}`];
}
};
const getManagerList = async (
page = 1,
limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => {
try {
const managerResponse = await makeRequest<never, RegisteredUsersResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
});
return [managerResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении менеджеров. ${error}`];
}
};
const getAdminList = async (
page = 1,
limit = 10
): Promise<[RegisteredUsersResponse | null, string?]> => {
try {
const adminResponse = await makeRequest<never, RegisteredUsersResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
});
return [adminResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении админов. ${error}`];
}
};
export const userApi = {
getUserInfo,
getUserList,
getManagerList,
getAdminList,
};

104
src/api/user/swr.ts Normal file

@ -0,0 +1,104 @@
import { useRef } from "react";
import useSwr from "swr";
import { enqueueSnackbar } from "notistack";
import { userApi } from "./requests";
export function useAdmins(page: number, pageSize: number) {
const adminPagesRef = useRef<number>(0);
const swrResponse = useSwr(
["admin", page, pageSize],
async ([_, page, pageSize]) => {
const [adminResponse, error] = await userApi.getManagerList(
page,
pageSize
);
if (error) {
throw new Error(error);
}
adminPagesRef.current = adminResponse?.totalPages || 1;
return adminResponse;
},
{
onError(err) {
console.log("Error fetching users", err);
enqueueSnackbar(err.message, { variant: "error" });
},
focusThrottleInterval: 60e3,
keepPreviousData: true,
}
);
return {
...swrResponse,
adminPages: adminPagesRef.current,
};
}
export function useManagers(page: number, pageSize: number) {
const managerPagesRef = useRef<number>(0);
const swrResponse = useSwr(
["manager", page, pageSize],
async ([_, page, pageSize]) => {
const [managerResponse, error] = await userApi.getManagerList(
page,
pageSize
);
if (error) {
throw new Error(error);
}
managerPagesRef.current = managerResponse?.totalPages || 1;
return managerResponse;
},
{
onError(err) {
console.log("Error fetching users", err);
enqueueSnackbar(err.message, { variant: "error" });
},
focusThrottleInterval: 60e3,
keepPreviousData: true,
}
);
return {
...swrResponse,
managerPages: managerPagesRef.current,
};
}
export function useUsers(page: number, pageSize: number) {
const userPagesRef = useRef<number>(0);
const swrResponse = useSwr(
["users", page, pageSize],
async ([_, page, pageSize]) => {
const [userResponse, error] = await userApi.getUserList(page, pageSize);
if (error) {
throw new Error(error);
}
userPagesRef.current = userResponse?.totalPages || 1;
return userResponse;
},
{
onError(err) {
console.log("Error fetching users", err);
enqueueSnackbar(err.message, { variant: "error" });
},
focusThrottleInterval: 60e3,
keepPreviousData: true,
}
);
return {
...swrResponse,
userPagesCount: userPagesRef.current,
};
}

@ -42,11 +42,21 @@ const columns: GridColDef<UserType, string>[] = [
interface Props {
handleSelectionChange: (selectionModel: GridSelectionModel) => void;
users: UserType[];
page: number;
setPage: (page: number) => void;
pageSize: number;
pagesCount: number;
onPageSizeChange?: (count: number) => void;
}
export default function ServiceUsersDG({
handleSelectionChange,
users = [],
page,
setPage,
pageSize = 10,
pagesCount = 1,
onPageSizeChange,
}: Props) {
const navigate = useNavigate();
@ -60,6 +70,13 @@ export default function ServiceUsersDG({
rows={users}
columns={columns}
components={{ Toolbar: GridToolbar }}
rowCount={pageSize * pagesCount}
rowsPerPageOptions={[10, 25, 50, 100]}
paginationMode="server"
page={page}
pageSize={pageSize}
onPageChange={setPage}
onPageSizeChange={onPageSizeChange}
onSelectionModelChange={handleSelectionChange}
onCellClick={({ row }, event) => {
event.stopPropagation();

@ -23,14 +23,24 @@ import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import ConditionalRender from "@root/pages/Setting/ConditionalRender";
import ModalUser from "@root/pages/dashboard/ModalUser";
import ServiceUsersDG from "./ServiceUsersDG";
import { getRegisteredUsers, getManagersList } from "@root/api/user";
import { useUsers, useManagers, useAdmins } from "@root/api/user/swr";
import { getRoles } from "@root/api/privilegies";
import { getRoles_mock, TMockData } from "../../../api/roles";
import theme from "../../../theme";
import type { UserType } from "../../../api/roles";
type Pages = {
adminPage: number;
managerPage: number;
userPage: number;
};
type PagesSize = {
adminPageSize: number;
managerPageSize: number;
userPageSize: number;
};
const Users: React.FC = () => {
const radioboxes = ["admin", "manager", "user"];
@ -39,11 +49,11 @@ const Users: React.FC = () => {
const navigate = useNavigate();
const [data, setData] = React.useState<TMockData>([]);
const [mockData, setMockData] = React.useState<TMockData>([]);
const handleChangeData = () => {
getRoles_mock().then((mockdata) => {
setData(mockdata);
setMockData(mockdata);
setAccordionText(mockdata[0].desc || "");
});
};
@ -53,7 +63,7 @@ const Users: React.FC = () => {
const handleChange = (value: string) => {
setSelectedValue(value);
setAccordionText(data.find(({ name }) => name === value)?.desc || "");
setAccordionText(mockData.find(({ name }) => name === value)?.desc || "");
if (selectedValue === "manager") {
}
@ -64,12 +74,33 @@ const Users: React.FC = () => {
};
const [roles, setRoles] = React.useState<TMockData>([]);
const [users, setUsers] = React.useState<UserType[]>([]);
const [manager, setManager] = React.useState<UserType[]>([]);
const [page, setPage] = useState<Pages>({
adminPage: 0,
managerPage: 0,
userPage: 0,
});
const [pageSize, setPageSize] = useState<PagesSize>({
adminPageSize: 10,
managerPageSize: 10,
userPageSize: 10,
});
const [openUserModal, setOpenUserModal] = useState<boolean>(false);
const [activeUserId, setActiveUserId] = useState<string>("");
const { userId } = useParams();
const { data: adminData, adminPages } = useAdmins(
page.adminPage + 1,
pageSize.adminPageSize
);
const { data: managerData, managerPages } = useManagers(
page.managerPage + 1,
pageSize.managerPageSize
);
const { data: userData, userPagesCount } = useUsers(
page.userPage + 1,
pageSize.userPageSize
);
useEffect(() => {
handleChangeData();
@ -88,18 +119,6 @@ const Users: React.FC = () => {
}, [userId]);
useEffect(() => {
getManagersList().then(([managersListResponse]) => {
if (managersListResponse) {
setManager(managersListResponse.users);
}
});
getRegisteredUsers().then(([registeredUsersResponse]) => {
if (registeredUsersResponse) {
setUsers(registeredUsersResponse.users);
}
});
getRoles().then(([rolesResponse]) => {
if (rolesResponse) {
setRoles(rolesResponse);
@ -210,8 +229,8 @@ const Users: React.FC = () => {
</TableHead>
<TableBody>
{data.length ? (
data.map(function (item, index) {
{mockData.length ? (
mockData.map(function (item, index) {
return (
<TableRow
sx={{
@ -394,16 +413,49 @@ const Users: React.FC = () => {
<ConditionalRender
isLoading={false}
role={selectedValue}
childrenAdmin={
<ServiceUsersDG
users={adminData?.users.length ? adminData.users : []}
page={page.adminPage}
setPage={(adminPage) =>
setPage((pages) => ({ ...pages, adminPage }))
}
pagesCount={adminPages}
pageSize={pageSize.adminPageSize}
handleSelectionChange={setSelectedTariffs}
onPageSizeChange={(adminPageSize) =>
setPageSize((pageSize) => ({ ...pageSize, adminPageSize }))
}
/>
}
childrenManager={
<ServiceUsersDG
users={manager}
users={managerData?.users.length ? managerData.users : []}
page={page.managerPage}
setPage={(managerPage) =>
setPage((pages) => ({ ...pages, managerPage }))
}
pagesCount={managerPages}
pageSize={pageSize.managerPageSize}
handleSelectionChange={setSelectedTariffs}
onPageSizeChange={(managerPageSize) =>
setPageSize((pageSize) => ({ ...pageSize, managerPageSize }))
}
/>
}
childrenUser={
<ServiceUsersDG
users={users}
users={userData?.users.length ? userData.users : []}
page={page.userPage}
setPage={(userPage) =>
setPage((pages) => ({ ...pages, userPage }))
}
pagesCount={userPagesCount}
pageSize={pageSize.userPageSize}
handleSelectionChange={setSelectedTariffs}
onPageSizeChange={(userPageSize) =>
setPageSize((pageSize) => ({ ...pageSize, userPageSize }))
}
/>
}
/>

@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { Box, Typography, useTheme, useMediaQuery } from "@mui/material";
import { getUserInfo } from "@root/api/user";
import { userApi } from "@root/api/user/requests";
import { getAccountInfo } from "@root/api/account";
import type { UserType } from "@root/api/roles";
@ -19,7 +19,7 @@ export const UserTab = ({ userId }: UserTabProps) => {
useEffect(() => {
if (userId) {
getUserInfo(userId).then(([userInfo]) => setUser(userInfo));
userApi.getUserInfo(userId).then(([userInfo]) => setUser(userInfo));
getAccountInfo(userId).then(([accountsInfo]) => setAccount(accountsInfo));
}
}, []);