// EditCell.js - обновленная версия import { useEffect, useRef, useLayoutEffect, useState } from 'react'; import { isFormula, extractFormula, calculateFormula, formatNumber } from '../../utils/formulaUtils'; import { saveToStorage, loadFromStorage } from '../../utils/localStorageUtils'; import { useRealtime } from '../../contexts/RealtimeContext'; const EditCell = ({ refCell, onChange, disabled, value, tableId, cellId, table }) => { const { endEditing: contextEndEditing } = useRealtime(); const [curValue, setCurValue] = useState(value); const [displayValue, setDisplayValue] = useState(value); const [isFormulaMode, setIsFormulaMode] = useState(false); // Ключ для хранения формул в localStorage const storageKey = `formula_${tableId}_${cellId}`; const trFrag = refCell.current.offsetParent.offsetParent; const tdFrag = refCell.current.offsetParent; const left = tdFrag.offsetLeft; const width = refCell.current.offsetParent.offsetWidth; const translateY = trFrag.style.transform; // Загружаем сохраненную формулу при монтировании useEffect(() => { const savedFormula = loadFromStorage(storageKey); if (savedFormula && isFormula(savedFormula)) { setIsFormulaMode(true); setCurValue(savedFormula); // Вычисляем и отображаем результат try { const formula = extractFormula(savedFormula); const result = calculateFormula(formula); setDisplayValue(formatNumber(result)); } catch (error) { setDisplayValue('#ОШИБКА'); } } else { setDisplayValue(value); } }, [storageKey, value]); function useAutoResize(value) { const ref = useRef(null); useLayoutEffect(() => { const el = ref.current; if (!el) return; el.style.height = 'auto'; el.style.minHeight = '3rem'; el.style.height = el.scrollHeight + 'px'; el.style.maxHeight = '180px'; }, [value]); return ref; } const ref = useAutoResize(value); useEffect(() => { if (ref.current && !disabled) { ref.current.focus(); ref.current.setSelectionRange( ref.current.value.length, ref.current.value.length, ); } }, [disabled, ref]); const handleSave = () => { // Проверяем, является ли введенное значение формулой if (isFormula(curValue)) { // Сохраняем формулу в localStorage saveToStorage(storageKey, curValue); // Вычисляем и сохраняем результат try { const formula = extractFormula(curValue); const result = calculateFormula(formula); const formattedResult = formatNumber(result); setDisplayValue(formattedResult); onChange?.(formattedResult); setIsFormulaMode(true); return; } catch (error) { setDisplayValue('#ОШИБКА'); onChange?.(curValue); // Сохраняем как текст, если ошибка return; } } else { // Если это не формула, удаляем сохраненную формулу localStorage.removeItem(storageKey); setIsFormulaMode(false); setDisplayValue(curValue); onChange?.(curValue); } }; const handleChangeValue = (event) => { const input = event.target.value; setCurValue(input); // При редактировании показываем введенный текст setDisplayValue(input); }; // Функция для отображения значения в ячейке const getDisplayValue = () => { if (isFormulaMode && isFormula(curValue)) { return displayValue; } return displayValue; }; const finishEditing = () => { if (!disabled) { handleSave(); } const editingCell = table.getState().editingCell || null; if (editingCell) { contextEndEditing?.(editingCell.row, editingCell.column); } }; useEffect(() => { const handleClickOutside = (event) => { // Проверяем, был ли клик внутри элемента редактирования const editElement = ref.current; if (editElement && !editElement.contains(event.target)) { finishEditing(); } }; document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, [ref, finishEditing]); return (
{isFormulaMode && (
fx
)}