/** * LeafletMapInner Component * Internal Leaflet map implementation (client-side only) */ 'use client'; import { useEffect, useRef } from 'react'; import L from 'leaflet'; import 'leaflet/dist/leaflet.css'; import type { School } from '@/lib/types'; // Fix for default marker icons in Next.js delete (L.Icon.Default.prototype as any)._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon-2x.png', iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-icon.png', shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.7.1/images/marker-shadow.png', }); interface LeafletMapInnerProps { schools: School[]; center: [number, number]; zoom: number; onMarkerClick?: (school: School) => void; } export default function LeafletMapInner({ schools, center, zoom, onMarkerClick }: LeafletMapInnerProps) { const mapRef = useRef(null); const mapContainerRef = useRef(null); useEffect(() => { if (!mapContainerRef.current) return; // Initialize map if (!mapRef.current) { mapRef.current = L.map(mapContainerRef.current).setView(center, zoom); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors', maxZoom: 19, }).addTo(mapRef.current); } // Clear existing markers mapRef.current.eachLayer((layer) => { if (layer instanceof L.Marker) { mapRef.current!.removeLayer(layer); } }); // Add markers for schools schools.forEach((school) => { if (school.latitude && school.longitude && mapRef.current) { const marker = L.marker([school.latitude, school.longitude]).addTo(mapRef.current); // Create popup content const popupContent = `
${school.school_name} ${school.local_authority ? `
📍 ${school.local_authority}
` : ''} ${school.school_type ? `
🏫 ${school.school_type}
` : ''} View Details
`; marker.bindPopup(popupContent); if (onMarkerClick) { marker.on('click', () => onMarkerClick(school)); } } }); // Update map view if (schools.length > 1) { const bounds = L.latLngBounds( schools .filter(s => s.latitude && s.longitude) .map(s => [s.latitude!, s.longitude!] as [number, number]) ); mapRef.current.fitBounds(bounds, { padding: [50, 50] }); } else { mapRef.current.setView(center, zoom); } // Cleanup return () => { // Don't destroy map on every update, just clean markers }; }, [schools, center, zoom, onMarkerClick]); // Cleanup map on unmount useEffect(() => { return () => { if (mapRef.current) { mapRef.current.remove(); mapRef.current = null; } }; }, []); return
; }