refactor this vue component code please, it seems to be programmed very bad

import {
  PropType,
  computed,
  defineComponent,
  onBeforeUnmount,
  onMounted,
  ref,
  toRefs,
  watch,
} from 'vue';

import styles from '@apps/admin/styles/components/dropdown/Dropdown.module.scss';

interface PropsType {
  value: (string | number)[];
  options: {
    id: string | number;
    title: string;
  }[];
}

function useDropDown(props: PropsType) {
  const opened = ref(false);
  const q = ref('');
  const el = ref<HTMLElement>();
  const ddValue = ref([...props.value]);

  watch(toRefs(props).value, () => (ddValue.value = [...props.value]));

  function close() {
    opened.value = false;
  }

  function openClose() {
    opened.value = !opened.value;
  }

  function isOptionVisible(title: string) {
    return title.toLowerCase().includes(q.value.toLowerCase());
  }

  function toggleOption(id: string | number) {
    if (ddValue.value.includes(id)) {
      ddValue.value.splice(ddValue.value.indexOf(id), 1);
    } else {
      ddValue.value.push(id);
    }
  }

  function optionClass(id: string | number) {
    return {
      [styles.option]: true,
      [styles.__active]: ddValue.value.includes(id),
    };
  }

  function clickOutside(e: Event) {
    if (!el.value) return;
    if (el.value.contains(e.target as Node)) return;

    close();
  }

  onMounted(() => window.addEventListener('click', clickOutside));
  onBeforeUnmount(() => window.removeEventListener('click', clickOutside));

  function toggleAll() {
    if (ddValue.value.length) {
      ddValue.value = [];
    } else {
      ddValue.value = props.options.map((el) => el.id);
    }

    close();
  }

  const selectedLabel = computed(() => {
    return ddValue.value.length == props.options.length
      ? 'Все'
      : ddValue.value.length.toString();
  });

  return {
    el,
    openClose,
    selectedLabel,
    opened,
    toggleAll,
    q,
    isOptionVisible,
    toggleOption,
    optionClass,
    ddValue,
  };
}

interface StringOptionType {
  id: string;
  title: string;
}

export const DropdownString = defineComponent({
  name: 'DropdownString',
  props: {
    value: { type: Array as PropType<string[]>, required: true },
    options: { type: Array as PropType<StringOptionType[]>, required: true },
    showZero: { type: Boolean, default: false },
    onChange: {
      type: Function as PropType<(value: string[]) => void>,
      required: true,
    },
  },
  setup(props, { slots }) {
    const {
      el,
      openClose,
      selectedLabel,
      opened,
      toggleAll,
      q,
      isOptionVisible,
      toggleOption,
      optionClass,
      ddValue,
    } = useDropDown(props);

    return () => (
      <div class={styles.dropdown} ref={el}>
        <button class={styles.trigger} type="button" onClick={openClose}>
          {slots.default ? slots.default() : ''}
          {selectedLabel.value && (
            <div class={styles.selectedLabel}>
              {props.showZero
                ? selectedLabel.value
                : selectedLabel.value === '0'
                  ? ''
                  : selectedLabel.value}
            </div>
          )}
        </button>
        {opened.value && (
          <div class={styles.wrapper}>
            <div class={styles.wrapperTitle}>
              <button type="button" onClick={close} class="text-black">
                {slots.default ? slots.default() : ''}
              </button>
              <button
                type="button"
                class={styles.reset}
                onClick={() => {
                  toggleAll();
                  props.onChange(ddValue.value as string[]);
                }}
              >
                Выбрать/Сбросить
              </button>
            </div>
            <input
              class={styles.search}
              autocomplete="off"
              value={q.value}
              onInput={(e) => (q.value = (e.target as HTMLInputElement).value)}
              placeholder="Поиск"
            />
            <div class={styles.options}>
              {props.options.map((el) => (
                <button
                  type="button"
                  v-show={isOptionVisible(el.title)}
                  onClick={() => {
                    toggleOption(el.id);
                    props.onChange(ddValue.value as string[]);
                  }}
                  class={optionClass(el.id)}
                >
                  {el.title}
                </button>
              ))}
            </div>
          </div>
        )}
      </div>
    );
  },
});

interface NumberOptionType {
  id: number;
  title: string;
}

export const DropdownNumber = defineComponent({
  name: 'DropdownNumber',
  props: {
    value: { type: Array as PropType<number[]>, required: true },
    options: { type: Array as PropType<NumberOptionType[]>, required: true },
    showZero: { type: Boolean, default: false },
    onChange: {
      type: Function as PropType<(value: number[]) => void>,
      required: true,
    },
    disabled: { type: Boolean, required: false, default: false },
  },
  setup(props, { slots }) {
    const {
      el,
      openClose,
      selectedLabel,
      opened,
      toggleAll,
      q,
      isOptionVisible,
      toggleOption,
      optionClass,
      ddValue,
    } = useDropDown(props);

    return () => (
      <div class={styles.dropdown} ref={el}>
        <button
          class={styles.trigger}
          type="button"
          onClick={openClose}
          disabled={props.disabled}
        >
          {slots.default ? slots.default() : ''}
          {selectedLabel.value && (
            <div class={styles.selectedLabel}>
              {props.showZero
                ? selectedLabel.value
                : selectedLabel.value === '0'
                  ? ''
                  : selectedLabel.value}
            </div>
          )}
        </button>
        {opened.value && (
          <div class={styles.wrapper}>
            <div class={styles.wrapperTitle}>
              <button type="button" onClick={close} class="text-black">
                {slots.default ? slots.default() : ''}
              </button>
              <button
                type="button"
                class={styles.reset}
                onClick={() => {
                  toggleAll();
                  props.onChange(ddValue.value as number[]);
                }}
              >
                Выбрать/Сбросить
              </button>
            </div>
            <input
              class={styles.search}
              autocomplete="off"
              value={q.value}
              onInput={(e) => (q.value = (e.target as HTMLInputElement).value)}
              placeholder="Поиск"
            />
            <div class={styles.options}>
              {props.options.map((el) => (
                <button
                  type="button"
                  v-show={isOptionVisible(el.title)}
                  onClick={() => {
                    toggleOption(el.id);
                    props.onChange(ddValue.value as number[]);
                  }}
                  class={optionClass(el.id)}
                >
                  {el.title}
                </button>
              ))}
            </div>
          </div>
        )}
      </div>
    );
  },
});