feat: привязка подсправочника к строкам родителя (parentRowIds)

This commit is contained in:
2026-07-21 10:43:28 +03:00
parent eff91bffad
commit 9edd90211f
6 changed files with 81 additions and 44 deletions

View File

@@ -3,7 +3,7 @@ import { useQuery } from '@tanstack/react-query';
import { apiRequest } from '@/lib/queryClient';
import TableFieldSelect from '@/components/TableFieldSelect';
import TableFieldMultiSelect from '@/components/TableFieldMultiSelect';
import type { DataTableSubdirectory } from '@shared/schema';
import type { DataTableRow, DataTableSubdirectory } from '@shared/schema';
interface TableFieldValue {
parentId?: string | null;
@@ -67,6 +67,23 @@ export default function TableFieldWithSubdirectory({
const showSubdirectory = !!opts.showSubdirectory;
const subdirectoryId = opts.subdirectoryId as number | undefined;
const { data: tableData } = useQuery<{
table: {
rows: DataTableRow[];
columns: Array<{ name: string }>;
treeColumnIndex: number | null;
treeDisplayColumnIndex: number | null;
treeColumns: number[] | null;
treeDisplayColumns: number[] | null;
};
}>({
queryKey: ['/api/directories', tableId],
enabled: !!tableId,
staleTime: 5 * 60 * 1000,
gcTime: 10 * 60 * 1000,
retry: false,
});
const { data: subdirectoriesData } = useQuery<{ subdirectories: DataTableSubdirectory[] }>({
queryKey: ['/api/directories', tableId, 'subdirectories'],
queryFn: async () => {
@@ -83,8 +100,25 @@ export default function TableFieldWithSubdirectory({
const { parentId, childId } = parseTableValue(value);
const parentRow = useMemo(() => {
if (!parentId || !tableData?.table?.rows) return null;
return tableData.table.rows.find((r) => r.id.toString() === parentId) || null;
}, [parentId, tableData]);
const isParentLinked = useMemo(() => {
if (!subdirectory || !parentId) return false;
return subdirectory.parentRowIds?.includes(Number(parentId)) ?? false;
}, [subdirectory, parentId]);
const childFilter = useMemo(() => {
if (!subdirectory || !parentRow) return undefined;
const col = String(subdirectory.childColumnIndex ?? 0);
const parentValue = parentRow.values?.[subdirectory.parentColumnIndex ?? 0] ?? '';
if (!parentValue) return undefined;
return { [col]: parentValue };
}, [subdirectory, parentRow]);
const handleParentChange = (newParentId: string) => {
// When parent changes, keep child only if it still belongs to new parent (simplified: reset child)
onChange(serializeTableValue(newParentId || null, null));
};
@@ -92,12 +126,6 @@ export default function TableFieldWithSubdirectory({
onChange(serializeTableValue(parentId, newChildId || null));
};
const childFilter = useMemo(() => {
if (!subdirectory || !parentId) return undefined;
const col = String(subdirectory.childColumnIndex ?? 0);
return { [col]: parentId };
}, [subdirectory, parentId]);
if (!showSubdirectory || !subdirectory || allowMultiple) {
const SelectComponent = allowMultiple ? TableFieldMultiSelect : TableFieldSelect;
return (
@@ -117,6 +145,7 @@ export default function TableFieldWithSubdirectory({
...opts,
tableId: subdirectory.childTableId,
displayColumn: subdirectory.childTable?.columns?.[subdirectory.childColumnIndex ?? 0]?.name || undefined,
filters: childFilter,
};
return (
@@ -129,14 +158,16 @@ export default function TableFieldWithSubdirectory({
value={parentId || ''}
onChange={handleParentChange}
/>
<TableFieldSelect
fieldId={fieldId}
fieldCode={`${fieldCode}_sub`}
placeholder={subdirectory.childTable?.name || 'Выберите подсправочник...'}
options={childOptions}
value={childId || ''}
onChange={handleChildChange}
/>
{isParentLinked && childFilter && (
<TableFieldSelect
fieldId={fieldId}
fieldCode={`${fieldCode}_sub`}
placeholder={subdirectory.childTable?.name || 'Выберите подсправочник...'}
options={childOptions}
value={childId || ''}
onChange={handleChildChange}
/>
)}
</div>
);
}