Spaces:
Build error
Build error
| import { useState, useEffect, useRef, useCallback } from 'react' | |
| export default function useMapData(filters, viewport, zoom, mapMode, buildFilterParams) { | |
| const [geojson, setGeojson] = useState(null) | |
| const [loading, setLoading] = useState(true) | |
| const [totalInViewport, setTotalInViewport] = useState(0) | |
| const abortRef = useRef(null) | |
| const debounceRef = useRef(null) | |
| const fetchData = useCallback(async () => { | |
| if (abortRef.current) abortRef.current.abort() | |
| const controller = new AbortController() | |
| abortRef.current = controller | |
| setLoading(true) | |
| try { | |
| const params = new URLSearchParams() | |
| params.set('min_lng', viewport.min_lng) | |
| params.set('max_lng', viewport.max_lng) | |
| params.set('min_lat', viewport.min_lat) | |
| params.set('max_lat', viewport.max_lat) | |
| params.set('zoom', zoom) | |
| buildFilterParams(params) | |
| const endpoint = mapMode === 'heatmap' ? `/api/entities/geojson?${params}&max_features=5000` : `/api/entities/clusters?${params}` | |
| const resp = await fetch(endpoint, { signal: controller.signal }) | |
| const data = await resp.json() | |
| setGeojson(data) | |
| setTotalInViewport(data.total_count || data.features?.length || 0) | |
| } catch (err) { | |
| if (err.name !== 'AbortError') console.error('Failed to fetch data:', err) | |
| } | |
| setLoading(false) | |
| }, [viewport, zoom, filters, mapMode, buildFilterParams]) | |
| useEffect(() => { | |
| clearTimeout(debounceRef.current) | |
| debounceRef.current = setTimeout(fetchData, 200) | |
| return () => clearTimeout(debounceRef.current) | |
| }, [fetchData]) | |
| return { geojson, loading, totalInViewport, fetchData } | |
| } | |