Files
WhiteNightsAdminPanel/src/pages/Station/StationListPage/index.tsx
2025-10-10 08:40:39 +03:00

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 {
languageStore,
stationsStore,
selectedCityStore,
cityStore,
} from "@shared";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
import { Eye, Pencil, Trash2, Minus } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
import { Box, CircularProgress } from "@mui/material";
export const StationListPage = observer(() => {
const { stationLists, getStationList, deleteStation } = stationsStore;
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 { language } = languageStore;
useEffect(() => {
const fetchStations = async () => {
setIsLoading(true);
await cityStore.getCities(language);
await getStationList();
setIsLoading(false);
};
fetchStations();
}, [language]);
const columns: GridColDef[] = [
{
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: "system_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: "direction",
headerName: "Направление",
width: 200,
align: "center",
headerAlign: "center",
renderCell: (params: GridRenderCellParams) => {
return (
<p
className={
params.row.direction === true ? "text-green-500" : "text-red-500"
}
>
{params.row.direction ? "Прямой" : "Обратный"}
</p>
);
},
},
{
field: "actions",
headerName: "Действия",
width: 140,
align: "center",
headerAlign: "center",
sortable: false,
renderCell: (params: GridRenderCellParams) => {
return (
<div className="flex h-full gap-7 justify-center items-center">
<button onClick={() => navigate(`/station/${params.row.id}/edit`)}>
<Pencil size={20} className="text-blue-500" />
</button>
<button onClick={() => navigate(`/station/${params.row.id}`)}>
<Eye size={20} className="text-green-500" />
</button>
<button
onClick={() => {
setIsDeleteModalOpen(true);
setRowId(params.row.id);
}}
>
<Trash2 size={20} className="text-red-500" />
</button>
</div>
);
},
},
];
// Фильтрация станций по выбранному городу
const filteredStations = () => {
const { selectedCityId } = selectedCityStore;
if (!selectedCityId) {
return stationLists[language].data;
}
return stationLists[language].data.filter(
(station: any) => station.city_id === selectedCityId
);
};
const rows = filteredStations().map((station: any) => ({
id: station.id,
name: station.name,
system_name: station.system_name,
direction: station.direction,
}));
return (
<>
<LanguageSwitcher />
<div className="w-full">
<div className="flex justify-between items-center mb-10">
<h1 className="text-2xl">Станции</h1>
<CreateButton label="Создать остановки" path="/station/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}
hideFooterPagination
checkboxSelection
loading={isLoading}
onRowSelectionModelChange={(newSelection) => {
setIds(Array.from(newSelection.ids) as number[]);
}}
hideFooter
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) {
deleteStation(rowId);
}
setIsDeleteModalOpen(false);
setRowId(null);
}}
onCancel={() => {
setIsDeleteModalOpen(false);
setRowId(null);
}}
/>
<DeleteModal
open={isBulkDeleteModalOpen}
onDelete={async () => {
await Promise.all(ids.map((id) => deleteStation(id)));
getStationList();
setIsBulkDeleteModalOpen(false);
setIds([]);
}}
onCancel={() => {
setIsBulkDeleteModalOpen(false);
}}
/>
</>
);
});