﻿
> function TableFieldSelect({ formField, value, onChange }: { 
    formField: FormFieldData; 
    value: any; 
    onChange: (value: string) => void;
  }) {
    const options = formField.options && !Array.isArray(formField.options) ? formField.options : {};
    const tableId = options.tableId;
    const displayColumn = options.displayColumn || '';
  
    const { data: tableData, isLoading, error } = useQuery<{ table: { rows: Array<{ id: number; values: string[] }>; co
lumns: Array<{ name: string }> } }>({
      queryKey: ['/api/directories', tableId],
      enabled: !!tableId,
      staleTime: 5 * 60 * 1000,
      gcTime: 10 * 60 * 1000,
      retry: false,
    });
  
    const [searchTerm, setSearchTerm] = useState('');
    const [isOpen, setIsOpen] = useState(false);
    const inputRef = useRef<HTMLInputElement>(null);
  
    if (!tableId) {
      return <div className="text-sm text-muted-foreground">Таблица не настроена</div>;
    }
  
    if (isLoading) {
      return <Input disabled className="h-8" placeholder="Загрузка..." />;
    }
  
    if (error) {
      return <div className="text-sm text-destructive">Нет доступа к таблице</div>;
    }
  
    const table = tableData?.table;
    if (!table || !table.rows?.length) {
      return <div className="text-sm text-muted-foreground">Таблица пуста</div>;
    }
  
    // Находим индекс столбца для отображения, с fallback на первый столбец
    let displayColumnIndex = table.columns?.findIndex(c => c.name === displayColumn);
    if (displayColumnIndex === undefined || displayColumnIndex < 0) {
      displayColumnIndex = 0;
    }
  
    const getDisplayValue = (rowId: string | number) => {
      const row = table.rows?.find(r => r.id.toString() === rowId?.toString());
      return row?.values[displayColumnIndex!] || row?.values[0] || '';
    };
  
    const selectedRow = table.rows?.find(r => r.id.toString() === value?.toString());
    const selectedDisplay = selectedRow ? (selectedRow.values[displayColumnIndex!] || selectedRow.values[0] || '') : ''
;
  
    const sortedRows = useMemo(() => {
      return [...table.rows].sort((a, b) => {
        const av = a.values[displayColumnIndex!] || a.values[0] || '';
        const bv = b.values[displayColumnIndex!] || b.values[0] || '';
        return av.localeCompare(bv, 'ru');
      });
    }, [table.rows, displayColumnIndex]);
  
    const filtered = useMemo(() => {
      if (!searchTerm.trim()) return sortedRows;
      const term = searchTerm.toLowerCase();
      return sortedRows.filter(r => {
        const display = r.values[displayColumnIndex!] || r.values[0] || '';
        return display.toLowerCase().includes(term);
      });
    }, [sortedRows, searchTerm, displayColumnIndex]);
  
    const handleSelect = (rowId: string) => {
      onChange(rowId);
      setSearchTerm('');
      setIsOpen(false);
    };
  
    return (
      <Popover open={isOpen} onOpenChange={setIsOpen}>
        <PopoverAnchor asChild>
          <div className="relative w-full">
            <Input
              ref={inputRef}
              className="h-8"
              placeholder={formField.placeholder || 'Выберите значение...'}
              value={isOpen ? searchTerm : (selectedDisplay || '')}
              onChange={(e) => {
                setSearchTerm(e.target.value);
                setIsOpen(true);
              }}
              onFocus={() => {
                setSearchTerm('');
                setIsOpen(true);
              }}
              data-testid={`select-table-${formField.code}`}
            />
          </div>
        </PopoverAnchor>
        <PopoverContent 
          className="p-0" 
          style={{ width: 'var(--radix-popper-anchor-width)' }}
          onOpenAutoFocus={(e) => e.preventDefault()}
          onInteractOutside={(e) => {
            if (inputRef.current && inputRef.current.contains(e.target as Node)) {
              e.preventDefault();
            }
          }}
        >
          <ul className="max-h-60 overflow-auto py-1">
            <li
              className="cursor-pointer px-3 py-2 hover:bg-accent text-sm text-muted-foreground"
              onMouseDown={(e) => { e.preventDefault(); handleSelect(''); }}
            >
              —
            </li>
            {filtered.map(row => (
              <li
                key={row.id}
                className="cursor-pointer px-3 py-2 hover:bg-accent"
                onMouseDown={(e) => { e.preventDefault(); handleSelect(row.id.toString()); }}
              >
                <div className="flex items-center gap-2 text-sm">
                  <Table className="w-3 h-3 text-muted-foreground" />
                  {row.values[displayColumnIndex!] || row.values[0]}
                </div>
              </li>
            ))}
            {filtered.length === 0 && (
              <li className="px-3 py-2 text-sm text-muted-foreground">Нет совпадений</li>
            )}
          </ul>
        </PopoverContent>
      </Popover>
    );
  }
  
  // Компонент выбора связанной задачи из другой формы
  function TaskFieldSelect({ formField, value, onChange }: { 


