import React, { useCallback, useEffect, useMemo, useState } from 'react' import { ChevronDown, ChevronRight } from 'lucide-react' import { allExpandableKeys, buildSkillCatalogTree, collectSkillLeavesFromTree, defaultExpandedKeysForSkillTree, filterSkillTreeByQuery, } from '../utils/skillCatalogTree' function normExclude(excludeIds) { return new Set( (excludeIds instanceof Set ? [...excludeIds] : excludeIds || []) .map((x) => Number(x)) .filter((n) => Number.isFinite(n)) ) } function SkillTreeNodes({ nodes, depth, expanded, exclude, onToggle, onPickSkill, pickMode }) { if (!nodes?.length) { return
  • Keine Fähigkeiten
  • } return nodes.map((node) => { if (node.type === 'skill') { if (exclude.has(node.skillId)) return null return (
  • ) } const hasKids = node.children?.length > 0 const isOpen = expanded.has(node.key) return (
  • {hasKids ? ( ) : ( )} {node.label}
    {hasKids && isOpen ? ( ) : null}
  • ) }) } /** * Ausklappbare Baumliste: Hauptgruppe → Kategorie → Fähigkeit (nur Hauptgruppe standard offen). */ export default function SkillTreePickerPanel({ skills = [], excludeIds, searchQuery = '', onPickSkill, pickMode = 'single', className = '', }) { const exclude = useMemo(() => normExclude(excludeIds), [excludeIds]) const fullTree = useMemo(() => buildSkillCatalogTree(skills), [skills]) const displayTree = useMemo( () => filterSkillTreeByQuery(fullTree, searchQuery), [fullTree, searchQuery] ) const [expanded, setExpanded] = useState(() => new Set()) useEffect(() => { if (searchQuery.trim()) { setExpanded(new Set(allExpandableKeys(displayTree))) } else { setExpanded(new Set(defaultExpandedKeysForSkillTree(displayTree))) } }, [searchQuery, displayTree]) useEffect(() => { if (!searchQuery.trim()) { setExpanded(new Set(defaultExpandedKeysForSkillTree(fullTree))) } }, [fullTree, searchQuery]) const onToggle = useCallback((key) => { setExpanded((prev) => { const next = new Set(prev) if (next.has(key)) next.delete(key) else next.add(key) return next }) }, []) const flatSearchHits = useMemo(() => { const q = searchQuery.trim() if (!q) return [] return collectSkillLeavesFromTree(fullTree, exclude).filter((leaf) => leaf.pathLabel.toLowerCase().includes(q.toLowerCase()) ) }, [fullTree, exclude, searchQuery]) if (searchQuery.trim() && flatSearchHits.length > 0) { return ( ) } return ( ) }