Files
WhiteNightsAdminPanel/src/pages/City/CityListPage/index.tsx

196 lines
6.0 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 { languageStore, cityStore, countryStore } 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, LanguageSwitcher } from "@widgets";
import { toast } from "react-toastify";
import { Box, CircularProgress } from "@mui/material";
export const CityListPage = observer(() => {
const { cities, getCities, deleteCity } = cityStore;
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 [rows, setRows] = useState<any[]>([]);
const { language } = languageStore;
useEffect(() => {
const fetchData = async () => {
setIsLoading(true);
await countryStore.getCountries("ru");
await countryStore.getCountries("en");
await countryStore.getCountries("zh");
await getCities(language);
setIsLoading(false);
};
fetchData();
}, [language]);
useEffect(() => {
let newRows = cities[language]?.data?.map((city) => ({
id: city.id,
name: city.name,
country: city.country_code,
}));
let newRows2: any[] = [];
for (const city of newRows) {
const name = countryStore.countries[language]?.data?.find(
(country) => country.code === city.country
)?.name;
if (name) {
newRows2.push(city);
}
}
setRows(newRows2 || []);
console.log(newRows2);
}, [cities, countryStore.countries, language, isLoading]);
const columns: GridColDef[] = [
{
field: "country",
headerName: "Страна",
width: 150,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="w-full h-full flex items-center">
{params.value ? (
countryStore.countries[language]?.data?.find(
(country) => country.code === params.value
)?.name
) : (
<Minus size={20} className="text-red-500" />
)}
</div>
);
},
},
{
field: "name",
headerName: "Название",
flex: 1,
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: "actions",
headerName: "Действия",
align: "center",
headerAlign: "center",
width: 200,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="flex h-full gap-7 justify-center items-center">
<button onClick={() => navigate(`/city/${params.row.id}/edit`)}>
<Pencil size={20} className="text-blue-500" />
</button>
{/* <button onClick={() => navigate(`/city/${params.row.id}`)}>
<Eye size={20} className="text-green-500" />
</button> */}
<button
onClick={(e) => {
e.stopPropagation();
setIsDeleteModalOpen(true);
setRowId(params.row.id);
}}
>
<Trash2 size={20} className="text-red-500" />
</button>
</div>
);
},
},
];
return (
<>
<LanguageSwitcher />
<div className="w-full">
<div className="flex justify-between items-center mb-10">
<h1 className="text-2xl">Города</h1>
<CreateButton label="Создать город" path="/city/create" />
</div>
<div
className="flex justify-end mb-5 duration-300"
style={{ opacity: ids.length > 0 ? 1 : 0 }}
>
<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}
hideFooter
checkboxSelection
loading={isLoading}
localeText={ruRU.components.MuiDataGrid.defaultProps.localeText}
onRowSelectionModelChange={(newSelection) => {
setIds(Array.from(newSelection.ids as unknown as number[]));
}}
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 deleteCity(rowId.toString());
toast.success("Город успешно удален");
}
setIsDeleteModalOpen(false);
setRowId(null);
}}
onCancel={() => {
setIsDeleteModalOpen(false);
setRowId(null);
}}
/>
<DeleteModal
open={isBulkDeleteModalOpen}
onDelete={async () => {
await Promise.all(ids.map((id) => deleteCity(id.toString())));
toast.success("Города успешно удалены");
getCities(language);
setIsBulkDeleteModalOpen(false);
setIds([]);
}}
onCancel={() => {
setIsBulkDeleteModalOpen(false);
}}
/>
</>
);
});