diff --git a/src/app/router/index.tsx b/src/app/router/index.tsx
index 5167e3f..f850029 100644
--- a/src/app/router/index.tsx
+++ b/src/app/router/index.tsx
@@ -39,6 +39,7 @@ import {
RouteCreatePage,
RoutePreview,
RouteEditPage,
+ ArticlePreviewPage,
} from "@pages";
import { authStore, createSightStore, editSightStore } from "@shared";
import { Layout } from "@widgets";
@@ -170,7 +171,7 @@ const router = createBrowserRouter([
// { path: "vehicle/:id/edit", element: },
// Article
{ path: "article", element: },
- // { path: "article/:id", element: },
+ { path: "article/:id", element: },
// { path: "media/create", element: },
],
},
diff --git a/src/pages/Article/ArticleCreatePage/index.tsx b/src/pages/Article/ArticleCreatePage/index.tsx
index 89dde3c..36c54b6 100644
--- a/src/pages/Article/ArticleCreatePage/index.tsx
+++ b/src/pages/Article/ArticleCreatePage/index.tsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React from "react";
import { useNavigate } from "react-router-dom";
import { ArrowLeft } from "lucide-react";
import { LanguageSwitcher } from "@widgets";
diff --git a/src/pages/Article/ArticleEditPage/index.tsx b/src/pages/Article/ArticleEditPage/index.tsx
index 2ab1749..b33980d 100644
--- a/src/pages/Article/ArticleEditPage/index.tsx
+++ b/src/pages/Article/ArticleEditPage/index.tsx
@@ -1,14 +1,14 @@
-import React, { useEffect, useState } from "react";
+import React, { useEffect } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { ArrowLeft } from "lucide-react";
import { LanguageSwitcher } from "@widgets";
-import { articlesStore, languageStore } from "@shared";
+import { articlesStore } from "@shared";
import { observer } from "mobx-react-lite";
const ArticleEditPage: React.FC = observer(() => {
const navigate = useNavigate();
const { id } = useParams();
- const { language } = languageStore;
+
const { articleData, getArticle } = articlesStore;
useEffect(() => {
diff --git a/src/pages/Article/ArticlePreviewPage/PreviewLeftWidget.tsx b/src/pages/Article/ArticlePreviewPage/PreviewLeftWidget.tsx
new file mode 100644
index 0000000..a2c9147
--- /dev/null
+++ b/src/pages/Article/ArticlePreviewPage/PreviewLeftWidget.tsx
@@ -0,0 +1,85 @@
+import { Paper, Box, Typography } from "@mui/material";
+import { MediaViewer, ReactMarkdownComponent } from "@widgets";
+import { articlesStore, languageStore } from "@shared";
+import { observer } from "mobx-react-lite";
+
+export const PreviewLeftWidget = observer(() => {
+ const { articleMedia, articleData } = articlesStore;
+ const { language } = languageStore;
+
+ return (
+
+
+ {articleMedia && }
+
+
+
+ {articleData?.[language]?.heading || "Название информации"}
+
+
+ {articleData?.[language]?.body && (
+
+
+
+ )}
+
+ );
+});
diff --git a/src/pages/Article/ArticlePreviewPage/PreviewRightWidget.tsx b/src/pages/Article/ArticlePreviewPage/PreviewRightWidget.tsx
new file mode 100644
index 0000000..33403e0
--- /dev/null
+++ b/src/pages/Article/ArticlePreviewPage/PreviewRightWidget.tsx
@@ -0,0 +1,139 @@
+import { Paper, Box, Typography } from "@mui/material";
+import { MediaViewer, ReactMarkdownComponent } from "@widgets";
+import { articlesStore, languageStore } from "@shared";
+import { observer } from "mobx-react-lite";
+import { ImagePlus } from "lucide-react";
+
+export const PreviewRightWidget = observer(() => {
+ const { articleData, articleMedia } = articlesStore;
+ const { language } = languageStore;
+ const article = articleData?.[language];
+ if (!article) return null;
+
+ return (
+
+
+ {articleMedia ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+ {article.heading || "Выберите статью"}
+
+
+
+
+ {article.body ? (
+
+ ) : (
+
+ Предпросмотр статьи появится здесь
+
+ )}
+
+
+ {/* @ts-ignore */}
+ {articleData?.right && articleData?.right.length > 1 && (
+
+ {/* @ts-ignore */}
+ {articleData.right.map((a, idx) => (
+
+ ))}
+
+ )}
+
+
+ );
+});
diff --git a/src/pages/Article/ArticlePreviewPage/index.tsx b/src/pages/Article/ArticlePreviewPage/index.tsx
new file mode 100644
index 0000000..bce26ed
--- /dev/null
+++ b/src/pages/Article/ArticlePreviewPage/index.tsx
@@ -0,0 +1,57 @@
+import { useNavigate, useParams } from "react-router-dom";
+import { useEffect } from "react";
+import { Box } from "@mui/material";
+import { PreviewLeftWidget } from "./PreviewLeftWidget";
+import { PreviewRightWidget } from "./PreviewRightWidget";
+import { articlesStore, languageStore } from "@shared";
+import { ArrowLeft } from "lucide-react";
+
+export const ArticlePreviewPage = () => {
+ const navigate = useNavigate();
+ const { id } = useParams();
+ const { getArticle, getArticleMedia, getArticlePreview } = articlesStore;
+ const { language } = languageStore;
+
+ useEffect(() => {
+ const fetchData = async () => {
+ if (id) {
+ await getArticle(Number(id), language);
+ await getArticleMedia(Number(id));
+ await getArticlePreview(Number(id));
+ }
+ };
+ fetchData();
+ }, [id, language]);
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
diff --git a/src/pages/Article/index.ts b/src/pages/Article/index.ts
index b9a8432..5354497 100644
--- a/src/pages/Article/index.ts
+++ b/src/pages/Article/index.ts
@@ -1 +1,2 @@
export * from "./ArticleListPage";
+export * from "./ArticlePreviewPage";
diff --git a/src/pages/Carrier/CarrierCreatePage/index.tsx b/src/pages/Carrier/CarrierCreatePage/index.tsx
index 93ae0c1..3f0d758 100644
--- a/src/pages/Carrier/CarrierCreatePage/index.tsx
+++ b/src/pages/Carrier/CarrierCreatePage/index.tsx
@@ -12,9 +12,9 @@ import { ArrowLeft, Save } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
-import { carrierStore, cityStore, mediaStore, languageStore } from "@shared";
+import { carrierStore, cityStore, mediaStore } from "@shared";
import { useState, useEffect } from "react";
-import { MediaViewer, ImageUploadCard, LanguageSwitcher } from "@widgets";
+import { ImageUploadCard, LanguageSwitcher } from "@widgets";
import {
SelectMediaDialog,
UploadMediaDialog,
@@ -23,7 +23,7 @@ import {
export const CarrierCreatePage = observer(() => {
const navigate = useNavigate();
- const { language } = languageStore;
+
const [fullName, setFullName] = useState("");
const [shortName, setShortName] = useState("");
const [cityId, setCityId] = useState(null);
diff --git a/src/pages/Carrier/CarrierEditPage/index.tsx b/src/pages/Carrier/CarrierEditPage/index.tsx
index eb40c2e..d7c200b 100644
--- a/src/pages/Carrier/CarrierEditPage/index.tsx
+++ b/src/pages/Carrier/CarrierEditPage/index.tsx
@@ -12,9 +12,9 @@ import { ArrowLeft, Save } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
-import { carrierStore, cityStore, mediaStore } from "@shared";
+import { carrierStore, cityStore, mediaStore, languageStore } from "@shared";
import { useState, useEffect } from "react";
-import { MediaViewer, ImageUploadCard } from "@widgets";
+import { ImageUploadCard, LanguageSwitcher } from "@widgets";
import {
SelectMediaDialog,
UploadMediaDialog,
@@ -24,8 +24,8 @@ import {
export const CarrierEditPage = observer(() => {
const navigate = useNavigate();
const { id } = useParams();
- const { carrier, getCarrier, setEditCarrierData, editCarrierData } =
- carrierStore;
+ const { getCarrier, setEditCarrierData, editCarrierData } = carrierStore;
+ const { language } = languageStore;
const [isLoading, setIsLoading] = useState(false);
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
@@ -41,16 +41,34 @@ export const CarrierEditPage = observer(() => {
await cityStore.getCities("ru");
await cityStore.getCities("en");
await cityStore.getCities("zh");
- await getCarrier(Number(id));
+ const carrierData = await getCarrier(Number(id));
- setEditCarrierData(
- carrier?.[Number(id)]?.full_name as string,
- carrier?.[Number(id)]?.short_name as string,
-
- carrier?.[Number(id)]?.city_id as number,
- carrier?.[Number(id)]?.slogan as string,
- carrier?.[Number(id)]?.logo as string
- );
+ if (carrierData) {
+ setEditCarrierData(
+ carrierData.ru?.full_name || "",
+ carrierData.ru?.short_name || "",
+ carrierData.ru?.city_id || 0,
+ carrierData.ru?.slogan || "",
+ carrierData.ru?.logo || "",
+ "ru"
+ );
+ setEditCarrierData(
+ carrierData.en?.full_name || "",
+ carrierData.en?.short_name || "",
+ carrierData.en?.city_id || 0,
+ carrierData.en?.slogan || "",
+ carrierData.en?.logo || "",
+ "en"
+ );
+ setEditCarrierData(
+ carrierData.zh?.full_name || "",
+ carrierData.zh?.short_name || "",
+ carrierData.zh?.city_id || 0,
+ carrierData.zh?.slogan || "",
+ carrierData.zh?.logo || "",
+ "zh"
+ );
+ }
mediaStore.getMedia();
})();
@@ -76,12 +94,12 @@ export const CarrierEditPage = observer(() => {
media_type: number;
}) => {
setEditCarrierData(
- editCarrierData.full_name,
- editCarrierData.short_name,
-
+ editCarrierData[language].full_name,
+ editCarrierData[language].short_name,
editCarrierData.city_id,
- editCarrierData.slogan,
- media.id
+ editCarrierData[language].slogan,
+ media.id,
+ language
);
};
@@ -91,6 +109,7 @@ export const CarrierEditPage = observer(() => {
return (
+
+
+
{editCarrierData.ru.full_name}
+
Город
@@ -110,15 +132,16 @@ export const CarrierEditPage = observer(() => {
required
onChange={(e) =>
setEditCarrierData(
- editCarrierData.full_name,
- editCarrierData.short_name,
+ editCarrierData[language].full_name,
+ editCarrierData[language].short_name,
Number(e.target.value),
- editCarrierData.slogan,
- editCarrierData.logo
+ editCarrierData[language].slogan,
+ editCarrierData.logo,
+ language
)
}
>
- {cityStore.cities.ru.data?.map((city) => (
+ {cityStore.cities[language].data?.map((city) => (
@@ -129,16 +152,16 @@ export const CarrierEditPage = observer(() => {
setEditCarrierData(
e.target.value,
- editCarrierData.short_name,
-
+ editCarrierData[language].short_name,
editCarrierData.city_id,
- editCarrierData.slogan,
- editCarrierData.logo
+ editCarrierData[language].slogan,
+ editCarrierData.logo,
+ language
)
}
/>
@@ -146,16 +169,16 @@ export const CarrierEditPage = observer(() => {
setEditCarrierData(
- editCarrierData.full_name,
+ editCarrierData[language].full_name,
e.target.value,
-
editCarrierData.city_id,
- editCarrierData.slogan,
- editCarrierData.logo
+ editCarrierData[language].slogan,
+ editCarrierData.logo,
+ language
)
}
/>
@@ -163,15 +186,15 @@ export const CarrierEditPage = observer(() => {
setEditCarrierData(
- editCarrierData.full_name,
- editCarrierData.short_name,
-
+ editCarrierData[language].full_name,
+ editCarrierData[language].short_name,
editCarrierData.city_id,
e.target.value,
- editCarrierData.logo
+ editCarrierData.logo,
+ language
)
}
/>
@@ -187,12 +210,12 @@ export const CarrierEditPage = observer(() => {
}}
onDeleteImageClick={() => {
setEditCarrierData(
- editCarrierData.full_name,
- editCarrierData.short_name,
-
+ editCarrierData[language].full_name,
+ editCarrierData[language].short_name,
editCarrierData.city_id,
- editCarrierData.slogan,
- ""
+ editCarrierData[language].slogan,
+ "",
+ language
);
setActiveMenuType(null);
}}
@@ -214,8 +237,8 @@ export const CarrierEditPage = observer(() => {
onClick={handleEdit}
disabled={
isLoading ||
- !editCarrierData.full_name ||
- !editCarrierData.short_name ||
+ !editCarrierData[language].full_name ||
+ !editCarrierData[language].short_name ||
!editCarrierData.city_id ||
!editCarrierData.logo
}
diff --git a/src/pages/Carrier/CarrierListPage/index.tsx b/src/pages/Carrier/CarrierListPage/index.tsx
index e2a93ad..7494e17 100644
--- a/src/pages/Carrier/CarrierListPage/index.tsx
+++ b/src/pages/Carrier/CarrierListPage/index.tsx
@@ -1,10 +1,10 @@
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
-import { carrierStore } from "@shared";
+import { carrierStore, languageStore } from "@shared";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
-import { Eye, Pencil, Trash2, Minus } from "lucide-react";
+import { Pencil, Trash2, Minus } from "lucide-react";
import { useNavigate } from "react-router-dom";
-import { CreateButton, DeleteModal } from "@widgets";
+import { CreateButton, DeleteModal, LanguageSwitcher } from "@widgets";
export const CarrierListPage = observer(() => {
const { carriers, getCarriers, deleteCarrier } = carrierStore;
@@ -13,10 +13,13 @@ export const CarrierListPage = observer(() => {
const [isBulkDeleteModalOpen, setIsBulkDeleteModalOpen] = useState(false);
const [rowId, setRowId] = useState(null);
const [ids, setIds] = useState([]);
+ const { language } = languageStore;
useEffect(() => {
- getCarriers();
- }, []);
+ (async () => {
+ await getCarriers(language);
+ })();
+ }, [language]);
const columns: GridColDef[] = [
{
@@ -96,7 +99,7 @@ export const CarrierListPage = observer(() => {
},
];
- const rows = carriers.data?.map((carrier) => ({
+ const rows = carriers[language].data?.map((carrier) => ({
id: carrier.id,
full_name: carrier.full_name,
short_name: carrier.short_name,
@@ -105,6 +108,7 @@ export const CarrierListPage = observer(() => {
return (
<>
+
Перевозчики
@@ -155,7 +159,7 @@ export const CarrierListPage = observer(() => {
open={isBulkDeleteModalOpen}
onDelete={async () => {
await Promise.all(ids.map((id) => deleteCarrier(id)));
- getCarriers();
+ await getCarriers(language);
setIsBulkDeleteModalOpen(false);
setIds([]);
}}
diff --git a/src/pages/Carrier/CarrierPreviewPage/index.tsx b/src/pages/Carrier/CarrierPreviewPage/index.tsx
deleted file mode 100644
index 82f98e9..0000000
--- a/src/pages/Carrier/CarrierPreviewPage/index.tsx
+++ /dev/null
@@ -1,116 +0,0 @@
-import { Paper } from "@mui/material";
-import { carrierStore, mediaStore } from "@shared";
-import { MediaViewer } from "@widgets";
-import { observer } from "mobx-react-lite";
-import { ArrowLeft } from "lucide-react";
-import { useEffect } from "react";
-import { useNavigate, useParams } from "react-router-dom";
-
-export const CarrierPreviewPage = observer(() => {
- const { id } = useParams();
- const { getCarrier, carrier, setEditCarrierData } = carrierStore;
- const { oneMedia, getOneMedia } = mediaStore;
- const navigate = useNavigate();
-
- useEffect(() => {
- (async () => {
- const carrierResponse = await getCarrier(Number(id));
- setEditCarrierData(
- carrierResponse?.full_name as string,
- carrierResponse?.short_name as string,
- carrierResponse?.city as string,
- carrierResponse?.city_id as number,
- // carrierResponse?.main_color as string,
- // carrierResponse?.left_color as string,
- // carrierResponse?.right_color as string,
- carrierResponse?.slogan as string,
- carrierResponse?.logo as string
- );
- console.log(carrierResponse);
- await getOneMedia(carrierResponse?.logo as string);
- })();
- }, [id]);
-
- return (
-
- {carrier && (
- <>
-
-
-
-
-
-
Полное имя
-
{carrier[Number(id)]?.full_name}
-
-
-
-
Полное имя
-
{carrier[Number(id)]?.full_name}
-
-
-
Город
-
{carrier[Number(id)]?.city}
-
- {/*
-
Основной цвет
-
- {carrier[Number(id)]?.main_color}
-
-
-
-
Цвет левого виджета
-
- {carrier[Number(id)]?.left_color}
-
-
-
-
Цвет правого виджета
-
- {carrier[Number(id)]?.right_color}
-
-
*/}
-
-
Краткое имя
-
{carrier[Number(id)]?.short_name}
-
- {oneMedia && (
-
-
Логотип
-
-
-
- )}
-
- >
- )}
-
- );
-});
diff --git a/src/pages/Carrier/index.ts b/src/pages/Carrier/index.ts
index f5ffa27..7bcfe37 100644
--- a/src/pages/Carrier/index.ts
+++ b/src/pages/Carrier/index.ts
@@ -1,4 +1,4 @@
export * from "./CarrierListPage";
-export * from "./CarrierPreviewPage";
+
export * from "./CarrierCreatePage";
export * from "./CarrierEditPage";
diff --git a/src/pages/City/CityCreatePage/index.tsx b/src/pages/City/CityCreatePage/index.tsx
index 45ccac5..64de3d7 100644
--- a/src/pages/City/CityCreatePage/index.tsx
+++ b/src/pages/City/CityCreatePage/index.tsx
@@ -6,16 +6,15 @@ import {
MenuItem,
FormControl,
InputLabel,
- Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
-import { ArrowLeft, Save, ImagePlus, Minus } from "lucide-react";
+import { ArrowLeft, Save, Minus } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate } from "react-router-dom";
import { toast } from "react-toastify";
import { cityStore, countryStore, languageStore, mediaStore } from "@shared";
import { useState, useEffect } from "react";
-import { LanguageSwitcher, MediaViewer, ImageUploadCard } from "@widgets";
+import { LanguageSwitcher, ImageUploadCard } from "@widgets";
import {
SelectMediaDialog,
UploadMediaDialog,
@@ -91,8 +90,8 @@ export const CityCreatePage = observer(() => {
-
-
Создание города
+
+
{createCityData.ru.name}
{
setEditCityData(zhData.name, zhData.country_code, zhData.arms, "zh");
await getOneMedia(ruData.arms as string);
- await getCountries(language);
+ await getCountries("ru");
await getMedia();
}
})();
@@ -108,7 +107,7 @@ export const CityEditPage = observer(() => {
-
+
{editCityData.ru.name}
{
);
}}
>
- {countryStore.countries[language].data.map((country) => (
+ {countryStore.countries.ru.data.map((country) => (
diff --git a/src/pages/City/CityListPage/index.tsx b/src/pages/City/CityListPage/index.tsx
index e6704b6..5fda47a 100644
--- a/src/pages/City/CityListPage/index.tsx
+++ b/src/pages/City/CityListPage/index.tsx
@@ -1,5 +1,5 @@
import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
-import { languageStore, cityStore, CashedCities } from "@shared";
+import { languageStore, cityStore } from "@shared";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
import { Eye, Pencil, Trash2, Minus } from "lucide-react";
diff --git a/src/pages/Country/CountryCreatePage/index.tsx b/src/pages/Country/CountryCreatePage/index.tsx
index d063bb3..4601465 100644
--- a/src/pages/Country/CountryCreatePage/index.tsx
+++ b/src/pages/Country/CountryCreatePage/index.tsx
@@ -41,8 +41,8 @@ export const CountryCreatePage = observer(() => {
-
-
Создание страны
+
+
{createCountryData.ru.name}
{
-
-
{editCountryData.ru.name}
+
+
{editCountryData.ru.name}
{
const [value, setValue] = useState(0);
const { sight, getSightInfo, needLeaveAgree } = editSightStore;
const { getArticles } = articlesStore;
- const { language } = languageStore;
+
const { id } = useParams();
const { getRuCities } = cityStore;
diff --git a/src/pages/MapPage/index.tsx b/src/pages/MapPage/index.tsx
index 3df771b..0640bed 100644
--- a/src/pages/MapPage/index.tsx
+++ b/src/pages/MapPage/index.tsx
@@ -3,7 +3,6 @@ import React, {
useRef,
useState,
useCallback,
- ReactNode,
useMemo,
} from "react";
import { useNavigate } from "react-router-dom";
@@ -33,7 +32,6 @@ import {
ArrowRightLeft,
Landmark,
Pencil,
- Lasso,
InfoIcon,
X,
Loader2,
@@ -86,9 +84,7 @@ class MapStore {
for (const id of routesIds) {
const route = await languageInstance("ru").get(`/route/${id}`);
this.routes.push({
- id: route.data.id,
- route_number: route.data.route_number,
- path: route.data.path,
+ ...route.data,
});
}
@@ -100,21 +96,14 @@ class MapStore {
getStations = async () => {
const stations = await languageInstance("ru").get("/station");
this.stations = stations.data.map((station: any) => ({
- id: station.id,
- name: station.name,
- latitude: station.latitude,
- longitude: station.longitude,
+ ...station,
}));
};
getSights = async () => {
const sights = await languageInstance("ru").get("/sight");
this.sights = sights.data.map((sight: any) => ({
- id: sight.id,
- name: sight.name,
- description: sight.description,
- latitude: sight.latitude,
- longitude: sight.longitude,
+ ...sight,
}));
};
@@ -194,9 +183,25 @@ class MapStore {
throw new Error(`Unknown feature type for update: ${featureType}`);
}
+ let oldData;
+ if (featureType === "route") {
+ oldData = this.routes.find((f) => f.id === numericId);
+ } else if (featureType === "station") {
+ oldData = this.stations.find((f) => f.id === numericId);
+ } else if (featureType === "sight") {
+ oldData = this.sights.find((f) => f.id === numericId);
+ }
+
+ console.log(oldData);
+ console.log(data);
+
const response = await languageInstance("ru").patch(
`/${featureType}/${numericId}`,
- data
+ {
+ ...oldData,
+ latitude: data.latitude,
+ longitude: data.longitude,
+ }
);
if (featureType === "route") {
@@ -277,6 +282,7 @@ class MapService {
private tooltipElement: HTMLElement;
private tooltipOverlay: Overlay | null;
private mode: string | null;
+ // @ts-ignore
private currentDrawingType: "Point" | "LineString" | null;
private currentDrawingFeatureType: FeatureType | null;
private currentInteraction: Draw | null;
@@ -620,7 +626,7 @@ class MapService {
filter: (_: FeatureLike, l: Layer | null) =>
l === this.vectorLayer,
});
-
+ // @ts-ignore
this.modifyInteraction.on("modifystart", (event) => {
const geoJSONFormat = new GeoJSON();
if (!this.map) return;
@@ -959,7 +965,8 @@ class MapService {
feature.set("name", `${baseName} ${maxNumber + 1}`);
await this.saveNewFeature(feature);
- this.stopDrawing();
+ // Убираем вызов stopDrawing, чтобы режим рисования оставался активным
+ // this.stopDrawing();
});
this.map.addInteraction(this.currentInteraction);
@@ -988,7 +995,8 @@ class MapService {
this.currentInteraction = null;
this.currentDrawingType = null;
this.currentDrawingFeatureType = null;
- this.activateEditMode();
+ // Убираем автоматическое переключение в режим редактирования
+ // this.activateEditMode();
}
public finishDrawing(): void {
@@ -1007,6 +1015,10 @@ class MapService {
this.currentInteraction instanceof Draw
) {
this.finishDrawing();
+ // После завершения рисования маршрута, останавливаем режим рисования
+ if (this.currentDrawingType === "LineString") {
+ this.stopDrawing();
+ }
}
}
@@ -1098,6 +1110,7 @@ class MapService {
if (this.mode === "edit") {
this.selectInteraction.getFeatures().clear();
this.selectInteraction.getFeatures().push(feature);
+ // @ts-ignore
const selectEvent = new SelectEvent("select", [feature], []);
this.selectInteraction.dispatchEvent(selectEvent);
}
@@ -1332,7 +1345,8 @@ class MapService {
feature.set("name", newName);
this.updateFeaturesInReact();
- this.selectFeature(newFeatureId);
+ // Убираем автоматический выбор созданного объекта
+ // this.selectFeature(newFeatureId);
} catch (error) {
console.error("Failed to save new feature:", error);
toast.error("Не удалось сохранить объект.");
@@ -1366,6 +1380,7 @@ interface ControlItem {
const MapControls: React.FC = ({
mapService,
activeMode,
+ // @ts-ignore
isLassoActive,
isUnselectDisabled,
}) => {
@@ -1473,11 +1488,13 @@ const MapSightbar: React.FC = ({
}, [mapFeatures, searchQuery]);
const handleFeatureClick = useCallback(
+ // @ts-ignore
(id) => mapService?.selectFeature(id),
[mapService]
);
const handleDeleteFeature = useCallback(
+ // @ts-ignore
(id, recourse) => {
if (
mapService &&
@@ -1490,6 +1507,7 @@ const MapSightbar: React.FC = ({
);
const handleCheckboxChange = useCallback(
+ // @ts-ignore
(id) => {
if (id === undefined) return;
const newSet = new Set(selectedIds);
@@ -1512,7 +1530,10 @@ const MapSightbar: React.FC = ({
}
}, [mapService, selectedIds, setSelectedIds]);
+ // @ts-ignore
+
const handleEditFeature = useCallback(
+ // @ts-ignore
(featureType, fullId) => {
if (!featureType || !fullId) return;
const numericId = String(fullId).split("-")[1];
@@ -1522,8 +1543,11 @@ const MapSightbar: React.FC = ({
);
const sortFeatures = (
+ // @ts-ignore
features,
+ // @ts-ignore
currentSelectedIds,
+ // @ts-ignore
currentSelectedFeature
) => {
const selectedId = currentSelectedFeature?.getId();
diff --git a/src/pages/Route/RouteCreatePage/index.tsx b/src/pages/Route/RouteCreatePage/index.tsx
index 6d8c599..9f4ce7a 100644
--- a/src/pages/Route/RouteCreatePage/index.tsx
+++ b/src/pages/Route/RouteCreatePage/index.tsx
@@ -6,7 +6,7 @@ import {
MenuItem,
FormControl,
InputLabel,
- Typography,
+ // Typography,
Box,
} from "@mui/material";
import { LanguageSwitcher } from "@widgets";
@@ -18,6 +18,7 @@ import { toast } from "react-toastify";
import { carrierStore } from "../../../shared/store/CarrierStore";
import { articlesStore } from "../../../shared/store/ArticlesStore";
import { Route, routeStore } from "../../../shared/store/RouteStore";
+import { languageStore } from "@shared";
export const RouteCreatePage = observer(() => {
const navigate = useNavigate();
@@ -33,11 +34,11 @@ export const RouteCreatePage = observer(() => {
const [centerLat, setCenterLat] = useState("");
const [centerLng, setCenterLng] = useState("");
const [isLoading, setIsLoading] = useState(false);
-
+ const { language } = languageStore;
useEffect(() => {
- carrierStore.getCarriers();
+ carrierStore.getCarriers(language);
articlesStore.getArticleList();
- }, []);
+ }, [language]);
const handleCreateRoute = async () => {
try {
@@ -65,8 +66,9 @@ export const RouteCreatePage = observer(() => {
// Собираем объект маршрута
const newRoute: Partial = {
carrier:
- carrierStore.carriers.data.find((c: any) => c.id === carrier_id)
- ?.full_name || "",
+ carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.find((c: any) => c.id === carrier_id)?.full_name || "",
carrier_id,
route_number: routeNumber,
route_sys_number: govRouteNumber,
@@ -112,16 +114,20 @@ export const RouteCreatePage = observer(() => {
value={carrier}
label="Выберите перевозчика"
onChange={(e) => setCarrier(e.target.value as string)}
- disabled={carrierStore.carriers.data.length === 0}
+ disabled={
+ carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.length === 0
+ }
>
- {carrierStore.carriers.data.map(
- (c: (typeof carrierStore.carriers.data)[number]) => (
-
- )
- )}
+ {carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.map((carrier) => (
+
+ ))}
{
const navigate = useNavigate();
const { id } = useParams();
const { editRouteData } = routeStore;
const [isLoading, setIsLoading] = useState(false);
-
+ const { language } = languageStore;
useEffect(() => {
const fetchData = async () => {
const response = await routeStore.getRoute(Number(id));
routeStore.setEditRouteData(response);
- carrierStore.getCarriers();
+ carrierStore.getCarriers(language);
articlesStore.getArticleList();
};
fetchData();
- }, [id]);
+ }, [id, language]);
const handleSave = async () => {
setIsLoading(true);
@@ -67,21 +68,26 @@ export const RouteEditPage = observer(() => {
routeStore.setEditRouteData({
carrier_id: Number(e.target.value),
carrier:
- carrierStore.carriers.data.find(
- (c) => c.id === Number(e.target.value)
- )?.full_name || "",
+ carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.find((c) => c.id === Number(e.target.value))
+ ?.full_name || "",
})
}
- disabled={carrierStore.carriers.data.length === 0}
+ disabled={
+ carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.length === 0
+ }
>
- {carrierStore.carriers.data.map(
- (c: (typeof carrierStore.carriers.data)[number]) => (
-
- )
- )}
+ {carrierStore.carriers[
+ language as keyof typeof carrierStore.carriers
+ ].data?.map((carrier) => (
+
+ ))}
{
-
-
Создание станции
+
+
{name}
{
const [type, setType] = useState("");
const [carrierId, setCarrierId] = useState(null);
const [isLoading, setIsLoading] = useState(false);
+ const { language } = languageStore;
useEffect(() => {
- carrierStore.getCarriers();
- }, []);
+ carrierStore.getCarriers(language);
+ }, [language]);
const handleCreate = async () => {
try {
@@ -32,7 +38,8 @@ export const VehicleCreatePage = observer(() => {
await vehicleStore.createVehicle(
Number(tailNumber),
Number(type),
- carrierStore.carriers.data.find((c) => c.id === carrierId)?.full_name!,
+ carrierStore.carriers[language].data?.find((c) => c.id === carrierId)
+ ?.full_name as string,
carrierId!
);
toast.success("Транспорт успешно создан");
@@ -88,7 +95,7 @@ export const VehicleCreatePage = observer(() => {
required
onChange={(e) => setCarrierId(e.target.value as number)}
>
- {carrierStore.carriers.data.map((carrier) => (
+ {carrierStore.carriers[language].data?.map((carrier) => (
diff --git a/src/pages/Vehicle/VehicleEditPage/index.tsx b/src/pages/Vehicle/VehicleEditPage/index.tsx
index ca26973..5e3858f 100644
--- a/src/pages/Vehicle/VehicleEditPage/index.tsx
+++ b/src/pages/Vehicle/VehicleEditPage/index.tsx
@@ -11,7 +11,12 @@ import { observer } from "mobx-react-lite";
import { ArrowLeft, Loader2, Save } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { useEffect, useState } from "react";
-import { carrierStore, VEHICLE_TYPES, vehicleStore } from "@shared";
+import {
+ carrierStore,
+ languageStore,
+ VEHICLE_TYPES,
+ vehicleStore,
+} from "@shared";
import { toast } from "react-toastify";
export const VehicleEditPage = observer(() => {
@@ -25,11 +30,12 @@ export const VehicleEditPage = observer(() => {
editVehicle,
} = vehicleStore;
const { getCarriers } = carrierStore;
-
+ const { language } = languageStore;
useEffect(() => {
(async () => {
await getVehicle(Number(id));
- await getCarriers();
+ await getCarriers(language);
+
setEditVehicleData({
tail_number: vehicle[Number(id)]?.vehicle.tail_number,
type: vehicle[Number(id)]?.vehicle.type,
@@ -37,7 +43,7 @@ export const VehicleEditPage = observer(() => {
carrier_id: vehicle[Number(id)]?.vehicle.carrier_id,
});
})();
- }, [id]);
+ }, [id, language]);
const [isLoading, setIsLoading] = useState(false);
const handleEdit = async () => {
try {
@@ -108,7 +114,7 @@ export const VehicleEditPage = observer(() => {
})
}
>
- {carrierStore.carriers.data.map((carrier) => (
+ {carrierStore.carriers[language].data?.map((carrier) => (
diff --git a/src/pages/Vehicle/VehicleListPage/index.tsx b/src/pages/Vehicle/VehicleListPage/index.tsx
index 1d56929..ecfd37c 100644
--- a/src/pages/Vehicle/VehicleListPage/index.tsx
+++ b/src/pages/Vehicle/VehicleListPage/index.tsx
@@ -19,7 +19,7 @@ export const VehicleListPage = observer(() => {
useEffect(() => {
getVehicles();
- getCarriers();
+ getCarriers(language);
}, [language]);
const columns: GridColDef[] = [
@@ -123,7 +123,7 @@ export const VehicleListPage = observer(() => {
tail_number: vehicle.vehicle.tail_number,
type: vehicle.vehicle.type,
carrier: vehicle.vehicle.carrier,
- city: carriers.data?.find(
+ city: carriers[language].data?.find(
(carrier) => carrier.id === vehicle.vehicle.carrier_id
)?.city,
}));
diff --git a/src/shared/config/constants.tsx b/src/shared/config/constants.tsx
index 938ba7c..f8c7909 100644
--- a/src/shared/config/constants.tsx
+++ b/src/shared/config/constants.tsx
@@ -8,7 +8,7 @@ import {
Earth,
Landmark,
GitBranch,
- Car,
+ // Car,
Table,
Notebook,
Split,
diff --git a/src/shared/store/CarrierStore/index.tsx b/src/shared/store/CarrierStore/index.tsx
index 982cb1c..a339811 100644
--- a/src/shared/store/CarrierStore/index.tsx
+++ b/src/shared/store/CarrierStore/index.tsx
@@ -1,4 +1,10 @@
-import { authInstance, cityStore, languageStore } from "@shared";
+import {
+ authInstance,
+ cityStore,
+ languageStore,
+ languageInstance,
+ Language,
+} from "@shared";
import { makeAutoObservable, runInAction } from "mobx";
export type Carrier = {
@@ -14,17 +20,40 @@ export type Carrier = {
// right_color: string;
};
-type Carriers = {
+type CarrierData = {
data: Carrier[];
loaded: boolean;
};
-type CashedCarrier = Record;
+type Carriers = {
+ ru: CarrierData;
+ en: CarrierData;
+ zh: CarrierData;
+};
+
+type CashedCarrier = Record<
+ number,
+ {
+ ru: Carrier | null;
+ en: Carrier | null;
+ zh: Carrier | null;
+ }
+>;
class CarrierStore {
carriers: Carriers = {
- data: [],
- loaded: false,
+ ru: {
+ data: [],
+ loaded: false,
+ },
+ en: {
+ data: [],
+ loaded: false,
+ },
+ zh: {
+ data: [],
+ loaded: false,
+ },
};
carrier: CashedCarrier = {};
@@ -32,14 +61,14 @@ class CarrierStore {
makeAutoObservable(this);
}
- getCarriers = async () => {
- if (this.carriers.loaded) return;
+ getCarriers = async (language: Language) => {
+ if (this.carriers[language as keyof Carriers].loaded) return;
const response = await authInstance.get("/carrier");
runInAction(() => {
- this.carriers.data = response.data;
- this.carriers.loaded = true;
+ this.carriers[language as keyof Carriers].data = response.data;
+ this.carriers[language as keyof Carriers].loaded = true;
});
};
@@ -47,116 +76,163 @@ class CarrierStore {
await authInstance.delete(`/carrier/${id}`);
runInAction(() => {
- this.carriers.data = this.carriers.data.filter(
- (carrier) => carrier.id !== id
- );
+ for (const language of ["ru", "en", "zh"] as const) {
+ this.carriers[language].data = this.carriers[language].data.filter(
+ (carrier: Carrier) => carrier.id !== id
+ );
+ }
delete this.carrier[id];
});
};
getCarrier = async (id: number) => {
- if (this.carrier[id]) return;
- const response = await authInstance.get(`/carrier/${id}`);
+ if (this.carrier[id]?.ru && this.carrier[id]?.en && this.carrier[id]?.zh)
+ return;
+
+ const ruResponse = await languageInstance("ru").get(`/carrier/${id}`);
+ const enResponse = await languageInstance("en").get(`/carrier/${id}`);
+ const zhResponse = await languageInstance("zh").get(`/carrier/${id}`);
runInAction(() => {
if (!this.carrier[id]) {
this.carrier[id] = {
- id: 0,
- short_name: "",
- full_name: "",
- slogan: "",
- city: "",
- city_id: 0,
- logo: "",
- // main_color: "",
- // left_color: "",
- // right_color: "",
+ ru: null,
+ en: null,
+ zh: null,
};
}
- this.carrier[id] = response.data;
+ this.carrier[id].ru = ruResponse.data;
+ this.carrier[id].en = enResponse.data;
+ this.carrier[id].zh = zhResponse.data;
});
- return response.data;
+ return this.carrier[id];
};
createCarrier = async (
fullName: string,
shortName: string,
-
cityId: number,
- // main_color: string,
- // left_color: string,
- // right_color: string,
slogan: string,
logoId: string
) => {
- const response = await authInstance.post("/carrier", {
+ const { language } = languageStore;
+ const cityName =
+ cityStore.cities[language].data.find((city) => city.id === cityId)
+ ?.name || "";
+
+ const response = await languageInstance(language).post("/carrier", {
full_name: fullName,
short_name: shortName,
- city: "",
+ city: cityName,
city_id: cityId,
- // main_color,
- // left_color,
- // right_color,
slogan,
logo: logoId,
});
+
+ const carrierId = response.data.id;
+
+ // Create translations for other languages
+ for (const lang of ["ru", "en", "zh"].filter((l) => l !== language)) {
+ await languageInstance(lang as Language).patch(`/carrier/${carrierId}`, {
+ full_name: fullName,
+ short_name: shortName,
+ city: cityName,
+ city_id: cityId,
+ slogan,
+ logo: logoId,
+ });
+ }
+
runInAction(() => {
- this.carriers.data.push(response.data);
+ for (const language of ["ru", "en", "zh"] as const) {
+ this.carriers[language].data.push(response.data);
+ }
});
};
editCarrierData = {
- full_name: "",
- short_name: "",
+ ru: {
+ full_name: "",
+ short_name: "",
+ // main_color: "",
+ // left_color: "",
+ // right_color: "",
+ slogan: "",
+ },
+ en: {
+ full_name: "",
+ short_name: "",
+
+ // main_color: "",
+ // left_color: "",
+ // right_color: "",
+ slogan: "",
+ },
city_id: 0,
- // main_color: "",
- // left_color: "",
- // right_color: "",
- slogan: "",
logo: "",
+ zh: {
+ full_name: "",
+ short_name: "",
+
+ // main_color: "",
+ // left_color: "",
+ // right_color: "",
+ slogan: "",
+ },
};
setEditCarrierData = (
fullName: string,
shortName: string,
-
cityId: number,
// main_color: string,
// left_color: string,
// right_color: string,
slogan: string,
- logoId: string
+ logoId: string,
+ language: Language
) => {
- this.editCarrierData = {
+ this.editCarrierData.city_id = cityId;
+ this.editCarrierData.logo = logoId;
+ this.editCarrierData[language] = {
full_name: fullName,
short_name: shortName,
-
- city_id: cityId,
// main_color: main_color,
// left_color: left_color,
// right_color: right_color,
slogan: slogan,
- logo: logoId,
};
};
editCarrier = async (id: number) => {
- const { language } = languageStore;
- const response = await authInstance.patch(`/carrier/${id}`, {
- ...this.editCarrierData,
- city: cityStore.cities[language].data.find(
+ const cityName =
+ cityStore.cities[languageStore.language].data.find(
(city) => city.id === this.editCarrierData.city_id
- )?.name,
- });
+ )?.name || "";
- runInAction(() => {
- this.carriers.data = this.carriers.data.map((carrier) =>
- carrier.id === id ? { ...carrier, ...response.data } : carrier
+ for (const language of ["ru", "en", "zh"] as const) {
+ const response = await languageInstance(language).patch(
+ `/carrier/${id}`,
+ {
+ ...this.editCarrierData[language],
+ city: cityName,
+ logo: this.editCarrierData.logo,
+ }
);
- this.carrier[id] = response.data;
- });
+ runInAction(() => {
+ if (this.carrier[id]) {
+ this.carrier[id][language] = response.data;
+ }
+ for (const language of ["ru", "en", "zh"] as const) {
+ this.carriers[language].data = this.carriers[language].data.map(
+ (carrier: Carrier) =>
+ carrier.id === id ? { ...carrier, ...response.data } : carrier
+ );
+ }
+ });
+ }
};
}
diff --git a/src/widgets/SightTabs/CreateInformationTab/index.tsx b/src/widgets/SightTabs/CreateInformationTab/index.tsx
index 2fac2bb..950ec02 100644
--- a/src/widgets/SightTabs/CreateInformationTab/index.tsx
+++ b/src/widgets/SightTabs/CreateInformationTab/index.tsx
@@ -175,9 +175,10 @@ export const CreateInformationTab = observer(
/>
city.id === sight.city_id) ?? null
+ ruCities.data.find((city) => city.id === sight.city_id) ??
+ null
}
getOptionLabel={(option) => option.name}
onChange={(_, value) => {
diff --git a/src/widgets/SightTabs/CreateLeftTab/index.tsx b/src/widgets/SightTabs/CreateLeftTab/index.tsx
index d67874c..ebf7b57 100644
--- a/src/widgets/SightTabs/CreateLeftTab/index.tsx
+++ b/src/widgets/SightTabs/CreateLeftTab/index.tsx
@@ -19,14 +19,7 @@ import {
MediaViewer,
DeleteModal,
} from "@widgets";
-import {
- Trash2,
- ImagePlus,
- Unlink,
- MousePointer,
- Plus,
- Save,
-} from "lucide-react";
+import { Trash2, ImagePlus, Unlink, Plus, Save, Search } from "lucide-react";
import { useState, useCallback } from "react";
import { observer } from "mobx-react-lite";
import { toast } from "react-toastify";
@@ -160,7 +153,7 @@ export const CreateLeftTab = observer(
variant="contained"
color="primary"
size="small"
- startIcon={}
+ startIcon={}
onClick={() => setIsSelectArticleDialogOpen(true)}
>
Выбрать статью
diff --git a/src/widgets/SightTabs/CreateRightTab/index.tsx b/src/widgets/SightTabs/CreateRightTab/index.tsx
index bf4edde..f32f666 100644
--- a/src/widgets/SightTabs/CreateRightTab/index.tsx
+++ b/src/widgets/SightTabs/CreateRightTab/index.tsx
@@ -551,6 +551,7 @@ export const CreateRightTab = observer(
media={
sight[language].right[activeArticleIndex].media[0]
}
+ fullWidth
/>
) : (
diff --git a/src/widgets/SightTabs/LeftWidgetTab/index.tsx b/src/widgets/SightTabs/LeftWidgetTab/index.tsx
index f623a76..e336a6c 100644
--- a/src/widgets/SightTabs/LeftWidgetTab/index.tsx
+++ b/src/widgets/SightTabs/LeftWidgetTab/index.tsx
@@ -18,14 +18,7 @@ import {
MediaViewer,
DeleteModal,
} from "@widgets";
-import {
- Trash2,
- ImagePlus,
- Unlink,
- Plus,
- MousePointer,
- Save,
-} from "lucide-react";
+import { Trash2, ImagePlus, Unlink, Plus, Save, Search } from "lucide-react";
import { useState, useCallback } from "react";
import { observer } from "mobx-react-lite";
import { toast } from "react-toastify";
@@ -175,7 +168,7 @@ export const LeftWidgetTab = observer(
variant="contained"
color="primary"
size="small"
- startIcon={}
+ startIcon={}
onClick={() => setIsSelectArticleDialogOpen(true)}
>
Выбрать статью
diff --git a/src/widgets/SightTabs/RightWidgetTab/index.tsx b/src/widgets/SightTabs/RightWidgetTab/index.tsx
index 96a93b6..2a360fd 100644
--- a/src/widgets/SightTabs/RightWidgetTab/index.tsx
+++ b/src/widgets/SightTabs/RightWidgetTab/index.tsx
@@ -493,6 +493,7 @@ export const RightWidgetTab = observer(
media={
sight[language].right[activeArticleIndex].media[0]
}
+ fullWidth
/>
) : (
diff --git a/src/widgets/SightsTable/index.tsx b/src/widgets/SightsTable/index.tsx
index 16e05ca..796c471 100644
--- a/src/widgets/SightsTable/index.tsx
+++ b/src/widgets/SightsTable/index.tsx
@@ -67,7 +67,7 @@ export const SightsTable = observer(() => {
- {rows(sights, cities[language])?.map((row) => (
+ {rows(sights, cities[language]?.data ?? [])?.map((row) => (