feat: add loader for saving route and description for stations
This commit is contained in:
@@ -1,4 +1,12 @@
|
||||
import { Button, Stack, TextField, Typography, Slider } from "@mui/material";
|
||||
import {
|
||||
Button,
|
||||
Stack,
|
||||
TextField,
|
||||
Typography,
|
||||
Slider,
|
||||
CircularProgress,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
import { useMapData } from "./MapDataContext";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTransform } from "./TransformContext";
|
||||
@@ -28,6 +36,7 @@ export function RightSidebar() {
|
||||
const [isUserEditing, setIsUserEditing] = useState<boolean>(false);
|
||||
const [iconSize, setIconSize] = useState<number>(100);
|
||||
const [fontSize, setFontSize] = useState<number>(100);
|
||||
const [isSaving, setIsSaving] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (originalRouteData) {
|
||||
@@ -150,11 +159,19 @@ export function RightSidebar() {
|
||||
newMinScale = 10;
|
||||
}
|
||||
|
||||
if (newMinScale > 300) {
|
||||
newMinScale = 297;
|
||||
}
|
||||
|
||||
setMinScale(newMinScale);
|
||||
|
||||
if (maxScale - newMinScale < 2) {
|
||||
let newMaxScale = newMinScale + 2;
|
||||
|
||||
if (newMaxScale > 300) {
|
||||
newMaxScale = 300;
|
||||
}
|
||||
|
||||
if (newMaxScale < 3) {
|
||||
newMaxScale = 3;
|
||||
setMinScale(1);
|
||||
@@ -443,18 +460,35 @@ export function RightSidebar() {
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{ mt: 2 }}
|
||||
sx={{ mt: 2, position: "relative" }}
|
||||
disabled={isSaving}
|
||||
onClick={async () => {
|
||||
setIsSaving(true);
|
||||
try {
|
||||
await saveChanges();
|
||||
toast.success("Изменения сохранены");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Ошибка при сохранении изменений");
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Сохранить изменения
|
||||
{isSaving ? (
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 1,
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={20} sx={{ color: "inherit" }} />
|
||||
<span>Сохранение...</span>
|
||||
</Box>
|
||||
) : (
|
||||
"Сохранить изменения"
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<svg
|
||||
|
||||
@@ -1382,13 +1382,78 @@ export const WebGLRouteMapPrototype = observer(() => {
|
||||
skipNextAutoFitRef.current = false;
|
||||
return;
|
||||
}
|
||||
resetTransform();
|
||||
|
||||
const currentTransform = transformRef.current ?? lastTransformRef.current;
|
||||
if (!currentTransform) {
|
||||
resetTransform();
|
||||
return;
|
||||
}
|
||||
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas || canvas.width === 0 || canvas.height === 0) {
|
||||
resetTransform();
|
||||
return;
|
||||
}
|
||||
|
||||
const preservedScale = currentTransform.scale;
|
||||
|
||||
const centerX = canvas.width / 2;
|
||||
const centerY = canvas.height / 2;
|
||||
|
||||
const worldCenterX =
|
||||
(centerX - currentTransform.translation.x) / preservedScale;
|
||||
const worldCenterY =
|
||||
(centerY - currentTransform.translation.y) / preservedScale;
|
||||
|
||||
const centerLat =
|
||||
routeData?.center_latitude ?? originalRouteData?.center_latitude;
|
||||
const centerLon =
|
||||
routeData?.center_longitude ?? originalRouteData?.center_longitude;
|
||||
|
||||
if (Number.isFinite(centerLat) && Number.isFinite(centerLon)) {
|
||||
const local = coordinatesToLocal(
|
||||
centerLat as number,
|
||||
centerLon as number
|
||||
);
|
||||
const baseX = local.x * UP_SCALE;
|
||||
const baseY = local.y * UP_SCALE;
|
||||
const cos = Math.cos(rotationAngle);
|
||||
const sin = Math.sin(rotationAngle);
|
||||
const rotatedX = baseX * cos - baseY * sin;
|
||||
const rotatedY = baseX * sin + baseY * cos;
|
||||
|
||||
const updatedTransform: Transform = {
|
||||
scale: preservedScale,
|
||||
translation: {
|
||||
x: centerX - rotatedX * preservedScale,
|
||||
y: centerY - rotatedY * preservedScale,
|
||||
},
|
||||
};
|
||||
|
||||
transformRef.current = updatedTransform;
|
||||
lastTransformRef.current = updatedTransform;
|
||||
setTransformState(updatedTransform);
|
||||
drawSceneRef.current();
|
||||
} else {
|
||||
const updatedTransform: Transform = {
|
||||
scale: preservedScale,
|
||||
translation: {
|
||||
x: centerX - worldCenterX * preservedScale,
|
||||
y: centerY - worldCenterY * preservedScale,
|
||||
},
|
||||
};
|
||||
|
||||
transformRef.current = updatedTransform;
|
||||
lastTransformRef.current = updatedTransform;
|
||||
setTransformState(updatedTransform);
|
||||
drawSceneRef.current();
|
||||
}
|
||||
}, [
|
||||
routeVertices,
|
||||
stationVertices,
|
||||
canvasSize.width,
|
||||
canvasSize.height,
|
||||
rotationAngle,
|
||||
routeData?.center_latitude,
|
||||
routeData?.center_longitude,
|
||||
originalRouteData?.center_latitude,
|
||||
originalRouteData?.center_longitude,
|
||||
resetTransform,
|
||||
]);
|
||||
|
||||
|
||||
@@ -275,7 +275,10 @@ export const InformationTab = observer(
|
||||
{sight.common.id !== 0 && (
|
||||
<LinkedStations
|
||||
parentId={sight.common.id}
|
||||
fields={[{ label: "Название", data: "name" }]}
|
||||
fields={[
|
||||
{ label: "Название", data: "name" },
|
||||
{ label: "Описание", data: "description" },
|
||||
]}
|
||||
type="edit"
|
||||
/>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user