import { useState, useEffect, useRef } from 'react'; import type { Bounds, POI, POIResponse } from '../types'; import { apiUrl, logNonAbortError, authHeaders } from '../lib/api'; const DEBOUNCE_MS = 150; export function usePOIData(bounds: Bounds | null, selectedCategories: Set) { const [pois, setPois] = useState([]); const debounceRef = useRef | null>(null); const abortControllerRef = useRef(null); useEffect(() => { if (!bounds || selectedCategories.size === 0) { setPois([]); return; } if (debounceRef.current) { clearTimeout(debounceRef.current); } debounceRef.current = setTimeout(async () => { if (abortControllerRef.current) { abortControllerRef.current.abort(); } abortControllerRef.current = new AbortController(); try { const boundsStr = `${bounds.south},${bounds.west},${bounds.north},${bounds.east}`; const categoriesStr = Array.from(selectedCategories).join(','); const params = new URLSearchParams({ categories: categoriesStr, bounds: boundsStr, }); const res = await fetch( apiUrl('pois', params), authHeaders({ signal: abortControllerRef.current.signal, }) ); const json: POIResponse = await res.json(); setPois(json.pois || []); } catch (err) { logNonAbortError('Failed to fetch POIs', err); } }, DEBOUNCE_MS); return () => { if (debounceRef.current) { clearTimeout(debounceRef.current); } }; }, [bounds, selectedCategories]); return pois; }