fix: zoom no longer resets after manual pan/zoom (fitBounds once per siruta)
The fitBounds effect was re-triggered every time mapReady toggled (which happened frequently due to the source-checking polling interval). Now uses boundsFittedForSirutaRef to ensure fitBounds runs only ONCE per siruta selection — changing UAT still zooms correctly, but manual zoom/pan is preserved afterwards. Fixed in both ParcelSync Harta tab and Portal map. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1161,6 +1161,7 @@ function HartaContent() {
|
|||||||
// Bounds state
|
// Bounds state
|
||||||
const boundsRef = useRef<[number, number, number, number] | null>(null);
|
const boundsRef = useRef<[number, number, number, number] | null>(null);
|
||||||
const appliedSirutaRef = useRef("");
|
const appliedSirutaRef = useRef("");
|
||||||
|
const boundsFittedForSirutaRef = useRef("");
|
||||||
const prevBoundsSirutaRef = useRef("");
|
const prevBoundsSirutaRef = useRef("");
|
||||||
|
|
||||||
// Layer visibility: show terenuri + cladiri
|
// Layer visibility: show terenuri + cladiri
|
||||||
@@ -1230,22 +1231,26 @@ function HartaContent() {
|
|||||||
if (data?.bounds) {
|
if (data?.bounds) {
|
||||||
const [[minLng, minLat], [maxLng, maxLat]] = data.bounds;
|
const [[minLng, minLat], [maxLng, maxLat]] = data.bounds;
|
||||||
boundsRef.current = [minLng, minLat, maxLng, maxLat];
|
boundsRef.current = [minLng, minLat, maxLng, maxLat];
|
||||||
|
boundsFittedForSirutaRef.current = "";
|
||||||
const map = asMap(mapHandleRef.current);
|
const map = asMap(mapHandleRef.current);
|
||||||
if (map) {
|
if (map) {
|
||||||
map.fitBounds([minLng, minLat, maxLng, maxLat], { padding: 40, duration: 1500 });
|
map.fitBounds([minLng, minLat, maxLng, maxLat], { padding: 40, duration: 1500 });
|
||||||
|
boundsFittedForSirutaRef.current = selectedSiruta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}, [selectedSiruta]);
|
}, [selectedSiruta]);
|
||||||
|
|
||||||
// When map becomes ready, fitBounds and apply filter
|
// When map becomes ready, fitBounds ONCE per siruta
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mapReady || !boundsRef.current) return;
|
if (!mapReady || !boundsRef.current || !selectedSiruta) return;
|
||||||
|
if (boundsFittedForSirutaRef.current === selectedSiruta) return;
|
||||||
const map = asMap(mapHandleRef.current);
|
const map = asMap(mapHandleRef.current);
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
map.fitBounds(boundsRef.current, { padding: 40, duration: 1500 });
|
map.fitBounds(boundsRef.current, { padding: 40, duration: 1500 });
|
||||||
}, [mapReady]);
|
boundsFittedForSirutaRef.current = selectedSiruta;
|
||||||
|
}, [mapReady, selectedSiruta]);
|
||||||
|
|
||||||
// Apply siruta filter to layers
|
// Apply siruta filter to layers
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ export function MapTab({ siruta, sirutaValid, sessionConnected, syncLocalCount,
|
|||||||
const appliedSirutaRef = useRef("");
|
const appliedSirutaRef = useRef("");
|
||||||
const boundsRef = useRef<[number, number, number, number] | null>(null);
|
const boundsRef = useRef<[number, number, number, number] | null>(null);
|
||||||
const prevCheckSirutaRef = useRef("");
|
const prevCheckSirutaRef = useRef("");
|
||||||
|
const boundsFittedForSirutaRef = useRef("");
|
||||||
|
|
||||||
/* Boundary check results */
|
/* Boundary check results */
|
||||||
const [mismatchSummary, setMismatchSummary] = useState<{
|
const [mismatchSummary, setMismatchSummary] = useState<{
|
||||||
@@ -164,12 +165,14 @@ export function MapTab({ siruta, sirutaValid, sessionConnected, syncLocalCount,
|
|||||||
if (data?.bounds) {
|
if (data?.bounds) {
|
||||||
const [[minLng, minLat], [maxLng, maxLat]] = data.bounds;
|
const [[minLng, minLat], [maxLng, maxLat]] = data.bounds;
|
||||||
boundsRef.current = [minLng, minLat, maxLng, maxLat];
|
boundsRef.current = [minLng, minLat, maxLng, maxLat];
|
||||||
|
boundsFittedForSirutaRef.current = ""; // reset — need to fit for new siruta
|
||||||
const map = asMap(mapHandleRef.current);
|
const map = asMap(mapHandleRef.current);
|
||||||
if (map) {
|
if (map) {
|
||||||
map.fitBounds([minLng, minLat, maxLng, maxLat], {
|
map.fitBounds([minLng, minLat, maxLng, maxLat], {
|
||||||
padding: 40,
|
padding: 40,
|
||||||
duration: 1500,
|
duration: 1500,
|
||||||
});
|
});
|
||||||
|
boundsFittedForSirutaRef.current = siruta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -178,13 +181,16 @@ export function MapTab({ siruta, sirutaValid, sessionConnected, syncLocalCount,
|
|||||||
.finally(() => setBoundsLoading(false));
|
.finally(() => setBoundsLoading(false));
|
||||||
}, [siruta, sirutaValid]);
|
}, [siruta, sirutaValid]);
|
||||||
|
|
||||||
/* ── When map becomes ready, fitBounds if we have bounds ───── */
|
/* ── When map becomes ready, fitBounds ONCE per siruta ──────── */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!mapReady || !boundsRef.current) return;
|
if (!mapReady || !boundsRef.current || !siruta) return;
|
||||||
|
// Only fit bounds once per siruta — don't reset zoom on basemap switch or re-render
|
||||||
|
if (boundsFittedForSirutaRef.current === siruta) return;
|
||||||
const map = asMap(mapHandleRef.current);
|
const map = asMap(mapHandleRef.current);
|
||||||
if (!map) return;
|
if (!map) return;
|
||||||
map.fitBounds(boundsRef.current, { padding: 40, duration: 1500 });
|
map.fitBounds(boundsRef.current, { padding: 40, duration: 1500 });
|
||||||
}, [mapReady]);
|
boundsFittedForSirutaRef.current = siruta;
|
||||||
|
}, [mapReady, siruta]);
|
||||||
|
|
||||||
/* ── Apply siruta filter + enrichment overlay ──────────────── */
|
/* ── Apply siruta filter + enrichment overlay ──────────────── */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
Reference in New Issue
Block a user