'use client' import { createContext, useContext, useState, useRef, useMemo, useCallback, type ReactNode, } from 'react' import type { MapRef } from 'react-map-gl/maplibre' import type { MapContextValue, MapViewport, MarkerData } from '../types' const MapContext = createContext(null) export interface MapProviderProps { children: ReactNode initialViewport?: Partial } const DEFAULT_VIEWPORT: MapViewport = { longitude: 115.1889, latitude: -8.4095, zoom: 10, bearing: 0, pitch: 0, } export function MapProvider({ children, initialViewport }: MapProviderProps) { const mapRef = useRef(null) const initialViewportRef = useRef({ ...DEFAULT_VIEWPORT, ...initialViewport, }) const [viewport, setViewportState] = useState(initialViewportRef.current) const [markers, setMarkers] = useState([]) const [selectedMarker, setSelectedMarker] = useState(null) const [hoveredFeature, setHoveredFeature] = useState(null) const [isLoaded, setIsLoaded] = useState(false) const setViewport = useCallback((newViewport: Partial) => { setViewportState((prev) => ({ ...prev, ...newViewport })) }, []) const resetToInitial = useCallback(() => { const map = mapRef.current if (map) { map.flyTo({ center: [initialViewportRef.current.longitude, initialViewportRef.current.latitude], zoom: initialViewportRef.current.zoom, bearing: initialViewportRef.current.bearing ?? 0, pitch: initialViewportRef.current.pitch ?? 0, duration: 1000, }) } }, []) const value = useMemo( () => ({ mapRef, viewport, setViewport, initialViewport: initialViewportRef.current, resetToInitial, markers, setMarkers, selectedMarker, setSelectedMarker, hoveredFeature, setHoveredFeature, isLoaded, setIsLoaded, }), [viewport, setViewport, resetToInitial, markers, selectedMarker, hoveredFeature, isLoaded] ) return {children} } export function useMapContext(): MapContextValue { const context = useContext(MapContext) if (!context) { throw new Error('useMapContext must be used within a MapProvider') } return context } export { MapContext }