diff --git a/src/pages/Article/ArticlePreviewPage/index.tsx b/src/pages/Article/ArticlePreviewPage/index.tsx
index bce26ed..40b8953 100644
--- a/src/pages/Article/ArticlePreviewPage/index.tsx
+++ b/src/pages/Article/ArticlePreviewPage/index.tsx
@@ -1,9 +1,9 @@
import { useNavigate, useParams } from "react-router-dom";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { Box } from "@mui/material";
import { PreviewLeftWidget } from "./PreviewLeftWidget";
import { PreviewRightWidget } from "./PreviewRightWidget";
-import { articlesStore, languageStore } from "@shared";
+import { articlesStore, languageStore, LoadingSpinner } from "@shared";
import { ArrowLeft } from "lucide-react";
export const ArticlePreviewPage = () => {
@@ -11,18 +11,41 @@ export const ArticlePreviewPage = () => {
const { id } = useParams();
const { getArticle, getArticleMedia, getArticlePreview } = articlesStore;
const { language } = languageStore;
+ const [isLoadingData, setIsLoadingData] = useState(true);
useEffect(() => {
const fetchData = async () => {
if (id) {
- await getArticle(Number(id), language);
- await getArticleMedia(Number(id));
- await getArticlePreview(Number(id));
+ setIsLoadingData(true);
+ try {
+ await getArticle(Number(id), language);
+ await getArticleMedia(Number(id));
+ await getArticlePreview(Number(id));
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
};
fetchData();
}, [id, language]);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
<>
diff --git a/src/pages/Carrier/CarrierEditPage/index.tsx b/src/pages/Carrier/CarrierEditPage/index.tsx
index ff6ed55..0b17050 100644
--- a/src/pages/Carrier/CarrierEditPage/index.tsx
+++ b/src/pages/Carrier/CarrierEditPage/index.tsx
@@ -6,13 +6,20 @@ import {
MenuItem,
FormControl,
InputLabel,
+ Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
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, languageStore } from "@shared";
+import {
+ carrierStore,
+ cityStore,
+ mediaStore,
+ languageStore,
+ LoadingSpinner,
+} from "@shared";
import { useState, useEffect } from "react";
import { ImageUploadCard, LanguageSwitcher, DeleteModal } from "@widgets";
import {
@@ -28,6 +35,7 @@ export const CarrierEditPage = observer(() => {
const { language } = languageStore;
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false);
const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
@@ -39,39 +47,48 @@ export const CarrierEditPage = observer(() => {
useEffect(() => {
(async () => {
- await cityStore.getCities("ru");
- await cityStore.getCities("en");
- await cityStore.getCities("zh");
- const carrierData = await getCarrier(Number(id));
-
- 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"
- );
+ if (!id) {
+ setIsLoadingData(false);
+ return;
}
+ setIsLoadingData(true);
+ try {
+ await cityStore.getCities("ru");
+ await cityStore.getCities("en");
+ await cityStore.getCities("zh");
+ const carrierData = await getCarrier(Number(id));
- mediaStore.getMedia();
+ 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"
+ );
+ }
+
+ await mediaStore.getMedia();
+ } finally {
+ setIsLoadingData(false);
+ }
})();
languageStore.setLanguage("ru");
@@ -110,6 +127,21 @@ export const CarrierEditPage = observer(() => {
? mediaStore.media.find((m) => m.id === editCarrierData.logo)
: null;
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/City/CityEditPage/index.tsx b/src/pages/City/CityEditPage/index.tsx
index dcccc3f..b5a274e 100644
--- a/src/pages/City/CityEditPage/index.tsx
+++ b/src/pages/City/CityEditPage/index.tsx
@@ -6,6 +6,7 @@ import {
MenuItem,
FormControl,
InputLabel,
+ Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Save } from "lucide-react";
@@ -18,6 +19,7 @@ import {
languageStore,
mediaStore,
CashedCities,
+ LoadingSpinner,
} from "@shared";
import { useEffect, useState } from "react";
import { LanguageSwitcher, ImageUploadCard } from "@widgets";
@@ -30,6 +32,7 @@ import {
export const CityEditPage = observer(() => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const [isSelectMediaOpen, setIsSelectMediaOpen] = useState(false);
const [isUploadMediaOpen, setIsUploadMediaOpen] = useState(false);
const [isPreviewMediaOpen, setIsPreviewMediaOpen] = useState(false);
@@ -62,19 +65,26 @@ export const CityEditPage = observer(() => {
useEffect(() => {
(async () => {
if (id) {
- await getCountries("ru");
+ setIsLoadingData(true);
+ try {
+ await getCountries("ru");
- const ruData = await getCity(id as string, "ru");
- const enData = await getCity(id as string, "en");
- const zhData = await getCity(id as string, "zh");
+ const ruData = await getCity(id as string, "ru");
+ const enData = await getCity(id as string, "en");
+ const zhData = await getCity(id as string, "zh");
- setEditCityData(ruData.name, ruData.country_code, ruData.arms, "ru");
- setEditCityData(enData.name, enData.country_code, enData.arms, "en");
- setEditCityData(zhData.name, zhData.country_code, zhData.arms, "zh");
+ setEditCityData(ruData.name, ruData.country_code, ruData.arms, "ru");
+ setEditCityData(enData.name, enData.country_code, enData.arms, "en");
+ setEditCityData(zhData.name, zhData.country_code, zhData.arms, "zh");
- await getOneMedia(ruData.arms as string);
+ await getOneMedia(ruData.arms as string);
- await getMedia();
+ await getMedia();
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
})();
}, [id]);
@@ -97,6 +107,21 @@ export const CityEditPage = observer(() => {
? mediaStore.media.find((m) => m.id === editCityData.arms)
: null;
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/Country/CountryEditPage/index.tsx b/src/pages/Country/CountryEditPage/index.tsx
index 5802069..fbfda84 100644
--- a/src/pages/Country/CountryEditPage/index.tsx
+++ b/src/pages/Country/CountryEditPage/index.tsx
@@ -1,16 +1,17 @@
-import { Button, Paper, TextField } from "@mui/material";
+import { Button, Paper, TextField, Box } from "@mui/material";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Save } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
-import { countryStore, languageStore } from "@shared";
+import { countryStore, languageStore, LoadingSpinner } from "@shared";
import { useEffect, useState } from "react";
import { LanguageSwitcher } from "@widgets";
export const CountryEditPage = observer(() => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const { language } = languageStore;
const { id } = useParams();
const { editCountryData, editCountry, getCountry, setEditCountryData } =
@@ -35,17 +36,39 @@ export const CountryEditPage = observer(() => {
useEffect(() => {
(async () => {
if (id) {
- const ruData = await getCountry(id as string, "ru");
- const enData = await getCountry(id as string, "en");
- const zhData = await getCountry(id as string, "zh");
+ setIsLoadingData(true);
+ try {
+ const ruData = await getCountry(id as string, "ru");
+ const enData = await getCountry(id as string, "en");
+ const zhData = await getCountry(id as string, "zh");
- setEditCountryData(ruData.name, "ru");
- setEditCountryData(enData.name, "en");
- setEditCountryData(zhData.name, "zh");
+ setEditCountryData(ruData.name, "ru");
+ setEditCountryData(enData.name, "en");
+ setEditCountryData(zhData.name, "zh");
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
})();
}, [id]);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/EditSightPage/index.tsx b/src/pages/EditSightPage/index.tsx
index 48c3f42..22549be 100644
--- a/src/pages/EditSightPage/index.tsx
+++ b/src/pages/EditSightPage/index.tsx
@@ -3,7 +3,12 @@ import { InformationTab, LeaveAgree, RightWidgetTab } from "@widgets";
import { LeftWidgetTab } from "@widgets";
import { useEffect, useState } from "react";
import { observer } from "mobx-react-lite";
-import { articlesStore, cityStore, editSightStore } from "@shared";
+import {
+ articlesStore,
+ cityStore,
+ editSightStore,
+ LoadingSpinner,
+} from "@shared";
import { useBlocker, useParams } from "react-router-dom";
function a11yProps(index: number) {
@@ -15,6 +20,7 @@ function a11yProps(index: number) {
export const EditSightPage = observer(() => {
const [value, setValue] = useState(0);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const { sight, getSightInfo, needLeaveAgree } = editSightStore;
const { getArticles } = articlesStore;
@@ -33,13 +39,20 @@ export const EditSightPage = observer(() => {
useEffect(() => {
const fetchData = async () => {
if (id) {
- await getCities("ru");
- await getSightInfo(+id, "ru");
- await getSightInfo(+id, "en");
- await getSightInfo(+id, "zh");
- await getArticles("ru");
- await getArticles("en");
- await getArticles("zh");
+ setIsLoadingData(true);
+ try {
+ await getCities("ru");
+ await getSightInfo(+id, "ru");
+ await getSightInfo(+id, "en");
+ await getSightInfo(+id, "zh");
+ await getArticles("ru");
+ await getArticles("en");
+ await getArticles("zh");
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
};
fetchData();
@@ -79,12 +92,25 @@ export const EditSightPage = observer(() => {
- {sight.common.id !== 0 && (
-
-
-
-
-
+ {isLoadingData ? (
+
+
+
+ ) : (
+ sight.common.id !== 0 && (
+
+
+
+
+
+ )
)}
{blocker.state === "blocked" ? : null}
diff --git a/src/pages/Media/MediaEditPage/index.tsx b/src/pages/Media/MediaEditPage/index.tsx
index 26237f3..f2136f2 100644
--- a/src/pages/Media/MediaEditPage/index.tsx
+++ b/src/pages/Media/MediaEditPage/index.tsx
@@ -21,6 +21,7 @@ import {
mediaStore,
MEDIA_TYPE_LABELS,
languageStore,
+ LoadingSpinner,
} from "@shared";
import { MediaViewer } from "@widgets";
@@ -138,8 +139,15 @@ export const MediaEditPage = observer(() => {
if (!media && id) {
return (
-
-
+
+
);
}
diff --git a/src/pages/Route/RouteEditPage/index.tsx b/src/pages/Route/RouteEditPage/index.tsx
index 5a03801..d78d9fd 100644
--- a/src/pages/Route/RouteEditPage/index.tsx
+++ b/src/pages/Route/RouteEditPage/index.tsx
@@ -27,6 +27,7 @@ import {
ArticleSelectOrCreateDialog,
SelectMediaDialog,
UploadMediaDialog,
+ LoadingSpinner,
} from "@shared";
import { toast } from "react-toastify";
import { stationsStore } from "@shared";
@@ -37,6 +38,7 @@ export const RouteEditPage = observer(() => {
const { id } = useParams();
const { editRouteData, copyRouteAction } = routeStore;
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const [isSelectArticleDialogOpen, setIsSelectArticleDialogOpen] =
useState(false);
const [isSelectVideoDialogOpen, setIsSelectVideoDialogOpen] = useState(false);
@@ -48,18 +50,27 @@ export const RouteEditPage = observer(() => {
useEffect(() => {
const fetchData = async () => {
- const response = await routeStore.getRoute(Number(id));
- routeStore.setEditRouteData(response);
- languageStore.setLanguage("ru");
+ if (!id) {
+ setIsLoadingData(false);
+ return;
+ }
+ setIsLoadingData(true);
+ try {
+ const response = await routeStore.getRoute(Number(id));
+ routeStore.setEditRouteData(response);
+ languageStore.setLanguage("ru");
+ } finally {
+ setIsLoadingData(false);
+ }
};
fetchData();
- }, []);
+ }, [id]);
useEffect(() => {
const fetchData = async () => {
- carrierStore.getCarriers(language);
- stationsStore.getStations();
- articlesStore.getArticleList();
+ await carrierStore.getCarriers(language);
+ await stationsStore.getStations();
+ await articlesStore.getArticleList();
};
fetchData();
}, [id, language]);
@@ -233,6 +244,21 @@ export const RouteEditPage = observer(() => {
(article) => article.id === editRouteData.governor_appeal
);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/Station/StationEditPage/index.tsx b/src/pages/Station/StationEditPage/index.tsx
index 69d3275..d1f28eb 100644
--- a/src/pages/Station/StationEditPage/index.tsx
+++ b/src/pages/Station/StationEditPage/index.tsx
@@ -6,13 +6,19 @@ import {
MenuItem,
FormControl,
InputLabel,
+ Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
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 {
+ stationsStore,
+ languageStore,
+ cityStore,
+ LoadingSpinner,
+} from "@shared";
import { useEffect, useState } from "react";
import { LanguageSwitcher } from "@widgets";
import { LinkedSights } from "../LinkedSights";
@@ -21,6 +27,7 @@ import { SaveWithoutCityAgree } from "@widgets";
export const StationEditPage = observer(() => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const { language } = languageStore;
const { id } = useParams();
const {
@@ -90,18 +97,41 @@ export const StationEditPage = observer(() => {
useEffect(() => {
const fetchAndSetStationData = async () => {
- if (!id) return;
+ if (!id) {
+ setIsLoadingData(false);
+ return;
+ }
- const stationId = Number(id);
- await getEditStation(stationId);
- await getCities("ru");
- await getCities("en");
- await getCities("zh");
+ setIsLoadingData(true);
+ try {
+ const stationId = Number(id);
+ await getEditStation(stationId);
+ await getCities("ru");
+ await getCities("en");
+ await getCities("zh");
+ } finally {
+ setIsLoadingData(false);
+ }
};
fetchAndSetStationData();
}, [id]);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/Station/StationPreviewPage/index.tsx b/src/pages/Station/StationPreviewPage/index.tsx
index d45dc72..6abfa92 100644
--- a/src/pages/Station/StationPreviewPage/index.tsx
+++ b/src/pages/Station/StationPreviewPage/index.tsx
@@ -1,9 +1,9 @@
-import { Paper } from "@mui/material";
-import { languageStore, stationsStore } from "@shared";
+import { Paper, Box } from "@mui/material";
+import { languageStore, stationsStore, LoadingSpinner } from "@shared";
import { LanguageSwitcher } from "@widgets";
import { observer } from "mobx-react-lite";
import { ArrowLeft } from "lucide-react";
-import { useEffect } from "react";
+import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom";
import { LinkedSights } from "../LinkedSights";
@@ -12,15 +12,38 @@ export const StationPreviewPage = observer(() => {
const { stationPreview, getStationPreview } = stationsStore;
const navigate = useNavigate();
const { language } = languageStore;
+ const [isLoadingData, setIsLoadingData] = useState(true);
useEffect(() => {
(async () => {
if (id) {
- await getStationPreview(Number(id));
+ setIsLoadingData(true);
+ try {
+ await getStationPreview(Number(id));
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
})();
}, [id, language]);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/pages/User/UserEditPage/index.tsx b/src/pages/User/UserEditPage/index.tsx
index b6def48..b5cd7a8 100644
--- a/src/pages/User/UserEditPage/index.tsx
+++ b/src/pages/User/UserEditPage/index.tsx
@@ -4,18 +4,20 @@ import {
Checkbox,
Paper,
TextField,
+ Box,
} from "@mui/material";
import { observer } from "mobx-react-lite";
import { ArrowLeft, Save } from "lucide-react";
import { Loader2 } from "lucide-react";
import { useNavigate, useParams } from "react-router-dom";
import { toast } from "react-toastify";
-import { userStore, languageStore } from "@shared";
+import { userStore, languageStore, LoadingSpinner } from "@shared";
import { useEffect, useState } from "react";
export const UserEditPage = observer(() => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(false);
+ const [isLoadingData, setIsLoadingData] = useState(true);
const { id } = useParams();
const { editUserData, editUser, getUser, setEditUserData } = userStore;
@@ -41,18 +43,40 @@ export const UserEditPage = observer(() => {
useEffect(() => {
(async () => {
if (id) {
- const data = await getUser(Number(id));
+ setIsLoadingData(true);
+ try {
+ const data = await getUser(Number(id));
- setEditUserData(
- data?.name || "",
- data?.email || "",
- data?.password || "",
- data?.is_admin || false
- );
+ setEditUserData(
+ data?.name || "",
+ data?.email || "",
+ data?.password || "",
+ data?.is_admin || false
+ );
+ } finally {
+ setIsLoadingData(false);
+ }
+ } else {
+ setIsLoadingData(false);
}
})();
}, [id]);
+ if (isLoadingData) {
+ return (
+
+
+
+ );
+ }
+
return (
diff --git a/src/shared/store/EditSightStore/index.tsx b/src/shared/store/EditSightStore/index.tsx
index 5c6ab82..291df55 100644
--- a/src/shared/store/EditSightStore/index.tsx
+++ b/src/shared/store/EditSightStore/index.tsx
@@ -86,28 +86,35 @@ class EditSightStore {
}
hasLoadedCommon = false;
+ isLoading = false;
+
getSightInfo = async (id: number, language: Language) => {
- const response = await languageInstance(language).get(`/sight/${id}`);
- const data = response.data;
+ this.isLoading = true;
+ try {
+ const response = await languageInstance(language).get(`/sight/${id}`);
+ const data = response.data;
- if (data.left_article != 0 && data.left_article != null) {
- await this.getLeftArticle(data.left_article);
- }
+ if (data.left_article != 0 && data.left_article != null) {
+ await this.getLeftArticle(data.left_article);
+ }
- runInAction(() => {
- this.sight[language] = {
- ...this.sight[language],
- ...data,
- };
-
- if (!this.hasLoadedCommon) {
- this.sight.common = {
- ...this.sight.common,
+ runInAction(() => {
+ this.sight[language] = {
+ ...this.sight[language],
...data,
};
- this.hasLoadedCommon = true;
- }
- });
+
+ if (!this.hasLoadedCommon) {
+ this.sight.common = {
+ ...this.sight.common,
+ ...data,
+ };
+ this.hasLoadedCommon = true;
+ }
+ });
+ } finally {
+ this.isLoading = false;
+ }
};
updateLeftInfo = (language: Language, heading: string, body: string) => {
@@ -168,6 +175,8 @@ class EditSightStore {
clearSightInfo = () => {
this.needLeaveAgree = false;
+ this.hasLoadedCommon = false;
+ this.isLoading = false;
this.sight = {
common: {
id: 0,
diff --git a/src/shared/ui/index.ts b/src/shared/ui/index.ts
index 4728641..1adb123 100644
--- a/src/shared/ui/index.ts
+++ b/src/shared/ui/index.ts
@@ -3,3 +3,4 @@ export * from "./BackButton";
export * from "./Modal";
export * from "./CoordinatesInput";
export * from "./AnimatedCircleButton";
+export * from "./LoadingSpinner";
diff --git a/src/widgets/MediaArea/index.tsx b/src/widgets/MediaArea/index.tsx
index f0696bb..6aaeb48 100644
--- a/src/widgets/MediaArea/index.tsx
+++ b/src/widgets/MediaArea/index.tsx
@@ -10,23 +10,25 @@ import { observer } from "mobx-react-lite";
import { useState, DragEvent, useRef } from "react";
import { toast } from "react-toastify";
+interface MediaAreaProps {
+ articleId: number;
+ mediaIds: { id: string; media_type: number; filename: string }[];
+ deleteMedia: (id: number, media_id: string) => void;
+ onFilesDrop?: (files: File[]) => void;
+ setSelectMediaDialogOpen: (open: boolean) => void;
+}
+
export const MediaArea = observer(
({
articleId,
mediaIds,
deleteMedia,
- onFilesDrop, // 👈 Проп для обработки загруженных файлов
+ onFilesDrop,
setSelectMediaDialogOpen,
- }: {
- articleId: number;
- mediaIds: { id: string; media_type: number; filename: string }[];
- deleteMedia: (id: number, media_id: string) => void;
- onFilesDrop?: (files: File[]) => void;
- setSelectMediaDialogOpen: (open: boolean) => void;
- }) => {
+ }: MediaAreaProps) => {
const [mediaModal, setMediaModal] = useState
(false);
const [mediaId, setMediaId] = useState("");
- const [isDragging, setIsDragging] = useState(false);
+ const [isDragging, setIsDragging] = useState(false);
const fileInputRef = useRef(null);
const handleMediaModal = (mediaId: string) => {
@@ -34,23 +36,29 @@ export const MediaArea = observer(
setMediaId(mediaId);
};
+ const processFiles = (files: File[]) => {
+ if (!files.length || !onFilesDrop) {
+ return;
+ }
+
+ const { validFiles, errors } = filterValidFiles(files);
+
+ if (errors.length > 0) {
+ errors.forEach((error) => toast.error(error));
+ }
+
+ if (validFiles.length > 0) {
+ onFilesDrop(validFiles);
+ }
+ };
+
const handleDrop = (e: DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
const files = Array.from(e.dataTransfer.files);
- if (files.length && onFilesDrop) {
- const { validFiles, errors } = filterValidFiles(files);
-
- if (errors.length > 0) {
- errors.forEach((error) => toast.error(error));
- }
-
- if (validFiles.length > 0) {
- onFilesDrop(validFiles);
- }
- }
+ processFiles(files);
};
const handleDragOver = (e: DragEvent) => {
@@ -68,19 +76,11 @@ export const MediaArea = observer(
const handleFileSelect = (event: React.ChangeEvent) => {
const files = Array.from(event.target.files || []);
- if (files.length && onFilesDrop) {
- const { validFiles, errors } = filterValidFiles(files);
+ processFiles(files);
- if (errors.length > 0) {
- errors.forEach((error) => toast.error(error));
- }
-
- if (validFiles.length > 0) {
- onFilesDrop(validFiles);
- }
+ if (event.target) {
+ event.target.value = "";
}
- // Сбрасываем значение input, чтобы можно было выбрать тот же файл снова
- event.target.value = "";
};
return (
@@ -96,7 +96,7 @@ export const MediaArea = observer(
- Перетащите медиа файлы сюда или нажмите для выбора
+
+ Перетащите медиа файлы сюда или нажмите для выбора
+
-
или
+
или
-
- {mediaIds.map((m) => (
-
+ )}
void;
+ onFinishUpload?: (mediaId: string) => void;
+ contextObjectName?: string;
+ contextType?: ContextType;
+ isArticle?: boolean;
+ articleName?: string;
+}
+
export const MediaAreaForSight = observer(
({
- onFilesDrop, // 👈 Проп для обработки загруженных файлов
+ onFilesDrop,
onFinishUpload,
contextObjectName,
contextType,
isArticle,
articleName,
- }: {
- onFilesDrop?: (files: File[]) => void;
- onFinishUpload?: (mediaId: string) => void;
- contextObjectName?: string;
- contextType?:
- | "sight"
- | "city"
- | "carrier"
- | "country"
- | "vehicle"
- | "station";
- isArticle?: boolean;
- articleName?: string;
- }) => {
- const [selectMediaDialogOpen, setSelectMediaDialogOpen] = useState(false);
- const [uploadMediaDialogOpen, setUploadMediaDialogOpen] = useState(false);
- const [isDragging, setIsDragging] = useState(false);
+ }: MediaAreaForSightProps) => {
+ const [selectMediaDialogOpen, setSelectMediaDialogOpen] =
+ useState(false);
+ const [uploadMediaDialogOpen, setUploadMediaDialogOpen] =
+ useState(false);
+ const [isDragging, setIsDragging] = useState(false);
const fileInputRef = useRef(null);
const { setFileToUpload } = editSightStore;
+ const processFiles = (files: File[]) => {
+ if (!files.length) {
+ return;
+ }
+
+ const { validFiles, errors } = filterValidFiles(files);
+
+ if (errors.length > 0) {
+ errors.forEach((error: string) => toast.error(error));
+ }
+
+ if (validFiles.length > 0) {
+ // Сохраняем первый файл для загрузки
+ setFileToUpload(validFiles[0]);
+
+ // Вызываем колбэк, если он передан
+ if (onFilesDrop) {
+ onFilesDrop(validFiles);
+ }
+
+ // Открываем диалог загрузки
+ setUploadMediaDialogOpen(true);
+ }
+ };
+
const handleDrop = (e: DragEvent) => {
e.preventDefault();
e.stopPropagation();
setIsDragging(false);
const files = Array.from(e.dataTransfer.files);
- if (files.length) {
- const { validFiles, errors } = filterValidFiles(files);
-
- if (errors.length > 0) {
- errors.forEach((error: string) => toast.error(error));
- }
-
- if (validFiles.length > 0 && onFilesDrop) {
- setFileToUpload(validFiles[0]);
- setUploadMediaDialogOpen(true);
- }
- }
+ processFiles(files);
};
const handleDragOver = (e: DragEvent) => {
@@ -74,22 +94,12 @@ export const MediaAreaForSight = observer(
const handleFileSelect = (event: React.ChangeEvent) => {
const files = Array.from(event.target.files || []);
- if (files.length) {
- const { validFiles, errors } = filterValidFiles(files);
-
- if (errors.length > 0) {
- errors.forEach((error: string) => toast.error(error));
- }
-
- if (validFiles.length > 0 && onFilesDrop) {
- setFileToUpload(validFiles[0]);
- onFilesDrop(validFiles);
- setUploadMediaDialogOpen(true);
- }
- }
+ processFiles(files);
// Сбрасываем значение input, чтобы можно было выбрать тот же файл снова
- event.target.value = "";
+ if (event.target) {
+ event.target.value = "";
+ }
};
return (
@@ -105,7 +115,7 @@ export const MediaAreaForSight = observer(
- Перетащите медиа файлы сюда или нажмите для выбора
+
+ Перетащите медиа файлы сюда или нажмите для выбора
+
-
или
+
или
)}
diff --git a/src/widgets/SightTabs/CreateRightTab/index.tsx b/src/widgets/SightTabs/CreateRightTab/index.tsx
index d76d2a3..653a738 100644
--- a/src/widgets/SightTabs/CreateRightTab/index.tsx
+++ b/src/widgets/SightTabs/CreateRightTab/index.tsx
@@ -434,49 +434,61 @@ export const CreateRightTab = observer(
) : type === "media" ? (
- {sight.preview_media && (
- <>
- {type === "media" && (
-
- {previewMedia && (
- <>
-
-
-
-
-
+ <>
+ {type === "media" && (
+
+ {previewMedia && (
+ <>
+
+
+
+
+
-
-
-
- >
- )}
-
- )}
- >
- )}
- {!previewMedia && (
- {
- linkPreviewMedia(mediaId);
- }}
- onFilesDrop={() => {}}
- contextObjectName={sight[language].name}
- contextType="sight"
- isArticle={false}
- />
- )}
+
+
+
+ >
+ )}
+
+ {!previewMedia && (
+
+
+ {
+ linkPreviewMedia(mediaId);
+ }}
+ onFilesDrop={() => {}}
+ contextObjectName={sight[language].name}
+ contextType="sight"
+ isArticle={false}
+ />
+
+
+ )}
+
+ )}
+ >
) : (
diff --git a/src/widgets/SightTabs/RightWidgetTab/index.tsx b/src/widgets/SightTabs/RightWidgetTab/index.tsx
index 02432d7..234e2c7 100644
--- a/src/widgets/SightTabs/RightWidgetTab/index.tsx
+++ b/src/widgets/SightTabs/RightWidgetTab/index.tsx
@@ -415,21 +415,12 @@ export const RightWidgetTab = observer(
media_type: previewMedia.media_type,
filename: previewMedia.filename || "",
}}
+ fullWidth
+ fullHeight
/>
>
)}
- {!previewMedia && (
-
{
- linkPreviewMedia(mediaId);
- }}
- onFilesDrop={() => {}}
- contextObjectName={sight[language].name}
- contextType="sight"
- isArticle={false}
- />
- )}
)}
>