54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
|
|
"use client";
|
||
|
|
|
||
|
|
import "leaflet/dist/leaflet.css";
|
||
|
|
import { MapContainer, Polyline, TileLayer, CircleMarker, useMap } from "react-leaflet";
|
||
|
|
import type { RoutePoint } from "@/lib/models/running";
|
||
|
|
|
||
|
|
type FitBoundsProps = { points: RoutePoint[] };
|
||
|
|
|
||
|
|
function FitBounds({ points }: FitBoundsProps) {
|
||
|
|
const map = useMap();
|
||
|
|
map.fitBounds(points, { padding: [24, 24] });
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
|
||
|
|
type RouteMapProps = { points: RoutePoint[] };
|
||
|
|
|
||
|
|
export function RouteMap({ points }: RouteMapProps) {
|
||
|
|
if (points.length === 0) return null;
|
||
|
|
|
||
|
|
const start = points[0];
|
||
|
|
const end = points[points.length - 1];
|
||
|
|
|
||
|
|
return (
|
||
|
|
<MapContainer
|
||
|
|
center={start}
|
||
|
|
zoom={13}
|
||
|
|
style={{ height: "100%", width: "100%", borderRadius: "inherit", background: "#2b2d42" }}
|
||
|
|
zoomControl={false}
|
||
|
|
attributionControl={false}
|
||
|
|
>
|
||
|
|
<TileLayer
|
||
|
|
url="https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png"
|
||
|
|
subdomains="abcd"
|
||
|
|
maxZoom={19}
|
||
|
|
/>
|
||
|
|
<FitBounds points={points} />
|
||
|
|
<Polyline
|
||
|
|
positions={points}
|
||
|
|
pathOptions={{ color: "#fb4617", weight: 3, opacity: 0.9 }}
|
||
|
|
/>
|
||
|
|
<CircleMarker
|
||
|
|
center={start}
|
||
|
|
radius={6}
|
||
|
|
pathOptions={{ color: "#f7f3e9", fillColor: "#fb4617", fillOpacity: 1, weight: 2 }}
|
||
|
|
/>
|
||
|
|
<CircleMarker
|
||
|
|
center={end}
|
||
|
|
radius={6}
|
||
|
|
pathOptions={{ color: "#f7f3e9", fillColor: "#2b2d42", fillOpacity: 1, weight: 2 }}
|
||
|
|
/>
|
||
|
|
</MapContainer>
|
||
|
|
);
|
||
|
|
}
|