diff --git a/admin-panel/src/views/OrganizationEditor.tsx b/admin-panel/src/views/OrganizationEditor.tsx index 8c45da6..c19ebeb 100644 --- a/admin-panel/src/views/OrganizationEditor.tsx +++ b/admin-panel/src/views/OrganizationEditor.tsx @@ -376,7 +376,7 @@ export default function OrganizationEditor() { const yGap = 110 // Zweistufiges Top-Band: Direktion ganz oben, darunter weitere ROOT-Knoten const topYDirector = 10 - const topYRootRow = topYDirector + yGap + let topYRootRow = topYDirector + yGap // Spaltenstart mit Abstand unterhalb der Top-Row, um Überlappungen zu vermeiden // yStart wird nach Messung der tatsächlichen Kartenhöhen berechnet let yStart = topYRootRow + yGap @@ -476,6 +476,10 @@ export default function OrganizationEditor() { placedIndices.add(directorIndex) directorRowHeight = getNodeHeight(rootNodes[directorIndex].id) } + // After measuring director, set dynamic Y for the second root row + if (directorRowHeight) { + topYRootRow = topYDirector + directorRowHeight + yGap + } // 2) Übrige ROOT-Knoten in einer zweiten Top-Reihe gleichmäßig verteilen const others: Node[] = rootNodes.filter((_, idx) => !placedIndices.has(idx)) @@ -493,11 +497,36 @@ export default function OrganizationEditor() { }) } - // Spaltenstart abhängig von den tatsächlichen Höhen berechnen - if (directorRowHeight || rootRowHeight) { - yStart = topYDirector + (directorRowHeight || 0) + yGap + (rootRowHeight ? (rootRowHeight + yGap) : 0) + 16 + // Optional: Leitungsstab-Kinder direkt unter dem Leitungsstab blockweise platzieren + const lStabNode = rootNodes.find(n => (String((n.data||{}).code).toUpperCase() === 'LSTAB') || (/leitungsstab/i.test(String((n.data||{}).name)))) + let lStabBlockBottom = 0 + if (lStabNode) { + const children = newNodes + .filter(n => (n.data?.parentId === lStabNode.id) && (n.data?.type === 'sachgebiet' || n.data?.type === 'teildezernat')) + .sort((a, b) => { + const pa = String(a.data?.code || '').match(/LStab\s+(\d+)/i) + const pb = String(b.data?.code || '').match(/LStab\s+(\d+)/i) + const va = pa ? parseInt(pa[1], 10) : 0 + const vb = pb ? parseInt(pb[1], 10) : 0 + return va - vb + }) + if (children.length) { + let yC = (lStabNode.position?.y || topYRootRow) + getNodeHeight(lStabNode.id) + yGap + const xC = (lStabNode.position?.x || xMargin) + 40 + children.forEach(c => { + c.position = { x: xC, y: yC } + yC += getNodeHeight(c.id) + yGap + }) + lStabBlockBottom = yC + } } + // Spaltenstart abhängig von den tatsächlichen Höhen berechnen (inkl. Leitungsstab-Block) + const baseTop = topYDirector + (directorRowHeight || 0) + (directorRowHeight ? yGap : 0) + const secondRow = rootRowHeight ? (rootRowHeight + yGap) : 0 + const lStabExtra = lStabBlockBottom ? (lStabBlockBottom - (topYRootRow)) + 16 : 0 + yStart = baseTop + Math.max(secondRow, lStabExtra) + // Arrange lanes let laneIndex = 0 laneOrder.forEach(key => {