{"version":3,"sources":["../src/hooks/useMapData.ts"],"sourcesContent":["import { useState, useEffect, useCallback, useRef } from 'react';\nimport type { FeatureCollection, MultiPolygon, Polygon } from 'geojson';\nimport type { RegionData as ChoroplethRegionData } from '../components/ChoroplethMap/ChoroplethMap.types';\nimport type {\n  MapFilters,\n  MapDataBounds,\n  MapDataRegion,\n  MapDataApiResponse,\n} from '../types/mapData';\n\n/**\n * Hook return type for useMapData\n */\nexport interface UseMapDataReturn {\n  /** Transformed region data for ChoroplethMap */\n  data: ChoroplethRegionData[];\n  /** Map bounds from API */\n  bounds: MapDataBounds | null;\n  /** Complete GeoJSON with NRE field for each municipality */\n  geoJSON: FeatureCollection<Polygon | MultiPolygon> | null;\n  /** Loading state */\n  loading: boolean;\n  /** Error message if request failed */\n  error: string | null;\n  /** Refetch data from API */\n  refetch: () => Promise<void>;\n}\n\n/**\n * Transform enriched GeoJSON features to ChoroplethMap region data.\n *\n * Each feature is one municipality: `name` is the city and `value`/`accessCount`\n * are its own per-city metric (colored individually). `groupName` carries the\n * NRE label used only to draw the grouping outline.\n *\n * @param geoJSON - Enriched GeoJSON FeatureCollection from backend\n * @returns Array of region data for ChoroplethMap\n */\nfunction transformGeoJSONFeatures(\n  geoJSON: FeatureCollection<Polygon | MultiPolygon>\n): ChoroplethRegionData[] {\n  return geoJSON.features.map((feature) => ({\n    id: feature.properties?.GEOCODIGO || feature.properties?.NOME || '',\n    name: feature.properties?.NOME || '',\n    groupName: feature.properties?.NRE\n      ? `NRE ${feature.properties.NRE}`\n      : undefined,\n    value: feature.properties?.value ?? 0,\n    accessCount: feature.properties?.totalAccess ?? 0,\n    geoJson: feature,\n    isManagedRegion: feature.properties?.isManagedRegion !== false,\n    accessBreakdown: feature.properties?.accessBreakdown,\n  }));\n}\n\n/**\n * Transform API region data to ChoroplethMap region data (fallback)\n * @param region - Region data from API\n * @returns Transformed region data for ChoroplethMap or null if no geoJson\n */\nfunction transformRegionData(\n  region: MapDataRegion\n): ChoroplethRegionData | null {\n  if (!region.geoJson) {\n    return null;\n  }\n\n  return {\n    id: region.schoolGroupId,\n    name: region.schoolGroupName,\n    code: region.schoolGroupCode,\n    value: region.value,\n    accessCount: region.totalAccess,\n    geoJson: region.geoJson,\n    isManagedRegion: region.isManagedRegion !== false,\n  };\n}\n\n/**\n * Factory function to create useMapData hook\n *\n * @param fetchMapDataApi - Function to fetch map data from API\n * @returns Hook for managing map data with auto-fetch on filter change\n *\n * @example\n * ```tsx\n * // In your app setup\n * const fetchMapDataApi = async (filters: MapFilters) => {\n *   const response = await api.post('/access-report/access/map', filters);\n *   return response.data;\n * };\n *\n * export const useMapData = createUseMapData(fetchMapDataApi);\n *\n * // In your component\n * const { data, bounds, loading, error } = useMapData(filters);\n * ```\n */\nexport const createUseMapData = (\n  fetchMapDataApi: (filters: MapFilters) => Promise<MapDataApiResponse>\n) => {\n  return (filters: MapFilters): UseMapDataReturn => {\n    const filtersRef = useRef(filters);\n    filtersRef.current = filters;\n    const filtersKey = JSON.stringify(filters);\n    const fetchIdRef = useRef(0);\n\n    const [data, setData] = useState<ChoroplethRegionData[]>([]);\n    const [bounds, setBounds] = useState<MapDataBounds | null>(null);\n    const [geoJSON, setGeoJSON] = useState<FeatureCollection<\n      Polygon | MultiPolygon\n    > | null>(null);\n    const [loading, setLoading] = useState(true);\n    const [error, setError] = useState<string | null>(null);\n\n    const fetchData = useCallback(async () => {\n      const fetchId = ++fetchIdRef.current;\n      setLoading(true);\n      setError(null);\n\n      try {\n        const mapData = await fetchMapDataApi(filtersRef.current);\n        if (fetchIdRef.current !== fetchId) return;\n\n        const transformedRegions = mapData.data.geoJSON\n          ? transformGeoJSONFeatures(mapData.data.geoJSON)\n          : mapData.data.regions\n              .map(transformRegionData)\n              .filter((r): r is ChoroplethRegionData => r !== null);\n        setData(transformedRegions);\n        setBounds(mapData.data.bounds);\n        setGeoJSON(mapData.data.geoJSON ?? null);\n      } catch (err) {\n        if (fetchIdRef.current !== fetchId) return;\n        const errorMessage =\n          err instanceof Error ? err.message : 'Erro ao carregar dados do mapa';\n        setError(errorMessage);\n        setData([]);\n        setBounds(null);\n        setGeoJSON(null);\n      } finally {\n        if (fetchIdRef.current === fetchId) {\n          setLoading(false);\n        }\n      }\n    }, [filtersKey]);\n\n    useEffect(() => {\n      fetchData();\n    }, [fetchData]);\n\n    return {\n      data,\n      bounds,\n      geoJSON,\n      loading,\n      error,\n      refetch: fetchData,\n    };\n  };\n};\n"],"mappings":";AAAA,SAAS,UAAU,WAAW,aAAa,cAAc;AAsCzD,SAAS,yBACP,SACwB;AACxB,SAAO,QAAQ,SAAS,IAAI,CAAC,aAAa;AAAA,IACxC,IAAI,QAAQ,YAAY,aAAa,QAAQ,YAAY,QAAQ;AAAA,IACjE,MAAM,QAAQ,YAAY,QAAQ;AAAA,IAClC,WAAW,QAAQ,YAAY,MAC3B,OAAO,QAAQ,WAAW,GAAG,KAC7B;AAAA,IACJ,OAAO,QAAQ,YAAY,SAAS;AAAA,IACpC,aAAa,QAAQ,YAAY,eAAe;AAAA,IAChD,SAAS;AAAA,IACT,iBAAiB,QAAQ,YAAY,oBAAoB;AAAA,IACzD,iBAAiB,QAAQ,YAAY;AAAA,EACvC,EAAE;AACJ;AAOA,SAAS,oBACP,QAC6B;AAC7B,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO;AAAA,EACT;AAEA,SAAO;AAAA,IACL,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,MAAM,OAAO;AAAA,IACb,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,SAAS,OAAO;AAAA,IAChB,iBAAiB,OAAO,oBAAoB;AAAA,EAC9C;AACF;AAsBO,IAAM,mBAAmB,CAC9B,oBACG;AACH,SAAO,CAAC,YAA0C;AAChD,UAAM,aAAa,OAAO,OAAO;AACjC,eAAW,UAAU;AACrB,UAAM,aAAa,KAAK,UAAU,OAAO;AACzC,UAAM,aAAa,OAAO,CAAC;AAE3B,UAAM,CAAC,MAAM,OAAO,IAAI,SAAiC,CAAC,CAAC;AAC3D,UAAM,CAAC,QAAQ,SAAS,IAAI,SAA+B,IAAI;AAC/D,UAAM,CAAC,SAAS,UAAU,IAAI,SAEpB,IAAI;AACd,UAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,UAAM,CAAC,OAAO,QAAQ,IAAI,SAAwB,IAAI;AAEtD,UAAM,YAAY,YAAY,YAAY;AACxC,YAAM,UAAU,EAAE,WAAW;AAC7B,iBAAW,IAAI;AACf,eAAS,IAAI;AAEb,UAAI;AACF,cAAM,UAAU,MAAM,gBAAgB,WAAW,OAAO;AACxD,YAAI,WAAW,YAAY,QAAS;AAEpC,cAAM,qBAAqB,QAAQ,KAAK,UACpC,yBAAyB,QAAQ,KAAK,OAAO,IAC7C,QAAQ,KAAK,QACV,IAAI,mBAAmB,EACvB,OAAO,CAAC,MAAiC,MAAM,IAAI;AAC1D,gBAAQ,kBAAkB;AAC1B,kBAAU,QAAQ,KAAK,MAAM;AAC7B,mBAAW,QAAQ,KAAK,WAAW,IAAI;AAAA,MACzC,SAAS,KAAK;AACZ,YAAI,WAAW,YAAY,QAAS;AACpC,cAAM,eACJ,eAAe,QAAQ,IAAI,UAAU;AACvC,iBAAS,YAAY;AACrB,gBAAQ,CAAC,CAAC;AACV,kBAAU,IAAI;AACd,mBAAW,IAAI;AAAA,MACjB,UAAE;AACA,YAAI,WAAW,YAAY,SAAS;AAClC,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,IACF,GAAG,CAAC,UAAU,CAAC;AAEf,cAAU,MAAM;AACd,gBAAU;AAAA,IACZ,GAAG,CAAC,SAAS,CAAC;AAEd,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX;AAAA,EACF;AACF;","names":[]}