import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { ruRU } from "@mui/x-data-grid/locales"; import { authStore, languageStore, stationsStore, selectedCityStore, SearchInput, } from "@shared"; import { useEffect, useState, useMemo } from "react"; import { observer } from "mobx-react-lite"; import { Pencil, Trash2, Minus, Route, Check, X } from "lucide-react"; import { useNavigate } from "react-router-dom"; import { CreateButton, DeleteModal, LanguageSwitcher, EditStationTransfersModal, } from "@widgets"; import { Box, CircularProgress, Tooltip } from "@mui/material"; export const StationListPage = observer(() => { const { stationLists, getStationList, deleteStation, sightCounts, sightCountsLoading, loadSightCounts } = stationsStore; const navigate = useNavigate(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [isBulkDeleteModalOpen, setIsBulkDeleteModalOpen] = useState(false); const [isTransfersModalOpen, setIsTransfersModalOpen] = useState(false); const [rowId, setRowId] = useState(null); const [selectedStationId, setSelectedStationId] = useState( null ); const [ids, setIds] = useState([]); const [isLoading, setIsLoading] = useState(false); const [paginationModel, setPaginationModel] = useState({ page: 0, pageSize: 50, }); const { language } = languageStore; const canWriteStations = authStore.canWrite("stations"); const [searchQuery, setSearchQuery] = useState(""); useEffect(() => { const fetchStations = async () => { setIsLoading(true); await getStationList(); setIsLoading(false); const stationIds = stationLists[language].data.map((s: any) => s.id); loadSightCounts(stationIds); }; fetchStations(); }, [language]); const columns: GridColDef[] = [ { field: "name", headerName: "Название", flex: 1, renderCell: (params: GridRenderCellParams) => { return (
{params.value ? ( params.value ) : ( )}
); }, }, { field: "description", headerName: "Описание", flex: 1, renderCell: (params: GridRenderCellParams) => { return (
{params.value ? ( params.value ) : ( )}
); }, }, { field: "sightCount", headerName: "Достопримечательности", width: 180, align: "center" as const, headerAlign: "center" as const, sortable: true, renderHeader: (params) => ( {params.colDef.headerName} ), renderCell: (params: GridRenderCellParams) => (
{params.value === null ? ( ) : ( params.value )}
), }, { field: "hasTransfers", headerName: "Пересадки", width: 120, align: "center" as const, headerAlign: "center" as const, sortable: true, renderHeader: (params) => ( {params.colDef.headerName} ), renderCell: (params: GridRenderCellParams) => ( {params.value ? ( ) : ( )} ), }, { field: "actions", headerName: "Действия", width: 200, align: "center" as const, headerAlign: "center" as const, sortable: false, renderCell: (params: GridRenderCellParams) => { return (
{canWriteStations && ( )} {canWriteStations && ( )} {canWriteStations && ( )}
); }, }, ]; const rows = useMemo(() => { const { selectedCityId } = selectedCityStore; const query = searchQuery.trim().toLowerCase(); return stationLists[language].data .filter((station: any) => !selectedCityId || station.city_id === selectedCityId) .filter( (station: any) => !query || (station.name ?? "").toLowerCase().includes(query) || (station.description ?? "").toLowerCase().includes(query) ) .map((station: any) => ({ id: station.id, name: station.name, description: station.description, sightCount: sightCounts.has(station.id) ? sightCounts.get(station.id) : null, hasTransfers: station.transfers ? Object.values(station.transfers).some((v: any) => v != null && v !== "") : false, })); }, [stationLists[language].data, selectedCityStore.selectedCityId, searchQuery, sightCounts.size, sightCountsLoading]); return ( <>

Остановки

{canWriteStations && ( )}
{canWriteStations && ids.length > 0 && (
)} canWriteStations && navigate(`/station/${params.row.id}/edit`)} checkboxSelection={canWriteStations} disableRowSelectionExcludeModel disableRowSelectionOnClick loading={isLoading} paginationModel={paginationModel} onPaginationModelChange={setPaginationModel} pageSizeOptions={[50]} onRowSelectionModelChange={ canWriteStations ? (newSelection: any) => { if (Array.isArray(newSelection)) { const selectedIds = newSelection .map((id: string | number) => { const numId = typeof id === "string" ? Number.parseInt(id, 10) : Number(id); return numId; }) .filter( (id: number) => !Number.isNaN(id) && id !== null && id !== undefined ); setIds(selectedIds); } else if ( newSelection && typeof newSelection === "object" && "ids" in newSelection ) { const idsSet = newSelection.ids as Set; const selectedIds = Array.from(idsSet) .map((id: string | number) => { const numId = typeof id === "string" ? Number.parseInt(id, 10) : Number(id); return numId; }) .filter( (id: number) => !Number.isNaN(id) && id !== null && id !== undefined ); setIds(selectedIds); } else { setIds([]); } } : undefined } localeText={ruRU.components.MuiDataGrid.defaultProps.localeText} slots={{ noRowsOverlay: () => ( {isLoading ? : "Нет остановок"} ), }} />
{ if (rowId) { deleteStation(rowId); } setIsDeleteModalOpen(false); setRowId(null); }} onCancel={() => { setIsDeleteModalOpen(false); setRowId(null); }} /> { await Promise.all(ids.map((id) => deleteStation(id))); getStationList(); setIsBulkDeleteModalOpen(false); setIds([]); }} onCancel={() => { setIsBulkDeleteModalOpen(false); }} /> { setIsTransfersModalOpen(false); setSelectedStationId(null); }} stationId={selectedStationId} /> ); });