PartnerAgreementSelect.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. <template>
  2. <DefaultSelect
  3. v-model="selectedPartner"
  4. v-bind="$attrs"
  5. use-input
  6. hide-selected
  7. fill-input
  8. clearable
  9. input-debounce="400"
  10. :options="partnerOptions"
  11. :label
  12. :loading
  13. :placeholder
  14. @filter="onFilter"
  15. @virtual-scroll="onVirtualScroll"
  16. >
  17. <template #no-option>
  18. <q-item>
  19. <q-item-section class="text-grey">
  20. {{ loading ? $t("common.status.loading") : $t("http.errors.no_records_found") }}
  21. </q-item-section>
  22. </q-item>
  23. </template>
  24. </DefaultSelect>
  25. </template>
  26. <script setup>
  27. import { ref, computed } from "vue";
  28. import { getPartnerAgreementsForSelect, getConveniosForSelect } from "src/api/partnerAgreement";
  29. import { useI18n } from "vue-i18n";
  30. import DefaultSelect from "src/components/defaults/DefaultSelect.vue";
  31. const { label, placeholder, forAssociado, type } = defineProps({
  32. label: {
  33. type: String,
  34. default: () => useI18n().t("ui.navigation.convenios"),
  35. },
  36. placeholder: {
  37. type: String,
  38. default: () => useI18n().t("common.actions.search"),
  39. },
  40. forAssociado: {
  41. type: Boolean,
  42. default: false,
  43. },
  44. type: {
  45. type: String,
  46. default: "agreement",
  47. },
  48. });
  49. const selectedPartner = defineModel({ type: Object });
  50. const PER_PAGE = 20;
  51. const loading = ref(false);
  52. const partnerOptions = ref([]);
  53. const total = ref(0);
  54. const search = ref("");
  55. const hasMore = computed(() => partnerOptions.value.length < total.value);
  56. const fetchPartners = async ({ reset = false } = {}) => {
  57. if (loading.value || (!reset && !hasMore.value)) return;
  58. loading.value = true;
  59. try {
  60. const page = reset ? 1 : Math.floor(partnerOptions.value.length / PER_PAGE) + 1;
  61. const payload = await (forAssociado ? getConveniosForSelect : getPartnerAgreementsForSelect)({
  62. page,
  63. perPage: PER_PAGE,
  64. search: search.value,
  65. type,
  66. });
  67. const mapped = (payload?.data ?? []).map((p) => ({
  68. label: p.trade_name || p.company_name,
  69. value: p.id,
  70. data: p,
  71. }));
  72. partnerOptions.value = reset ? mapped : partnerOptions.value.concat(mapped);
  73. total.value = payload?.total ?? partnerOptions.value.length;
  74. } catch (e) {
  75. console.error(e);
  76. } finally {
  77. loading.value = false;
  78. }
  79. };
  80. const onFilter = (val, update) => {
  81. search.value = val ?? "";
  82. fetchPartners({ reset: true }).then(() => update());
  83. };
  84. const onVirtualScroll = ({ to }) => {
  85. if (to === partnerOptions.value.length - 1) fetchPartners();
  86. };
  87. </script>