import { useEffect, useState } from 'react'; import { MapContainer, TileLayer, Marker, Popup, useMap } from 'react-leaflet'; import L, { type LatLngExpression, type LatLngTuple } from 'leaflet'; import iconRetinaUrl from 'leaflet/dist/images/marker-icon-2x.png'; import iconUrl from 'leaflet/dist/images/marker-icon.png'; import shadowUrl from 'leaflet/dist/images/marker-shadow.png'; import 'leaflet/dist/leaflet.css'; import useMediaQuery from '../../../../hooks/useMediaQuery'; import type { BreweryLocation } from '../../breweries.server'; import { formatBreweryAddress } from '../../utils/format-address'; delete (L.Icon.Default.prototype as unknown as { _getIconUrl?: unknown })._getIconUrl; L.Icon.Default.mergeOptions({ iconRetinaUrl, iconUrl, shadowUrl }); export interface BreweryMapPin { id: string; name: string; latitude: number; longitude: number; location: BreweryLocation | null; } interface BreweryMapProps { breweries: BreweryMapPin[]; } const FALLBACK_CENTER: LatLngExpression = [20, 0]; const WORLD_BOUNDS: LatLngTuple[] = [ [-90, -180], [90, 180], ]; const CURRENT_LOCATION_ICON = L.divIcon({ className: 'brewery-map-current-location', html: '', iconSize: [14, 14], iconAnchor: [7, 7], }); const useCurrentLocation = () => { const [position, setPosition] = useState(null); useEffect(() => { if (!navigator.geolocation) return; navigator.geolocation.getCurrentPosition( (pos) => setPosition([pos.coords.latitude, pos.coords.longitude]), () => setPosition(null), { enableHighAccuracy: true }, ); }, []); return position; }; const CurrentLocationMarker = ({ position }: { position: LatLngTuple }) => ( Your location ); const CURRENT_LOCATION_ZOOM = 6; const RecenterMap = ({ bounds, currentLocation, }: { bounds: LatLngTuple[]; currentLocation: LatLngTuple | null; }) => { const map = useMap(); useEffect(() => { if (currentLocation) { map.setView(currentLocation, CURRENT_LOCATION_ZOOM, { animate: false }); } else if (bounds.length > 0) { map.fitBounds(bounds, { padding: [32, 32], maxZoom: 6, animate: false }); } }, [map, bounds, currentLocation]); return null; }; const BreweryMap = ({ breweries }: BreweryMapProps) => { const currentLocation = useCurrentLocation(); const bounds: LatLngTuple[] = breweries.map((brewery) => [brewery.latitude, brewery.longitude]); return ( {currentLocation && } {breweries.map((brewery) => (

{brewery.name}

{brewery.location && (

{formatBreweryAddress(brewery.location)}

)} View brewery →
))}
); }; export default BreweryMap;