ConceptPortal-public/rsconcept/frontend/src/dialogs/DlgCreateCst/FormCreateCst.tsx

145 lines
5.0 KiB
TypeScript
Raw Normal View History

2024-04-01 15:11:17 +03:00
'use client';
2024-06-09 20:41:33 +03:00
import clsx from 'clsx';
import { useCallback, useEffect, useMemo, useState } from 'react';
2024-04-01 15:11:17 +03:00
2024-05-16 22:39:28 +03:00
import BadgeHelp from '@/components/info/BadgeHelp';
2024-04-01 15:11:17 +03:00
import RSInput from '@/components/RSInput';
import SelectSingle from '@/components/ui/SelectSingle';
import TextArea from '@/components/ui/TextArea';
import TextInput from '@/components/ui/TextInput';
2024-04-01 19:07:20 +03:00
import { HelpTopic } from '@/models/miscellaneous';
2024-04-01 15:11:17 +03:00
import { CstType, ICstCreateData, IRSForm } from '@/models/rsform';
import { generateAlias, isBaseSet, isBasicConcept, isFunctional, validateNewAlias } from '@/models/rsformAPI';
2024-06-09 20:41:33 +03:00
import { PARAMETER } from '@/utils/constants';
2024-04-01 15:11:17 +03:00
import { labelCstType } from '@/utils/labels';
import { SelectorCstType } from '@/utils/selectors';
interface FormCreateCstProps {
schema: IRSForm;
state: ICstCreateData;
partialUpdate: React.Dispatch<Partial<ICstCreateData>>;
2024-05-23 13:06:23 +03:00
setValidated?: React.Dispatch<React.SetStateAction<boolean>>;
2024-04-01 15:11:17 +03:00
}
function FormCreateCst({ schema, state, partialUpdate, setValidated }: FormCreateCstProps) {
const [forceComment, setForceComment] = useState(false);
const isBasic = useMemo(() => isBasicConcept(state.cst_type), [state]);
const isElementary = useMemo(() => isBaseSet(state.cst_type), [state]);
const showConvention = useMemo(() => !!state.convention || forceComment || isBasic, [state, forceComment, isBasic]);
useEffect(() => {
2024-04-01 15:11:17 +03:00
setForceComment(false);
}, [state.cst_type, partialUpdate, schema]);
useEffect(() => {
2024-05-23 13:06:23 +03:00
if (setValidated) {
setValidated(validateNewAlias(state.alias, state.cst_type, schema));
}
2024-04-01 15:11:17 +03:00
}, [state.alias, state.cst_type, schema, setValidated]);
2024-08-29 12:42:26 +03:00
const handleTypeChange = useCallback(
(target: CstType) => partialUpdate({ cst_type: target, alias: generateAlias(target, schema) }),
2024-10-23 16:21:08 +03:00
[partialUpdate, schema]
2024-08-29 12:42:26 +03:00
);
2024-04-01 15:11:17 +03:00
return (
<>
<div className='flex items-center self-center gap-3'>
2024-04-01 15:11:17 +03:00
<SelectSingle
id='dlg_cst_type'
placeholder='Выберите тип'
2024-09-21 20:04:07 +03:00
className='w-[16rem]'
2024-04-01 15:11:17 +03:00
options={SelectorCstType}
value={{ value: state.cst_type, label: labelCstType(state.cst_type) }}
2024-08-29 12:42:26 +03:00
onChange={data => handleTypeChange(data?.value ?? CstType.BASE)}
2024-06-09 20:41:33 +03:00
/>
2024-04-01 15:11:17 +03:00
<TextInput
id='dlg_cst_alias'
dense
label='Имя'
2024-08-30 11:03:45 +03:00
className='w-[7rem]'
2024-04-01 15:11:17 +03:00
value={state.alias}
onChange={event => partialUpdate({ alias: event.target.value })}
/>
2024-08-29 12:42:26 +03:00
<BadgeHelp
topic={HelpTopic.CC_CONSTITUENTA}
offset={16}
className={clsx(PARAMETER.TOOLTIP_WIDTH, 'sm:max-w-[40rem]')}
/>
2024-04-01 15:11:17 +03:00
</div>
2024-04-01 15:11:17 +03:00
<TextArea
id='dlg_cst_term'
2024-08-28 22:38:50 +03:00
fitContent
2024-04-01 15:11:17 +03:00
spellCheck
label='Термин'
placeholder='Обозначение для текстовых определений'
2024-08-28 22:38:50 +03:00
className='max-h-[3.6rem]'
2024-04-01 15:11:17 +03:00
value={state.term_raw}
onChange={event => partialUpdate({ term_raw: event.target.value })}
/>
{!!state.definition_formal || !isElementary ? (
2024-04-01 15:11:17 +03:00
<RSInput
id='dlg_cst_expression'
2024-08-29 12:42:26 +03:00
noTooltip
2024-04-01 15:11:17 +03:00
label={
state.cst_type === CstType.STRUCTURED
? 'Область определения'
: isFunctional(state.cst_type)
? 'Определение функции'
: 'Формальное определение'
}
placeholder={
2024-09-23 14:58:53 +03:00
state.cst_type !== CstType.STRUCTURED ? 'Родоструктурное выражение' : 'Типизация родовой структуры'
2024-04-01 15:11:17 +03:00
}
value={state.definition_formal}
onChange={value => partialUpdate({ definition_formal: value })}
2024-06-18 19:55:23 +03:00
schema={schema}
2024-04-01 15:11:17 +03:00
/>
) : null}
{!!state.definition_raw || !isElementary ? (
2024-04-01 15:11:17 +03:00
<TextArea
id='dlg_cst_definition'
spellCheck
2024-08-28 22:38:50 +03:00
fitContent
2024-04-01 15:11:17 +03:00
label='Текстовое определение'
placeholder='Текстовая интерпретация формального выражения'
2024-08-28 22:38:50 +03:00
className='max-h-[3.6rem]'
2024-04-01 15:11:17 +03:00
value={state.definition_raw}
onChange={event => partialUpdate({ definition_raw: event.target.value })}
/>
) : null}
2024-04-01 15:11:17 +03:00
{!showConvention ? (
<button
id='dlg_cst_show_comment'
2024-05-11 20:53:36 +03:00
tabIndex={-1}
2024-04-01 15:11:17 +03:00
type='button'
className='self-start cc-label clr-text-url hover:underline'
onClick={() => setForceComment(true)}
>
Добавить комментарий
</button>
) : (
2024-04-01 15:11:17 +03:00
<TextArea
id='dlg_cst_convention'
spellCheck
2024-08-28 22:38:50 +03:00
fitContent
2024-04-01 15:11:17 +03:00
label={isBasic ? 'Конвенция' : 'Комментарий'}
placeholder={isBasic ? 'Договоренность об интерпретации' : 'Пояснение разработчика'}
2024-08-28 22:38:50 +03:00
className='max-h-[5.4rem]'
2024-04-01 15:11:17 +03:00
value={state.convention}
onChange={event => partialUpdate({ convention: event.target.value })}
/>
)}
</>
2024-04-01 15:11:17 +03:00
);
}
export default FormCreateCst;