AddressSelect.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. <template>
  2. <q-select
  3. v-model="selectedAddress"
  4. :options="filteredAddresses"
  5. :label="label"
  6. outlined
  7. use-input
  8. clearable
  9. input-debounce="300"
  10. option-label="label"
  11. option-value="value"
  12. :rules="rules"
  13. :error="error"
  14. :error-message="errorMessage"
  15. :disabled="disabled"
  16. :loading="loading"
  17. @filter="filterFn"
  18. @update:model-value="updateValue"
  19. >
  20. <template #no-option>
  21. <q-item>
  22. <q-item-section class="text-grey">
  23. {{ disabled ? $t('common.messages.select_client_first') : $t('common.status.no_results') }}
  24. </q-item-section>
  25. </q-item>
  26. </template>
  27. </q-select>
  28. </template>
  29. <script setup>
  30. import { reactive, ref, watch } from 'vue'
  31. import { getAddresses } from 'src/api/address'
  32. import { normalizeString } from 'src/helpers/utils'
  33. const props = defineProps({
  34. label: {
  35. type: String,
  36. default: 'Endereço'
  37. },
  38. rules: {
  39. type: Array,
  40. default: () => []
  41. },
  42. error: {
  43. type: Boolean,
  44. default: false
  45. },
  46. errorMessage: {
  47. type: String,
  48. default: ''
  49. },
  50. initialId: {
  51. type: Number,
  52. default: null
  53. },
  54. clientId: {
  55. type: Number,
  56. default: null
  57. },
  58. disabled: {
  59. type: Boolean,
  60. default: false
  61. },
  62. type: {
  63. type: String,
  64. default: null // home / commercial
  65. }
  66. })
  67. const model = defineModel({
  68. type: Object,
  69. default: null
  70. })
  71. const emit = defineEmits(['update:modelValue'])
  72. const addresses = ref([])
  73. let filteredAddresses = reactive([])
  74. const selectedAddress = ref(null)
  75. const loading = ref(false)
  76. const loadAddresses = async () => {
  77. if (!props.clientId) {
  78. addresses.value = []
  79. filteredAddresses = []
  80. return
  81. }
  82. loading.value = true
  83. try {
  84. const response = await getAddresses('client', props.clientId);
  85. addresses.value = response.map((address) => ({
  86. label: `${address.address_full}`,
  87. value: address.id,
  88. ...address
  89. }));
  90. filteredAddresses = addresses.value;
  91. if (props.initialId) {
  92. selectAddressById(props.initialId);
  93. }
  94. } catch (error) {
  95. console.error('Error loading addresses:', error);
  96. } finally {
  97. loading.value = false;
  98. }
  99. }
  100. const filterFn = (val, update) => {
  101. update(() => {
  102. const needle = normalizeString(val);
  103. filteredAddresses = addresses.value.filter((address) => {
  104. const addressString = normalizeString(address.label);
  105. return addressString.includes(needle);
  106. })
  107. })
  108. }
  109. const updateValue = (value) => {
  110. model.value = value;
  111. emit('update:modelValue', value);
  112. }
  113. const selectAddressById = (id) => {
  114. const address = addresses.value.find((a) => a.value === id);
  115. if (address) {
  116. selectedAddress.value = address;
  117. updateValue(address);
  118. }
  119. }
  120. watch(() => props.clientId, (newClientId) => {
  121. if (newClientId) {
  122. loadAddresses()
  123. } else {
  124. addresses.value = []
  125. filteredAddresses = []
  126. selectedAddress.value = null
  127. updateValue(null)
  128. }
  129. }, { immediate: true });
  130. watch(() => props.type, (newType) => {
  131. if (newType) {
  132. filteredAddresses = addresses.value.filter(addr => addr.address_type === newType);
  133. } else {
  134. loadAddresses()
  135. }
  136. })
  137. watch(() => props.initialId, (newId) => {
  138. if (newId && addresses.value.length > 0) {
  139. selectAddressById(newId)
  140. }
  141. })
  142. </script>