'use client' import { useCallback, useEffect, useMemo, useRef } from 'react' import MarkerIcon from '@/components/icons/MarkerIcon' import { getMapirMapComponent, MAPIR_STYLE_URL } from '@/components/map/mapirMapFactory' import { getPublicMapApiKey, toMapirLngLat } from '@/helpers/mapir' interface MapirLocationPickerProps { centerLat: number centerLng: number markerLat?: number | null markerLng?: number | null zoom?: number scrollZoom?: boolean height?: number | string onLocationPick: (lat: number, lng: number) => void } interface MapLike { resize: () => void jumpTo: (opts: { center: [number, number] }) => void } const DEFAULT_ZOOM = 13 const MapirLocationPicker = ({ centerLat, centerLng, markerLat, markerLng, zoom = DEFAULT_ZOOM, scrollZoom = true, height = '100%', onLocationPick, }: MapirLocationPickerProps) => { const apiKey = getPublicMapApiKey() const Map = useMemo(() => { const k = apiKey.trim() if (!k) return null return getMapirMapComponent(k) }, [apiKey]) // اگر مارکر انتخاب شده، همان نقطه مرکز نقشه باشد تا پین وسط روی موقعیت درست بنشیند const viewLat = markerLat != null && Number.isFinite(markerLat) ? markerLat : centerLat const viewLng = markerLng != null && Number.isFinite(markerLng) ? markerLng : centerLng const center = useMemo(() => toMapirLngLat(viewLat, viewLng), [viewLat, viewLng]) const zoomArr = useMemo(() => [zoom] as [number], [zoom]) const mapRef = useRef(null) const onPickRef = useRef(onLocationPick) const rootRef = useRef(null) const hasSelection = markerLat != null && markerLng != null && Number.isFinite(markerLat) && Number.isFinite(markerLng) useEffect(() => { onPickRef.current = onLocationPick }, [onLocationPick]) useEffect(() => { const root = rootRef.current if (!root || typeof ResizeObserver === 'undefined') return const resize = () => { mapRef.current?.resize() } const observer = new ResizeObserver(resize) observer.observe(root) const timer = window.setTimeout(resize, 320) return () => { observer.disconnect() window.clearTimeout(timer) } }, []) const onStyleLoad = useCallback((map: MapLike) => { mapRef.current = map map.resize() }, []) // mapir-react listener اول onClick را نگه می‌دارد؛ pick را از ref می‌خوانیم const onClick = useCallback((_map: MapLike, evt: { lngLat?: { lat: number; lng: number } }) => { const ll = evt?.lngLat if (!ll) return // پین CSS همیشه وسط است؛ با jumpTo نقطهٔ کلیک زیر پین می‌آید mapRef.current?.jumpTo({ center: [ll.lng, ll.lat] }) onPickRef.current(ll.lat, ll.lng) }, []) if (!Map) { return null } // Map.ir Map is memoized/cached by API key in getMapirMapComponent — not recreated each render. /* eslint-disable react-hooks/static-components -- Map component comes from mapir setToken cache */ return (
{/* پین ثابت وسط نقشه — بدون وابستگی به Mapir.Marker که در مودال نامرئی می‌ماند */}
) /* eslint-enable react-hooks/static-components */ } export default MapirLocationPicker