import React from 'react'; import type { LayerPanelProps } from '../types/ui.types'; import type { CADLayer, CADElement } from '../types/cad.types'; import type { TreeNode } from '../types/ui.types'; import TreeView from './TreeView'; const elementTypeLabels: Record = { line: 'Linie', rect: 'Rechteck', circle: 'Kreis', arc: 'Bogen', polyline: 'Polylinie', polygon: 'Polygon', text: 'Text', dimension: 'Bemassung', leader: 'Hinweislinie', revcloud: 'Revisionswolke', hatch: 'Schraffur', chair: 'Stuhl', 'seating-row': 'Reihe', 'seating-block': 'Block', table: 'Tisch', stage: 'Buhne', 'seating-template': 'Vorlage', }; const layerIcon = ( ); const groupIcon = ( ); const elementIcons: Record = { line: , rect: , circle: , arc: , polyline: , polygon: , text: , dimension: , leader: , revcloud: , hatch: , chair: , 'seating-row': , 'seating-block': , table: , stage: , 'seating-template': , }; const defaultIcon = ; const LayerPanel: React.FC = ({ layers, elements = [], activeLayerId, selectedElementIds = [], groups = [], onSelectLayer, onSelectElement, onAddLayer, onToggleLayer, onDeleteLayer, onRenameLayer, onDuplicateLayer, onToggleLock, onReorder, onAddSubLayer, onElementsDeleted, onToggleElementVisible, }) => { const buildTree = (parentId: string | null): TreeNode[] => { return layers .filter((l) => l.parentId === parentId) .sort((a, b) => a.sortOrder - b.sortOrder) .map((l) => { const layerElements = elements.filter((e) => e.layerId === l.id); // Build group nodes for this layer const layerGroups = groups.filter((g) => g.elementIds.some((eid) => layerElements.some((e) => e.id === eid)) ); const groupNodes: TreeNode[] = layerGroups.map((g) => { const groupElementIds = g.elementIds.filter((eid) => layerElements.some((e) => e.id === eid) ); const groupElementsList = groupElementIds .map((eid) => elements.find((e) => e.id === eid)) .filter((e): e is CADElement => e !== undefined); const groupChildNodes: TreeNode[] = groupElementsList.map((e) => ({ id: e.id, name: elementTypeLabels[e.type] || e.type, icon: elementIcons[e.type] || defaultIcon, expanded: false, active: selectedElementIds.includes(e.id), children: [], })); // A group is "active" if any of its elements are selected const groupActive = groupElementIds.some((eid) => selectedElementIds.includes(eid)); return { id: g.id, name: g.name, icon: groupIcon, expanded: false, active: groupActive, children: groupChildNodes, count: groupElementIds.length > 0 ? groupElementIds.length : undefined, } as TreeNode; }); // Build element nodes — only elements NOT in any group go directly under layer const groupedElementIds = new Set(); for (const g of layerGroups) { for (const eid of g.elementIds) { if (layerElements.some((e) => e.id === eid)) { groupedElementIds.add(eid); } } } const ungroupedElements = layerElements.filter((e) => !groupedElementIds.has(e.id)); const elementNodes: TreeNode[] = ungroupedElements.map((e) => ({ id: e.id, name: elementTypeLabels[e.type] || e.type, icon: elementIcons[e.type] || defaultIcon, expanded: false, active: selectedElementIds.includes(e.id), children: [], })); const subLayerNodes = buildTree(l.id); // Groups appear above elements, sublayers appear first return { id: l.id, name: l.name, icon: layerIcon, expanded: false, active: l.id === activeLayerId, children: [...subLayerNodes, ...groupNodes, ...elementNodes], count: layerElements.length > 0 ? layerElements.length : undefined, } as TreeNode; }); }; const tree = buildTree(null); // Determine which IDs are layer IDs vs element IDs vs group IDs for dispatch const layerIds = new Set(layers.map((l) => l.id)); const groupIds = new Set(groups.map((g) => g.id)); const handleSelect = (id: string) => { if (layerIds.has(id)) { onSelectLayer(id); } else if (groupIds.has(id)) { const group = groups.find((g) => g.id === id); if (group && group.elementIds.length > 0) { onSelectElement?.(group.elementIds[0]); } } else { // It's an element ID onSelectElement?.(id); } }; const handleAddSubLayer = (parentId: string) => { if (onAddSubLayer) { onAddSubLayer(parentId); } }; return (
Ebenen
{tree.length === 0 ? (
Keine Ebenen vorhanden
) : ( node.icon} renderActions={(node) => { const layer = layers.find((l) => l.id === node.id); if (layer) { return (
); } const element = elements.find((el) => el.id === node.id); if (element) { const isVisible = element.properties?.visible !== false; return (
); } return null; }} /> )}
); }; export default LayerPanel;