feat: Move route-preview
This commit is contained in:
232
src/pages/Route/route-preview/RightSidebar.tsx
Normal file
232
src/pages/Route/route-preview/RightSidebar.tsx
Normal file
@@ -0,0 +1,232 @@
|
||||
import { Button, Stack, TextField, Typography } from "@mui/material";
|
||||
import { useMapData } from "./MapDataContext";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTransform } from "./TransformContext";
|
||||
import { coordinatesToLocal, localToCoordinates } from "./utils";
|
||||
|
||||
export function RightSidebar() {
|
||||
const {
|
||||
routeData,
|
||||
setScaleRange,
|
||||
saveChanges,
|
||||
originalRouteData,
|
||||
setMapRotation,
|
||||
setMapCenter,
|
||||
} = useMapData();
|
||||
const {
|
||||
rotation,
|
||||
position,
|
||||
screenToLocal,
|
||||
screenCenter,
|
||||
rotateToAngle,
|
||||
setTransform,
|
||||
} = useTransform();
|
||||
const [minScale, setMinScale] = useState<number>(1);
|
||||
const [maxScale, setMaxScale] = useState<number>(10);
|
||||
const [localCenter, setLocalCenter] = useState<{ x: number; y: number }>({
|
||||
x: 0,
|
||||
y: 0,
|
||||
});
|
||||
const [rotationDegrees, setRotationDegrees] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
if (originalRouteData) {
|
||||
setMinScale(originalRouteData.scale_min ?? 1);
|
||||
setMaxScale(originalRouteData.scale_max ?? 10);
|
||||
setRotationDegrees(originalRouteData.rotate ?? 0);
|
||||
setLocalCenter({
|
||||
x: originalRouteData.center_latitude ?? 0,
|
||||
y: originalRouteData.center_longitude ?? 0,
|
||||
});
|
||||
}
|
||||
}, [originalRouteData]);
|
||||
|
||||
useEffect(() => {
|
||||
if (minScale && maxScale) {
|
||||
setScaleRange(minScale, maxScale);
|
||||
}
|
||||
}, [minScale, maxScale]);
|
||||
|
||||
useEffect(() => {
|
||||
setRotationDegrees(
|
||||
((Math.round((rotation * 180) / Math.PI) % 360) + 360) % 360
|
||||
);
|
||||
}, [rotation]);
|
||||
useEffect(() => {
|
||||
setMapRotation(rotationDegrees);
|
||||
}, [rotationDegrees]);
|
||||
|
||||
useEffect(() => {
|
||||
const center = screenCenter ?? { x: 0, y: 0 };
|
||||
const localCenter = screenToLocal(center.x, center.y);
|
||||
const coordinates = localToCoordinates(localCenter.x, localCenter.y);
|
||||
setLocalCenter({ x: coordinates.latitude, y: coordinates.longitude });
|
||||
}, [position]);
|
||||
|
||||
useEffect(() => {
|
||||
setMapCenter(localCenter.x, localCenter.y);
|
||||
}, [localCenter]);
|
||||
|
||||
function setRotationFromDegrees(degrees: number) {
|
||||
rotateToAngle((degrees * Math.PI) / 180);
|
||||
}
|
||||
|
||||
function pan({ x, y }: { x: number; y: number }) {
|
||||
const coordinates = coordinatesToLocal(x, y);
|
||||
setTransform(coordinates.x, coordinates.y);
|
||||
}
|
||||
|
||||
if (!routeData) {
|
||||
console.error("routeData is null");
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack
|
||||
position="absolute"
|
||||
right={8}
|
||||
top={8}
|
||||
bottom={8}
|
||||
p={2}
|
||||
gap={1}
|
||||
minWidth="400px"
|
||||
bgcolor="primary.main"
|
||||
border="1px solid #e0e0e0"
|
||||
borderRadius={2}
|
||||
>
|
||||
<Typography variant="h6" sx={{ mb: 2, color: "#fff" }} textAlign="center">
|
||||
Детали о достопримечательностях
|
||||
</Typography>
|
||||
|
||||
<Stack spacing={2} direction="row" alignItems="center">
|
||||
<TextField
|
||||
type="number"
|
||||
label="Минимальный масштаб"
|
||||
variant="filled"
|
||||
value={minScale}
|
||||
onChange={(e) => setMinScale(Number(e.target.value))}
|
||||
style={{ backgroundColor: "#222", borderRadius: 4 }}
|
||||
sx={{
|
||||
"& .MuiInputLabel-root": {
|
||||
color: "#fff",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
color: "#fff",
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
input: {
|
||||
min: 0.1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
type="number"
|
||||
label="Максимальный масштаб"
|
||||
variant="filled"
|
||||
value={maxScale}
|
||||
onChange={(e) => setMaxScale(Number(e.target.value))}
|
||||
style={{ backgroundColor: "#222", borderRadius: 4, color: "#fff" }}
|
||||
sx={{
|
||||
"& .MuiInputLabel-root": {
|
||||
color: "#fff",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
color: "#fff",
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
input: {
|
||||
min: 0.1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<TextField
|
||||
type="number"
|
||||
label="Поворот (в градусах)"
|
||||
variant="filled"
|
||||
value={rotationDegrees}
|
||||
onChange={(e) => {
|
||||
const value = Number(e.target.value);
|
||||
if (!isNaN(value)) {
|
||||
setRotationFromDegrees(value);
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
e.currentTarget.blur();
|
||||
}
|
||||
}}
|
||||
style={{ backgroundColor: "#222", borderRadius: 4 }}
|
||||
sx={{
|
||||
"& .MuiInputLabel-root": {
|
||||
color: "#fff",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
color: "#fff",
|
||||
},
|
||||
}}
|
||||
slotProps={{
|
||||
input: {
|
||||
min: 0,
|
||||
max: 360,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<Stack direction="row" spacing={2}>
|
||||
<TextField
|
||||
type="number"
|
||||
label="Центр карты, широта"
|
||||
variant="filled"
|
||||
value={Math.round(localCenter.x * 100000) / 100000}
|
||||
onChange={(e) => {
|
||||
setLocalCenter((prev) => ({ ...prev, x: Number(e.target.value) }));
|
||||
pan({ x: Number(e.target.value), y: localCenter.y });
|
||||
}}
|
||||
style={{ backgroundColor: "#222", borderRadius: 4 }}
|
||||
sx={{
|
||||
"& .MuiInputLabel-root": {
|
||||
color: "#fff",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
color: "#fff",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
type="number"
|
||||
label="Центр карты, высота"
|
||||
variant="filled"
|
||||
value={Math.round(localCenter.y * 100000) / 100000}
|
||||
onChange={(e) => {
|
||||
setLocalCenter((prev) => ({ ...prev, y: Number(e.target.value) }));
|
||||
pan({ x: localCenter.x, y: Number(e.target.value) });
|
||||
}}
|
||||
style={{ backgroundColor: "#222", borderRadius: 4 }}
|
||||
sx={{
|
||||
"& .MuiInputLabel-root": {
|
||||
color: "#fff",
|
||||
},
|
||||
"& .MuiInputBase-input": {
|
||||
color: "#fff",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
sx={{ mt: 2 }}
|
||||
onClick={() => {
|
||||
saveChanges();
|
||||
}}
|
||||
>
|
||||
Сохранить изменения
|
||||
</Button>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user