Files
iistwin/client/src/components/SubdirectoryFieldConfig.tsx

174 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { useMemo } from 'react';
import { useQuery } from '@tanstack/react-query';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Table, Link2 } from 'lucide-react';
import { apiRequest } from '@/lib/queryClient';
import type { DataTableSubdirectory } from '@shared/schema';
interface FormFieldTable {
id?: number;
type: string;
allowMultiple?: boolean;
options?: Record<string, any>;
}
interface SubdirectoryFieldConfigProps {
field: FormFieldTable;
index: number;
tablesData?: { tables: Array<{ id: number; name: string; columns: any[] }> };
updateField: (index: number, updates: Partial<FormFieldTable>) => void;
}
export default function SubdirectoryFieldConfig({
field,
index,
tablesData,
updateField,
}: SubdirectoryFieldConfigProps) {
const tableId = field.options?.tableId as number | undefined;
const { data: subdirectoriesData } = useQuery<{ subdirectories: DataTableSubdirectory[] }>({
queryKey: ['/api/directories', tableId, 'subdirectories'],
queryFn: async () => {
const res = await apiRequest('GET', `/api/directories/${tableId}/subdirectories`);
return res.json();
},
enabled: !!tableId,
staleTime: 60 * 1000,
});
const subdirectories = subdirectoriesData?.subdirectories || [];
const showSubdirectory = !!field.options?.showSubdirectory;
const selectedTable = useMemo(() => {
return tablesData?.tables?.find((t) => t.id === tableId);
}, [tablesData, tableId]);
const handleTableChange = (value: string) => {
if (value === 'none') {
updateField(index, {
options: {
...field.options,
tableId: undefined,
displayColumn: undefined,
showSubdirectory: undefined,
},
});
return;
}
const newTableId = parseInt(value);
const newSelectedTable = tablesData?.tables?.find((t) => t.id === newTableId);
updateField(index, {
options: {
...field.options,
tableId: newTableId,
displayColumn: newSelectedTable?.columns?.[0]?.name || undefined,
showSubdirectory: undefined,
},
});
};
const handleShowSubdirectoryChange = (checked: boolean) => {
updateField(index, {
options: {
...field.options,
showSubdirectory: checked,
},
});
};
return (
<div className="mt-3 space-y-3">
<div className="flex items-center space-x-2">
<Checkbox
checked={field.allowMultiple || false}
onCheckedChange={(checked) => updateField(index, { allowMultiple: !!checked })}
data-testid={`checkbox-field-table-allow-multiple-${index}`}
/>
<label className="text-sm font-medium">Разрешить множественный выбор</label>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium">Таблица</label>
<Select value={tableId?.toString() || 'none'} onValueChange={handleTableChange}>
<SelectTrigger data-testid={`select-field-table-${index}`}>
<SelectValue placeholder="Выберите таблицу" />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">Не выбрано</SelectItem>
{tablesData?.tables?.map((table) => (
<SelectItem key={table.id} value={table.id.toString()}>
<div className="flex items-center gap-2">
<Table className="w-4 h-4" />
{table.name}
</div>
</SelectItem>
))}
</SelectContent>
</Select>
</div>
{tableId && (
<div>
<label className="text-sm font-medium">Отображаемый столбец</label>
<Select
value={field.options?.displayColumn || 'none'}
onValueChange={(value) =>
updateField(index, {
options: { ...field.options, displayColumn: value === 'none' ? undefined : value },
})
}
>
<SelectTrigger data-testid={`select-field-column-${index}`}>
<SelectValue placeholder="Выберите столбец" />
</SelectTrigger>
<SelectContent>
<SelectItem value="none">Не выбрано</SelectItem>
{selectedTable?.columns?.map((col: any, idx: number) => (
<SelectItem key={idx} value={col.name || `col-${idx}`}>
{col.name}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
)}
</div>
{tableId && (
<div className="border rounded-md p-3 space-y-3 bg-muted/20">
<div className="flex items-center space-x-2">
<Checkbox
checked={showSubdirectory}
onCheckedChange={handleShowSubdirectoryChange}
data-testid={`checkbox-field-show-subdirectory-${index}`}
/>
<label className="text-sm font-medium flex items-center gap-1.5">
<Link2 className="w-3.5 h-3.5" />
Отображать подсправочник
</label>
</div>
{showSubdirectory && (
<p className="text-xs text-muted-foreground">
При выборе строки родительского справочника будет показан подсправочник, привязанный к этой строке.
{subdirectories.length > 0
? ` Найдено подсправочников: ${subdirectories.length}.`
: ' Нет привязанных подсправочников.'}
</p>
)}
</div>
)}
</div>
);
}