```
import React, { useState, useEffect, useRef } from 'react';
import CryptoJS from 'crypto-js'; // Correct import for crypto-js
import './styles.css'; // Импорт стилей
import { InputText } from 'primereact/inputtext';
import { InputNumber } from 'primereact/inputnumber'; // Правильный импорт для InputNumber
import { Toolbar } from 'primereact/toolbar';
import { Button } from 'primereact/button';
import { SplitButton } from 'primereact/splitbutton';

import { IconField } from 'primereact/iconfield';
import { InputIcon } from 'primereact/inputicon';

import 'primereact/resources/themes/saga-blue/theme.css'; // Choose a theme
import 'primereact/resources/primereact.min.css'; // Core CSS
import 'primeicons/primeicons.css'; // Icons
import UpperPanel from './menu';


const GRID_SIZE = 20;
const SECRET_KEY = 'your-secret-key';

const App = () => {
	const [elements, setElements] = useState([
		{ id: 1, x: 40, y: 180, connectedTo: 2, color: 'white', stroke: 'black', borderRadius: 7, text: 'Входящий поток', description: 'lore' },
		{ id: 2, x: 200, y: 100, connectedTo: 3, color: 'white', stroke: 'black', borderRadius: 7, text: 'Python', description: 'description' },
		{ id: 3, x: 560, y: 180, connectedTo: 4, color: 'white', stroke: 'black', borderRadius: 7, text: 'Scala', description: 'description' },
		{ id: 4, x: 700, y: 100, connectedTo: null, color: 'white', stroke: 'black', borderRadius: 7, text: 'ECMAScript', description: 'description' }
	]);

    // Load elements from localStorage on component mount
    useEffect(() => {
		const loadElements = () => {
			const encryptedData = localStorage.getItem('elements');
			if (encryptedData) {
				const bytes = CryptoJS.AES.decrypt(encryptedData, SECRET_KEY);
				const decryptedData = bytes.toString(CryptoJS.enc.Utf8);
				if (decryptedData) {
					const loadedElements = JSON.parse(decryptedData);
					setElements(loadedElements);
					console.log("Elements loaded:", loadedElements); // Отладка
				}
			}
		};

        loadElements();
    }, []);

	const saveElements = () => {
		const encryptedData = CryptoJS.AES.encrypt(JSON.stringify(elements), SECRET_KEY).toString();
		localStorage.setItem('elements', encryptedData);
		console.log("Elements saved:", elements); // Отладка
	};

    useEffect(() => {
        saveElements();
    }, [elements]);

	const [draggingElement, setDraggingElement] = useState(null);
	const [offset, setOffset] = useState({ x: 0, y: 0 });
	const [draggingLine, setDraggingLine] = useState(null);
	const [selectedElement, setSelectedElement] = useState(null);
	const [borderRadius, setBorderRadius] = useState(0);
	const [color, setColor] = useState('blue');
	const [text, setText] = useState('');
	const [description, setDescription] = useState('');
	const [showConfigPanel, setShowConfigPanel] = useState(false);
	const [panelPosition, setPanelPosition] = useState({ x: 0, y: 0 });
	const [linePosition, setLinePosition] = useState(null);
	const [isDraggingPanel, setIsDraggingPanel] = useState(false);
	const [panelOffset, setPanelOffset] = useState({ x: 0, y: 0 });
	const [showIcons, setShowIcons] = useState(true);
	const [selectedIcon, setSelectedIcon] = useState(null);

	const icons = [
		{ id: 1, name: 'Контур', icon: 'pi-check', state: false },
		{ id: 2, name: 'Скругление', icon: 'pi-send', state: false },
		{ id: 3, name: 'Заголовок', icon: 'pi-send', state: false },
		{ id: 4, name: 'Описание', icon: 'pi-check', state: false },
		{ id: 5, name: 'Описание 1', icon: 'pi-check', state: false },
		{ id: 6, name: 'Описание 2', icon: 'pi-check', state: false },
		{ id: 7, name: 'Описание 2', icon: 'pi-check', state: false },
		{ id: 8, name: 'Описание 2', icon: 'pi-check', state: false },
		{ id: 9, name: 'Описание 2', icon: 'pi-check', state: false },
	];

	const handleMouseDown = (e, element) => {
		console.log("Dragging element:", element); // Check if the correct element is being logged
		setDraggingElement(element);
		setOffset({ x: e.clientX - element.x, y: e.clientY - element.y });
	};

	const handleMouseMove = (e) => {
		if (draggingElement) {
			const newX = Math.round((e.clientX - offset.x) / GRID_SIZE) * GRID_SIZE;
			const newY = Math.round((e.clientY - offset.y) / GRID_SIZE) * GRID_SIZE;
			
			setElements((prevElements) =>
				prevElements.map((el) =>
					el.id === draggingElement.id ? { ...el, x: newX, y: newY } : el
				)
			);
		}

		if (draggingLine) {
			const newX2 = e.clientX;
			const newY2 = e.clientY;

			setDraggingLine((prev) => ({
				...prev,
				x2: newX2,
				y2: newY2,
			}));
			
		}

		if (isDraggingPanel) {
			const newPanelX = e.clientX - panelOffset.x;
			const newPanelY = e.clientY - panelOffset.y;
			setPanelPosition({ x: newPanelX, y: newPanelY });
		}
		
	};

	const handleMouseUp = (e) => {
		if (draggingLine) {
			const dropX = Math.round(e.clientX / GRID_SIZE) * GRID_SIZE;
			const dropY = Math.round(e.clientY / GRID_SIZE) * GRID_SIZE;

			const targetElement = elements.find((el) => {
				const circleX = el.x;
				const circleY = el.y + 25;
				const radius = 10;

				return (
					dropX >= circleX - radius &&
					dropX <= circleX + radius &&
					dropY >= circleY - radius &&
					dropY <= circleY + radius
				);
			});

			if (targetElement) {
				setElements((prevElements) =>
					prevElements.map((el) =>
						el.id === draggingLine.elementId
							? { ...el, connectedTo: targetElement.id }
							: el
					)
				);
				setDraggingLine((prev) => ({ ...prev, targetId: targetElement.id }));
			} else {
				setElements((prevElements) =>
					prevElements.map((el) =>
						el.id === draggingLine.elementId
							? { ...el, connectedTo: null }
							: el
					)
				);
			}
		}

		setDraggingElement(null);
		setDraggingLine(null);
		setIsDraggingPanel(false);
	};


	const startDraggingPanel = (e) => {
		setIsDraggingPanel(true);
		setPanelOffset({ x: e.clientX - panelPosition.x, y: e.clientY - panelPosition.y });
	};

	const handleBackgroundClick = (e) => {
		if (showConfigPanel && !e.target.closest('.style-panel')) {
			setShowConfigPanel(false);
		}
	};

	const findOptimalPath = (start, end) => {
		const path = [];
		const startX = start.x + calculateWidth(start); // Center of the start element
		const startY = start.y + 25;  // Center vertically
		const endX = end.x; // Center of the end element
		const endY = end.y + 25;
	
		if (startY === endY) {
			path.push({ x: startX, y: startY });
			path.push({ x: endX, y: startY });
		} else {
			path.push({ x: startX, y: startY });
			path.push({ x: startX, y: endY });
			path.push({ x: endX, y: endY });
		}
	
		return path;
	};

	const startDraggingLine = (element) => {
		const width = calculateWidth(element);

		setDraggingLine({
			elementId: element.id,
			targetId: null,
			x1: element.x + width, // Центр по ширине (правый круг)
			y1: element.y + 25,     // Центр по высоте (по центру элемента)
			x2: element.x + width,  // Начальная точка линии
			y2: element.y + 25,     // Начальная точка линии
		});
	};
	
	const renderLines = () => {
		return elements.map((start, index) => {
			if (start.connectedTo) {
				const end = elements.find((el) => el.id === start.connectedTo);
				const path = findOptimalPath(start, end);
				console.log(elements[index].connectedTo);
				
				const lastSegmentStart = path[path.length - 2];
				const lastSegmentEnd = path[path.length - 1];
				const midX = (lastSegmentStart.x + lastSegmentEnd.x) / 2;
				const midY = (lastSegmentStart.y + lastSegmentEnd.y) / 2;
	
				const textContent = start.connectedTo.toString();
				const textWidth = textContent.length * 7;
				const textHeight = 20;

				return (
					<g key={`line-${start.id}-${end.id}`}>
						{path.map((point, index) => {
							if (index < path.length - 1) {
								return (
									<line
										key={`line-segment-${index}`}
										x1={point.x}
										y1={point.y}
										x2={path[index + 1].x}
										y2={path[index + 1].y}
										stroke="black"
										strokeWidth={2}
									/>
								);
							}
							return null;
						})}
						<rect
							x={midX - textWidth / 2 - 5}
							y={midY - textHeight / 2 - 5}
							width={textWidth + 10}
							height={textHeight + 10}
							fill="black"
							stroke="orange"
							strokeWidth={2}
						/>
						<text x={midX} y={midY} fill="white" fontSize="12" textAnchor="middle" alignmentBaseline="middle">
							{textContent}
						</text>
					</g>
				);
			}
			return null;
		}).concat(
			draggingLine ? (
				<line
					key={`dragging-line`}
					x1={draggingLine.x1}
					y1={draggingLine.y1}
					x2={draggingLine.x2}
					y2={draggingLine.y2}
					stroke="red"
					strokeWidth={2}
					strokeDasharray="5,5"
				/>
			) : null
		);
	};

	useEffect(() => {
		const handleMouseMove = (e) => {
			if (draggingElement) {
				const newX = Math.round((e.clientX - offset.x) / GRID_SIZE) * GRID_SIZE;
				const newY = Math.round((e.clientY - offset.y) / GRID_SIZE) * GRID_SIZE;

				setElements((prevElements) =>
					prevElements.map((el) =>
						el.id === draggingElement.id ? { ...el, x: newX, y: newY } : el
					)
				);
			}

			if (draggingLine) {
				const newX2 = e.clientX;
				const newY2 = e.clientY;

				setDraggingLine((prev) => ({
					...prev,
					x2: newX2,
					y2: newY2,
				}));
			}

			if (isDraggingPanel) {
				const newPanelX = e.clientX - panelOffset.x;
				const newPanelY = e.clientY - panelOffset.y;
				setPanelPosition({ x: newPanelX, y: newPanelY });
			}
		};

		const handleMouseUp = (e) => {
			if (draggingLine) {
				const dropX = Math.round(e.clientX / GRID_SIZE) * GRID_SIZE;
				const dropY = Math.round(e.clientY / GRID_SIZE) * GRID_SIZE;

				const targetElement = elements.find((el) => {
					const circleX = el.x;
					const circleY = el.y + 25;
					const radius = 10;

					return (
						dropX >= circleX - radius &&
						dropX <= circleX + radius &&
						dropY >= circleY - radius &&
						dropY <= circleY + radius
					);
				});

				const { elementId } = draggingLine;

				setElements((prevElements) =>
					prevElements.map((el) => {
						if (el.id === elementId) {
							return {
								...el,
								connectedTo: targetElement ? targetElement.id : null,
							};
						}
						return el;
					})
				);

				if (targetElement) {
					setDraggingLine((prev) => ({ ...prev, targetId: targetElement.id }));
				}
			}
	

			setDraggingElement(null);
			setDraggingLine(null);
			setIsDraggingPanel(false);
		};

		
		window.addEventListener('mousemove', handleMouseMove);
		window.addEventListener('mouseup', handleMouseUp);
		return () => {
			window.removeEventListener('mousemove', handleMouseMove);
			window.removeEventListener('mouseup', handleMouseUp);
		};
		
	}, [draggingElement, draggingLine, offset, elements, isDraggingPanel, panelOffset]);

	const handleElementClick = (e, element) => {
		if (e.shiftKey) {
			setSelectedElement(element.id);
			setText(element.text);
			setDescription(element.description);
			setPanelPosition({ x: e.clientX, y: e.clientY });
			setShowConfigPanel(true);
		 }
	};

	const updateElementStyle = () => {
		if (selectedElement) {
			setElements((prevElements) =>
				prevElements.map((el) =>
					el.id === selectedElement ? { ...el, color, borderRadius, text, description } : el
				)
			);
			setText('');
			setDescription('');
			setShowConfigPanel(false);
		}
	};

	const calculateWidth = (el) => {
		const description = el.description;
		const text = el.text
		const minWidth = 50;
		const maxWidth = 300;
		const baseWidth_desc = Math.max(minWidth, Math.min(maxWidth, description.length * 7));
		const baseWidth_text = Math.max(minWidth, Math.min(maxWidth, text.length * 7));
		return baseWidth_desc > baseWidth_text ? baseWidth_desc : baseWidth_text;
	};

	const CrossIcon = ({ x, y, onMouseDown }) => (<i className={`pi pi-check`} style={{ position: 'absolute', top: y, left: x, fontSize: '2em', color: 'green' }}></i>);

	const renderIcons = () => {
		const radius = 100; // Радиус для расположения иконок
		const iconRadius = 10; // Радиус иконки
		const centerX = panelPosition.x + 100; // Центр по X
		const centerY = panelPosition.y + 100; // Центр по Y

		const startingIcon = (
			<div
				key="starting-icon"
				onClick={() => setSelectedIcon(0)} // Уникальный id для начальной иконки
				style={{
					position: 'absolute',
					background: 'black',
					cursor: 'pointer',
					padding: '5px',
					borderRadius: '25%',
					left: centerX,
					top: centerY - radius - 30, // Расположите выше центра
					transform: 'translate(-50%, -50%)',
					zIndex: 2,
				}}
			>
				<i className={`pi pi-check`}  style={{ fontSize: '2em', color: 'green' }}></i>
			</div>
		);

		const otherIcons = icons.map((icon, index) => {
			const angle = (index / icons.length) * 2 * Math.PI - Math.PI / 2; // Сдвиг на 90 градусов
			const x = centerX + radius * Math.cos(angle); // X координата
			const y = centerY + radius * Math.sin(angle); // Y координата
	
			const lineStartX = centerX; // Начало линии от центра
			const lineStartY = centerY - radius - 30 + iconRadius; // Смещение вниз на радиус иконки
	
			return (
				<div
					key={icon.id}
					onClick={() => setSelectedIcon(icon.id)}
					style={{
						display: showIcons ? 'flex' : 'none',
						position: 'absolute',
						background: 'black',
						cursor: 'pointer',
						padding: '5px',
						borderRadius: '25%',
						left: x,
						top: y,
						transform: 'translate(-50%, -50%)',
						zIndex: 2,
					}}
				>
					<i className={`pi ${icon.icon}`} style={{ fontSize: '2em', color: 'green' }}></i>
					<line
						x1={lineStartX}
						y1={lineStartY} // Начальная точка линии (с учетом радиуса иконки)
						x2={x}
						y2={y}
						stroke="black"
						strokeWidth={2}
					/>
				</div>
			);
		});
	
		return (
			<>
				{otherIcons}
			</>
		);
	};


	return (
		<div className="background" onClick={handleBackgroundClick}>
			{ UpperPanel() }
			{showConfigPanel && (
				<div className="style-panel" style={{ left: panelPosition.x, top: panelPosition.y, zIndex: 1 }}>
					{ renderIcons(showConfigPanel) }
					<svg width="200" height="200">
						<circle cx={panelPosition.x + 100} cy={panelPosition.y + 100} r={30} fill="green" onClick={updateElementStyle} onMouseDown={startDraggingPanel} />
						<text x={panelPosition.x + 100} y={panelPosition.y + 100} textAnchor="middle" alignmentBaseline="middle" fill="white">✔</text>
						<line x1={panelPosition.x + 270} y1={panelPosition.y - 40} x2={panelPosition.x + 270 } y2={panelPosition.y + 250} stroke="gray" strokeWidth={3} />
					</svg>
					<div style={{ marginTop: '10px', left: panelPosition.x, top: panelPosition.y, position: 'absolute' }}>
						{icons.map((item) => (
							<>
								<InputText style={{ display: item.state ? 'block' : 'none' }} value={text} onChange={(e) => setText(e.target.value)} placeholder="Text" />
								<InputText style={{ display: item.state ? 'block' : 'none' }} onChange={(e) => setDescription(e.target.value)} placeholder="Description" />
								<InputNumber style={{ display: item.state ? 'block' : 'none' }} value={borderRadius} onValueChange={(e) => setBorderRadius(e.value)} placeholder="Border radius" />
								<InputText style={{ display: item.state ? 'block' : 'none' }} onChange={(e) => setColor(e.target.value)} placeholder="Color" />
							</>
						))}
					</div>
				</div>
			)}

		
			<svg width="100%" height="100%">
				{renderLines()}
				{elements.map((el) => (
					<g key={el.id} onClick={(e) => handleElementClick(e, el)}>
					<foreignObject x={el.x} y={el.y} width={calculateWidth(el)} height={300}>
						<div xmlns="http://www.w3.org/1999/xhtml" style={{ 
							width: '100%', 
							maxHeight: '300px', 
							minWidth: '50px', 
							maxWidth: '300px', 
							display: 'flex',
							flexDirection: 'column',
							justifyContent: 'center',
							background: 'white',
							border: `1px solid black`, 
							borderRadius: `${el.borderRadius}`,  
							alignItems: 'center', 
							padding: '12px', 
							overflow: 'hidden' 
						}}>
							{el.text && <span style={{ fontSize: '10px', color: 'black' }}>{el.text}</span>}
							{el.description && <span style={{ fontSize: '8px', color: 'gray' }}>{el.description}</span>}
						</div>
					</foreignObject>
					<circle
						cx={el.x + calculateWidth(el)} // Центр по ширине (правый круг)
						cy={el.y + 25} // Центр по высоте (по центру элемента)
						r={10} // Можно изменить на динамическое значение
						fill="green"
						onMouseDown={() => startDraggingLine(el)}
					/>
					<circle
						cx={el.x} // Центр по ширине (правый круг)
						cy={el.y + 60} // Центр по высоте (по центру элемента)
						r={20} // Можно изменить на динамическое значение
						fill="white"
						stroke='#ccc'
						style={{'cursor': 'move'}}
						onMouseDown={(e) => {
							e.stopPropagation();
							handleMouseDown(e, el);
						}}
					/>
					<circle
						cx={el.x} // Слева от элемента
						cy={el.y + 25} // Центр по высоте (по центру элемента)
						r={10} // Можно изменить на динамическое значение
						fill="orange"
					/>
					<foreignObject x={el.x - 10} y={el.y + 35} style={{zIndex: '9', width: '50px', height: '50px', top: '10px'}} className='text_p'>
						<p className='text_p'><i className="pi pi-arrows-alt text_p" style={{ fontSize: '1.5em', color: 'black', zIndex: '9' }}></i></p>
					</foreignObject>

				</g>
				))}
				{linePosition && (
					<line
						x1={linePosition.x}
						y1={linePosition.y}
						x2={linePosition.x + 100} // Измените на нужные координаты
						y2={linePosition.y + 25}   // Измените на нужные координаты
						stroke="blue"
						strokeWidth={2}
					/>
				)}
			</svg>
		</div>
	);
};

export default App;
```


// Добавить изменения в код выше коментирую прошлую функциональность с пометкой тут были изменения
// Сранить состояние линий и расположения узлов при изменении и сохранять состояние шифруя данные для localstorage.
// Добавить в данный файл все изменения учитыва предыдущие