import React, { useEffect, useRef } from 'react'; import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; // Fix for default marker icon in Leaflet with Next.js if (typeof window !== 'undefined') { const DefaultIcon = L.icon({ iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png', shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png', iconSize: [25, 41], iconAnchor: [12, 41], }); L.Marker.prototype.options.icon = DefaultIcon; } export interface MapLocation { name: string; address: string; lat: number; lng: number; } interface LeafletMapProps { locations: MapLocation[]; } export default function LeafletMap({ locations }: LeafletMapProps) { const mapRef = useRef(null); const mapInstanceRef = useRef(null); useEffect(() => { if (!mapRef.current || mapInstanceRef.current || !locations.length) return; // Calculate center based on markers or first marker const firstLoc = locations[0]; const map = L.map(mapRef.current, { center: [firstLoc.lat, firstLoc.lng], zoom: 6, // Zoom out to see both or more scrollWheelZoom: false, }); // Add tiles (Dark mode themed for industrial feel if possible, but standard OSM is safer for now) L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', }).addTo(map); const bounds = L.latLngBounds([]); locations.forEach((loc) => { const marker = L.marker([loc.lat, loc.lng]).addTo(map); const popupContent = `
${loc.name}
${loc.address.replace(/\n/g, '
')}
`; marker.bindPopup(popupContent); bounds.extend([loc.lat, loc.lng]); }); // Fit bounds if more than 1 location if (locations.length > 1) { map.fitBounds(bounds, { padding: [50, 50] }); } mapInstanceRef.current = map; // Cleanup on unmount return () => { if (mapInstanceRef.current) { mapInstanceRef.current.remove(); mapInstanceRef.current = null; } }; }, [locations]); return
; }