0
0
Fork 0

feat: vnLocation changes

This commit is contained in:
Javier Segarra 2024-07-24 14:58:51 +02:00
parent fdec25dc88
commit 3a0204d27b
4 changed files with 98 additions and 69 deletions

View File

@ -1,18 +1,23 @@
<script setup> <script setup>
import { ref, toRefs, computed, watch, onMounted } from 'vue'; import { ref, toRefs, onMounted, nextTick } from 'vue';
import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue'; import CreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
import VnSelectDialog from 'components/common/VnSelectDialog.vue'; import VnSelectDialog from 'components/common/VnSelectDialog.vue';
import FetchData from 'components/FetchData.vue'; const emit = defineEmits(['update:selected', 'update:options']);
const emit = defineEmits(['update:modelValue', 'update:options']);
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useArrayData } from 'src/composables/useArrayData';
const { t } = useI18n(); const { t } = useI18n();
const postcodesOptions = ref([]); const postcodesOptions = ref([]);
const postcodesRef = ref(null); const postcodesOptionsOriginal = ref([]);
// const postcodesRef = ref(null);
const $props = defineProps({ const $props = defineProps({
modelValue: { postalCodeKey: {
type: [String, Number, Object], type: String,
default: 'postalCode',
},
location: {
type: Object,
default: null, default: null,
}, },
options: { options: {
@ -41,89 +46,115 @@ const $props = defineProps({
}, },
}); });
const { options } = toRefs($props); const selectedId = ref(null);
const myOptions = ref([]); const mySelect = ref();
const myOptionsOriginal = ref([]); const modelValue = ref($props.location[$props.postalCodeKey]);
const arrayData = useArrayData('postcodes', {
const value = computed({ url: 'Postcodes/filter',
get() { limit: 1,
return $props.modelValue;
},
set(value) {
emit(
'update:modelValue',
postcodesOptions.value.find((p) => p.code === value)
);
},
}); });
onMounted(() => { function sanitizePostcode(data) {
locationFilter($props.modelValue); return data.map((postcode) => ({
}); ...postcode,
original: postcode,
id: sanitizeId(postcode),
label: sanitizeLabel(postcode),
}));
}
function sanitizeId(postcode) {
return `${postcode.code ?? postcode[$props.postalCodeKey]}_${postcode.provinceFk}_${
postcode.countryFk
}`;
}
onMounted(async () => {
await retriveOptions();
nextTick(() => mySelect.value.showPopup());
});
async function retriveOptions() {
let options = [];
if (modelValue.value) {
await locationFilter(modelValue.value, () => {});
options = arrayData.store.data;
} else {
const { data } = await arrayData.fetch({ updateRouter: false, append: true });
options = data;
}
setOptions(options);
}
function findOptionById(postcode) {
return postcodesOptions.value.find((p) => p.id === postcode);
}
function setOptions(data) { function setOptions(data) {
myOptions.value = JSON.parse(JSON.stringify(data)); postcodesOptions.value = sanitizePostcode(data);
myOptionsOriginal.value = JSON.parse(JSON.stringify(data)); if (modelValue.value) {
} const { [$props.postalCodeKey]: code } = $props.location;
setOptions(options.value); selectedId.value =
findOptionById(sanitizeId({ ...$props.location, code })) ??
watch(options, (newValue) => { sanitizePostcode([$props.location])[0];
setOptions(newValue); }
}); postcodesOptionsOriginal.value = JSON.parse(JSON.stringify(postcodesOptions.value));
function showLabel(data) {
return `${data.code} - ${data.town}(${data.province}), ${data.country}`;
} }
function locationFilter(search = '') { async function handleInput(value) {
if ( if (value) emit('update:selected', findOptionById(value));
search && if (modelValue.value) {
(search.includes('undefined') || search.startsWith(`${$props.modelValue} - `)) modelValue.value = value;
) arrayData.store.userFilter = {};
await retriveOptions();
mySelect.value.showPopup();
} else postcodesOptions.value = postcodesOptionsOriginal.value;
}
function sanitizeLabel(postcode) {
return `${postcode.code ?? postcode[$props.postalCodeKey]} - ${postcode.town}(${
postcode.province
}), ${postcode.country}`;
}
async function locationFilter(search, update) {
if (search.length === 0) {
return; return;
}
let where = { search }; let where = { search };
postcodesRef.value.fetch({ filter: { where }, limit: 30 }); arrayData.store.userFilter = { filter: { where } };
await arrayData.fetch({ append: false, updateRouter: false });
update(() => {
postcodesOptions.value = sanitizePostcode(arrayData.store.data);
});
} }
function handleFetch(data) {
postcodesOptions.value = data;
}
function onDataSaved(newPostcode) { function onDataSaved(newPostcode) {
postcodesOptions.value.push(newPostcode); postcodesOptions.value.push(newPostcode);
value.value = newPostcode.code; selectedId.value = newPostcode.code ?? newPostcode[$props.postalCodeKey];
} }
</script> </script>
<template> <template>
<FetchData
ref="postcodesRef"
url="Postcodes/filter"
@on-fetch="(data) => handleFetch(data)"
/>
<VnSelectDialog <VnSelectDialog
v-if="postcodesRef" ref="mySelect"
:option-label="(opt) => showLabel(opt) ?? 'code'" option-label="label"
:option-value="(opt) => opt.code" option-value="id"
v-model="value" v-model="selectedId"
:options="postcodesOptions" :options="postcodesOptions"
:label="t('Location')" :label="t('Location')"
@update:model-value="handleInput"
:placeholder="t('search_by_postalcode')" :placeholder="t('search_by_postalcode')"
@input-value="locationFilter" @filter="locationFilter"
:default-filter="false"
:input-debounce="300" :input-debounce="300"
:class="{ required: $attrs.required }" :class="{ required: $attrs.required }"
v-bind="$attrs" v-bind="$attrs"
clearable clearable
emit-value
> >
<template #form> <template #form>
<CreateNewPostcode <CreateNewPostcode @on-data-saved="onDataSaved" />
@on-data-saved="onDataSaved"
/>
</template> </template>
<template #option="{ itemProps, opt }"> <template #option="{ itemProps, opt }">
<QItem v-bind="itemProps"> <QItem v-bind="itemProps">
<QItemSection v-if="opt.code"> <QItemSection v-if="opt.code">
<QItemLabel>{{ opt.code }}</QItemLabel> <QItemLabel>{{ opt.code }}</QItemLabel>
<QItemLabel caption>{{ showLabel(opt) }}</QItemLabel> <QItemLabel caption>{{ opt.label }}</QItemLabel>
</QItemSection> </QItemSection>
</QItem> </QItem>
</template> </template>

View File

@ -95,9 +95,9 @@ function handleLocation(data, location) {
<VnLocation <VnLocation
:rules="validate('Worker.postcode')" :rules="validate('Worker.postcode')"
:roles-allowed-to-create="['deliveryAssistant']" :roles-allowed-to-create="['deliveryAssistant']"
:options="postcodesOptions" :location="data"
v-model="data.postcode" postal-code-key="postcode"
@update:model-value="(location) => handleLocation(data, location)" @update:selected="(location) => handleLocation(data, location)"
> >
</VnLocation> </VnLocation>
</VnRow> </VnRow>

View File

@ -17,11 +17,10 @@ const sageTaxTypesOptions = ref([]);
const sageWithholdingsOptions = ref([]); const sageWithholdingsOptions = ref([]);
const sageTransactionTypesOptions = ref([]); const sageTransactionTypesOptions = ref([]);
const supplierActivitiesOptions = ref([]); const supplierActivitiesOptions = ref([]);
const postcodesOptions = ref([]);
function handleLocation(data, location) { function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {}; const { town, label, provinceFk, countryFk } = location ?? {};
data.postCode = code; data.postCode = label;
data.city = town; data.city = town;
data.provinceFk = provinceFk; data.provinceFk = provinceFk;
data.countryFk = countryFk; data.countryFk = countryFk;
@ -131,9 +130,8 @@ function handleLocation(data, location) {
<VnLocation <VnLocation
:rules="validate('Worker.postcode')" :rules="validate('Worker.postcode')"
:roles-allowed-to-create="['deliveryAssistant']" :roles-allowed-to-create="['deliveryAssistant']"
:options="postcodesOptions" :location="data"
v-model="data.postCode" @update:selected="(location) => handleLocation(data, location)"
@update:model-value="(location) => handleLocation(data, location)"
> >
</VnLocation> </VnLocation>
</VnRow> </VnRow>

View File

@ -17,7 +17,7 @@ describe('VnLocation', () => {
cy.get(inputLocation).click(); cy.get(inputLocation).click();
cy.get(inputLocation).clear(); cy.get(inputLocation).clear();
cy.get(inputLocation).type('al'); cy.get(inputLocation).type('al');
cy.get(locationOptions).should('have.length.at.least', 3); cy.get(locationOptions).should('have.length.at.least', 4);
}); });
it('input filter location as "ecuador"', function () { it('input filter location as "ecuador"', function () {
cy.get(inputLocation).click(); cy.get(inputLocation).click();