hotfix admin panel

This commit is contained in:
Микаэл Оганесян
2025-09-27 22:29:13 -07:00
parent 34ba3c1db0
commit b25df42960
14 changed files with 461 additions and 582 deletions

View File

@@ -35,8 +35,7 @@ import { Save } from "lucide-react";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
// Мокап для всплывающей подсказки
import { SaveWithoutCityAgree } from "@widgets";
export const CreateInformationTab = observer(
({ value, index }: { value: number; index: number }) => {
@@ -51,7 +50,6 @@ export const CreateInformationTab = observer(
const [, setCity] = useState<number>(sight.city_id ?? 0);
const [coordinates, setCoordinates] = useState<string>(`0, 0`);
// Menu state for each media button
const [menuAnchorEl, setMenuAnchorEl] = useState<null | HTMLElement>(null);
const [activeMenuType, setActiveMenuType] = useState<
"thumbnail" | "watermark_lu" | "watermark_rd" | "video_preview" | null
@@ -62,21 +60,15 @@ export const CreateInformationTab = observer(
"thumbnail" | "watermark_lu" | "watermark_rd" | "video_preview" | null
>(null);
// НОВОЕ СОСТОЯНИЕ ДЛЯ ПРЕДУПРЕЖДАЮЩЕГО ОКНА
const [isSaveWarningOpen, setIsSaveWarningOpen] = useState(false);
useEffect(() => {}, [hardcodeType]);
// const handleMenuOpen = (
// event: React.MouseEvent<HTMLElement>,
// type: "thumbnail" | "watermark_lu" | "watermark_rd"
// ) => {
// setMenuAnchorEl(event.currentTarget);
// setActiveMenuType(type);
// };
useEffect(() => {
// Показывать только при инициализации (не менять при ошибках пользователя)
if (sight.latitude !== 0 || sight.longitude !== 0) {
setCoordinates(`${sight.latitude}, ${sight.longitude}`);
}
// если координаты обнулились — оставить поле как есть
}, [sight.latitude, sight.longitude]);
const handleMenuClose = () => {
@@ -125,6 +117,29 @@ export const CreateInformationTab = observer(
}
};
const handleSave = async () => {
const isCityMissing = !sight.city_id;
const isNameMissing = !sight[language].name;
if (isCityMissing || isNameMissing) {
setIsSaveWarningOpen(true);
return;
}
await createSight(language);
toast.success("Достопримечательность создана");
};
const handleConfirmSave = async () => {
setIsSaveWarningOpen(false);
await createSight(language);
toast.success("Достопримечательность создана");
};
const handleCancelSave = () => {
setIsSaveWarningOpen(false);
};
return (
<>
<TabPanel value={value} index={index}>
@@ -134,7 +149,7 @@ export const CreateInformationTab = observer(
flexDirection: "column",
gap: 3,
position: "relative",
paddingBottom: "70px" /* Space for save button */,
paddingBottom: "70px",
}}
>
<div className="flex gap-10 items-center mb-5 max-w-[80%]">
@@ -146,12 +161,11 @@ export const CreateInformationTab = observer(
sx={{
display: "flex",
gap: 4, // Added gap between the two main columns
gap: 4,
width: "100%",
flexDirection: "column",
}}
>
{/* Left column with main fields */}
<Box
sx={{
flexGrow: 1,
@@ -215,14 +229,13 @@ export const CreateInformationTab = observer(
value={coordinates}
onChange={(e) => {
const input = e.target.value;
setCoordinates(input); // показываем как есть
setCoordinates(input);
const [latStr, lonStr] = input.split(/\s+/); // учитываем любые пробелы
const [latStr, lonStr] = input.split(/\s+/);
const lat = parseFloat(latStr);
const lon = parseFloat(lonStr);
// Проверка, что обе координаты валидные числа
const isValidLat = !isNaN(lat);
const isValidLon = !isNaN(lon);
@@ -260,7 +273,7 @@ export const CreateInformationTab = observer(
justifyContent: "space-around",
width: "80%",
gap: 2,
flexDirection: { xs: "column", sm: "row" }, // Stack on extra small, side-by-side on small and up
flexDirection: { xs: "column", sm: "row" },
}}
>
<ImageUploadCard
@@ -348,7 +361,7 @@ export const CreateInformationTab = observer(
/>
<VideoPreviewCard
title="Видео превью"
title="Видеозаставка"
videoId={sight.video_preview}
onVideoClick={handleVideoPreviewClick}
onDeleteVideoClick={() => {
@@ -358,12 +371,10 @@ export const CreateInformationTab = observer(
}}
onSelectVideoClick={(file) => {
if (file) {
// Если передан файл, открываем диалог загрузки медиа
createSightStore.setFileToUpload(file);
setActiveMenuType("video_preview");
setIsUploadMediaOpen(true);
} else {
// Если файл не передан, открываем диалог выбора существующих медиа
setActiveMenuType("video_preview");
setIsAddMediaOpen(true);
}
@@ -373,31 +384,25 @@ export const CreateInformationTab = observer(
</Box>
</Box>
{/* LanguageSwitcher positioned at the top right */}
<LanguageSwitcher />
{/* Save Button fixed at the bottom right */}
<Box
sx={{
position: "absolute",
bottom: 0,
right: 0,
padding: 2,
backgroundColor: "background.paper", // To ensure it stands out over content
width: "100%", // Take full width to cover content below it
backgroundColor: "background.paper",
width: "100%",
display: "flex",
justifyContent: "flex-end", // Align to the right
justifyContent: "flex-end",
}}
>
<Button
variant="contained"
color="success"
startIcon={<Save color="white" size={18} />}
onClick={async () => {
await createSight(language);
toast.success("Достопримечательность создана");
}}
onClick={handleSave}
>
Сохранить
</Button>
@@ -405,7 +410,6 @@ export const CreateInformationTab = observer(
</Box>
</TabPanel>
{/* Media Menu */}
<MuiMenu
anchorEl={menuAnchorEl}
open={Boolean(menuAnchorEl)}
@@ -471,7 +475,6 @@ export const CreateInformationTab = observer(
initialFile={createSightStore.fileToUpload || undefined}
/>
{/* Модальное окно предпросмотра видео */}
{sight.video_preview && sight.video_preview !== "" && (
<Dialog
open={isVideoPreviewOpen}
@@ -498,7 +501,17 @@ export const CreateInformationTab = observer(
</DialogActions>
</Dialog>
)}
{/* ИНТЕГРИРОВАННОЕ ПРЕДУПРЕЖДАЮЩЕЕ ОКНО */}
{isSaveWarningOpen && (
<SaveWithoutCityAgree
blocker={{
proceed: handleConfirmSave,
reset: handleCancelSave,
}}
/>
)}
</>
);
}
);
);