import { useCallback } from 'react' import { Trash2 } from 'lucide-react' import { cn } from '@/lib/utils' import type { DeviceProperties, DiagramEdge } from '@/types' import type { Node, Edge } from '@xyflow/react' import type { DeviceNodeData } from '../nodes/DeviceNode' interface PropertiesPanelProps { selectedNode: Node | null selectedEdge: Edge | null onNodeUpdate: (nodeId: string, data: Partial) => void onEdgeUpdate: (edgeId: string, data: Partial) => void onDeleteNode: (nodeId: string) => void onDeleteEdge: (edgeId: string) => void } const STATUS_OPTIONS = ['unknown', 'online', 'offline', 'degraded'] as const const CONNECTION_TYPE_OPTIONS = ['ethernet', 'fiber', 'wifi', 'vpn', 'vlan', 'wan'] as const function FieldLabel({ children }: { children: React.ReactNode }) { return ( ) } function FieldInput({ value, onChange, placeholder, mono }: { value: string onChange: (val: string) => void placeholder?: string mono?: boolean }) { return ( onChange(e.target.value)} placeholder={placeholder} className={cn( 'w-full rounded border border-default bg-input px-2 py-1.5 text-xs text-primary placeholder:text-muted-foreground focus:border-accent focus:outline-none', mono && 'font-mono', )} /> ) } export function PropertiesPanel({ selectedNode, selectedEdge, onNodeUpdate, onEdgeUpdate, onDeleteNode, onDeleteEdge, }: PropertiesPanelProps) { const handlePropertyChange = useCallback((field: keyof DeviceProperties, value: string) => { if (!selectedNode) return const nodeData = selectedNode.data as unknown as DeviceNodeData onNodeUpdate(selectedNode.id, { properties: { ...nodeData.properties, [field]: value }, } as Partial) }, [selectedNode, onNodeUpdate]) const handleLabelChange = useCallback((value: string) => { if (!selectedNode) return onNodeUpdate(selectedNode.id, { label: value } as Partial) }, [selectedNode, onNodeUpdate]) if (!selectedNode && !selectedEdge) { return (

Select a device or connection to edit its properties

) } if (selectedEdge) { const edgeData = (selectedEdge.data || {}) as Record const connectionType = (edgeData.connectionType as string) || 'ethernet' const isCustomType = !CONNECTION_TYPE_OPTIONS.includes(connectionType as typeof CONNECTION_TYPE_OPTIONS[number]) return (

Connection

Label onEdgeUpdate(selectedEdge.id, { label: val || null })} placeholder="Connection label" />
Connection Type {isCustomType && ( onEdgeUpdate(selectedEdge.id, { connectionType: val })} placeholder="Custom type name" /> )}
Speed onEdgeUpdate(selectedEdge.id, { speed: val || null })} placeholder="e.g. 1 Gbps" />
Notes onEdgeUpdate(selectedEdge.id, { notes: val || null })} placeholder="Port info, cable type..." mono />
) } const nodeData = selectedNode!.data as unknown as DeviceNodeData const props = nodeData.properties || {} as DeviceProperties return (

Device Properties

Label
Hostname handlePropertyChange('hostname', v)} placeholder="e.g. core-rtr-01" mono />
IP Address handlePropertyChange('ip', v)} placeholder="e.g. 10.0.0.1" mono />
Subnet handlePropertyChange('subnet', v)} placeholder="e.g. 10.0.0.0/24" mono />
Vendor handlePropertyChange('vendor', v)} placeholder="e.g. Cisco" />
Model handlePropertyChange('model', v)} placeholder="e.g. ISR 4331" />
Role handlePropertyChange('role', v)} placeholder="e.g. Core gateway" />
VLAN handlePropertyChange('vlan', v)} placeholder="e.g. 10" />
Status
Notes