snap radius to 2.5 meters and added indicator for snap

This commit is contained in:
2025-12-14 21:25:59 +05:00
parent d85849debe
commit 7e4bd35f3a

View File

@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
import { useMapEvents, Polyline, Marker } from 'react-leaflet';
import { useMapEvents, Polyline, Marker, Circle } from 'react-leaflet';
import { useDrawingStore } from '../../stores/drawingStore';
import { useUIStore } from '../../stores/uiStore';
import { mapItemService } from '../../services/mapItemService';
@@ -18,6 +18,8 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
const [allItems, setAllItems] = useState<any[]>([]);
const [startDeviceId, setStartDeviceId] = useState<string | null>(null);
const [endDeviceId, setEndDeviceId] = useState<string | null>(null);
const [nearbyDevice, setNearbyDevice] = useState<any | null>(null);
const [nearbyFullDevice, setNearbyFullDevice] = useState<any | null>(null);
const isCableTool = ['fiber', 'cat6', 'cat6_poe'].includes(activeTool);
const isDeviceTool = ['switch', 'indoor_ap', 'outdoor_ap', 'other_device', 'info'].includes(activeTool);
@@ -37,7 +39,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
}, [mapId]);
// Find nearby device for snapping (exclude info markers)
const findNearbyDevice = (lat: number, lng: number, radiusMeters = 1): any | null => {
const findNearbyDevice = (lat: number, lng: number, radiusMeters = 2.5): any | null => {
const devices = allItems.filter(item =>
['switch', 'indoor_ap', 'outdoor_ap', 'other_device'].includes(item.type) &&
item.geometry.type === 'Point'
@@ -78,6 +80,10 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
let { lat, lng } = e.latlng;
let clickedDevice = null;
// Clear snap indicator on click
setNearbyDevice(null);
setNearbyFullDevice(null);
// Check for nearby device when drawing cables
if (isCableTool && map) {
clickedDevice = findNearbyDevice(lat, lng);
@@ -151,7 +157,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
// Wireless mesh - connect AP to AP only
if (isWirelessTool) {
// Must click on an AP
const ap = findNearbyDevice(lat, lng, 1);
const ap = findNearbyDevice(lat, lng, 2.5);
if (!ap || !['indoor_ap', 'outdoor_ap'].includes(ap.type)) {
showToast('Wireless mesh can only connect between Access Points. Please click on an AP.', 'error');
return;
@@ -191,6 +197,40 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
if (isDrawing && (isCableTool || isWirelessTool)) {
setCursorPosition([e.latlng.lat, e.latlng.lng]);
}
// Check for nearby device to show snap indicator
if ((isCableTool || isWirelessTool) && map) {
const nearby = findNearbyDevice(e.latlng.lat, e.latlng.lng);
// For wireless mesh, only show indicator for APs
if (isWirelessTool) {
if (nearby && ['indoor_ap', 'outdoor_ap'].includes(nearby.type)) {
setNearbyDevice(nearby);
setNearbyFullDevice(null);
} else {
setNearbyDevice(null);
setNearbyFullDevice(null);
}
} else if (isCableTool) {
// For cables, check port availability
if (nearby) {
if (hasAvailablePorts(nearby)) {
setNearbyDevice(nearby);
setNearbyFullDevice(null);
} else {
// Device has full ports - show red indicator
setNearbyDevice(null);
setNearbyFullDevice(nearby);
}
} else {
setNearbyDevice(null);
setNearbyFullDevice(null);
}
}
} else {
setNearbyDevice(null);
setNearbyFullDevice(null);
}
},
contextmenu: async (e) => {
@@ -214,6 +254,8 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
if (e.key === 'Escape' && isDrawing) {
resetDrawing();
setCursorPosition(null);
setNearbyDevice(null);
setNearbyFullDevice(null);
}
};
@@ -221,6 +263,12 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
return () => document.removeEventListener('keydown', handleKeyDown);
}, [isDrawing, resetDrawing]);
// Clear nearby device indicator when tool changes
useEffect(() => {
setNearbyDevice(null);
setNearbyFullDevice(null);
}, [activeTool]);
const finishCable = async () => {
if (drawingPoints.length < 2) return;
@@ -244,6 +292,8 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
setCursorPosition(null);
setStartDeviceId(null);
setEndDeviceId(null);
setNearbyDevice(null);
setNearbyFullDevice(null);
// Reload items
const items = await mapItemService.getMapItems(mapId);
setAllItems(items);
@@ -283,6 +333,8 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
setCursorPosition(null);
setStartDeviceId(null);
setEndDeviceId(null);
setNearbyDevice(null);
setNearbyFullDevice(null);
// Reload items
const items = await mapItemService.getMapItems(mapId);
setAllItems(items);
@@ -293,11 +345,12 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
setCursorPosition(null);
setStartDeviceId(null);
setEndDeviceId(null);
setNearbyDevice(null);
setNearbyFullDevice(null);
}
};
// Render drawing preview
if (isDrawing && drawingPoints.length > 0) {
// Render drawing preview and snap indicator
const color = isCableTool
? CABLE_COLORS[activeTool as CableType]
: isWirelessTool
@@ -307,6 +360,37 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
const dashArray = isWirelessTool ? '10, 10' : undefined;
return (
<>
{/* Green snap indicator - show when hovering near a device with available ports */}
{nearbyDevice && nearbyDevice.geometry.type === 'Point' && (
<Circle
center={[nearbyDevice.geometry.coordinates[1], nearbyDevice.geometry.coordinates[0]]}
radius={3}
pathOptions={{
color: '#10B981',
fillColor: '#10B981',
fillOpacity: 0.2,
weight: 2,
}}
/>
)}
{/* Red snap indicator - show when hovering near a device with full ports */}
{nearbyFullDevice && nearbyFullDevice.geometry.type === 'Point' && (
<Circle
center={[nearbyFullDevice.geometry.coordinates[1], nearbyFullDevice.geometry.coordinates[0]]}
radius={3}
pathOptions={{
color: '#EF4444',
fillColor: '#EF4444',
fillOpacity: 0.2,
weight: 2,
}}
/>
)}
{/* Drawing preview - only show when actively drawing */}
{isDrawing && drawingPoints.length > 0 && (
<>
{/* Main line connecting all points */}
{drawingPoints.length > 1 && (
@@ -335,8 +419,7 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
<Marker key={idx} position={point} />
))}
</>
)}
</>
);
}
return null;
}