Untitled

 avatar
unknown
plain_text
a year ago
6.4 kB
4
Indexable
function Autocomplete(props: AutocompleteProps) {
  const [input, setInput] = useState<string>('');
  const [isSelected, setIsSelected] = useState<boolean>(false);
  const [invalid, setInvalid] = useState<boolean>(true);

  const filteredData = useMemo(
    () => {
      const matchedData =
        props.filterFields?.length > 0
          ? props.options?.filter((val: any) => {
              for (const field of props.filterFields) {
                if (
                  val[field]
                    .toLowerCase()
                    .includes(
                      typeof input === 'string' ? input.toLowerCase() : input[field].toLowerCase()
                    )
                ) {
                  return true;
                }
              }

              return false;
            })
          : props.options?.filter((val: any) => {
              return val.toLowerCase().includes(input.toLowerCase());
            });

      return matchedData;
    },
    props.maps ? [props.options] : [input]
  );

  const [selectedValue, setSelectedValue] = useState<string>();

  const handleListSelect = (option: any) => {
    setSelectedValue(
      textContent(
        <div className="flex w-full items-center justify-start gap-3 overflow-hidden text-xs text-black">
          <span className="font-light capitalize ">
            {props.displayFields
              ? props.displayFields.map((field: string) => `${option[field]} `)
              : option}
          </span>
        </div>
      )
    );
    setInput(option);
    setInvalid(false);
  };

  function textContent(elem: React.JSX.Element): string {
    if (!elem) {
      return '';
    }
    if (typeof elem === 'string') {
      return elem;
    }
    const children = elem.props && elem.props.children;
    if (children instanceof Array) {
      return children.map(textContent).join('');
    }

    return textContent(children);
  }

  const chooseData = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    setInput(e.currentTarget.textContent || '');
    setIsSelected(true);
  };

  const messages = props.validationObjects || [];

  return (
    <div className="flex flex-col">
      <LabelText
        invalid={invalid}
        isClicked={props.isClicked}
        required={props.required}
        label={props.label}
      >
        {props.label}
      </LabelText>
      <div
        className={`relative flex size-full flex-col  truncate rounded-3xl bg-bgColor shadow-inner duration-200 ${
          props.isClicked && invalid ? 'border border-red' : ''
        }`}
      >
        {props.IconOne && (
          <span className="absolute left-6 top-3  flex items-center justify-center pb-1">
            {props.IconOne}
          </span>
        )}
        <input
          className={`${props.IconOne ? 'pl-14' : 'pl-6'}  flex h-12 w-full justify-center  rounded-full bg-transparent px-6 py-2 font-text text-sm font-light outline-none duration-300 ease-in-out md:text-base`}
          value={selectedValue}
          defaultValue={props.defaultValue}
          required={props.required}
          placeholder={
            props.value && Object.keys(props.value).length !== 0 ? '' : props.placeholder
          }
          onChange={(e) => {
            setInput(e.target.value);
            setIsSelected(false);
            setInvalid(true);
            setSelectedValue(undefined);
            if (props.handleChange) props.handleChange(e.target.value);
          }}
        />
        <input
          type="hidden"
          name={props.name}
          value={typeof input === 'object' ? JSON.stringify(input) : input}
        />
        {!isSelected && (
          <div
            className={`flex flex-col justify-start duration-300 ${
              props.IconOne ? 'px-10' : 'px-2'
            } divide-y divide-gray-400/30 overflow-auto ${
              input?.length > 0 ? 'max-h-52' : 'max-h-0'
            }`}
          >
            {filteredData?.length > 0 ? (
              filteredData?.map((option, idx) => (
                <div
                  className={`flex w-full items-center justify-start gap-20 px-4 py-5 hover:bg-bgColorHover ${
                    input?.length === 0 ? 'h-0 p-0 opacity-0' : 'h-8 py-1'
                  } cursor-pointer duration-200`}
                  key={idx}
                  onClick={(e) => {
                    chooseData(e);
                    handleListSelect(option);
                  }}
                >
                  {props.displayFields ? (
                    <div className="flex w-full items-center justify-start gap-3 overflow-hidden text-xs text-black">
                      <span className="font-light capitalize ">
                        {props.displayFields.map((field: string) => `${option[field]} `)}
                      </span>
                    </div>
                  ) : (
                    <div className="flex w-full items-center justify-start gap-3 overflow-hidden text-xs text-black">
                      <span className="font-light capitalize">{option}</span>
                    </div>
                  )}
                </div>
              ))
            ) : (
              <div className="relative flex flex-col items-center justify-center whitespace-normal py-4">
                <span
                  className={`${
                    props.HandleNoMatch ? '' : 'w-full'
                  } flex items-center justify-start gap-20 px-4 py-5 text-inputLabelAccent ${
                    input?.length === 0 ? 'h-0 p-0 opacity-0' : 'h-11 py-4'
                  } cursor-pointer duration-200`}
                >
                  Sorry, there is nothing that matches your search
                </span>
                {props.HandleNoMatch && (
                  <div className="flex w-full justify-center py-4">{props.HandleNoMatch}</div>
                )}
              </div>
            )}
          </div>
        )}
      </div>
      {messages.map((message, index) => (
        <span
          key={index}
          className={`mx-4 pt-1 text-sm text-red ${props.isClicked && invalid ? 'block' : 'hidden'}`}
        >
          {message}
        </span>
      ))}
    </div>
  );
}
Editor is loading...
Leave a Comment