From ddde2db900af50e5f1c24bcbc17e361a915288b3 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Sat, 7 Mar 2026 16:35:26 +0200 Subject: [PATCH] fix: auto-scan race condition for no-geometry scan - handleNoGeomScan accepts optional targetSiruta parameter - useRef tracks last auto-scanned siruta to prevent duplicate scans - Show zero result on error instead of hiding card (null) - Fixes: FELEACU scan disappearing after 2s while COSBUC worked --- .../components/parcel-sync-module.tsx | 79 ++++++++++--------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/src/modules/parcel-sync/components/parcel-sync-module.tsx b/src/modules/parcel-sync/components/parcel-sync-module.tsx index 1b8623d..fa9f504 100644 --- a/src/modules/parcel-sync/components/parcel-sync-module.tsx +++ b/src/modules/parcel-sync/components/parcel-sync-module.tsx @@ -679,46 +679,53 @@ export function ParcelSyncModule() { /* No-geometry scan */ /* ════════════════════════════════════════════════════════════ */ - const handleNoGeomScan = useCallback(async () => { - if (!siruta || noGeomScanning) return; - setNoGeomScanning(true); - setNoGeomScan(null); - try { - const res = await fetch("/api/eterra/no-geom-scan", { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ siruta }), - }); - const data = (await res.json()) as { - totalImmovables?: number; - totalInDb?: number; - noGeomCount?: number; - error?: string; - }; - if (data.error) { - setNoGeomScan(null); - } else { - setNoGeomScan({ - totalImmovables: data.totalImmovables ?? 0, - totalInDb: data.totalInDb ?? 0, - noGeomCount: data.noGeomCount ?? 0, - }); - setNoGeomScanSiruta(siruta); - } - } catch { + const handleNoGeomScan = useCallback( + async (targetSiruta?: string) => { + const s = targetSiruta ?? siruta; + if (!s) return; + setNoGeomScanning(true); setNoGeomScan(null); - } - setNoGeomScanning(false); - }, [siruta, noGeomScanning]); + setNoGeomScanSiruta(s); + try { + const res = await fetch("/api/eterra/no-geom-scan", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ siruta: s }), + }); + const data = (await res.json()) as { + totalImmovables?: number; + totalInDb?: number; + noGeomCount?: number; + error?: string; + }; + if (data.error) { + // Show zero result instead of hiding the card entirely + setNoGeomScan({ totalImmovables: 0, totalInDb: 0, noGeomCount: 0 }); + } else { + setNoGeomScan({ + totalImmovables: data.totalImmovables ?? 0, + totalInDb: data.totalInDb ?? 0, + noGeomCount: data.noGeomCount ?? 0, + }); + } + } catch { + // Show zero result on network error + setNoGeomScan({ totalImmovables: 0, totalInDb: 0, noGeomCount: 0 }); + } + setNoGeomScanning(false); + }, + [siruta], + ); // Auto-scan for no-geometry parcels when UAT is selected + connected + const noGeomAutoScanRef = useRef(""); useEffect(() => { - if (!siruta || !session.connected || noGeomScanning) return; - // Don't re-scan if we already scanned this siruta - if (noGeomScanSiruta === siruta && noGeomScan !== null) return; - void handleNoGeomScan(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [siruta, session.connected]); + if (!siruta || !session.connected) return; + // Don't re-scan if we already scanned (or are scanning) this siruta + if (noGeomAutoScanRef.current === siruta) return; + noGeomAutoScanRef.current = siruta; + void handleNoGeomScan(siruta); + }, [siruta, session.connected, handleNoGeomScan]); /* ════════════════════════════════════════════════════════════ */ /* Layer feature counts */