From 1d2601189eaae07e43024f815ba6f2f7220fdd8c Mon Sep 17 00:00:00 2001 From: SangLv Date: Thu, 3 Aug 2023 14:18:30 +0700 Subject: [PATCH] add params sort and filter --- frontend/src/api/users/UsersApiDTO.ts | 3 + frontend/src/pages/AccountManager/index.tsx | 109 ++++++++++++++++++-- 2 files changed, 102 insertions(+), 10 deletions(-) diff --git a/frontend/src/api/users/UsersApiDTO.ts b/frontend/src/api/users/UsersApiDTO.ts index 8b6c1a981..4a82ca0b4 100644 --- a/frontend/src/api/users/UsersApiDTO.ts +++ b/frontend/src/api/users/UsersApiDTO.ts @@ -15,6 +15,9 @@ export type AddUserDTO = { } export type ListUsersQueryDTO = { + name?: string + email?: string + sort?: string[] offset?: number limit?: number } diff --git a/frontend/src/pages/AccountManager/index.tsx b/frontend/src/pages/AccountManager/index.tsx index a9faa0504..060cc31f2 100644 --- a/frontend/src/pages/AccountManager/index.tsx +++ b/frontend/src/pages/AccountManager/index.tsx @@ -1,6 +1,6 @@ import EditIcon from "@mui/icons-material/Edit"; import DeleteIcon from "@mui/icons-material/Delete"; -import {ChangeEvent, useEffect, useMemo} from "react"; +import {ChangeEvent, useCallback, useEffect, useMemo} from "react"; import {Box, Button, Pagination, styled} from "@mui/material"; import {useDispatch, useSelector} from "react-redux"; import {selectCurrentUser, selectListUser, selectLoading} from "../../store/slice/User/UserSelector"; @@ -10,6 +10,7 @@ import { DataGridPro } from "@mui/x-data-grid-pro"; import Loading from "../../components/common/Loading"; import {UserDTO} from "../../api/users/UsersApiDTO"; import {ROLE} from "../../@types"; +import {GridFilterModel, GridSortDirection, GridSortModel} from "@mui/x-data-grid"; const AccountManager = () => { @@ -20,8 +21,24 @@ const AccountManager = () => { const user = useSelector(selectCurrentUser) const [searchParams, setParams] = useSearchParams() - const limit = searchParams.get('limit') || undefined - const offset = searchParams.get('offset') || undefined + const limit = searchParams.get('limit') || 50 + const offset = searchParams.get('offset') || 0 + const name = searchParams.get('name') || undefined + const email = searchParams.get('email') || undefined + const sort = searchParams.getAll('sort') || [] + + const sortParams = useMemo(() => { + return { + sort: sort + } + }, [JSON.stringify(sort)]) + + const filterParams = useMemo(() => { + return { + name: name, + email: email + } + }, [name, email]) const params = useMemo(() => { return { @@ -31,7 +48,7 @@ const AccountManager = () => { }, [limit, offset]) useEffect(() => { - dispatch(getListUser(params)) + dispatch(getListUser({...filterParams, ...sortParams, ...params})) //eslint-disable-next-line }, [params]) @@ -40,26 +57,70 @@ const AccountManager = () => { setParams(`limit=${listUser.limit}&offset=${page - 1}`) } + const getParamsData = () => { + const dataFilter = Object.keys(filterParams) + .filter((key) => (filterParams as any)[key]) + .map((key) => `${key}=${(filterParams as any)[key]}`) + .join('&') + return dataFilter + } + + const paramsManager = useCallback( + (page?: number) => { + return `limit=${limit}&offset=${ + page ? page - 1 : offset + }` + }, + [limit, offset], + ) + + const handleSort = useCallback( + (rowSelectionModel: GridSortModel) => { + const filter = getParamsData() + if (!rowSelectionModel[0]) { + setParams(`${filter}&sort=&sort=&${paramsManager()}`) + return + } + setParams( + `${filter}&sort=${rowSelectionModel[0].field}&sort=${rowSelectionModel[0].sort}&${paramsManager()}`, + ) + }, + //eslint-disable-next-line + [paramsManager, getParamsData], + ) + + const handleFilter = (model: GridFilterModel) => { + let filter = '' + if (!!model.items[0]?.value) { + filter = model.items + .filter((item) => item.value) + .map((item: any) => { + return `${item.field}=${item?.value}` + }) + .join('&') + } + const { sort } = sortParams + setParams( + `${filter}&sort=${sort[0] || ''}&sort=${sort[1] || ''}&${paramsManager()}`, + ) + } + const columns = useMemo(() => [ { headerName: 'UID', field: 'uid', - sortable: false, filterable: false, minWidth: 350 }, { headerName: 'Name', field: 'name', - sortable: false, - filterable: false, minWidth: 200 }, { headerName: 'Role', field: 'role_id', - sortable: false, filterable: false, minWidth: 200, renderCell: (params: {value: number}) => { @@ -86,8 +147,6 @@ const AccountManager = () => { { headerName: 'Mail', field: 'email', - sortable: false, - filterable: false, minWidth: 350 }, { @@ -128,7 +187,37 @@ const AccountManager = () => { sx={{ minHeight: 400, height: 'calc(100vh - 250px)'}} columns={columns as any} rows={listUser?.items || []} + filterMode={'server'} + sortingMode={'server'} hideFooter + onSortModelChange={handleSort} + initialState={{ + sorting: { + sortModel: [ + { + field: sortParams.sort[0], + sort: sortParams.sort[1] as GridSortDirection, + }, + ], + }, + filter: { + filterModel: { + items: [ + { + field: 'name', + operator: 'contains', + value: filterParams.name, + }, + { + field: 'email', + operator: 'contains', + value: filterParams.email, + } + ], + }, + }, + }} + onFilterModelChange={handleFilter as any} />