Untitled

mail@pastecode.io avatarunknown
typescript
11 days ago
3.2 kB
1
Indexable
Never
import { Select, SelectProps, Spin } from "antd";
import { DefaultOptionType } from "antd/lib/select";
import { debounce, rest } from "lodash";
import { useEffect, useState } from "react";
import { QueryParamsType } from "types/common/RequestType";
import { filterOption } from "utils/select-options";

interface SelectAsyncFetchDataProps {
  queryParams?: QueryParamsType;
  columnsToSearch?: Array<string>;
}

export interface SelectAsyncProps extends SelectProps {
  fetchData: (props: SelectAsyncFetchDataProps) => Promise<any>;
  fetchItem?: (itemId: string) => Promise<any>;
  fieldsLabel: string[];
  columnsToSearch: string[];
  propInValue?: string;
  selectValue?: string | string[];
}

const ITEMS_PER_PAGE = "20";

function optionLabelFormatter(option: any, fieldsLabel: string[]) {
  if (fieldsLabel.length > 1) {
    const label = fieldsLabel.map(field => option[field]);
    return label.join(" - ")
  } else {
    const [field] = fieldsLabel;
    return option[field];
  }
}

function generateOptions(data: any, fieldsLabel: string[], propInValue?: string) {
  const optionsFormatted = data.map(option => {
    return {
      value: propInValue ? option[propInValue] ?? "" : option.uuid,
      label: optionLabelFormatter(option, fieldsLabel)
    }
  });

  return optionsFormatted;
}

export function SelectAsync({
  fetchData,
  fetchItem,
  fieldsLabel,
  columnsToSearch,
  propInValue,
  selectValue,
  ...props
}: SelectAsyncProps) {
  const [options, setOptions] = useState<DefaultOptionType[]>([]);
  const [optionsIsLoading, setOptionsIsLoading] = useState<boolean>(false);

  useEffect(() => {
    if (selectValue && !propInValue && fetchItem) { // tem que ter selectValue (array ou não), não pode ser propInValue (o fetch não funciona se for propInValue porque não é o UUID)
      setOptionsIsLoading(true);

      if (Array.isArray(selectValue)) {
        Promise.all(selectValue.map(itemToFetch => fetchItem(itemToFetch))).then(responses => {
          const optionsFormatted = generateOptions([...responses], fieldsLabel);
          setOptions(optionsFormatted);
        }).catch(error => {
          setOptions([]);
        }).finally(() => {
          setOptionsIsLoading(false)
        })

        return;
      }

      fetchItem(selectValue).then(response => {
        const optionsFormatted = generateOptions([response], fieldsLabel);
        setOptions(optionsFormatted);
      }).catch(error => {
        setOptions([]);
      }).finally(() => {
        setOptionsIsLoading(false);
      });
    }
  }, [JSON.stringify(selectValue)]);

  return (
    <Select
      value={selectValue}
      placeholder={"Selecione uma opção"}
      showSearch
      allowClear
      filterOption={false}
      onSearch={() => { }}
      onClear={() => { }}
      options={options}
      loading={optionsIsLoading}
      notFoundContent={optionsIsLoading ? <Spin size="small" /> : "Nenhum resultado encontrado"}
      defaultActiveFirstOption={false}

      {...selectValue && Array.isArray(selectValue) && {
        mode: "multiple"
      }}

      {...props}
    />
  );
}