diff --git a/apps/planner/app/components/PlannerMap.tsx b/apps/planner/app/components/PlannerMap.tsx index 6f05030..c6ca334 100644 --- a/apps/planner/app/components/PlannerMap.tsx +++ b/apps/planner/app/components/PlannerMap.tsx @@ -18,6 +18,7 @@ import { NoGoAreaLayer } from "./NoGoAreaLayer"; import { ColoredRoute, findSegmentForPoint, type ColorMode } from "./ColoredRoute"; import { RouteInteraction } from "./RouteInteraction"; import { PoiPanel, PoiMarkers } from "./PoiPanel"; +import { WaypointContextMenu } from "./WaypointContextMenu"; import "leaflet/dist/leaflet.css"; /** Distance from a point to a line segment in degrees (approximate) */ @@ -368,6 +369,7 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted useYjsPoiSync(yjs, poiState); const [enabledOverlays, setEnabledOverlays] = useState([]); const [selectedBaseLayer, setSelectedBaseLayer] = useState(baseLayers[0]!.name); + const [contextMenu, setContextMenu] = useState<{ x: number; y: number; index: number } | null>(null); const [draggingOver, setDraggingOver] = useState(false); const dragCounterRef = useRef(0); const [routeCoordinates, setRouteCoordinates] = useState<[number, number, number][] | null>(null); @@ -687,12 +689,8 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted }, contextmenu: (e) => { L.DomEvent.preventDefault(e as unknown as Event); - // Middle waypoints: toggle overnight. First/last: delete. - if (i > 0 && i < waypoints.length - 1) { - setOvernight(yjs, i, !wp.overnight); - } else { - deleteWaypoint(i); - } + const orig = e.originalEvent as MouseEvent; + setContextMenu({ x: orig.clientX, y: orig.clientY, index: i }); }, }} /> @@ -742,6 +740,17 @@ export function PlannerMap({ yjs, onRouteRequest, highlightPosition, highlighted /> )} + {contextMenu && ( + deleteWaypoint(contextMenu.index)} + onToggleOvernight={() => setOvernight(yjs, contextMenu.index, !waypoints[contextMenu.index]?.overnight)} + onClose={() => setContextMenu(null)} + /> + )} ); } diff --git a/apps/planner/app/components/WaypointContextMenu.tsx b/apps/planner/app/components/WaypointContextMenu.tsx new file mode 100644 index 0000000..365a034 --- /dev/null +++ b/apps/planner/app/components/WaypointContextMenu.tsx @@ -0,0 +1,60 @@ +import { useEffect, useRef } from "react"; +import { useTranslation } from "react-i18next"; + +interface WaypointContextMenuProps { + position: { x: number; y: number }; + isFirst: boolean; + isLast: boolean; + isOvernight: boolean; + onDelete: () => void; + onToggleOvernight: () => void; + onClose: () => void; +} + +export function WaypointContextMenu({ + position, + isFirst, + isLast, + isOvernight, + onDelete, + onToggleOvernight, + onClose, +}: WaypointContextMenuProps) { + const { t } = useTranslation("planner"); + const ref = useRef(null); + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (ref.current && !ref.current.contains(e.target as Node)) onClose(); + }; + document.addEventListener("mousedown", handler); + return () => document.removeEventListener("mousedown", handler); + }, [onClose]); + + const canToggleOvernight = !isFirst && !isLast; + + return ( +
+ {canToggleOvernight && ( + + )} + +
+ ); +}