diff --git a/src/features/navigation/ui/index.tsx b/src/features/navigation/ui/index.tsx
index 2cc1983..28c6bc3 100644
--- a/src/features/navigation/ui/index.tsx
+++ b/src/features/navigation/ui/index.tsx
@@ -1,7 +1,7 @@
import List from "@mui/material/List";
import Divider from "@mui/material/Divider";
import { NAVIGATION_ITEMS } from "@shared";
-import { NavigationItemComponent } from "@entities";
+import { NavigationItem, NavigationItemComponent } from "@entities";
export const NavigationList = ({ open }: { open: boolean }) => {
const primaryItems = NAVIGATION_ITEMS.primary;
@@ -11,13 +11,21 @@ export const NavigationList = ({ open }: { open: boolean }) => {
<>
{primaryItems.map((item) => (
-
+
))}
{secondaryItems.map((item) => (
-
+
))}
>
diff --git a/src/pages/CreateSightPage/index.tsx b/src/pages/CreateSightPage/index.tsx
index 8134015..38ed3a0 100644
--- a/src/pages/CreateSightPage/index.tsx
+++ b/src/pages/CreateSightPage/index.tsx
@@ -1,5 +1,5 @@
import { Box, Tab, Tabs } from "@mui/material";
-import { articlesStore, cityStore } from "@shared";
+import { articlesStore, cityStore, languageStore } from "@shared";
import { InformationTab, RightWidgetTab } from "@widgets";
import { LeftWidgetTab } from "@widgets";
import { useEffect, useState } from "react";
@@ -22,7 +22,7 @@ export const CreateSightPage = observer(() => {
useEffect(() => {
getCities();
- getArticles();
+ getArticles(languageStore.language);
}, []);
return (
diff --git a/src/pages/EditSightPage/index.tsx b/src/pages/EditSightPage/index.tsx
index b74e10b..73c104c 100644
--- a/src/pages/EditSightPage/index.tsx
+++ b/src/pages/EditSightPage/index.tsx
@@ -3,7 +3,12 @@ import { InformationTab, RightWidgetTab } from "@widgets";
import { LeftWidgetTab } from "@widgets";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
-import { articlesStore, languageStore, sightsStore } from "@shared";
+import {
+ articlesStore,
+ cityStore,
+ editSightStore,
+ languageStore,
+} from "@shared";
import { useParams } from "react-router-dom";
function a11yProps(index: number) {
@@ -15,10 +20,11 @@ function a11yProps(index: number) {
export const EditSightPage = observer(() => {
const [value, setValue] = useState(0);
- const { sight, getSight } = sightsStore;
- const { articles, getArticles } = articlesStore;
+ const { getSightInfo } = editSightStore;
+ const { getArticles } = articlesStore;
const { language } = languageStore;
const { id } = useParams();
+ const { getCities } = cityStore;
const handleChange = (_: React.SyntheticEvent, newValue: number) => {
setValue(newValue);
@@ -27,55 +33,53 @@ export const EditSightPage = observer(() => {
useEffect(() => {
const fetchData = async () => {
if (id) {
- await getSight(Number(id));
+ await getSightInfo(+id, language);
await getArticles(language);
+ await getCities();
}
};
fetchData();
}, [id, language]);
return (
- articles &&
- sight && (
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
- )
+
+
+
+
+
+
+
);
});
diff --git a/src/shared/api/index.tsx b/src/shared/api/index.tsx
index dd3973d..1a803db 100644
--- a/src/shared/api/index.tsx
+++ b/src/shared/api/index.tsx
@@ -1,16 +1,28 @@
import { languageStore, Language } from "@shared";
-import axios from "axios";
+import axios, { AxiosError, InternalAxiosRequestConfig } from "axios";
const authInstance = axios.create({
baseURL: "https://wn.krbl.ru",
});
-authInstance.interceptors.request.use((config) => {
+authInstance.interceptors.request.use((config: InternalAxiosRequestConfig) => {
+ console.log(config);
config.headers.Authorization = `Bearer ${localStorage.getItem("token")}`;
config.headers["X-Language"] = languageStore.language ?? "ru";
return config;
});
+authInstance.interceptors.response.use(
+ (response) => response,
+ (error: AxiosError) => {
+ if (error.response?.status === 401) {
+ localStorage.removeItem("token");
+ window.location.href = "/login";
+ }
+ return Promise.reject(error);
+ }
+);
+
const languageInstance = (language: Language) => {
const instance = axios.create({
baseURL: "https://wn.krbl.ru",
diff --git a/src/shared/config/constants.tsx b/src/shared/config/constants.tsx
index 125514b..db715fe 100644
--- a/src/shared/config/constants.tsx
+++ b/src/shared/config/constants.tsx
@@ -1,3 +1,4 @@
+import { authStore } from "@shared";
import { Power, LucideIcon, Building2, MonitorSmartphone } from "lucide-react";
export const DRAWER_WIDTH = 300;
@@ -5,7 +6,8 @@ interface NavigationItem {
id: string;
label: string;
icon: LucideIcon;
- path: string;
+ path?: string;
+ onClick?: () => void;
}
export const NAVIGATION_ITEMS: {
@@ -31,7 +33,9 @@ export const NAVIGATION_ITEMS: {
id: "logout",
label: "Выйти",
icon: Power,
- path: "/logout",
+ onClick: () => {
+ authStore.logout();
+ },
},
],
};
diff --git a/src/shared/modals/PreviewMediaDialog/index.tsx b/src/shared/modals/PreviewMediaDialog/index.tsx
index 43d6a15..a7f96b7 100644
--- a/src/shared/modals/PreviewMediaDialog/index.tsx
+++ b/src/shared/modals/PreviewMediaDialog/index.tsx
@@ -1,13 +1,6 @@
-import {
- articlesStore,
- authStore,
- Language,
- mediaStore,
- MEDIA_TYPE_LABELS,
- API_URL,
-} from "@shared";
+import { mediaStore, MEDIA_TYPE_LABELS } from "@shared";
import { observer } from "mobx-react-lite";
-import { useEffect, useRef, useState, useCallback } from "react";
+import { useEffect, useState } from "react";
import {
Dialog,
DialogTitle,
@@ -17,13 +10,12 @@ import {
TextField,
Paper,
Box,
- Typography,
CircularProgress,
Alert,
Snackbar,
} from "@mui/material";
import { Download, Save } from "lucide-react";
-import { ReactMarkdownComponent, MediaViewer } from "@widgets";
+import { MediaViewer } from "@widgets";
import { authInstance } from "@shared";
interface PreviewMediaDialogProps {
diff --git a/src/shared/modals/SelectArticleDialog/index.tsx b/src/shared/modals/SelectArticleDialog/index.tsx
index cf27742..8c0e831 100644
--- a/src/shared/modals/SelectArticleDialog/index.tsx
+++ b/src/shared/modals/SelectArticleDialog/index.tsx
@@ -1,4 +1,4 @@
-import { articlesStore, authStore, Language } from "@shared";
+import { articlesStore } from "@shared";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import {
@@ -73,7 +73,10 @@ export const SelectArticleModal = observer(
setIsLoading(true);
try {
- await Promise.all([getArticle(articleId), getArticleMedia(articleId)]);
+ await Promise.all([
+ getArticle(Number(articleId)),
+ getArticleMedia(Number(articleId)),
+ ]);
} catch (error) {
console.error("Failed to fetch article data:", error);
// Reset article data on error
@@ -83,9 +86,11 @@ export const SelectArticleModal = observer(
setIsLoading(false);
}
};
-
+ // @ts-ignore
const filteredArticles = articles
+ // @ts-ignore
.filter((article) => !linkedArticleIds.includes(article.id))
+ // @ts-ignore
.filter((article) =>
article.service_name.toLowerCase().includes(searchQuery.toLowerCase())
);
@@ -140,6 +145,7 @@ export const SelectArticleModal = observer(
{searchQuery ? "Статьи не найдены" : "Нет доступных статей"}
) : (
+ // @ts-ignore
filteredArticles.map((article) => (
{
- editSightStore.sightInfo[languageStore.language].right = response.data;
+ editSightStore.sight[languageStore.language].right = response.data;
});
};
@@ -66,10 +66,14 @@ class ArticlesStore {
};
getArticleByArticleId = computed(() => {
- if (editSightStore.sightInfo.left_article) {
- return this.articles[languageStore.language].find(
- (a) => a.id == editSightStore.sightInfo.left_article
+ if (editSightStore.sight.common.left_article) {
+ const language = languageStore.language;
+ const foundArticle = this.articles[language].find(
+ (a) => a.id == editSightStore.sight.common.left_article
);
+ editSightStore.sight[language].left.heading = foundArticle?.heading ?? "";
+ editSightStore.sight[language].left.body = foundArticle?.body ?? "";
+ return foundArticle;
}
return null;
});
diff --git a/src/shared/store/AuthStore/index.tsx b/src/shared/store/AuthStore/index.tsx
index 0b30d65..e317155 100644
--- a/src/shared/store/AuthStore/index.tsx
+++ b/src/shared/store/AuthStore/index.tsx
@@ -79,7 +79,7 @@ class AuthStore {
};
get isAuthenticated() {
- return this.payload?.token !== null;
+ return this.payload !== null;
}
get user() {
diff --git a/src/shared/store/EditSightStore/index.tsx b/src/shared/store/EditSightStore/index.tsx
index 8faf2d9..19b8c8b 100644
--- a/src/shared/store/EditSightStore/index.tsx
+++ b/src/shared/store/EditSightStore/index.tsx
@@ -1,15 +1,16 @@
// @shared/stores/editSightStore.ts
-import { Language } from "@shared";
-import { makeAutoObservable } from "mobx";
+import { authInstance, Language } from "@shared";
+import { makeAutoObservable, runInAction } from "mobx";
-export interface MediaObject {
- id: string;
- filename: string;
- media_type: number;
-}
-
-type SightBaseInfo = {
+export type SightLanguageInfo = {
id: number;
+ name: string;
+ address: string;
+ left: { heading: string; body: string };
+ right: { heading: string; body: string }[];
+};
+
+export type SightCommonInfo = {
city_id: number;
city: string;
latitude: number;
@@ -22,103 +23,14 @@ type SightBaseInfo = {
video_preview: string;
};
-export interface RightArticleBlock {
- id: string;
- type: "article" | "preview_media";
- name: string;
- linkedArticleId?: string;
- heading: string;
- body: string;
- media: MediaObject | null;
-}
-
-type SightInfo = SightBaseInfo & {
- [key in Language]: {
- info: {
- name: string;
- address: string;
- };
- left: {
- loaded: boolean; // Означает, что данные для этого языка были инициализированы/загружены
- heading: string;
- body: string;
- media: MediaObject | null;
- };
- right: RightArticleBlock[];
- };
+export type SightBaseInfo = {
+ common: SightCommonInfo;
+} & {
+ [key in Language]: SightLanguageInfo;
};
-
class EditSightStore {
- sightInfo: SightInfo = {
- id: 0,
- city_id: 0,
- city: "",
- latitude: 0,
- longitude: 0,
- thumbnail: "",
- watermark_lu: "",
- watermark_rd: "",
- left_article: 0,
- preview_media: "",
- video_preview: "",
- ru: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
- right: [],
- },
- en: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
- right: [],
- },
- zh: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
- right: [],
- },
- };
-
- constructor() {
- makeAutoObservable(this);
- }
-
- // loadSightInfo: Используется для первоначальной загрузки данных для ЯЗЫКА.
- // Она устанавливает loaded: true, чтобы в будущем не перезатирать данные.
- loadSightInfo = (
- language: Language,
- heading: string,
- body: string,
- media: MediaObject | null
- ) => {
- // Важно: если данные уже были загружены или изменены, не перезаписывайте их.
- // Это предотвращает потерю пользовательского ввода при переключении языков.
- // Если хотите принудительную загрузку, добавьте другой метод или параметр.
- if (!this.sightInfo[language].left.loaded) {
- // <--- Только если еще не загружено
- this.sightInfo[language].left.heading = heading;
- this.sightInfo[language].left.body = body;
- this.sightInfo[language].left.media = media;
- this.sightInfo[language].left.loaded = true; // <--- Устанавливаем loaded только при загрузке
- }
- };
-
- // updateSightInfo: Используется для сохранения ЛЮБЫХ пользовательских изменений.
- // Она НЕ должна влиять на флаг 'loaded', который управляется 'loadSightInfo'.
- updateSightInfo = (
- language: Language,
- heading: string,
- body: string,
- media: MediaObject | null
- ) => {
- this.sightInfo[language].left.heading = heading;
- this.sightInfo[language].left.body = body;
- this.sightInfo[language].left.media = media;
- // this.sightInfo[language].left.loaded = true; // <-- УДАЛИТЕ эту строку
- };
-
- clearSightInfo = () => {
- this.sightInfo = {
- id: 0,
+ sight: SightBaseInfo = {
+ common: {
city_id: 0,
city: "",
latitude: 0,
@@ -129,23 +41,123 @@ class EditSightStore {
left_article: 0,
preview_media: "",
video_preview: "",
+ },
+ ru: {
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
+ right: [],
+ },
+ en: {
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
+ right: [],
+ },
+ zh: {
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
+ right: [],
+ },
+ };
+
+ constructor() {
+ makeAutoObservable(this);
+ }
+
+ hasLoadedCommon = false;
+ getSightInfo = async (id: number, language: Language) => {
+ if (this.sight[language].id === id) {
+ return;
+ }
+
+ const response = await authInstance.get(`/sight/${id}`);
+ const data = response.data;
+
+ runInAction(() => {
+ // Обновляем языковую часть
+ this.sight[language] = {
+ ...this.sight[language],
+ ...data,
+ };
+
+ // Только при первом запросе обновляем общую часть
+ if (!this.hasLoadedCommon) {
+ this.sight.common = {
+ ...this.sight.common,
+ ...data,
+ };
+ this.hasLoadedCommon = true;
+ }
+ });
+ };
+
+ updateLeftInfo = (language: Language, heading: string, body: string) => {
+ this.sight[language].left.heading = heading;
+ this.sight[language].left.body = body;
+ };
+
+ clearSightInfo = () => {
+ this.sight = {
+ common: {
+ city_id: 0,
+ city: "",
+ latitude: 0,
+ longitude: 0,
+ thumbnail: "",
+ watermark_lu: "",
+ watermark_rd: "",
+ left_article: 0,
+ preview_media: "",
+ video_preview: "",
+ },
ru: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
right: [],
},
+
en: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
right: [],
},
+
zh: {
- info: { name: "", address: "" },
- left: { loaded: false, heading: "", body: "", media: null },
+ id: 0,
+ name: "",
+ address: "",
+ left: { heading: "", body: "" },
right: [],
},
};
};
+
+ updateSightInfo = (
+ language: Language,
+ content: Partial,
+ common: boolean = false
+ ) => {
+ if (common) {
+ this.sight.common = {
+ ...this.sight.common,
+ ...content,
+ };
+ } else {
+ this.sight[language] = {
+ ...this.sight[language],
+ ...content,
+ };
+ }
+ };
}
export const editSightStore = new EditSightStore();
diff --git a/src/shared/store/SightsStore/index.tsx b/src/shared/store/SightsStore/index.tsx
index 5df9823..62897aa 100644
--- a/src/shared/store/SightsStore/index.tsx
+++ b/src/shared/store/SightsStore/index.tsx
@@ -1,9 +1,8 @@
import {
- articlesStore,
authInstance,
languageInstance,
languageStore,
- editSightStore,
+ SightBaseInfo,
} from "@shared";
import { computed, makeAutoObservable, runInAction } from "mobx";
@@ -59,48 +58,40 @@ class SightsStore {
});
};
- getSight = async (id: number) => {
- const response = await authInstance.get(`/sight/${id}`);
+ // getSight = async (id: number) => {
+ // const response = await authInstance.get(`/sight/${id}`);
- runInAction(() => {
- this.sight = response.data;
- editSightStore.sightInfo = {
- ...editSightStore.sightInfo,
- id: response.data.id,
- city_id: response.data.city_id,
- city: response.data.city,
- latitude: response.data.latitude,
- longitude: response.data.longitude,
- thumbnail: response.data.thumbnail,
- watermark_lu: response.data.watermark_lu,
- watermark_rd: response.data.watermark_rd,
- left_article: response.data.left_article,
- preview_media: response.data.preview_media,
- video_preview: response.data.video_preview,
- [languageStore.language]: {
- info: {
- name: response.data.name,
- address: response.data.address,
- description: response.data.description,
- },
- left: {
- heading: editSightStore.sightInfo[languageStore.language].left
- .loaded
- ? editSightStore.sightInfo[languageStore.language].left.heading
- : articlesStore.articles[languageStore.language].find(
- (article) => article.id === response.data.left_article
- )?.heading,
- body: editSightStore.sightInfo[languageStore.language].left.loaded
- ? editSightStore.sightInfo[languageStore.language].left.body
- : articlesStore.articles[languageStore.language].find(
- (article) => article.id === response.data.left_article
- )?.body,
- },
- },
- };
- console.log(editSightStore.sightInfo);
- });
- };
+ // runInAction(() => {
+ // this.sight = response.data;
+ // editSightStore.sightInfo = {
+ // ...editSightStore.sightInfo,
+ // id: response.data.id,
+ // city_id: response.data.city_id,
+ // city: response.data.city,
+ // latitude: response.data.latitude,
+ // longitude: response.data.longitude,
+ // thumbnail: response.data.thumbnail,
+ // watermark_lu: response.data.watermark_lu,
+ // watermark_rd: response.data.watermark_rd,
+ // left_article: response.data.left_article,
+ // preview_media: response.data.preview_media,
+ // video_preview: response.data.video_preview,
+
+ // [languageStore.language]: {
+ // info: {
+ // name: response.data.name,
+ // address: response.data.address,
+ // },
+ // left: {
+ // heading: articlesStore.articles[languageStore.language].find(
+ // (article) => article.id === response.data.left_article
+ // )?.heading,
+ // body: articlesStore.articles[languageStore.language].find(
+ // },
+ // },
+ // };
+ // });
+ // };
createSightAction = async (
city: number,
@@ -160,12 +151,32 @@ class SightsStore {
language: Language,
content: Partial
) => {
- runInAction(() => {
- this.createSight[language] = {
- ...this.createSight[language],
+ this.createSight[language] = {
+ ...this.createSight[language],
+ ...content,
+ };
+ };
+
+ updateSight = (
+ language: Language,
+ content: Partial,
+ common: boolean
+ ) => {
+ if (common) {
+ // @ts-ignore
+ this.sight!.common = {
+ // @ts-ignore
+ ...this.sight!.common,
...content,
};
- });
+ } else {
+ // @ts-ignore
+ this.sight![language] = {
+ // @ts-ignore
+ ...this.sight![language],
+ ...content,
+ };
+ }
};
clearCreateSight = () => {
diff --git a/src/shared/ui/CoordinatesInput/index.tsx b/src/shared/ui/CoordinatesInput/index.tsx
index b34361b..9a0b603 100644
--- a/src/shared/ui/CoordinatesInput/index.tsx
+++ b/src/shared/ui/CoordinatesInput/index.tsx
@@ -23,7 +23,7 @@ export const CoordinatesInput = ({
{
setInputValue(e.target.value);
}}
diff --git a/src/widgets/DevicesTable/index.tsx b/src/widgets/DevicesTable/index.tsx
index bbc40c9..58cceaf 100644
--- a/src/widgets/DevicesTable/index.tsx
+++ b/src/widgets/DevicesTable/index.tsx
@@ -5,7 +5,7 @@ import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
-import { Check, RotateCcw, Send, X } from "lucide-react";
+import { Check, RotateCcw, X } from "lucide-react";
import {
authInstance,
devicesStore,
@@ -49,7 +49,7 @@ function createData(
}
// Keep the rows function as you provided it, without additional filters
-const rows = (devices: any[], vehicles: any[]) => {
+const rows = (vehicles: any[]) => {
return vehicles.map((vehicle) => {
return createData(
vehicle?.vehicle?.tail_number ?? "1243000", // Using tail_number as UUID, as in your original code
@@ -72,11 +72,11 @@ export const DevicesTable = observer(() => {
toggleSendSnapshotModal,
} = devicesStore;
const { snapshots, getSnapshots } = snapshotStore;
- const { vehicles, getVehicles } = vehicleStore;
+ const { getVehicles } = vehicleStore;
const [selectedDevices, setSelectedDevices] = useState([]);
// Get the current list of rows displayed in the table
- const currentRows = rows(devices, vehicles);
+ const currentRows = rows(devices);
useEffect(() => {
const fetchData = async () => {
diff --git a/src/widgets/Layout/index.tsx b/src/widgets/Layout/index.tsx
index 35c765e..7238714 100644
--- a/src/widgets/Layout/index.tsx
+++ b/src/widgets/Layout/index.tsx
@@ -2,7 +2,6 @@ import * as React from "react";
import Box from "@mui/material/Box";
import Toolbar from "@mui/material/Toolbar";
import IconButton from "@mui/material/IconButton";
-import Typography from "@mui/material/Typography";
import { Menu, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { useTheme } from "@mui/material/styles";
import { AppBar } from "./ui/AppBar";
diff --git a/src/widgets/SightTabs/InformationTab/index.tsx b/src/widgets/SightTabs/InformationTab/index.tsx
index 2d044ee..3b771a5 100644
--- a/src/widgets/SightTabs/InformationTab/index.tsx
+++ b/src/widgets/SightTabs/InformationTab/index.tsx
@@ -6,46 +6,45 @@ import {
Typography,
Paper,
Tooltip,
- Dialog,
- DialogTitle,
MenuItem,
Menu as MuiMenu,
} from "@mui/material";
import {
BackButton,
- sightsStore,
TabPanel,
languageStore,
- CreateSight,
Language,
cityStore,
- CoordinatesInput,
editSightStore,
SelectMediaDialog,
PreviewMediaDialog,
+ SightLanguageInfo,
+ SightCommonInfo,
} from "@shared";
import { LanguageSwitcher } from "@widgets";
import { Info, ImagePlus } from "lucide-react";
import { observer } from "mobx-react-lite";
-import { useRef, useState } from "react";
+import { useEffect, useState } from "react";
// Мокап для всплывающей подсказки
export const InformationTab = observer(
({ value, index }: { value: number; index: number }) => {
const { cities } = cityStore;
- const [isMediaModalOpen, setIsMediaModalOpen] = useState(false);
+ const [, setIsMediaModalOpen] = useState(false);
const [mediaId, setMediaId] = useState("");
const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
- const { createSight, updateCreateSight, createSightAction } = sightsStore;
- const { sightInfo } = editSightStore;
- const [city, setCity] = useState(sightInfo.city_id ?? 0);
- const [coordinates, setCoordinates] = useState({
- latitude: sightInfo.latitude ?? 0,
- longitude: sightInfo.longitude ?? 0,
- });
+
const { language } = languageStore;
+ const { sight, updateSightInfo } = editSightStore;
+
+ const data = sight[language];
+ const common = sight.common;
+
+ const [, setCity] = useState(common.city_id ?? 0);
+ const [coordinates, setCoordinates] = useState(`0 0`);
+
const token = localStorage.getItem("token");
// Menu state for each media button
@@ -63,6 +62,14 @@ export const InformationTab = observer(
setActiveMenuType(type);
};
+ useEffect(() => {
+ // Показывать только при инициализации (не менять при ошибках пользователя)
+ if (common.latitude !== 0 || common.longitude !== 0) {
+ setCoordinates(`${common.latitude} ${common.longitude}`);
+ }
+ // если координаты обнулились — оставить поле как есть
+ }, [common.latitude, common.longitude]);
+
const handleMenuClose = () => {
setMenuAnchorEl(null);
setActiveMenuType(null);
@@ -77,7 +84,7 @@ export const InformationTab = observer(
handleMenuClose();
};
- const handleMediaSelect = (selectedMediaId: string) => {
+ const handleMediaSelect = () => {
if (!activeMenuType) return;
// Close the dialog
@@ -87,17 +94,10 @@ export const InformationTab = observer(
const handleChange = (
language: Language,
- content: Partial
+ content: Partial,
+ common: boolean = false
) => {
- updateCreateSight(language, content);
- };
-
- const handleSave = async () => {
- try {
- await createSightAction(city, coordinates);
- } catch (error) {
- console.error(error);
- }
+ updateSightInfo(language, content, common);
};
return (
@@ -135,7 +135,7 @@ export const InformationTab = observer(
>
{
handleChange(language as Language, {
name: e.target.value,
@@ -147,7 +147,7 @@ export const InformationTab = observer(
{
handleChange(language as Language, {
address: e.target.value,
@@ -158,20 +158,57 @@ export const InformationTab = observer(
/>
city.id === sightInfo.city_id)}
+ options={cities ?? []}
+ value={
+ cities.find((city) => city.id === common.city_id) ?? null
+ }
getOptionLabel={(option) => option.name}
onChange={(_, value) => {
setCity(value?.id ?? 0);
+ handleChange(
+ language as Language,
+ {
+ city_id: value?.id ?? 0,
+ },
+ true
+ );
}}
renderInput={(params) => (
)}
/>
- {
+ const input = e.target.value;
+ setCoordinates(input); // показываем как есть
+
+ const [latStr, lonStr] = input.split(/\s+/); // учитываем любые пробелы
+
+ const lat = parseFloat(latStr);
+ const lon = parseFloat(lonStr);
+
+ // Проверка, что обе координаты валидные числа
+ const isValidLat = !isNaN(lat);
+ const isValidLon = !isNaN(lon);
+
+ if (isValidLat && isValidLon) {
+ handleChange(language as Language, {
+ latitude: lat,
+ longitude: lon,
+ });
+ } else {
+ handleChange(language as Language, {
+ latitude: 0,
+ longitude: 0,
+ });
+ }
+ }}
+ fullWidth
+ variant="outlined"
+ placeholder="Введите координаты в формате: широта долгота"
/>
@@ -222,11 +259,9 @@ export const InformationTab = observer(
justifyContent: "center",
borderRadius: 1,
mb: 1,
- cursor: editSightStore.sightInfo?.thumbnail
- ? "pointer"
- : "default", // Only clickable if there's an image
+ cursor: common.thumbnail ? "pointer" : "default",
"&:hover": {
- backgroundColor: editSightStore.sightInfo?.thumbnail
+ backgroundColor: common.thumbnail
? "red.300"
: "grey.200",
},
@@ -235,16 +270,16 @@ export const InformationTab = observer(
setIsMediaModalOpen(true);
}}
>
- {editSightStore.sightInfo?.thumbnail ? (
+ {common.thumbnail ? (
{
setIsPreviewMediaOpen(true);
- setMediaId(editSightStore.sightInfo?.thumbnail);
+ setMediaId(common.thumbnail);
}}
/>
) : (
@@ -297,31 +332,28 @@ export const InformationTab = observer(
justifyContent: "center",
borderRadius: 1,
mb: 1,
- cursor: editSightStore.sightInfo?.watermark_lu
- ? "pointer"
- : "default", // Only clickable if there's an image
+ cursor: common.watermark_lu ? "pointer" : "default",
"&:hover": {
- backgroundColor: editSightStore.sightInfo
- ?.watermark_lu
+ backgroundColor: common.watermark_lu
? "grey.300"
: "grey.200",
},
}}
onClick={() => {
setIsPreviewMediaOpen(true);
- setMediaId(editSightStore.sightInfo?.watermark_lu);
+ setMediaId(common.watermark_lu);
}}
>
- {editSightStore.sightInfo?.watermark_lu ? (
+ {common.watermark_lu ? (
{
setIsMediaModalOpen(true);
- setMediaId(editSightStore.sightInfo?.watermark_lu);
+ setMediaId(common.watermark_lu);
}}
/>
) : (
@@ -375,28 +407,28 @@ export const InformationTab = observer(
justifyContent: "center",
borderRadius: 1,
mb: 1,
- cursor: editSightStore.sightInfo?.watermark_rd
- ? "pointer"
- : "default", // Only clickable if there's an image
+ cursor: common.watermark_rd ? "pointer" : "default",
"&:hover": {
- backgroundColor: editSightStore.sightInfo
- ?.watermark_rd
+ backgroundColor: common.watermark_rd
? "grey.300"
: "grey.200",
},
}}
- onClick={() => editSightStore.sightInfo?.watermark_rd}
+ onClick={() => {
+ setIsMediaModalOpen(true);
+ setMediaId(common.watermark_rd);
+ }}
>
- {editSightStore.sightInfo?.watermark_rd ? (
+ {common.watermark_rd ? (
{
setIsPreviewMediaOpen(true);
- setMediaId(editSightStore.sightInfo?.watermark_rd);
+ setMediaId(common.watermark_rd);
}}
/>
) : (
@@ -432,7 +464,13 @@ export const InformationTab = observer(
justifyContent: "flex-end", // Align to the right
}}
>
-
)}
-
+ */}
{/* Правая колонка: Предпросмотр */}
@@ -247,7 +225,6 @@ export const LeftWidgetTab = observer(
gap: 1.5,
}}
>
- Предпросмотр
- {/* Медиа в превью (если есть) */}
- {data.left.media ? (
+ {/* {data.left.media?.filename ? (
) : (
-
-
-
- )}
+
+ )} */}
+
+
+
+
{/* Заголовок в превью */}
- {data.left.heading || "Название информации"}
+ {data?.left?.heading || "Название информации"}
@@ -324,7 +302,7 @@ export const LeftWidgetTab = observer(
flexGrow: 1,
}}
>
-
+
diff --git a/src/widgets/SightTabs/RightWidgetTab/index.tsx b/src/widgets/SightTabs/RightWidgetTab/index.tsx
index 53c80af..c04442c 100644
--- a/src/widgets/SightTabs/RightWidgetTab/index.tsx
+++ b/src/widgets/SightTabs/RightWidgetTab/index.tsx
@@ -1,404 +1,371 @@
-// RightWidgetTab.tsx
-import { Box, Button, Paper, TextField, Typography } from "@mui/material";
import {
- TabPanel,
+ Box,
+ Button,
+ List,
+ ListItemButton,
+ ListItemText,
+ Paper,
+ Typography,
+ Menu,
+ MenuItem,
+} from "@mui/material";
+import {
+ articlesStore,
BackButton,
- languageStore, // Предполагаем, что он есть в @shared
- Language, // Предполагаем, что он есть в @shared
- // SelectArticleModal, // Добавим позже
- // articlesStore, // Добавим позже
+ SelectArticleModal,
+ TabPanel,
} from "@shared";
-import { LanguageSwitcher } from "@widgets"; // Предполагаем, что LanguageSwitcher у вас есть
+import { SightEdit } from "@widgets";
+import { Plus } from "lucide-react";
import { observer } from "mobx-react-lite";
-import { useState, useMemo, useEffect } from "react";
-import { editSightStore, BlockItem } from "@shared"; // Путь к вашему стору
+import { useState } from "react";
-// Импортируем сюда же определения BlockItem, если не выносим в types.ts
-// export interface BlockItem { id: string; type: 'media' | 'article'; nameForSidebar: string; linkedArticleStoreId?: string; }
-
-// --- Начальные данные для структуры блоков (позже это может загружаться) ---
-// ID здесь должны быть уникальными для списка.
-const initialBlockStructures: Omit[] = [
- { id: "preview_media_main", type: "media" },
- { id: "article_1_local", type: "article" }, // Эти статьи будут редактироваться локально
- { id: "article_2_local", type: "article" },
+// --- Mock Data (can be moved to a separate file or fetched from an API) ---
+const mockRightWidgetBlocks = [
+ { id: "preview_media", name: "Превью-медиа", type: "special" },
+ { id: "article_1", name: "1. История", type: "article" },
+ { id: "article_2", name: "2. Факты", type: "article" },
+ {
+ id: "article_3",
+ name: "3. Блокада (Пример длинного названия)",
+ type: "article",
+ },
];
-interface RightWidgetTabProps {
- value: number;
- index: number;
+const mockSelectedBlockData = {
+ id: "article_1",
+ heading: "История основания Санкт-Петербурга",
+ body: "## Начало\nГород был основан 27 мая 1703 года Петром I...",
+ media: [],
+};
+
+// --- ArticleListSidebar Component ---
+interface ArticleBlock {
+ id: string;
+ name: string;
+ type: string;
+ linkedArticleId?: string; // Added for linked articles
}
-export const RightWidgetTab = observer(
- ({ value, index }: RightWidgetTabProps) => {
- const { language } = languageStore; // Текущий язык
- const { sightInfo } = editSightStore; // Данные достопримечательности
+interface ArticleListSidebarProps {
+ blocks: ArticleBlock[];
+ selectedBlockId: string | null;
+ onSelectBlock: (blockId: string) => void;
+ onCreateNew: () => void;
+ onSelectExisting: () => void;
+}
- // 1. Структура блоков: порядок, тип, связи (не сам контент)
- // Имена nameForSidebar будут динамически браться из sightInfo или articlesStore
- const [blockItemsStructure, setBlockItemsStructure] = useState<
- Omit[]
- >(initialBlockStructures);
+const ArticleListSidebar = ({
+ blocks,
+ selectedBlockId,
+ onSelectBlock,
+ onCreateNew,
+ onSelectExisting,
+}: ArticleListSidebarProps) => {
+ const [menuAnchorEl, setMenuAnchorEl] = useState(null);
- // 2. ID выбранного блока для редактирования
- const [selectedBlockId, setSelectedBlockId] = useState(
- () => {
- // По умолчанию выбираем первый блок, если он есть
- return initialBlockStructures.length > 0
- ? initialBlockStructures[0].id
- : null;
- }
+ const handleMenuOpen = (event: React.MouseEvent) => {
+ setMenuAnchorEl(event.currentTarget);
+ };
+
+ const handleMenuClose = () => {
+ setMenuAnchorEl(null);
+ };
+
+ return (
+
+
+ {blocks.map((block) => (
+ onSelectBlock(block.id)}
+ sx={{
+ borderRadius: 1,
+ mb: 0.5,
+ backgroundColor:
+ selectedBlockId === block.id ? "primary.light" : "transparent",
+ "&.Mui-selected": {
+ backgroundColor: "primary.main",
+ color: "primary.contrastText",
+ "&:hover": {
+ backgroundColor: "primary.dark",
+ },
+ },
+ "&:hover": {
+ backgroundColor:
+ selectedBlockId !== block.id ? "action.hover" : undefined,
+ },
+ }}
+ >
+
+
+ ))}
+
+
+
+
+
+
+
+ );
+};
+
+// --- ArticleEditorPane Component ---
+interface ArticleData {
+ id: string;
+ heading: string;
+ body: string;
+ media: any[]; // Define a proper type for media if available
+}
+
+interface ArticleEditorPaneProps {
+ articleData: ArticleData | null;
+}
+
+const ArticleEditorPane = ({ articleData }: ArticleEditorPaneProps) => {
+ if (!articleData) {
+ return (
+
+
+ Выберите блок для редактирования
+
+
);
+ }
- // 3. Состояние для модального окна выбора существующей статьи (добавим позже)
- // const [isSelectModalOpen, setIsSelectModalOpen] = useState(false);
+ return (
+
+
+
+
+ МЕДИА
+
+
+ Нет медиа
+
+ Выбрать/Загрузить медиа
+
+
+ );
+};
- // --- Производные данные (Derived State) ---
+// --- RightWidgetTab (Parent) Component ---
+export const RightWidgetTab = observer(
+ ({ value, index }: { value: number; index: number }) => {
+ const [rightWidgetBlocks, setRightWidgetBlocks] = useState(
+ mockRightWidgetBlocks
+ );
+ const [selectedBlockId, setSelectedBlockId] = useState(
+ mockRightWidgetBlocks[1]?.id || null
+ );
+ const [isSelectModalOpen, setIsSelectModalOpen] = useState(false);
- // Блоки для отображения в сайдбаре (с локализованными именами)
- const blocksForSidebar: BlockItem[] = useMemo(() => {
- return blockItemsStructure.map((struct) => {
- let name = `Блок ${struct.id}`; // Имя по умолчанию
-
- if (struct.type === "media" && struct.id === "preview_media_main") {
- name = "Превью-медиа"; // Фиксированное имя для этого блока
- } else if (struct.type === "article") {
- if (struct.linkedArticleStoreId) {
- // TODO: Найти имя в articlesStore по struct.linkedArticleStoreId
- name = `Связанная: ${struct.linkedArticleStoreId}`;
- } else {
- // Это локальная статья, берем заголовок из editSightStore
- const articleContent = sightInfo[language]?.right?.find(
- (a) => a.id === struct.id
- );
- name =
- articleContent?.heading ||
- `Статья ${struct.id.slice(-4)} (${language.toUpperCase()})`;
- }
- }
- return { ...struct, nameForSidebar: name };
- });
- }, [blockItemsStructure, language, sightInfo]);
-
- // Данные выбранного блока (структура + контент)
- const selectedBlockData = useMemo(() => {
- if (!selectedBlockId) return null;
- const structure = blockItemsStructure.find(
- (b) => b.id === selectedBlockId
- );
- if (!structure) return null;
-
- if (structure.type === "article" && !structure.linkedArticleStoreId) {
- const content = sightInfo[language]?.right?.find(
- (a) => a.id === selectedBlockId
- );
- return {
- structure,
- content: content || { id: selectedBlockId, heading: "", body: "" }, // Заглушка, если нет контента
- };
- }
- // Для media или связанных статей пока просто структура
- return { structure, content: null };
- }, [selectedBlockId, blockItemsStructure, language, sightInfo]);
-
- // --- Обработчики событий ---
const handleSelectBlock = (blockId: string) => {
setSelectedBlockId(blockId);
+ console.log("Selected block:", blockId);
};
- const handleCreateNewArticle = () => {
- const newBlockId = `article_local_${Date.now()}`;
- const newBlockStructure: Omit = {
- id: newBlockId,
- type: "article",
- };
- setBlockItemsStructure((prev) => [...prev, newBlockStructure]);
-
- // Добавляем пустой контент для этой статьи во все языки в editSightStore
- const baseName = `Новая статья ${
- blockItemsStructure.filter((b) => b.type === "article").length + 1
- }`;
- ["ru", "en", "zh"].forEach((lang) => {
- const currentLang = lang as Language;
- if (
- editSightStore.sightInfo[currentLang] &&
- !editSightStore.sightInfo[currentLang].right?.find(
- (r) => r.id === newBlockId
- )
- ) {
- editSightStore.sightInfo[currentLang].right.push({
- id: newBlockId,
- heading: `${baseName} (${currentLang.toUpperCase()})`,
- body: `Содержимое для ${baseName} (${currentLang.toUpperCase()})...`,
- });
- }
- });
+ const handleCreateNew = () => {
+ const newBlockId = `article_${Date.now()}`;
+ setRightWidgetBlocks((prevBlocks) => [
+ ...prevBlocks,
+ {
+ id: newBlockId,
+ name: `${
+ prevBlocks.filter((b) => b.type === "article").length + 1
+ }. Новый блок`,
+ type: "article",
+ },
+ ]);
setSelectedBlockId(newBlockId);
};
- const handleHeadingChange = (newHeading: string) => {
- if (
- selectedBlockData &&
- selectedBlockData.structure.type === "article" &&
- !selectedBlockData.structure.linkedArticleStoreId
- ) {
- const blockId = selectedBlockData.structure.id;
- const langData = editSightStore.sightInfo[language];
- const article = langData?.right?.find((a) => a.id === blockId);
- if (article) {
- article.heading = newHeading;
- } else if (langData) {
- // Если статьи еще нет, добавляем
- langData.right.push({ id: blockId, heading: newHeading, body: "" });
- }
- // Обновить имя в сайдбаре (т.к. blocksForSidebar пересчитается)
- // Для этого достаточно, чтобы sightInfo был observable и blocksForSidebar от него зависел
- }
+ const handleSelectExisting = () => {
+ setIsSelectModalOpen(true);
};
- const handleBodyChange = (newBody: string) => {
- if (
- selectedBlockData &&
- selectedBlockData.structure.type === "article" &&
- !selectedBlockData.structure.linkedArticleStoreId
- ) {
- const blockId = selectedBlockData.structure.id;
- const langData = editSightStore.sightInfo[language];
- const article = langData?.right?.find((a) => a.id === blockId);
- if (article) {
- article.body = newBody;
- } else if (langData) {
- // Если статьи еще нет, добавляем
- langData.right.push({ id: blockId, heading: "", body: newBody });
- }
- }
+ const handleCloseSelectModal = () => {
+ setIsSelectModalOpen(false);
};
- const handleDeleteBlock = (blockIdToDelete: string) => {
- setBlockItemsStructure((prev) =>
- prev.filter((b) => b.id !== blockIdToDelete)
- );
- // Удаляем контент из editSightStore для всех языков
- ["ru", "en", "zh"].forEach((lang) => {
- const currentLang = lang as Language;
- if (editSightStore.sightInfo[currentLang]) {
- editSightStore.sightInfo[currentLang].right =
- editSightStore.sightInfo[currentLang].right?.filter(
- (r) => r.id !== blockIdToDelete
- );
- }
- });
-
- if (selectedBlockId === blockIdToDelete) {
- setSelectedBlockId(
- blockItemsStructure.length > 1
- ? blockItemsStructure.filter((b) => b.id !== blockIdToDelete)[0]?.id
- : null
- );
+ const handleSelectArticle = (articleId: string) => {
+ // @ts-ignore
+ const article = articlesStore.articles.find((a) => a.id === articleId);
+ if (article) {
+ const newBlockId = `article_linked_${article.id}_${Date.now()}`;
+ setRightWidgetBlocks((prevBlocks) => [
+ ...prevBlocks,
+ {
+ id: newBlockId,
+ name: `${
+ prevBlocks.filter((b) => b.type === "article").length + 1
+ }. ${article.service_name}`,
+ type: "article",
+ linkedArticleId: article.id,
+ },
+ ]);
+ setSelectedBlockId(newBlockId);
}
+ handleCloseSelectModal();
};
const handleSave = () => {
- console.log(
- "Сохранение Right Widget:",
- JSON.stringify(editSightStore.sightInfo, null, 2)
- );
- // Здесь будет логика отправки editSightStore.sightInfo на сервер
- alert("Данные для сохранения (см. консоль)");
+ console.log("Saving right widget...");
+ // Implement save logic here, e.g., send data to an API
};
- // --- Инициализация контента в сторе для initialBlockStructures (если его там нет) ---
- useEffect(() => {
- initialBlockStructures.forEach((struct) => {
- if (struct.type === "article" && !struct.linkedArticleStoreId) {
- const baseName = `Статья ${struct.id.split("_")[1]}`; // Пример "История" или "Факты"
- ["ru", "en", "zh"].forEach((lang) => {
- const currentLang = lang as Language;
- if (
- editSightStore.sightInfo[currentLang] &&
- !editSightStore.sightInfo[currentLang].right?.find(
- (r) => r.id === struct.id
- )
- ) {
- editSightStore.sightInfo[currentLang].right?.push({
- id: struct.id,
- heading: `${baseName} (${currentLang.toUpperCase()})`, // Например: "История (RU)"
- body: `Начальное содержимое для ${baseName} на ${currentLang.toUpperCase()}.`,
- });
- }
- });
- }
- });
- }, []); // Запускается один раз при монтировании
+ // Determine the current block data to pass to the editor pane
+ const currentBlockToEdit = selectedBlockId
+ ? selectedBlockId === mockSelectedBlockData.id
+ ? mockSelectedBlockData
+ : {
+ id: selectedBlockId,
+ heading:
+ rightWidgetBlocks.find((b) => b.id === selectedBlockId)?.name ||
+ "Заголовок...",
+ body: "Содержимое...",
+ media: [],
+ }
+ : null;
+
+ // Get list of already linked article IDs
+ const linkedArticleIds = rightWidgetBlocks
+ .filter((block) => block.linkedArticleId)
+ .map((block) => block.linkedArticleId as string);
return (
-
-
- {/* Компонент сайдбара списка блоков */}
-
-
- Блоки
-
-
- {blocksForSidebar.map((block) => (
- handleSelectBlock(block.id)}
- sx={{
- justifyContent: "flex-start",
- mb: 0.5,
- textTransform: "none",
- }}
- >
- {block.nameForSidebar}
-
- ))}
-
-
- + Новая статья
-
- {/* TODO: Кнопка "Выбрать существующую" */}
-
+
+
- {/* Компонент редактора выбранного блока */}
-
-
- Редактор блока ({language.toUpperCase()})
-
- {selectedBlockData ? (
-
-
- ID: {selectedBlockData.structure.id}
-
-
- Тип: {selectedBlockData.structure.type}
-
- {selectedBlockData.structure.type === "media" && (
-
-
- Загрузчик медиа для "{selectedBlockData.structure.id}"
-
-
- )}
- {selectedBlockData.structure.type === "article" &&
- !selectedBlockData.structure.linkedArticleStoreId &&
- selectedBlockData.content && (
-
- handleHeadingChange(e.target.value)}
- sx={{ mb: 2 }}
- />
- handleBodyChange(e.target.value)}
- sx={{ mb: 2 }}
- // Здесь позже можно будет вставить SightEdit
- />
- {/* TODO: Секция медиа для статьи */}
-
- handleDeleteBlock(selectedBlockData.structure.id)
- }
- >
- Удалить эту статью
-
-
- )}
- {selectedBlockData.structure.type === "article" &&
- selectedBlockData.structure.linkedArticleStoreId && (
-
-
- Это связанная статья:{" "}
- {selectedBlockData.structure.linkedArticleStoreId}
-
- {/* TODO: Кнопки "Открепить", "Удалить из списка" */}
-
- )}
-
- ) : (
-
- Выберите блок для редактирования
-
- )}
-
+
-
+
Сохранить изменения
- {/* */}
+
+
);
}
diff --git a/src/widgets/SightsTable/index.tsx b/src/widgets/SightsTable/index.tsx
index cc5f262..8bd0bee 100644
--- a/src/widgets/SightsTable/index.tsx
+++ b/src/widgets/SightsTable/index.tsx
@@ -8,7 +8,7 @@ import Paper from "@mui/material/Paper";
import { authInstance, cityStore, languageStore, sightsStore } from "@shared";
import { useEffect } from "react";
import { observer } from "mobx-react-lite";
-import { Button, Checkbox } from "@mui/material";
+import { Button } from "@mui/material";
import { LanguageSwitcher } from "@widgets";
import { Pencil, Trash2 } from "lucide-react";
import { useNavigate } from "react-router-dom";
diff --git a/src/widgets/modals/SelectArticleDialog/index.tsx b/src/widgets/modals/SelectArticleDialog/index.tsx
index e59b718..4c7a776 100644
--- a/src/widgets/modals/SelectArticleDialog/index.tsx
+++ b/src/widgets/modals/SelectArticleDialog/index.tsx
@@ -1,4 +1,4 @@
-import { articlesStore } from "@shared";
+import { articlesStore, languageStore } from "@shared";
import { observer } from "mobx-react-lite";
import { useEffect, useRef, useState } from "react";
import {
@@ -44,7 +44,7 @@ export const SelectArticleModal = observer(
useEffect(() => {
if (hoveredArticleId) {
hoverTimerRef.current = setTimeout(() => {
- getArticle(hoveredArticleId);
+ getArticle(Number(hoveredArticleId));
}, 200);
}
@@ -66,7 +66,8 @@ export const SelectArticleModal = observer(
}
};
- const filteredArticles = articles
+ const filteredArticles = articles[languageStore.language]
+ // @ts-ignore
.filter((article) => !linkedArticleIds.includes(article.id))
.filter((article) =>
article.service_name.toLowerCase().includes(searchQuery.toLowerCase())
@@ -96,11 +97,12 @@ export const SelectArticleModal = observer(
}}
/>
+ {/* @ts-ignore */}
{filteredArticles.map((article) => (
onSelectArticle(article.id)}
- onMouseEnter={() => handleArticleHover(article.id)}
+ onClick={() => onSelectArticle(article.id.toString())}
+ onMouseEnter={() => handleArticleHover(article.id.toString())}
onMouseLeave={handleArticleLeave}
sx={{
borderRadius: 1,
diff --git a/tsconfig.json b/tsconfig.json
index 5436761..3f20fd8 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -25,6 +25,5 @@
"@app": ["src/app"]
}
},
- "include": ["src"],
- "references": [{ "path": "./tsconfig.node.json" }]
+ "include": ["src"]
}
diff --git a/tsconfig.tsbuildinfo b/tsconfig.tsbuildinfo
new file mode 100644
index 0000000..1735a1a
--- /dev/null
+++ b/tsconfig.tsbuildinfo
@@ -0,0 +1 @@
+{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/app/index.tsx","./src/app/router/index.tsx","./src/entities/index.ts","./src/entities/navigation/index.ts","./src/entities/navigation/model/index.ts","./src/entities/navigation/ui/index.tsx","./src/features/index.ts","./src/features/navigation/index.ts","./src/features/navigation/ui/index.tsx","./src/pages/index.ts","./src/pages/createsightpage/index.tsx","./src/pages/devicespage/index.tsx","./src/pages/editsightpage/index.tsx","./src/pages/loginpage/index.tsx","./src/pages/mainpage/index.tsx","./src/pages/sightpage/index.tsx","./src/shared/index.tsx","./src/shared/api/index.tsx","./src/shared/config/constants.tsx","./src/shared/config/index.ts","./src/shared/const/index.ts","./src/shared/lib/index.ts","./src/shared/lib/decodejwt/index.ts","./src/shared/lib/mui/theme.ts","./src/shared/modals/index.ts","./src/shared/modals/previewmediadialog/index.tsx","./src/shared/modals/selectarticledialog/index.tsx","./src/shared/modals/selectmediadialog/index.tsx","./src/shared/store/index.ts","./src/shared/store/articlesstore/index.tsx","./src/shared/store/authstore/index.tsx","./src/shared/store/citystore/index.tsx","./src/shared/store/devicesstore/index.tsx","./src/shared/store/editsightstore/index.tsx","./src/shared/store/languagestore/index.tsx","./src/shared/store/mediastore/index.tsx","./src/shared/store/sightsstore/index.tsx","./src/shared/store/snapshotstore/index.ts","./src/shared/store/vehiclestore/index.ts","./src/shared/ui/index.ts","./src/shared/ui/backbutton/index.tsx","./src/shared/ui/coordinatesinput/index.tsx","./src/shared/ui/input/index.tsx","./src/shared/ui/modal/index.tsx","./src/shared/ui/tabpanel/index.tsx","./src/widgets/index.ts","./src/widgets/devicestable/index.tsx","./src/widgets/languageswitcher/index.tsx","./src/widgets/layout/index.tsx","./src/widgets/layout/ui/appbar.tsx","./src/widgets/layout/ui/drawer.tsx","./src/widgets/layout/ui/drawerheader.tsx","./src/widgets/mediaviewer/threeview.tsx","./src/widgets/mediaviewer/index.tsx","./src/widgets/reactmarkdown/index.tsx","./src/widgets/reactmarkdowneditor/index.tsx","./src/widgets/sightedit/index.tsx","./src/widgets/sightheader/index.ts","./src/widgets/sightheader/ui/index.tsx","./src/widgets/sighttabs/index.ts","./src/widgets/sighttabs/informationtab/index.tsx","./src/widgets/sighttabs/leftwidgettab/index.tsx","./src/widgets/sighttabs/rightwidgettab/index.tsx","./src/widgets/sightstable/index.tsx","./src/widgets/modals/index.ts","./src/widgets/modals/selectarticledialog/index.tsx"],"errors":true,"version":"5.8.3"}
\ No newline at end of file