ConceptPortal-public/rsconcept/frontend/src/dialogs/DlgEditReference/EntityTab.tsx

104 lines
3.5 KiB
TypeScript
Raw Normal View History

'use client';
2023-12-01 22:50:43 +03:00
import { useEffect, useLayoutEffect, useState } from 'react';
import ConstituentaPicker from '@/components/ConstituentaPicker';
import SelectGrammeme from '@/components/SelectGrammeme';
import FlexColumn from '@/components/ui/FlexColumn';
import Label from '@/components/ui/Label';
import TextInput from '@/components/ui/TextInput';
import { ReferenceType } from '@/models/language';
import { parseEntityReference, parseGrammemes } from '@/models/languageAPI';
2023-12-26 14:23:51 +03:00
import { CstMatchMode } from '@/models/miscellaneous';
import { IConstituenta } from '@/models/rsform';
import { matchConstituenta } from '@/models/rsformAPI';
import { prefixes } from '@/utils/constants';
2023-12-27 19:34:39 +03:00
import { IGrammemeOption, SelectorGrammemes } from '@/utils/selectors';
2023-12-01 22:50:43 +03:00
import { IReferenceInputState } from './DlgEditReference';
2023-12-08 19:24:08 +03:00
import SelectWordForm from './SelectWordForm';
2023-12-01 22:50:43 +03:00
interface EntityTabProps {
2023-12-28 14:04:44 +03:00
initial: IReferenceInputState;
items: IConstituenta[];
setIsValid: React.Dispatch<React.SetStateAction<boolean>>;
setReference: React.Dispatch<React.SetStateAction<string>>;
2023-12-01 22:50:43 +03:00
}
function EntityTab({ initial, items, setIsValid, setReference }: EntityTabProps) {
const [selectedCst, setSelectedCst] = useState<IConstituenta | undefined>(undefined);
const [alias, setAlias] = useState('');
const [term, setTerm] = useState('');
const [selectedGrams, setSelectedGrams] = useState<IGrammemeOption[]>([]);
// Initialization
2023-12-28 14:04:44 +03:00
useLayoutEffect(() => {
2023-12-01 22:50:43 +03:00
if (!!initial.refRaw && initial.type === ReferenceType.ENTITY) {
const ref = parseEntityReference(initial.refRaw);
setAlias(ref.entity);
const grams = parseGrammemes(ref.form);
2023-12-27 19:34:39 +03:00
setSelectedGrams(SelectorGrammemes.filter(data => grams.includes(data.value)));
2023-12-01 22:50:43 +03:00
}
}, [initial, items]);
// Produce result
2023-12-28 14:04:44 +03:00
useEffect(() => {
2023-12-01 22:50:43 +03:00
setIsValid(alias !== '' && selectedGrams.length > 0);
setReference(`@{${alias}|${selectedGrams.map(gram => gram.value).join(',')}}`);
}, [alias, selectedGrams, setIsValid, setReference]);
// Update term when alias changes
2023-12-28 14:04:44 +03:00
useEffect(() => {
const cst = items.find(item => item.alias === alias);
setTerm(cst?.term_resolved ?? '');
2023-12-01 22:50:43 +03:00
}, [alias, term, items]);
function handleSelectConstituenta(cst: IConstituenta) {
setAlias(cst.alias);
setSelectedCst(cst);
}
2023-12-28 14:04:44 +03:00
return (
<FlexColumn>
<ConstituentaPicker
2024-01-29 14:44:51 +03:00
initialFilter={initial.text}
2023-12-28 14:04:44 +03:00
value={selectedCst}
data={items}
onSelectValue={handleSelectConstituenta}
prefixID={prefixes.cst_modal_list}
describeFunc={cst => cst.term_resolved}
matchFunc={(cst, filter) => matchConstituenta(cst, filter, CstMatchMode.TERM)}
onBeginFilter={cst => cst.term_resolved !== ''}
rows={8}
2023-12-08 19:24:08 +03:00
/>
2023-12-01 22:50:43 +03:00
2023-12-28 14:04:44 +03:00
<div className='flex gap-3'>
<TextInput
dense
label='Конституента'
placeholder='Имя'
className='w-[11rem]'
value={alias}
onChange={event => setAlias(event.target.value)}
/>
<TextInput disabled dense noBorder label='Термин' className='flex-grow text-sm' value={term} title={term} />
</div>
<SelectWordForm selected={selectedGrams} setSelected={setSelectedGrams} />
<div className='flex items-center gap-4'>
<Label text='Словоформа' />
<SelectGrammeme
placeholder='Выберите граммемы'
className='flex-grow'
menuPlacement='top'
value={selectedGrams}
setValue={setSelectedGrams}
/>
</div>
</FlexColumn>
);
2023-12-01 22:50:43 +03:00
}
2023-12-28 14:04:44 +03:00
export default EntityTab;