195 lines
6.0 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 (
<tr>
<td>
<div
key="blockForEdit"
style={{
position: 'absolute',
left: left,
zIndex: 12,
width: width,
transform: translateY,
top: 0,
}}
>
{isFormulaMode && (
<div style={{
position: 'absolute',
top: '-20px',
left: '4px',
fontSize: '10px',
color: '#666',
background: '#f0f0f0',
padding: '2px 6px',
borderRadius: '3px',
pointerEvents: 'none'
}}>
fx
</div>
)}
<textarea
ref={ref}
disabled={disabled}
style={{
width: '100%',
height: 'auto',
fieldSizing: 'content',
fontSize: 'inherit',
backgroundColor: isFormulaMode ? '#f8f9fa' : 'white',
border: isFormulaMode ? '2px solid #4a90d9' : undefined,
}}
onChange={handleChangeValue}
value={curValue}
onKeyDown={(e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
finishEditing();
}
}}
placeholder={isFormulaMode ? 'Введите формулу (начинается с =)' : ''}
/>
</div>
</td>
</tr>
);
};
export default EditCell;