"use client"; import { MapContainer, TileLayer, Marker } from 'react-leaflet'; import 'leaflet/dist/leaflet.css'; import L from 'leaflet'; import { useState, useEffect } from 'react'; import { useTheme } from "next-themes"; import Navbar from "./Navbar"; import { MapStyleControl } from "./MapStyleControl"; import { ZoomControls } from "./ZoomControls"; interface CoffeeShop { id: number; name: string; description: string; lat: number; lng: number; address: string; phone: string; website: string; image: string; } interface MapProps { shops: CoffeeShop[]; onShopSelect: (shop: CoffeeShop) => void; } const Map = ({ shops, onShopSelect }: MapProps) => { useEffect(() => { // Fix for Leaflet default icon not found // @ts-expect-error Fix for Leaflet default icon not found delete L.Icon.Default.prototype._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', }); }, []); const createCustomIcon = () => { return new L.DivIcon({ className: 'custom-icon', html: `
`, iconSize: [32, 32], iconAnchor: [16, 32], popupAnchor: [0, -32], }); }; const customIcon = createCustomIcon(); const { resolvedTheme, setTheme } = useTheme(); const [mapStyle, setMapStyle] = useState(resolvedTheme === 'light' ? 'light' : 'dark'); // Sync map style with theme useEffect(() => { if (resolvedTheme === 'dark' && mapStyle === 'light') { setMapStyle('dark'); } else if (resolvedTheme === 'light' && (mapStyle === 'dark' || mapStyle === 'satellite')) { setMapStyle('light'); } }, [resolvedTheme, mapStyle]); // Handle manual style change const handleStyleChange = (newStyle: string) => { setMapStyle(newStyle); if (newStyle === 'dark') { setTheme('dark'); } else if (newStyle === 'light') { setTheme('light'); } else if (newStyle === 'satellite') { setTheme('dark'); } }; const getTileLayer = () => { switch (mapStyle) { case "light": return "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png"; case "satellite": return "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"; case "dark": default: return "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"; } }; const getAttribution = () => { switch (mapStyle) { case "satellite": return 'Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'; default: return '© OpenStreetMap contributors © CARTO'; } }; return (
{shops.map((shop) => ( onShopSelect(shop), }} /> ))}
); }; export default Map;