feat: Implement route planning feature with project selection and optimization
- Added route planning functionality to the map page, allowing users to select projects for routing. - Implemented state management for route projects, start/end points, and search functionality. - Integrated OpenRouteService API for route calculation and optimization. - Enhanced UI with a route planning panel, including search and drag-and-drop reordering of projects. - Added visual indicators for route start and end points on the map. - Included translations for route planning features in both Polish and English. - Created utility functions for route calculations, optimizations, and formatting of route data.
This commit is contained in:
@@ -186,6 +186,10 @@ export default function EnhancedLeafletMap({
|
||||
isMeasuring = false,
|
||||
measurementPoints = [],
|
||||
onMeasurementClick,
|
||||
currentTool = "move",
|
||||
routeProjects = [],
|
||||
onProjectClick,
|
||||
routeData = null,
|
||||
}) {
|
||||
useEffect(() => {
|
||||
fixLeafletIcons();
|
||||
@@ -292,17 +296,88 @@ export default function EnhancedLeafletMap({
|
||||
}
|
||||
</>
|
||||
)}{" "}
|
||||
{markers.map((marker, index) => (
|
||||
<Marker
|
||||
key={index}
|
||||
position={marker.position}
|
||||
icon={
|
||||
marker.color ? createColoredMarkerIcon(marker.color) : undefined
|
||||
}
|
||||
>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
))}
|
||||
{markers.map((marker, index) => {
|
||||
const isInRoute = routeProjects.some(p => p.project_id === marker.project?.project_id);
|
||||
const isRouteTool = currentTool === "route";
|
||||
|
||||
return (
|
||||
<Marker
|
||||
key={index}
|
||||
position={marker.position}
|
||||
icon={
|
||||
isRouteTool && isInRoute
|
||||
? createColoredMarkerIcon("blue")
|
||||
: marker.color ? createColoredMarkerIcon(marker.color) : undefined
|
||||
}
|
||||
eventHandlers={{
|
||||
click: () => {
|
||||
if (isRouteTool && marker.project && onProjectClick) {
|
||||
onProjectClick(marker.project);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
{marker.popup && <Popup>{marker.popup}</Popup>}
|
||||
</Marker>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Route visualization */}
|
||||
{routeData && routeData.geometry && routeData.geometry.length > 0 && (
|
||||
<>
|
||||
<Polyline
|
||||
positions={routeData.geometry}
|
||||
color="blue"
|
||||
weight={4}
|
||||
opacity={0.8}
|
||||
/>
|
||||
{/* Start marker */}
|
||||
{routeData.geometry.length > 0 && (
|
||||
<Marker
|
||||
position={routeData.geometry[0]}
|
||||
icon={L.divIcon({
|
||||
html: '<div style="background-color: green; width: 12px; height: 12px; border-radius: 50%; border: 2px solid white; box-shadow: 0 0 4px rgba(0,0,0,0.3);"></div>',
|
||||
className: 'custom-route-marker',
|
||||
iconSize: [12, 12],
|
||||
iconAnchor: [6, 6]
|
||||
})}
|
||||
>
|
||||
<Popup>Route Start</Popup>
|
||||
</Marker>
|
||||
)}
|
||||
{/* End marker */}
|
||||
{routeData.geometry.length > 1 && (
|
||||
<Marker
|
||||
position={routeData.geometry[routeData.geometry.length - 1]}
|
||||
icon={L.divIcon({
|
||||
html: '<div style="background-color: red; width: 12px; height: 12px; border-radius: 50%; border: 2px solid white; box-shadow: 0 0 4px rgba(0,0,0,0.3);"></div>',
|
||||
className: 'custom-route-marker',
|
||||
iconSize: [12, 12],
|
||||
iconAnchor: [6, 6]
|
||||
})}
|
||||
>
|
||||
<Popup>Route End</Popup>
|
||||
</Marker>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{/* Fallback: straight line route if no geometry */}
|
||||
{routeProjects.length > 1 && (!routeData || !routeData.geometry || routeData.geometry.length === 0) && (
|
||||
<Polyline
|
||||
positions={routeProjects.map(project => {
|
||||
if (project.coordinates) {
|
||||
const [lat, lng] = project.coordinates.split(",").map(coord => parseFloat(coord.trim()));
|
||||
return [lat, lng];
|
||||
}
|
||||
return null;
|
||||
}).filter(pos => pos !== null)}
|
||||
color="blue"
|
||||
weight={4}
|
||||
opacity={0.8}
|
||||
dashArray="10, 10"
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Measurement elements */}
|
||||
{isMeasuring && measurementPoints.length > 0 && (
|
||||
|
||||
Reference in New Issue
Block a user