"use client" import { useEffect, useRef, useState } from "react" import mapboxgl from "mapbox-gl" import "mapbox-gl/dist/mapbox-gl.css" import { MapPin } from "lucide-react" type LngLat = { lng: number; lat: number } /** * MapPointPicker * * Rendered ONLY when the user chooses "Velg punkt på kart", and always via * next/dynamic(..., { ssr: false }) from the parent. It mounts once per * sheet-open and stays mounted until the sheet closes, so the Mapbox map is * created exactly once (empty-deps useEffect) — taps, pans and marker drags * never re-initialise it. This keeps Mapbox map loads (which are billed) to a * single load per sheet-open. */ export function MapPointPicker({ onConfirm }: { onConfirm: (lngLat: LngLat) => void }) { const containerRef = useRef(null) const mapRef = useRef(null) const markerRef = useRef(null) const [loaded, setLoaded] = useState(false) const [point, setPoint] = useState(null) const [error, setError] = useState(null) useEffect(() => { const token = process.env.NEXT_PUBLIC_MAPBOX_TOKEN const container = containerRef.current if (!container) return if (!token) { setError("Kartet er ikke tilgjengelig akkurat nå. Bruk «Min posisjon nå» i stedet.") return } mapboxgl.accessToken = token const map = new mapboxgl.Map({ container, style: "mapbox://styles/mapbox/satellite-v9", center: [10.7522, 59.9139], // Oslo fallback; real app centers on last-known position zoom: 16, attributionControl: false, }) mapRef.current = map map.on("load", () => setLoaded(true)) map.on("error", () => setError("Kunne ikke laste kartet.")) // Tap to place/move a single draggable marker — never re-inits the map. map.on("click", (e) => { const lngLat = { lng: e.lngLat.lng, lat: e.lngLat.lat } if (!markerRef.current) { const marker = new mapboxgl.Marker({ draggable: true, color: "#d2551a" }) .setLngLat(e.lngLat) .addTo(map) marker.on("dragend", () => { const p = marker.getLngLat() setPoint({ lng: p.lng, lat: p.lat }) }) markerRef.current = marker } else { markerRef.current.setLngLat(e.lngLat) } setPoint(lngLat) }) return () => { markerRef.current?.remove() markerRef.current = null map.remove() mapRef.current = null } }, []) return (
{/* Map canvas host — kept mounted for the map's whole lifetime. */}
{!loaded && !error ? (

Laster kart …

) : null} {error ? (

{error}

) : null} {loaded && !point && !error ? (

) : null}
) } export default MapPointPicker