diff --git a/ordinis-admin-ui/src/components/form/SchemaDrivenForm.tsx b/ordinis-admin-ui/src/components/form/SchemaDrivenForm.tsx index d114e3d..214757d 100644 --- a/ordinis-admin-ui/src/components/form/SchemaDrivenForm.tsx +++ b/ordinis-admin-ui/src/components/form/SchemaDrivenForm.tsx @@ -54,6 +54,11 @@ type Props = { formId?: string /** Notifies parent of dirty-field count (for "N полей" footer caption). */ onDirtyChange?: (dirtyCount: number) => void + /** Layout mode (default 'tabs' для backward compat): + * - 'tabs': single bucket visible at once, tab bar для switch (legacy) + * - 'sections': all buckets vertically scrollable + section chips strip + * на верху для quick jump. Per handoff Screen 3 RecordDrawer design. */ + layout?: 'tabs' | 'sections' } const ajv = new Ajv({ allErrors: true, strict: false }) @@ -98,6 +103,7 @@ export const SchemaDrivenForm = ({ onCancel, formId, onDirtyChange, + layout = 'tabs', }: Props) => { const { t } = useTranslation() const [activeTab, setActiveTab] = useState('identity') @@ -188,15 +194,55 @@ export const SchemaDrivenForm = ({ onDirtyChange?.(dirtyCount) }, [dirtyCount, onDirtyChange]) + // Section visibility — в 'sections' layout все buckets рендерятся подряд, + // в 'tabs' — только active. Sections layout per handoff Screen 3 prototype. + const showAllSections = layout === 'sections' + const sectionVisible = (id: TabId) => showAllSections || activeTab === id + + // Scroll-to-section для chip click (только в sections mode). + const scrollToSection = (id: TabId) => { + document.getElementById(`form-section-${formId ?? 'default'}-${id}`)?.scrollIntoView({ + behavior: 'smooth', + block: 'start', + }) + } + return (
- setActiveTab(id as TabId)} /> + {/* Section chips strip per handoff (sections mode) OR tab bar (legacy). */} + {showAllSections ? ( +
+ {visibleTabs.map((tab) => ( + + ))} +
+ ) : ( + setActiveTab(id as TabId)} /> + )} -
+
+ {showAllSections && ( +

+ {t('form.tabs.identity')} +

+ )}
{!idSource && (
@@ -258,7 +304,15 @@ export const SchemaDrivenForm = ({
-
+
+ {showAllSections && buckets.description.length > 0 && ( +

+ {t('form.tabs.description')} +

+ )}
{buckets.description.map((key) => (
-
+
+ {showAllSections && buckets.extra.length > 0 && ( +

+ {t('form.tabs.extra')} +

+ )}
{buckets.extra.map((key) => ( setEdit({ kind: 'closed' })} formId="record-form" + layout="sections" onDirtyChange={setRecordDirtyCount} /> )} @@ -1031,6 +1032,7 @@ function DictionaryDetail() { onSubmit={handleSubmit} onCancel={() => setEdit({ kind: 'closed' })} formId="record-form" + layout="sections" onDirtyChange={setRecordDirtyCount} /> )}