import { useCallback } from 'react'; import { isLeafNode } from './nodeUtils'; import { getStatusColor } from '../dataUtils'; export const useDataParser = (nodePositions, collapsedNodes) => { const getNodeStyle = useCallback((item, isLeaf) => ({ width: isLeaf ? 60 : 70, height: isLeaf ? 60 : 70, borderRadius: '50%', backgroundColor: getStatusColor(item.status), display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'black', border: '2px solid #fff', fontSize: isLeaf ? '0.8rem' : '1rem' }), []); const getCenterNodeStyle = useCallback((item) => ({ width: 80, height: 80, borderRadius: '50%', backgroundColor: getStatusColor(item.status), display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'black', border: '2px solid #fff', fontSize: '1.2rem' }), []); const parseData = useCallback((data) => { if (!data) return { nodes: [], edges: [] }; const nodes = []; const edges = []; const centerX = 500; const centerY = 400; const baseLevelRadius = 150; const traverse = (item, parentId = null, level = 0, angleStart = 0, angleEnd = 2 * Math.PI, parentRadius = 0) => { if (!item || collapsedNodes[parentId]) return; // Пропускаем свёрнутые узлы const nodeId = item.id; const items = item.items || []; const isLeaf = isLeafNode(item); const savedPosition = nodePositions[nodeId]; let position = savedPosition || { x: Math.round(centerX + Math.cos((angleStart + angleEnd) / 2) * (parentRadius + baseLevelRadius)), y: Math.round(centerY + Math.sin((angleStart + angleEnd) / 2) * (parentRadius + baseLevelRadius)) }; const node = { id: nodeId, type: 'customNode', position, data: { ...item, label: item.title, style: getNodeStyle(item, isLeaf), // Переносим стили в data hasChildren: items.length > 0, collapsed: collapsedNodes[nodeId] } }; nodes.push(node); if (parentId) { edges.push({ id: `${parentId}-${nodeId}`, source: parentId, target: nodeId, style: { stroke: isLeaf ? '#aaa' : '#666', strokeWidth: isLeaf ? 1 : 2 } }); } if (!collapsedNodes[nodeId] && items.length > 0) { const spreadAngle = angleEnd - angleStart; items.forEach((child, index) => { if (!child) return; const itemAngleStart = angleStart + (index / items.length) * spreadAngle; const itemAngleEnd = angleStart + ((index + 1) / items.length) * spreadAngle; traverse(child, nodeId, level + 1, itemAngleStart, itemAngleEnd, parentRadius + baseLevelRadius); }); } }; const centerNode = { id: data.id, type: 'customNode', // Добавляем тип узла position: nodePositions[data.id] || { x: centerX, y: centerY }, style: getCenterNodeStyle(data), data: { label: data.title, hasChildren: data.items.length > 0, collapsed: collapsedNodes[data.id] } }; nodes.push(centerNode); if (!collapsedNodes[data.id] && data.items.length > 0) { const angleStep = (2 * Math.PI) / data.items.length; data.items.forEach((child, index) => { if (!child) return; traverse(child, data.id, 1, index * angleStep, (index + 1) * angleStep, 0); }); } return { nodes, edges }; }, [nodePositions, collapsedNodes, getNodeStyle, getCenterNodeStyle]); return { parseData }; };