From e2e750877af99e1d4c0a8ed608069b54030c3a03 Mon Sep 17 00:00:00 2001 From: itoshi Date: Mon, 9 Jun 2025 18:48:25 +0300 Subject: [PATCH] feat: Add `checkbox for sightbar` entity + fix build errors --- src/pages/Carrier/CarrierCreatePage/index.tsx | 4 +- .../Carrier/CarrierPreviewPage/index.tsx | 2 +- src/pages/City/CityEditPage/index.tsx | 2 +- src/pages/CreateSightPage/index.tsx | 2 +- src/pages/MapPage/index.tsx | 223 ++++++++++++++---- src/pages/Media/MediaListPage/index.tsx | 2 +- src/pages/Route/RouteCreatePage/index.tsx | 3 - src/pages/Route/RouteListPage/index.tsx | 4 +- .../Route/route-preview/MapDataContext.tsx | 10 +- src/pages/Route/route-preview/Sight.tsx | 188 +++++++-------- src/pages/Route/route-preview/Station.tsx | 4 +- src/pages/Route/route-preview/index.tsx | 4 +- src/pages/Snapshot/SnapshotListPage/index.tsx | 2 +- src/pages/Station/StationEditPage/index.tsx | 6 +- src/pages/User/UserEditPage/index.tsx | 2 +- src/pages/Vehicle/VehicleCreatePage/index.tsx | 2 +- src/pages/Vehicle/VehicleEditPage/index.tsx | 2 +- src/shared/config/constants.tsx | 3 - src/shared/store/CarrierStore/index.tsx | 2 +- src/shared/store/CityStore/fd.tsx | 73 ------ src/shared/store/StationsStore/index.ts | 21 +- src/shared/store/VehicleStore/index.ts | 2 +- src/widgets/DevicesTable/index.tsx | 2 +- src/widgets/SightsTable/index.tsx | 4 +- tsconfig.tsbuildinfo | 2 +- 25 files changed, 302 insertions(+), 269 deletions(-) delete mode 100644 src/shared/store/CityStore/fd.tsx diff --git a/src/pages/Carrier/CarrierCreatePage/index.tsx b/src/pages/Carrier/CarrierCreatePage/index.tsx index 98fbfcf..33569ec 100644 --- a/src/pages/Carrier/CarrierCreatePage/index.tsx +++ b/src/pages/Carrier/CarrierCreatePage/index.tsx @@ -6,7 +6,6 @@ import { MenuItem, FormControl, InputLabel, - Box, } from "@mui/material"; import { observer } from "mobx-react-lite"; import { ArrowLeft, Save } from "lucide-react"; @@ -15,8 +14,7 @@ import { useNavigate } from "react-router-dom"; import { toast } from "react-toastify"; import { carrierStore, cityStore, mediaStore } from "@shared"; import { useState, useEffect } from "react"; -import { LanguageSwitcher, MediaViewer } from "@widgets"; -import { HexColorPicker } from "react-colorful"; +import { MediaViewer } from "@widgets"; export const CarrierCreatePage = observer(() => { const navigate = useNavigate(); diff --git a/src/pages/Carrier/CarrierPreviewPage/index.tsx b/src/pages/Carrier/CarrierPreviewPage/index.tsx index f3df3c9..ac5814f 100644 --- a/src/pages/Carrier/CarrierPreviewPage/index.tsx +++ b/src/pages/Carrier/CarrierPreviewPage/index.tsx @@ -1,5 +1,5 @@ import { Paper } from "@mui/material"; -import { carrierStore, languageStore, mediaStore } from "@shared"; +import { carrierStore, mediaStore } from "@shared"; import { MediaViewer } from "@widgets"; import { observer } from "mobx-react-lite"; import { ArrowLeft } from "lucide-react"; diff --git a/src/pages/City/CityEditPage/index.tsx b/src/pages/City/CityEditPage/index.tsx index 2f066ec..c8e5757 100644 --- a/src/pages/City/CityEditPage/index.tsx +++ b/src/pages/City/CityEditPage/index.tsx @@ -32,7 +32,7 @@ export const CityEditPage = observer(() => { const { id } = useParams(); const { editCityData, editCity, getCity, setEditCityData } = cityStore; const { getCountries } = countryStore; - const { getMedia, getOneMedia, oneMedia } = mediaStore; + const { getMedia, getOneMedia } = mediaStore; const handleEdit = async () => { try { diff --git a/src/pages/CreateSightPage/index.tsx b/src/pages/CreateSightPage/index.tsx index 96cdeea..0820d96 100644 --- a/src/pages/CreateSightPage/index.tsx +++ b/src/pages/CreateSightPage/index.tsx @@ -40,7 +40,7 @@ export const CreateSightPage = observer(() => { useEffect(() => { const fetchData = async () => { - await getCities(); + await getCities("ru"); await getArticles(languageStore.language); }; fetchData(); diff --git a/src/pages/MapPage/index.tsx b/src/pages/MapPage/index.tsx index 005e0d9..11d5bfc 100644 --- a/src/pages/MapPage/index.tsx +++ b/src/pages/MapPage/index.tsx @@ -13,7 +13,6 @@ import VectorLayer from "ol/layer/Vector"; import VectorSource, { VectorSourceEvent } from "ol/source/Vector"; import { Draw, Modify, Select } from "ol/interaction"; import { DrawEvent } from "ol/interaction/Draw"; -import { ModifyEvent } from "ol/interaction/Modify"; import { SelectEvent } from "ol/interaction/Select"; import { Style, @@ -34,7 +33,6 @@ import { Landmark, Pencil, Save, - Plus, Loader2, } from "lucide-react"; import { toast } from "react-toastify"; @@ -382,7 +380,8 @@ class MapService { this.modifyInteraction = new Modify({ source: this.vectorSource, - style: (feature) => { + // @ts-ignore + style: (feature: FeatureLike) => { const originalFeature = feature.get("features")[0]; if ( originalFeature && @@ -475,7 +474,7 @@ class MapService { ); }); - this.modifyInteraction.on("modifyend", (event: ModifyEvent) => { + this.modifyInteraction.on("modifyend", () => { if (this.beforeModifyState) { this.addStateToHistory("modify-before", this.beforeModifyState); this.beforeModifyState = null; @@ -976,7 +975,54 @@ class MapService { } } - // --- ИСПРАВЛЕННЫЙ МЕТОД --- + // --- НОВОЕ --- + // Метод для множественного удаления объектов по их ID + public deleteMultipleFeatures(featureIds: (string | number)[]): void { + if (!featureIds || featureIds.length === 0) return; + + // Вывод в консоль по требованию + console.log("Запрос на множественное удаление. ID объектов:", featureIds); + + const currentState = this.getCurrentStateAsGeoJSON(); + if (currentState) { + this.addStateToHistory("multiple delete", currentState); + } + + const selectedFeaturesCollection = this.selectInteraction?.getFeatures(); + let deletedCount = 0; + + featureIds.forEach((id) => { + const feature = this.vectorSource.getFeatureById(id); + if (feature) { + // Удаление из "бэкенда"/стора для каждого объекта + const recourse = String(id).split("-")[0]; + const numericId = String(id).split("-")[1]; + if (recourse && numericId) { + mapStore.deleteRecourse(recourse, Number(numericId)); + } + + // Если удаляемый объект выбран для редактирования, убираем его из выделения + if (selectedFeaturesCollection?.getArray().includes(feature)) { + selectedFeaturesCollection.remove(feature); + } + + // Удаляем объект с карты + this.vectorSource.removeFeature(feature); + deletedCount++; + } + }); + + if (deletedCount > 0) { + // Если основное выделение стало пустым, оповещаем React + if (selectedFeaturesCollection?.getLength() === 0) { + this.onFeatureSelect(null); + } + toast.success(`Удалено ${deletedCount} объект(ов).`); + } else { + toast.warn("Не найдено объектов для удаления."); + } + } + public getAllFeaturesAsGeoJSON(): string | null { if (!this.vectorSource || !this.map) return null; const feats = this.vectorSource.getFeatures(); @@ -984,11 +1030,9 @@ class MapService { const geoJSONFmt = new GeoJSON(); - // Просто передаем опции трансформации в метод writeFeatures. - // Он сам всё сделает правильно, не трогая оригинальные объекты. return geoJSONFmt.writeFeatures(feats, { - dataProjection: "EPSG:4326", // В какую проекцию конвертировать (стандарт для GeoJSON) - featureProjection: this.map.getView().getProjection(), // В какой проекции находятся объекты на карте + dataProjection: "EPSG:4326", + featureProjection: this.map.getView().getProjection(), }); } @@ -1111,6 +1155,11 @@ const MapSightbar: React.FC = ({ const [activeSection, setActiveSection] = useState("layers"); const navigate = useNavigate(); const [isLoading, setIsLoading] = useState(false); + // --- НОВОЕ --- + // Состояние для хранения ID объектов, выбранных для удаления + const [selectedForDeletion, setSelectedForDeletion] = useState< + Set + >(new Set()); const toggleSection = (id: string) => setActiveSection(activeSection === id ? null : id); @@ -1135,6 +1184,40 @@ const MapSightbar: React.FC = ({ [mapService] ); + // --- НОВОЕ --- + // Обработчик изменения состояния чекбокса + const handleCheckboxChange = useCallback( + (id: string | number | undefined) => { + if (id === undefined) return; + setSelectedForDeletion((prev) => { + const newSet = new Set(prev); + if (newSet.has(id)) { + newSet.delete(id); + } else { + newSet.add(id); + } + return newSet; + }); + }, + [] + ); + + // --- НОВОЕ --- + // Обработчик для запуска множественного удаления + const handleBulkDelete = useCallback(() => { + if (!mapService || selectedForDeletion.size === 0) return; + + if ( + window.confirm( + `Вы уверены, что хотите удалить ${selectedForDeletion.size} объект(ов)? Это действие нельзя отменить.` + ) + ) { + const idsToDelete = Array.from(selectedForDeletion); + mapService.deleteMultipleFeatures(idsToDelete); + setSelectedForDeletion(new Set()); // Очищаем выбор после удаления + } + }, [mapService, selectedForDeletion]); + const handleEditFeature = useCallback( (featureType: string | undefined, fullId: string | number | undefined) => { if (!featureType || !fullId) return; @@ -1191,18 +1274,35 @@ const MapSightbar: React.FC = ({ const sId = s.getId(); const sName = (s.get("name") as string) || "Без названия"; const isSelected = selectedFeature?.getId() === sId; + // --- ИЗМЕНЕНИЕ --- + const isCheckedForDeletion = + sId !== undefined && selectedForDeletion.has(sId); return (
handleFeatureClick(sId)} > -
+ {/* --- НОВОЕ: Чекбокс для множественного выбора --- */} +
+ handleCheckboxChange(sId)} + onClick={(e) => e.stopPropagation()} + aria-label={`Выбрать ${sName} для удаления`} + /> +
+ +
handleFeatureClick(sId)} + >
= ({ const lId = l.getId(); const lName = (l.get("name") as string) || "Без названия"; const isSelected = selectedFeature?.getId() === lId; + const isCheckedForDeletion = + lId !== undefined && selectedForDeletion.has(lId); const lGeom = l.getGeometry(); let lineLengthText: string | null = null; if (lGeom instanceof LineString) { @@ -1276,14 +1378,26 @@ const MapSightbar: React.FC = ({ return (
handleFeatureClick(lId)} > -
+
+ handleCheckboxChange(lId)} + onClick={(e) => e.stopPropagation()} + aria-label={`Выбрать ${lName} для удаления`} + /> +
+
handleFeatureClick(lId)} + >
= ({ const sId = s.getId(); const sName = (s.get("name") as string) || "Без названия"; const isSelected = selectedFeature?.getId() === sId; + const isCheckedForDeletion = + sId !== undefined && selectedForDeletion.has(sId); return (
handleFeatureClick(sId)} > -
+
+ handleCheckboxChange(sId)} + onClick={(e) => e.stopPropagation()} + aria-label={`Выбрать ${sName} для удаления`} + /> +
+
handleFeatureClick(sId)} + > = ({ } return ( + // --- ИЗМЕНЕНИЕ: Реструктуризация для футера с кнопками ---

Панель управления

-
-
+
+
{sections.map((s) => (
= ({
- )} - + +
); }; @@ -1502,9 +1643,8 @@ export const MapPage: React.FC = () => { const tooltipRef = useRef(null); const [mapServiceInstance, setMapServiceInstance] = useState(null); - // --- ИЗМЕНЕНИЕ: Разделение состояния загрузки --- - const [isMapLoading, setIsMapLoading] = useState(true); // Для рендеринга карты - const [isDataLoading, setIsDataLoading] = useState(true); // Для загрузки данных с API + const [isMapLoading, setIsMapLoading] = useState(true); + const [isDataLoading, setIsDataLoading] = useState(true); const [error, setError] = useState(null); const [currentMapMode, setCurrentMapMode] = useState("edit"); const [mapFeatures, setMapFeatures] = useState[]>([]); @@ -1525,12 +1665,10 @@ export const MapPage: React.FC = () => { useEffect(() => { let service: MapService | null = null; if (mapRef.current && tooltipRef.current && !mapServiceInstance) { - // Изначально оба процесса загрузки активны setIsMapLoading(true); setIsDataLoading(true); setError(null); - // --- ИЗМЕНЕНИЕ: Логика загрузки данных вынесена и управляет своим состоянием --- const loadInitialData = async (mapService: MapService) => { console.log("Starting data load..."); try { @@ -1548,7 +1686,6 @@ export const MapPage: React.FC = () => { console.error("Failed to load initial map data:", e); setError("Не удалось загрузить данные для карты."); } finally { - // Завершаем состояние загрузки данных независимо от результата setIsDataLoading(false); } }; @@ -1556,7 +1693,7 @@ export const MapPage: React.FC = () => { try { service = new MapService( { ...mapConfig, target: mapRef.current }, - setIsMapLoading, // MapService теперь управляет только состоянием загрузки карты + setIsMapLoading, setError, setCurrentMapMode, handleFeaturesChange, @@ -1565,7 +1702,6 @@ export const MapPage: React.FC = () => { ); setMapServiceInstance(service); - // Запускаем загрузку данных loadInitialData(service); } catch (e: any) { console.error("MapPage useEffect error:", e); @@ -1574,7 +1710,6 @@ export const MapPage: React.FC = () => { e.message || "Неизвестная ошибка" }. Пожалуйста, проверьте консоль.` ); - // В случае критической ошибки инициализации, завершаем все загрузки setIsMapLoading(false); setIsDataLoading(false); } @@ -1607,7 +1742,6 @@ export const MapPage: React.FC = () => { pointerEvents: "none", }} >
- {/* --- ИЗМЕНЕНИЕ: Обновленный лоадер --- */} {showLoader && (
@@ -1629,7 +1763,6 @@ export const MapPage: React.FC = () => {
)}
- {/* --- ИЗМЕНЕНИЕ: Условие для отображения контента --- */} {showContent && ( { const { media, getMedia, deleteMedia } = mediaStore; diff --git a/src/pages/Route/RouteCreatePage/index.tsx b/src/pages/Route/RouteCreatePage/index.tsx index 2bca4e2..b77ed92 100644 --- a/src/pages/Route/RouteCreatePage/index.tsx +++ b/src/pages/Route/RouteCreatePage/index.tsx @@ -80,9 +80,6 @@ export const RouteCreatePage = observer(() => { path, }; - // Отправка на сервер (пример, если есть routeStore.createRoute) - let createdRoute: Route | null = null; - await routeStore.createRoute(newRoute); toast.success("Маршрут успешно создан"); navigate(-1); diff --git a/src/pages/Route/RouteListPage/index.tsx b/src/pages/Route/RouteListPage/index.tsx index dab1c0a..c0f4e2c 100644 --- a/src/pages/Route/RouteListPage/index.tsx +++ b/src/pages/Route/RouteListPage/index.tsx @@ -2,9 +2,9 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { languageStore, routeStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { Eye, Map, Pencil, Trash2 } from "lucide-react"; +import { Map, Pencil, Trash2 } from "lucide-react"; import { useNavigate } from "react-router-dom"; -import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets"; +import { CreateButton, DeleteModal } from "@widgets"; export const RouteListPage = observer(() => { const { routes, getRoutes, deleteRoute } = routeStore; diff --git a/src/pages/Route/route-preview/MapDataContext.tsx b/src/pages/Route/route-preview/MapDataContext.tsx index dacb7ff..b0b1012 100644 --- a/src/pages/Route/route-preview/MapDataContext.tsx +++ b/src/pages/Route/route-preview/MapDataContext.tsx @@ -171,20 +171,14 @@ export const MapDataProvider = observer( async function saveStationChanges() { for (const station of stationChanges) { - const response = await authInstance.patch( - `/route/${routeId}/station`, - station - ); + await authInstance.patch(`/route/${routeId}/station`, station); } } async function saveSightChanges() { console.log("sightChanges", sightChanges); for (const sight of sightChanges) { - const response = await authInstance.patch( - `/route/${routeId}/sight`, - sight - ); + await authInstance.patch(`/route/${routeId}/sight`, sight); } } diff --git a/src/pages/Route/route-preview/Sight.tsx b/src/pages/Route/route-preview/Sight.tsx index 039ecfa..f857a76 100644 --- a/src/pages/Route/route-preview/Sight.tsx +++ b/src/pages/Route/route-preview/Sight.tsx @@ -2,118 +2,106 @@ import { useEffect, useState } from "react"; import { useTransform } from "./TransformContext"; import { SightData } from "./types"; import { Assets, FederatedMouseEvent, Graphics, Texture } from "pixi.js"; -import { COLORS } from "../../contexts/color-mode/theme"; + import { SIGHT_SIZE, UP_SCALE } from "./Constants"; import { coordinatesToLocal, localToCoordinates } from "./utils"; import { useMapData } from "./MapDataContext"; interface SightProps { - sight: SightData; - id: number; + sight: SightData; + id: number; } -export function Sight({ - sight, id -}: Readonly) { - const { rotation, scale } = useTransform(); - const { setSightCoordinates } = useMapData(); +export function Sight({ sight, id }: Readonly) { + const { rotation, scale } = useTransform(); + const { setSightCoordinates } = useMapData(); - const [position, setPosition] = useState(coordinatesToLocal(sight.latitude, sight.longitude)); - const [isDragging, setIsDragging] = useState(false); - const [startPosition, setStartPosition] = useState({ x: 0, y: 0 }); - const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 }); + const [position, setPosition] = useState( + coordinatesToLocal(sight.latitude, sight.longitude) + ); + const [isDragging, setIsDragging] = useState(false); + const [startPosition, setStartPosition] = useState({ x: 0, y: 0 }); + const [startMousePosition, setStartMousePosition] = useState({ x: 0, y: 0 }); - const handlePointerDown = (e: FederatedMouseEvent) => { - setIsDragging(true); - setStartPosition({ - x: position.x, - y: position.y - }); - setStartMousePosition({ - x: e.globalX, - y: e.globalY - }); - - e.stopPropagation(); - }; - const handlePointerMove = (e: FederatedMouseEvent) => { - if (!isDragging) return; - const dx = (e.globalX - startMousePosition.x) / scale / UP_SCALE; - const dy = (e.globalY - startMousePosition.y) / scale / UP_SCALE; - const cos = Math.cos(rotation); - const sin = Math.sin(rotation); - const newPosition = { - x: startPosition.x + dx * cos + dy * sin, - y: startPosition.y - dx * sin + dy * cos - }; - setPosition(newPosition); - const coordinates = localToCoordinates(newPosition.x, newPosition.y); - setSightCoordinates(sight.id, coordinates.latitude, coordinates.longitude); - e.stopPropagation(); + const handlePointerDown = (e: FederatedMouseEvent) => { + setIsDragging(true); + setStartPosition({ + x: position.x, + y: position.y, + }); + setStartMousePosition({ + x: e.globalX, + y: e.globalY, + }); + + e.stopPropagation(); + }; + const handlePointerMove = (e: FederatedMouseEvent) => { + if (!isDragging) return; + const dx = (e.globalX - startMousePosition.x) / scale / UP_SCALE; + const dy = (e.globalY - startMousePosition.y) / scale / UP_SCALE; + const cos = Math.cos(rotation); + const sin = Math.sin(rotation); + const newPosition = { + x: startPosition.x + dx * cos + dy * sin, + y: startPosition.y - dx * sin + dy * cos, }; + setPosition(newPosition); + const coordinates = localToCoordinates(newPosition.x, newPosition.y); + setSightCoordinates(sight.id, coordinates.latitude, coordinates.longitude); + e.stopPropagation(); + }; - const handlePointerUp = (e: FederatedMouseEvent) => { - setIsDragging(false); - e.stopPropagation(); - }; + const handlePointerUp = (e: FederatedMouseEvent) => { + setIsDragging(false); + e.stopPropagation(); + }; - const [texture, setTexture] = useState(Texture.EMPTY); - useEffect(() => { - if (texture === Texture.EMPTY) { - Assets - .load('/SightIcon.png') - .then((result) => { - setTexture(result) - }); - } - }, [texture]); + const [texture, setTexture] = useState(Texture.EMPTY); + useEffect(() => { + if (texture === Texture.EMPTY) { + Assets.load("/SightIcon.png").then((result) => { + setTexture(result); + }); + } + }, [texture]); - function draw(g: Graphics) { - g.clear(); - g.circle(0, 0, 20); - g.fill({color: COLORS.primary}); // Fill circle with primary color - } + function draw(g: Graphics) { + g.clear(); + g.circle(0, 0, 20); + g.fill({ color: "#000" }); // Fill circle with primary color + } - if(!sight) { - console.error("sight is null"); - return null; - } + if (!sight) { + console.error("sight is null"); + return null; + } - const coordinates = coordinatesToLocal(sight.latitude, sight.longitude); - - return ( - - - - - - ); -} \ No newline at end of file + return ( + + + + + + ); +} diff --git a/src/pages/Route/route-preview/Station.tsx b/src/pages/Route/route-preview/Station.tsx index fbdea11..b738be2 100644 --- a/src/pages/Route/route-preview/Station.tsx +++ b/src/pages/Route/route-preview/Station.tsx @@ -7,12 +7,11 @@ import { UP_SCALE, } from "./Constants"; import { useTransform } from "./TransformContext"; -import { useCallback, useEffect, useRef, useState } from "react"; +import { useCallback, useState } from "react"; import { StationData } from "./types"; import { useMapData } from "./MapDataContext"; import { coordinatesToLocal } from "./utils"; import { observer } from "mobx-react-lite"; -import { languageStore } from "@shared"; interface StationProps { station: StationData; @@ -47,7 +46,6 @@ export const Station = observer( export const StationLabel = observer( ({ station, ruLabel }: Readonly) => { - const { language } = languageStore; const { rotation, scale } = useTransform(); const { setStationOffset } = useMapData(); diff --git a/src/pages/Route/route-preview/index.tsx b/src/pages/Route/route-preview/index.tsx index 68a2771..00a537f 100644 --- a/src/pages/Route/route-preview/index.tsx +++ b/src/pages/Route/route-preview/index.tsx @@ -1,6 +1,6 @@ import { useRef, useEffect, useState } from "react"; -import { Application, ApplicationRef, extend } from "@pixi/react"; +import { Application, extend } from "@pixi/react"; import { Container, Graphics, @@ -13,7 +13,7 @@ import { Stack } from "@mui/material"; import { MapDataProvider, useMapData } from "./MapDataContext"; import { TransformProvider, useTransform } from "./TransformContext"; import { InfiniteCanvas } from "./InfiniteCanvas"; -import { Sight } from "./Sight"; + import { UP_SCALE } from "./Constants"; import { Station } from "./Station"; import { TravelPath } from "./TravelPath"; diff --git a/src/pages/Snapshot/SnapshotListPage/index.tsx b/src/pages/Snapshot/SnapshotListPage/index.tsx index aaf44b7..a1ca189 100644 --- a/src/pages/Snapshot/SnapshotListPage/index.tsx +++ b/src/pages/Snapshot/SnapshotListPage/index.tsx @@ -2,7 +2,7 @@ import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid"; import { languageStore, snapshotStore } from "@shared"; import { useEffect, useState } from "react"; import { observer } from "mobx-react-lite"; -import { DatabaseBackup, Eye, Trash2 } from "lucide-react"; +import { DatabaseBackup, Trash2 } from "lucide-react"; import { CreateButton, DeleteModal, SnapshotRestore } from "@widgets"; diff --git a/src/pages/Station/StationEditPage/index.tsx b/src/pages/Station/StationEditPage/index.tsx index 8cdd5ed..9028429 100644 --- a/src/pages/Station/StationEditPage/index.tsx +++ b/src/pages/Station/StationEditPage/index.tsx @@ -6,17 +6,15 @@ import { MenuItem, FormControl, InputLabel, - Box, } from "@mui/material"; import { observer } from "mobx-react-lite"; -import { ArrowLeft, Save, ImagePlus } from "lucide-react"; +import { ArrowLeft, Save } from "lucide-react"; import { Loader2 } from "lucide-react"; import { useNavigate, useParams } from "react-router-dom"; import { toast } from "react-toastify"; import { stationsStore, languageStore, cityStore } from "@shared"; import { useEffect, useState } from "react"; -import { LanguageSwitcher, MediaViewer } from "@widgets"; -import { SelectMediaDialog } from "@shared"; +import { LanguageSwitcher } from "@widgets"; export const StationEditPage = observer(() => { const navigate = useNavigate(); diff --git a/src/pages/User/UserEditPage/index.tsx b/src/pages/User/UserEditPage/index.tsx index 69516b6..a7c8f3c 100644 --- a/src/pages/User/UserEditPage/index.tsx +++ b/src/pages/User/UserEditPage/index.tsx @@ -17,7 +17,7 @@ export const UserEditPage = observer(() => { const navigate = useNavigate(); const [isLoading, setIsLoading] = useState(false); const { id } = useParams(); - const { editUserData, editUser, getUser, setEditUserData, user } = userStore; + const { editUserData, editUser, getUser, setEditUserData } = userStore; const handleEdit = async () => { try { diff --git a/src/pages/Vehicle/VehicleCreatePage/index.tsx b/src/pages/Vehicle/VehicleCreatePage/index.tsx index 658f555..579ac9f 100644 --- a/src/pages/Vehicle/VehicleCreatePage/index.tsx +++ b/src/pages/Vehicle/VehicleCreatePage/index.tsx @@ -31,7 +31,7 @@ export const VehicleCreatePage = observer(() => { setIsLoading(true); await vehicleStore.createVehicle( Number(tailNumber), - type, + Number(type), carrierStore.carriers.data.find((c) => c.id === carrierId)?.full_name!, carrierId! ); diff --git a/src/pages/Vehicle/VehicleEditPage/index.tsx b/src/pages/Vehicle/VehicleEditPage/index.tsx index e543e83..ca26973 100644 --- a/src/pages/Vehicle/VehicleEditPage/index.tsx +++ b/src/pages/Vehicle/VehicleEditPage/index.tsx @@ -108,7 +108,7 @@ export const VehicleEditPage = observer(() => { }) } > - {carrierStore.carriers.map((carrier) => ( + {carrierStore.carriers.data.map((carrier) => ( {carrier.full_name} diff --git a/src/shared/config/constants.tsx b/src/shared/config/constants.tsx index a72099d..e92abb6 100644 --- a/src/shared/config/constants.tsx +++ b/src/shared/config/constants.tsx @@ -8,11 +8,8 @@ import { Earth, Landmark, BusFront, - Bus, GitBranch, Car, - Train, - Ship, Table, Split, Newspaper, diff --git a/src/shared/store/CarrierStore/index.tsx b/src/shared/store/CarrierStore/index.tsx index 6fe5120..5131af4 100644 --- a/src/shared/store/CarrierStore/index.tsx +++ b/src/shared/store/CarrierStore/index.tsx @@ -1,4 +1,4 @@ -import { authInstance, languageStore } from "@shared"; +import { authInstance } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type Carrier = { diff --git a/src/shared/store/CityStore/fd.tsx b/src/shared/store/CityStore/fd.tsx deleted file mode 100644 index 17cf51f..0000000 --- a/src/shared/store/CityStore/fd.tsx +++ /dev/null @@ -1,73 +0,0 @@ -import { authInstance, languageInstance } from "@shared"; -import { makeAutoObservable, runInAction } from "mobx"; - -type City = { - id: number; - name: string; - country_code: string; - country: string; - arms?: string; -}; - -class CityStore { - cities: City[] = []; - ruCities: City[] = []; - city: City | null = null; - - constructor() { - makeAutoObservable(this); - } - - getCities = async () => { - const response = await authInstance.get("/city"); - - runInAction(() => { - this.cities = response.data; - }); - }; - - getRuCities = async () => { - const response = await languageInstance("ru").get("/city"); - - runInAction(() => { - this.ruCities = response.data; - }); - }; - - deleteCity = async (id: number) => { - await authInstance.delete(`/city/${id}`); - - runInAction(() => { - this.cities = this.cities.filter((city) => city.id !== id); - }); - }; - - getCity = async (id: string) => { - const response = await authInstance.get(`/city/${id}`); - - runInAction(() => { - this.city = response.data; - }); - - return response.data; - }; - - createCity = async ( - name: string, - country: string, - countryCode: string, - mediaId: string - ) => { - const response = await authInstance.post("/city", { - name: name, - country: country, - country_code: countryCode, - arms: mediaId, - }); - runInAction(() => { - this.cities.push(response.data); - }); - }; -} - -// export const cityStore = new CityStore(); diff --git a/src/shared/store/StationsStore/index.ts b/src/shared/store/StationsStore/index.ts index 9b0463d..956c1ed 100644 --- a/src/shared/store/StationsStore/index.ts +++ b/src/shared/store/StationsStore/index.ts @@ -256,14 +256,17 @@ class StationsStore { // Update the cached preview data and station lists after successful patch if (this.stationPreview[id]) { this.stationPreview[id][language] = { - ...this.stationPreview[id][language], // Preserve common fields that might not be in the language-specific patch response - id: response.data.id, - name: response.data.name, - system_name: response.data.system_name, - description: response.data.description, - address: response.data.address, - ...commonDataPayload, - } as Station; // Cast to Station to satisfy type + loaded: true, + data: { + ...this.stationPreview[id][language].data, + id: response.data.id, + name: response.data.name, + system_name: response.data.system_name, + description: response.data.description, + address: response.data.address, + ...commonDataPayload, + } as Station, + }; } if (this.stationLists[language].data) { this.stationLists[language].data = this.stationLists[ @@ -327,8 +330,8 @@ class StationsStore { }; } this.stationPreview[id][language] = { - data: response.data, loaded: true, + data: response.data as Station, }; }); }; diff --git a/src/shared/store/VehicleStore/index.ts b/src/shared/store/VehicleStore/index.ts index abbb0c3..014c2dd 100644 --- a/src/shared/store/VehicleStore/index.ts +++ b/src/shared/store/VehicleStore/index.ts @@ -1,4 +1,4 @@ -import { authInstance, languageStore, languageInstance } from "@shared"; +import { languageInstance } from "@shared"; import { makeAutoObservable, runInAction } from "mobx"; export type Vehicle = { diff --git a/src/widgets/DevicesTable/index.tsx b/src/widgets/DevicesTable/index.tsx index 242991e..8388dcd 100644 --- a/src/widgets/DevicesTable/index.tsx +++ b/src/widgets/DevicesTable/index.tsx @@ -121,7 +121,7 @@ export const DevicesTable = observer(() => { // Transform the raw devices data into rows suitable for the table // This will also filter out devices without a UUID, as those cannot be acted upon. const currentTableRows = transformDevicesToRows( - vehicles as Vehicle[] + vehicles.data as Vehicle[] // devices as ConnectedDevice[] ); diff --git a/src/widgets/SightsTable/index.tsx b/src/widgets/SightsTable/index.tsx index 27798ea..16e05ca 100644 --- a/src/widgets/SightsTable/index.tsx +++ b/src/widgets/SightsTable/index.tsx @@ -35,7 +35,7 @@ export const SightsTable = observer(() => { useEffect(() => { const fetchData = async () => { await getSights(); - await getCities(); + await getCities(language); }; fetchData(); }, [language, getSights, getCities]); @@ -67,7 +67,7 @@ export const SightsTable = observer(() => { - {rows(sights, cities)?.map((row) => ( + {rows(sights, cities[language])?.map((row) => (