69 lines
2.0 KiB
React
69 lines
2.0 KiB
React
import { MapContainer, TileLayer, Marker, useMapEvents } from "react-leaflet";
|
|
import L from "leaflet";
|
|
|
|
// Configuración del icono por defecto. Leaflet no encuentra sus iconos cuando
|
|
// se empaqueta con Vite; los referenciamos desde el CDN para no copiar
|
|
// archivos a public/.
|
|
const icon = new L.Icon({
|
|
iconUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png",
|
|
iconRetinaUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png",
|
|
shadowUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png",
|
|
iconSize: [25, 41],
|
|
iconAnchor: [12, 41],
|
|
});
|
|
|
|
const DEFAULT_CENTER = [40.4168, -3.7038];
|
|
const DEFAULT_ZOOM = 13;
|
|
|
|
function LocationPicker({ onPick }) {
|
|
useMapEvents({
|
|
click(e) {
|
|
onPick({ lat: e.latlng.lat, lng: e.latlng.lng });
|
|
},
|
|
});
|
|
return null;
|
|
}
|
|
|
|
export default function MapView({
|
|
businesses,
|
|
selectedId,
|
|
onSelect,
|
|
pickingLocation,
|
|
onPickLocation,
|
|
pickedLocation,
|
|
}) {
|
|
return (
|
|
<div className="map">
|
|
<MapContainer
|
|
center={DEFAULT_CENTER}
|
|
zoom={DEFAULT_ZOOM}
|
|
style={{ height: "100%", width: "100%" }}
|
|
>
|
|
<TileLayer
|
|
attribution='© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
|
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
/>
|
|
{businesses.map((b) => (
|
|
<Marker
|
|
key={b.id}
|
|
position={[b.lat, b.lng]}
|
|
icon={icon}
|
|
eventHandlers={{ click: () => onSelect(b.id) }}
|
|
opacity={selectedId && selectedId !== b.id ? 0.6 : 1}
|
|
/>
|
|
))}
|
|
{pickingLocation && <LocationPicker onPick={onPickLocation} />}
|
|
{pickedLocation && (
|
|
<Marker
|
|
position={[pickedLocation.lat, pickedLocation.lng]}
|
|
icon={icon}
|
|
/>
|
|
)}
|
|
</MapContainer>
|
|
{pickingLocation && (
|
|
<div className="map-hint">Haz clic en el mapa para fijar la ubicación</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|