Files
WhiteNightsAdminPanel/src/pages/User/UserListPage/index.tsx

211 lines
6.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
import { ruRU } from "@mui/x-data-grid/locales";
import { userStore } from "@shared";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
import { Pencil, Trash2, Minus } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { CreateButton, DeleteModal } from "@widgets";
import { Box, CircularProgress } from "@mui/material";
export const UserListPage = observer(() => {
const { users, getUsers, deleteUser } = userStore;
const navigate = useNavigate();
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isBulkDeleteModalOpen, setIsBulkDeleteModalOpen] = useState(false);
const [rowId, setRowId] = useState<number | null>(null);
const [ids, setIds] = useState<number[]>([]);
const [isLoading, setIsLoading] = useState(false);
const [paginationModel, setPaginationModel] = useState({
page: 0,
pageSize: 50,
});
useEffect(() => {
const fetchUsers = async () => {
setIsLoading(true);
await getUsers();
setIsLoading(false);
};
fetchUsers();
}, []);
const columns: GridColDef[] = [
{
field: "name",
headerName: "Имя",
width: 400,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="w-full h-full flex items-center">
{params.value ? (
params.value
) : (
<Minus size={20} className="text-red-500" />
)}
</div>
);
},
},
{
field: "email",
headerName: "Email",
width: 400,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="w-full h-full flex items-center">
{params.value ? (
params.value
) : (
<Minus size={20} className="text-red-500" />
)}
</div>
);
},
},
{
field: "is_admin",
headerName: "Роль",
flex: 1,
renderCell: (params: GridRenderCellParams) => {
return (
<p
className={
params.row.is_admin === true ? "text-green-500" : "text-red-500"
}
>
{params.row.is_admin ? "Администратор" : "Пользователь"}
</p>
);
},
},
{
field: "actions",
headerName: "Действия",
flex: 1,
align: "center",
headerAlign: "center",
sortable: false,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="flex h-full gap-7 justify-center items-center">
<button>
<Pencil
size={20}
className="text-blue-500"
onClick={() => {
navigate(`/user/${params.row.id}/edit`);
}}
/>
</button>
<button
onClick={() => {
setIsDeleteModalOpen(true);
setRowId(params.row.id);
}}
>
<Trash2 size={20} className="text-red-500" />
</button>
</div>
);
},
},
];
const rows = users.data?.map((user) => ({
id: user.id,
email: user.email,
is_admin: user.is_admin,
name: user.name,
}));
return (
<>
<div className="w-full">
<div className="flex justify-between items-center mb-10">
<h1 className="text-2xl">Пользователи</h1>
<CreateButton label="Создать пользователя" path="/user/create" />
</div>
{ids.length > 0 && (
<div className="flex justify-end mb-5 duration-300">
<button
className="px-4 py-2 bg-red-500 text-white rounded flex gap-2 items-center"
onClick={() => setIsBulkDeleteModalOpen(true)}
>
<Trash2 size={20} className="text-white" /> Удалить выбранные (
{ids.length})
</button>
</div>
)}
<DataGrid
rows={rows}
columns={columns}
checkboxSelection
disableRowSelectionExcludeModel
loading={isLoading}
paginationModel={paginationModel}
onPaginationModelChange={setPaginationModel}
pageSizeOptions={[50]}
onRowSelectionModelChange={(newSelection: any) => {
if (Array.isArray(newSelection)) {
const selectedIds = newSelection.map((id: string | number) => Number(id));
setIds(selectedIds);
} else if (newSelection && typeof newSelection === 'object' && 'ids' in newSelection) {
const idsSet = newSelection.ids as Set<string | number>;
const selectedIds = Array.from(idsSet).map((id: string | number) => Number(id));
setIds(selectedIds);
} else {
setIds([]);
}
}}
localeText={ruRU.components.MuiDataGrid.defaultProps.localeText}
slots={{
noRowsOverlay: () => (
<Box sx={{ mt: 5, textAlign: "center", color: "text.secondary" }}>
{isLoading ? (
<CircularProgress size={20} />
) : (
"Нет пользователей"
)}
</Box>
),
}}
/>
</div>
<DeleteModal
open={isDeleteModalOpen}
onDelete={async () => {
if (rowId) {
await deleteUser(rowId);
}
setIsDeleteModalOpen(false);
setRowId(null);
}}
onCancel={() => {
setIsDeleteModalOpen(false);
setRowId(null);
}}
/>
<DeleteModal
open={isBulkDeleteModalOpen}
onDelete={async () => {
await Promise.all(ids.map((id) => deleteUser(id)));
getUsers();
setIsBulkDeleteModalOpen(false);
setIds([]);
}}
onCancel={() => {
setIsBulkDeleteModalOpen(false);
}}
/>
</>
);
});