227 lines
8.1 KiB
TypeScript
227 lines
8.1 KiB
TypeScript
// "use client"
|
|
|
|
// import { useState, useEffect, useRef } from "react"
|
|
// import { useMap } from "react-map-gl/mapbox"
|
|
// import { MAPBOX_TILESET_ID } from "@/app/_utils/const/map"
|
|
// import { $Enums } from "@prisma/client"
|
|
|
|
// import type { ICrimes } from "@/app/_utils/types/crimes"
|
|
// import DistrictLayer, { DistrictFeature } from "./district-layer"
|
|
// import DistrictExtrusionLayer from "./district-extrusion-layer"
|
|
// import CrimeClusterLayer from "./crime-cluster-layer"
|
|
|
|
// export interface MapLayerManagerProps {
|
|
// visible?: boolean
|
|
// crimes: ICrimes[]
|
|
// year: string
|
|
// month: string
|
|
// filterCategory: string | "all"
|
|
// tilesetId?: string
|
|
// isTimelapsePlaying?: boolean
|
|
// onDistrictClick?: (feature: DistrictFeature) => void
|
|
// }
|
|
|
|
// export default function MapLayerManager({
|
|
// visible = true,
|
|
// crimes = [],
|
|
// year,
|
|
// month,
|
|
// filterCategory = "all",
|
|
// tilesetId = MAPBOX_TILESET_ID,
|
|
// isTimelapsePlaying = false,
|
|
// onDistrictClick,
|
|
// }: MapLayerManagerProps) {
|
|
// const { current: map } = useMap()
|
|
// const [focusedDistrictId, setFocusedDistrictId] = useState<string | null>(null)
|
|
// const [isStyleLoaded, setIsStyleLoaded] = useState<boolean>(false)
|
|
// const [beforeId, setBeforeId] = useState<string | undefined>(undefined)
|
|
// const initAttempts = useRef(0)
|
|
|
|
// // Compute crime data by district for all layer components to use
|
|
// const crimeDataByDistrict = crimes.reduce(
|
|
// (acc, crime) => {
|
|
// const districtId = crime.district_id
|
|
// acc[districtId] = {
|
|
// number_of_crime: crime.number_of_crime,
|
|
// level: crime.level,
|
|
// }
|
|
// return acc
|
|
// },
|
|
// {} as Record<string, { number_of_crime?: number; level?: $Enums.crime_rates }>,
|
|
// )
|
|
|
|
// // Ensure map is ready after mounting - try multiple approaches
|
|
// useEffect(() => {
|
|
// if (!map) {
|
|
// console.error("Map not available in MapLayerManager");
|
|
// return;
|
|
// }
|
|
|
|
// console.log("MapLayerManager mounted, checking map status");
|
|
|
|
// // Direct initialization if already loaded
|
|
// if (map.getMap().isStyleLoaded()) {
|
|
// console.log("Map style already loaded - direct init");
|
|
// setIsStyleLoaded(true);
|
|
// try {
|
|
// const layers = map.getMap().getStyle().layers;
|
|
// for (const layer of layers) {
|
|
// if (layer.type === "symbol") {
|
|
// setBeforeId(layer.id);
|
|
// break;
|
|
// }
|
|
// }
|
|
// } catch (err) {
|
|
// console.warn("Error finding symbol layer:", err);
|
|
// }
|
|
// return;
|
|
// }
|
|
|
|
// // Listen for style load event
|
|
// const onStyleLoad = () => {
|
|
// console.log("Map style.load event fired");
|
|
// setIsStyleLoaded(true);
|
|
// try {
|
|
// const layers = map.getMap().getStyle().layers;
|
|
// for (const layer of layers) {
|
|
// if (layer.type === "symbol") {
|
|
// setBeforeId(layer.id);
|
|
// break;
|
|
// }
|
|
// }
|
|
// } catch (err) {
|
|
// console.warn("Error finding symbol layer:", err);
|
|
// }
|
|
// };
|
|
|
|
// // Add event listener
|
|
// map.getMap().once('style.load', onStyleLoad);
|
|
|
|
// // Multiple retry attempts with increasing delays
|
|
// const checkStyleLoaded = () => {
|
|
// initAttempts.current += 1;
|
|
|
|
// if (initAttempts.current > 10) {
|
|
// console.error("Failed to detect loaded map style after 10 attempts");
|
|
// return;
|
|
// }
|
|
|
|
// if (map.getMap().isStyleLoaded()) {
|
|
// console.log(`Map style loaded (detected on attempt ${initAttempts.current})`);
|
|
// map.getMap().off('style.load', onStyleLoad);
|
|
// setIsStyleLoaded(true);
|
|
// try {
|
|
// const layers = map.getMap().getStyle().layers;
|
|
// for (const layer of layers) {
|
|
// if (layer.type === "symbol") {
|
|
// setBeforeId(layer.id);
|
|
// break;
|
|
// }
|
|
// }
|
|
// } catch (err) {
|
|
// console.warn("Error finding symbol layer:", err);
|
|
// }
|
|
// } else {
|
|
// console.log(`Waiting for map style to load... (attempt ${initAttempts.current})`);
|
|
// setTimeout(checkStyleLoaded, 200 * initAttempts.current); // Increasing delay
|
|
// }
|
|
// };
|
|
|
|
// // Start checking after a short delay
|
|
// setTimeout(checkStyleLoaded, 100);
|
|
|
|
// // Cleanup
|
|
// return () => {
|
|
// map.getMap().off('style.load', onStyleLoad);
|
|
// };
|
|
// }, [map]);
|
|
|
|
// // Force a re-check when map or visibility changes
|
|
// useEffect(() => {
|
|
// if (!map || !visible) return;
|
|
|
|
// if (!isStyleLoaded && map.getMap().isStyleLoaded()) {
|
|
// console.log("Map style detected as loaded after prop change");
|
|
// setIsStyleLoaded(true);
|
|
// try {
|
|
// const layers = map.getMap().getStyle().layers;
|
|
// for (const layer of layers) {
|
|
// if (layer.type === "symbol") {
|
|
// setBeforeId(layer.id);
|
|
// break;
|
|
// }
|
|
// }
|
|
// } catch (err) {
|
|
// console.warn("Error finding symbol layer:", err);
|
|
// }
|
|
// }
|
|
// }, [map, visible, isStyleLoaded]);
|
|
|
|
// // Print debug info
|
|
// useEffect(() => {
|
|
// console.log("MapLayerManager state:", {
|
|
// mapAvailable: !!map,
|
|
// isStyleLoaded,
|
|
// beforeId,
|
|
// crimeCount: crimes.length,
|
|
// visible
|
|
// });
|
|
// }, [map, isStyleLoaded, beforeId, crimes, visible]);
|
|
|
|
// // Debug: Force isStyleLoaded after a timeout as a last resort
|
|
// useEffect(() => {
|
|
// if (isStyleLoaded || !map) return;
|
|
|
|
// const forceTimeout = setTimeout(() => {
|
|
// if (!isStyleLoaded && map) {
|
|
// console.warn("Forcing isStyleLoaded=true after timeout");
|
|
// setIsStyleLoaded(true);
|
|
// }
|
|
// }, 2000);
|
|
|
|
// return () => clearTimeout(forceTimeout);
|
|
// }, [map, isStyleLoaded]);
|
|
|
|
// if (!visible || !map) {
|
|
// console.log("MapLayerManager not rendering: visible=", visible, "map=", !!map);
|
|
// return null;
|
|
// }
|
|
|
|
// return (
|
|
// <>
|
|
// {map && (isStyleLoaded || initAttempts.current > 5) && (
|
|
// <>
|
|
// <DistrictLayer
|
|
// visible={true}
|
|
// onClick={onDistrictClick}
|
|
// year={year}
|
|
// month={month}
|
|
// filterCategory={filterCategory}
|
|
// crimes={crimes}
|
|
// tilesetId={tilesetId}
|
|
// isTimelapsePlaying={isTimelapsePlaying}
|
|
// onDistrictFocus={setFocusedDistrictId}
|
|
// />
|
|
|
|
// <DistrictExtrusionLayer
|
|
// visible={true}
|
|
// focusedDistrictId={focusedDistrictId}
|
|
// crimeDataByDistrict={crimeDataByDistrict}
|
|
// tilesetId={tilesetId!}
|
|
// beforeId={beforeId}
|
|
// />
|
|
|
|
// <CrimeClusterLayer
|
|
// visible={!focusedDistrictId}
|
|
// crimes={crimes}
|
|
// filterCategory={filterCategory}
|
|
// isTimelapsePlaying={isTimelapsePlaying}
|
|
// beforeId={beforeId}
|
|
// />
|
|
// </>
|
|
// )
|
|
// }
|
|
// </>
|
|
// );
|
|
// }
|