import { useCallback, useLayoutEffect, useMemo, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { toast } from 'react-toastify'; import MiniButton from '../../components/Common/MiniButton'; import SubmitButton from '../../components/Common/SubmitButton'; import TextArea from '../../components/Common/TextArea'; import { DumpBinIcon, SaveIcon, SmallPlusIcon } from '../../components/Icons'; import { useRSForm } from '../../context/RSFormContext'; import { type CstType, EditMode, type ICstCreateData, ICstUpdateData, SyntaxTree } from '../../utils/models'; import { createAliasFor, getCstTypeLabel } from '../../utils/staticUI'; import DlgCreateCst from './DlgCreateCst'; import EditorRSExpression from './EditorRSExpression'; import ViewSideConstituents from './elements/ViewSideConstituents'; import { RSTabsList } from './RSTabs'; interface EditorConstituentaProps { onShowAST: (ast: SyntaxTree) => void } function EditorConstituenta({onShowAST}: EditorConstituentaProps) { const navigate = useNavigate(); const { activeCst, activeID, schema, setActiveID, processing, isEditable, cstDelete, cstUpdate, cstCreate } = useRSForm(); const [showCstModal, setShowCstModal] = useState(false); const [isModified, setIsModified] = useState(false); const [editMode, setEditMode] = useState(EditMode.TEXT); const [alias, setAlias] = useState(''); const [type, setType] = useState(''); const [term, setTerm] = useState(''); const [textDefinition, setTextDefinition] = useState(''); const [expression, setExpression] = useState(''); const [convention, setConvention] = useState(''); const [typification, setTypification] = useState('N/A'); const isEnabled = useMemo(() => activeCst && isEditable, [activeCst, isEditable]); useLayoutEffect(() => { if (schema && schema?.items.length > 0) { setActiveID((prev) => (prev ?? schema.items[0].id ?? undefined)); } }, [schema, setActiveID]); useLayoutEffect(() => { if (!activeCst) { setIsModified(false); return; } setIsModified( activeCst.term.raw !== term || activeCst.definition.text.raw !== textDefinition || activeCst.convention !== convention || activeCst.definition.formal !== expression ); }, [activeCst, activeCst?.term, activeCst?.definition.formal, activeCst?.definition.text.raw, activeCst?.convention, term, textDefinition, expression, convention]); useLayoutEffect(() => { if (activeCst) { setAlias(activeCst.alias); setType(getCstTypeLabel(activeCst.cstType)); setConvention(activeCst.convention ?? ''); setTerm(activeCst.term?.raw ?? ''); setTextDefinition(activeCst.definition?.text?.raw ?? ''); setExpression(activeCst.definition?.formal ?? ''); setTypification(activeCst?.parse?.typification || 'N/A'); } }, [activeCst]); const handleSubmit = (event: React.FormEvent) => { event.preventDefault(); if (!activeID || processing) { return; } const data: ICstUpdateData = { id: activeID, alias: alias, convention: convention, definition_formal: expression, definition_raw: textDefinition, term_raw: term }; cstUpdate(data, () => { toast.success('Изменения сохранены'); }); }; const handleDelete = useCallback( () => { if (!activeID || !schema?.items || !window.confirm('Вы уверены, что хотите удалить конституенту?')) { return; } const data = { items: [{ id: activeID }] } const index = schema.items.findIndex((cst) => cst.id === activeID); let newActive: number | undefined = undefined if (index !== -1 && index + 1 < schema.items.length) { newActive = schema.items[index + 1].id; } cstDelete(data, () => toast.success('Конституента удалена')); if (newActive) navigate(`/rsforms/${schema.id}?tab=${RSTabsList.CST_EDIT}&active=${newActive}`); }, [activeID, schema, cstDelete, navigate]); const handleAddNew = useCallback( (type?: CstType) => { if (!activeID || !schema?.items) { return; } if (!type) { setShowCstModal(true); } else { const data: ICstCreateData = { cst_type: type, alias: createAliasFor(type, schema), insert_after: activeID } cstCreate(data, newCst => { navigate(`/rsforms/${schema.id}?tab=${RSTabsList.CST_EDIT}&active=${newCst.id}`); toast.success(`Конституента добавлена: ${newCst.alias}`); }); } }, [activeID, schema, cstCreate, navigate]); const handleRename = useCallback(() => { toast.info('Переименование в разработке'); }, []); const handleChangeType = useCallback(() => { toast.info('Изменение типа в разработке'); }, []); return (
{showCstModal && { setShowCstModal(false); }} onCreate={handleAddNew} defaultType={activeCst?.cstType as CstType} />}
{alias} {type}
{ handleAddNew(); }} icon={} /> } />