import { Button, Stack, TextField, Typography, Slider } from "@mui/material"; import { useMapData } from "./MapDataContext"; import { useEffect, useState } from "react"; import { useTransform } from "./TransformContext"; import { coordinatesToLocal, localToCoordinates } from "./utils"; import { SCALE_FACTOR } from "./Constants"; import { toast } from "react-toastify"; export function RightSidebar() { const { routeData, setScaleRange, saveChanges, originalRouteData, setMapRotation, setMapCenter, } = useMapData(); const { rotation, position, screenToLocal, screenCenter, rotateToAngle, setTransform, scale, setScaleAtCenter, } = useTransform(); const [minScale, setMinScale] = useState(1); const [maxScale, setMaxScale] = useState(5); const [localCenter, setLocalCenter] = useState<{ x: number; y: number }>({ x: 0, y: 0, }); const [rotationDegrees, setRotationDegrees] = useState(0); const [isUserEditing, setIsUserEditing] = useState(false); useEffect(() => { if (originalRouteData) { // Проверяем и сбрасываем минимальный масштаб если нужно const originalMinScale = originalRouteData.scale_min ?? 1; const resetMinScale = originalMinScale < 1 ? 1 : originalMinScale; // Проверяем и сбрасываем максимальный масштаб если нужно const originalMaxScale = originalRouteData.scale_max ?? 5; const resetMaxScale = originalMaxScale < 3 ? 3 : originalMaxScale; setMinScale(resetMinScale); setMaxScale(resetMaxScale); 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(() => { if (!isUserEditing) { 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, screenCenter, screenToLocal, localToCoordinates, setLocalCenter, isUserEditing, ]); 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) { return null; } return ( Детали о достопримечательностях { let newMinScale = Number(e.target.value); // Сбрасываем к 1 если меньше if (newMinScale < 1) { newMinScale = 1; } setMinScale(newMinScale); if (maxScale - newMinScale < 2) { let newMaxScale = newMinScale + 2; // Сбрасываем максимальный к 3 если меньше минимального if (newMaxScale < 3) { newMaxScale = 3; setMinScale(1); // Сбрасываем минимальный к 1 } setMaxScale(newMaxScale); } if (newMinScale > scale * SCALE_FACTOR) { setScaleAtCenter(newMinScale / SCALE_FACTOR); } }} style={{ backgroundColor: "#222", borderRadius: 4 }} sx={{ "& .MuiInputLabel-root": { color: "#fff", }, "& .MuiInputBase-input": { color: "#fff", }, }} slotProps={{ input: { min: 1, max: 10, }, }} /> { let newMaxScale = Number(e.target.value); // Сбрасываем к 3 если меньше минимального if (newMaxScale < 3) { newMaxScale = 3; } setMaxScale(newMaxScale); if (newMaxScale - minScale < 2) { let newMinScale = newMaxScale - 2; // Сбрасываем минимальный к 1 если меньше if (newMinScale < 1) { newMinScale = 1; setMaxScale(3); // Сбрасываем максимальный к минимальному значению } setMinScale(newMinScale); } if (newMaxScale < scale * SCALE_FACTOR) { setScaleAtCenter(newMaxScale / SCALE_FACTOR); } }} style={{ backgroundColor: "#222", borderRadius: 4, color: "#fff" }} sx={{ "& .MuiInputLabel-root": { color: "#fff", }, "& .MuiInputBase-input": { color: "#fff", }, }} slotProps={{ input: { min: 3, max: 10, }, }} /> Текущий масштаб: {Math.round(scale * SCALE_FACTOR * 100) / 100} { if (typeof newValue === "number") { setScaleAtCenter(newValue / SCALE_FACTOR); } }} min={minScale} max={maxScale} step={0.1} sx={{ color: "#fff", "& .MuiSlider-thumb": { backgroundColor: "#fff", }, "& .MuiSlider-track": { backgroundColor: "#fff", }, "& .MuiSlider-rail": { backgroundColor: "#666", }, }} /> { const newScale = Number(e.target.value); if ( !isNaN(newScale) && newScale >= minScale && newScale <= maxScale ) { setScaleAtCenter(newScale / SCALE_FACTOR); } }} style={{ backgroundColor: "#222", borderRadius: 4 }} sx={{ "& .MuiInputLabel-root": { color: "#fff", }, "& .MuiInputBase-input": { color: "#fff", }, }} inputProps={{ min: minScale, max: maxScale, }} /> { 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, }, }} /> { setIsUserEditing(true); setLocalCenter((prev) => ({ ...prev, x: Number(e.target.value) })); pan({ x: Number(e.target.value), y: localCenter.y }); }} onBlur={() => setIsUserEditing(false)} style={{ backgroundColor: "#222", borderRadius: 4 }} sx={{ "& .MuiInputLabel-root": { color: "#fff", }, "& .MuiInputBase-input": { color: "#fff", }, }} inputProps={{ step: 0.001, }} /> { setIsUserEditing(true); setLocalCenter((prev) => ({ ...prev, y: Number(e.target.value) })); pan({ x: localCenter.x, y: Number(e.target.value) }); }} onBlur={() => setIsUserEditing(false)} style={{ backgroundColor: "#222", borderRadius: 4 }} sx={{ "& .MuiInputLabel-root": { color: "#fff", }, "& .MuiInputBase-input": { color: "#fff", }, }} inputProps={{ step: 0.001, }} /> ); }