0
0
Fork 0

Merge branch 'dev' into 6933-fetchedTagsRefact

This commit is contained in:
Alex Moreno 2024-02-29 11:02:49 +00:00
commit 9119865ed6
13 changed files with 709 additions and 483 deletions

View File

@ -1,5 +1,6 @@
FROM node:stretch-slim FROM node:stretch-slim
RUN npm install -g @quasar/cli RUN corepack enable pnpm
RUN pnpm install -g @quasar/cli
WORKDIR /app WORKDIR /app
COPY dist/spa ./ COPY dist/spa ./
CMD ["quasar", "serve", "./", "--history", "--hostname", "0.0.0.0"] CMD ["quasar", "serve", "./", "--history", "--hostname", "0.0.0.0"]

4
Jenkinsfile vendored
View File

@ -62,7 +62,7 @@ pipeline {
NODE_ENV = "" NODE_ENV = ""
} }
steps { steps {
sh 'npm install --prefer-offline' sh 'pnpm install --prefer-offline'
} }
} }
stage('Test') { stage('Test') {
@ -73,7 +73,7 @@ pipeline {
NODE_ENV = "" NODE_ENV = ""
} }
steps { steps {
sh 'npm run test:unit:ci' sh 'pnpm run test:unit:ci'
} }
post { post {
always { always {

View File

@ -1,10 +1,11 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "24.10.0", "version": "24.12.0",
"description": "Salix frontend", "description": "Salix frontend",
"productName": "Salix", "productName": "Salix",
"author": "Verdnatura", "author": "Verdnatura",
"private": true, "private": true,
"packageManager": "pnpm@8.15.1",
"scripts": { "scripts": {
"lint": "eslint --ext .js,.vue ./", "lint": "eslint --ext .js,.vue ./",
"format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore", "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
@ -16,12 +17,12 @@
}, },
"dependencies": { "dependencies": {
"@quasar/cli": "^2.3.0", "@quasar/cli": "^2.3.0",
"@quasar/extras": "^1.16.4", "@quasar/extras": "^1.16.9",
"axios": "^1.4.0", "axios": "^1.4.0",
"chromium": "^3.0.3", "chromium": "^3.0.3",
"croppie": "^2.6.5", "croppie": "^2.6.5",
"pinia": "^2.1.3", "pinia": "^2.1.3",
"quasar": "^2.12.0", "quasar": "^2.14.5",
"validator": "^13.9.0", "validator": "^13.9.0",
"vue": "^3.3.4", "vue": "^3.3.4",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
@ -30,9 +31,9 @@
"devDependencies": { "devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.8.1", "@intlify/unplugin-vue-i18n": "^0.8.1",
"@pinia/testing": "^0.1.2", "@pinia/testing": "^0.1.2",
"@quasar/app-vite": "^1.4.3", "@quasar/app-vite": "^1.7.3",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.3.0", "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
"@vue/test-utils": "^2.3.2", "@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"cypress": "^12.13.0", "cypress": "^12.13.0",
"eslint": "^8.41.0", "eslint": "^8.41.0",
@ -50,8 +51,8 @@
"bun": ">= 1.0.25" "bun": ">= 1.0.25"
}, },
"overrides": { "overrides": {
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^5.0.4",
"vite": "^4.3.5", "vite": "^5.1.4",
"vitest": "^0.31.1" "vitest": "^0.31.1"
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
<script setup> <script setup>
import axios from 'axios'; import axios from 'axios';
import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue'; import { onMounted, onUnmounted, computed, ref, watch, nextTick } from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
@ -8,6 +9,7 @@ import { useStateStore } from 'stores/useStateStore';
import { useValidator } from 'src/composables/useValidator'; import { useValidator } from 'src/composables/useValidator';
import useNotify from 'src/composables/useNotify.js'; import useNotify from 'src/composables/useNotify.js';
import SkeletonForm from 'components/ui/SkeletonForm.vue'; import SkeletonForm from 'components/ui/SkeletonForm.vue';
import VnConfirm from './ui/VnConfirm.vue';
const quasar = useQuasar(); const quasar = useQuasar();
const state = useState(); const state = useState();
@ -93,6 +95,19 @@ onMounted(async () => {
} }
}); });
onBeforeRouteLeave((to, from, next) => {
if (!hasChanges.value) next();
quasar.dialog({
component: VnConfirm,
componentProps: {
title: t('Unsaved changes will be lost'),
message: t('Are you sure exit without saving?'),
promise: () => next(),
},
});
});
onUnmounted(() => { onUnmounted(() => {
state.unset($props.model); state.unset($props.model);
}); });
@ -255,3 +270,8 @@ watch(formUrl, async () => {
padding: 32px; padding: 32px;
} }
</style> </style>
<i18n>
es:
Unsaved changes will be lost: Los cambios que no haya guardado se perderán
Are you sure exit without saving?: ¿Seguro que quiere salir sin guardar?
</i18n>

View File

@ -94,16 +94,6 @@ async function send() {
<QSpace /> <QSpace />
<QBtn icon="close" :disable="isLoading" flat round dense v-close-popup /> <QBtn icon="close" :disable="isLoading" flat round dense v-close-popup />
</QCardSection> </QCardSection>
<QCardSection v-if="props.locale">
<QBanner class="bg-amber text-white" rounded dense>
<template #avatar>
<QIcon name="warning" />
</template>
<span
v-html="t('CustomerDefaultLanguage', { locale: t(props.locale) })"
></span>
</QBanner>
</QCardSection>
<QCardSection class="q-pb-xs"> <QCardSection class="q-pb-xs">
<QSelect <QSelect
:label="t('Language')" :label="t('Language')"
@ -184,11 +174,10 @@ async function send() {
<i18n> <i18n>
en: en:
CustomerDefaultLanguage: This customer uses <strong>{locale}</strong> as their default language
templates: templates:
pendingPayment: 'Your order is pending of payment. pendingPayment: 'Your order is pending of payment.
Please, enter the website and make the payment with a credit card. Thank you.' Please, enter the website and make the payment with a credit card. Thank you.'
minAmount: 'A minimum amount of 50 (VAT excluded) is required for your order minAmount: 'A minimum amount of 50 (VAT excluded) is required for your order
{ orderId } of { shipped } to receive it without additional shipping costs.' { orderId } of { shipped } to receive it without additional shipping costs.'
orderChanges: 'Order {orderId} of { shipped }: { changes }' orderChanges: 'Order {orderId} of { shipped }: { changes }'
en: English en: English
@ -197,7 +186,6 @@ en:
pt: Portuguese pt: Portuguese
es: es:
Send SMS: Enviar SMS Send SMS: Enviar SMS
CustomerDefaultLanguage: Este cliente utiliza <strong>{locale}</strong> como idioma por defecto
Language: Idioma Language: Idioma
Phone: Móvil Phone: Móvil
Subject: Asunto Subject: Asunto
@ -205,7 +193,7 @@ es:
templates: templates:
pendingPayment: 'Su pedido está pendiente de pago. pendingPayment: 'Su pedido está pendiente de pago.
Por favor, entre en la página web y efectue el pago con tarjeta. Muchas gracias.' Por favor, entre en la página web y efectue el pago con tarjeta. Muchas gracias.'
minAmount: 'Es necesario un importe mínimo de 50 (Sin IVA) en su pedido minAmount: 'Es necesario un importe mínimo de 50 (Sin IVA) en su pedido
{ orderId } del día { shipped } para recibirlo sin portes adicionales.' { orderId } del día { shipped } para recibirlo sin portes adicionales.'
orderChanges: 'Pedido {orderId} día { shipped }: { changes }' orderChanges: 'Pedido {orderId} día { shipped }: { changes }'
en: Inglés en: Inglés
@ -222,7 +210,7 @@ fr:
templates: templates:
pendingPayment: 'Votre commande est en attente de paiement. pendingPayment: 'Votre commande est en attente de paiement.
Veuillez vous connecter sur le site web et effectuer le paiement par carte. Merci beaucoup.' Veuillez vous connecter sur le site web et effectuer le paiement par carte. Merci beaucoup.'
minAmount: 'Un montant minimum de 50 (TVA non incluse) est requis pour votre commande minAmount: 'Un montant minimum de 50 (TVA non incluse) est requis pour votre commande
{ orderId } du { shipped } afin de la recevoir sans frais de port supplémentaires.' { orderId } du { shipped } afin de la recevoir sans frais de port supplémentaires.'
orderChanges: 'Commande { orderId } du { shipped }: { changes }' orderChanges: 'Commande { orderId } du { shipped }: { changes }'
en: Anglais en: Anglais
@ -239,7 +227,7 @@ pt:
templates: templates:
pendingPayment: 'Seu pedido está pendente de pagamento. pendingPayment: 'Seu pedido está pendente de pagamento.
Por favor, acesse o site e faça o pagamento com cartão. Muito obrigado.' Por favor, acesse o site e faça o pagamento com cartão. Muito obrigado.'
minAmount: 'É necessário um valor mínimo de 50 (sem IVA) em seu pedido minAmount: 'É necessário um valor mínimo de 50 (sem IVA) em seu pedido
{ orderId } do dia { shipped } para recebê-lo sem custos de envio adicionais.' { orderId } do dia { shipped } para recebê-lo sem custos de envio adicionais.'
orderChanges: 'Pedido { orderId } dia { shipped }: { changes }' orderChanges: 'Pedido { orderId } dia { shipped }: { changes }'
en: Inglês en: Inglês

View File

@ -1,16 +1,18 @@
<template> <template>
<div id="row" class="q-gutter-md"> <div id="row" class="q-gutter-md q-mb-md">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<style lang="scss" scopped> <style lang="scss" scopped>
#row { #row {
display: grid; display: flex;
grid-template-columns: 1fr 1fr; > * {
flex: 1;
}
} }
@media screen and (max-width: 800px) { @media screen and (max-width: 800px) {
#row { #row {
grid-template-columns: 1fr; flex-direction: column;
} }
} }
</style> </style>

View File

@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import VnLocation from 'src/components/common/VnLocation.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue'; import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
@ -20,13 +20,9 @@ const router = useRouter();
const formInitialData = reactive({ isDefaultAddress: false }); const formInitialData = reactive({ isDefaultAddress: false });
const townsFetchDataRef = ref(null);
const postcodeFetchDataRef = ref(null);
const urlCreate = ref(''); const urlCreate = ref('');
const postcodesOptions = ref([]); const postcodesOptions = ref([]);
const citiesLocationOptions = ref([]);
const provincesLocationOptions = ref([]);
const agencyModes = ref([]); const agencyModes = ref([]);
const incoterms = ref([]); const incoterms = ref([]);
const customsAgents = ref([]); const customsAgents = ref([]);
@ -36,14 +32,6 @@ onBeforeMount(() => {
getCustomsAgents(); getCustomsAgents();
}); });
const onPostcodeCreated = async ({ code, provinceFk, townFk }, formData) => {
await postcodeFetchDataRef.value.fetch();
await townsFetchDataRef.value.fetch();
formData.postalCode = code;
formData.provinceFk = provinceFk;
formData.city = citiesLocationOptions.value.find((town) => town.id === townFk).name;
};
const getCustomsAgents = async () => { const getCustomsAgents = async () => {
const { data } = await axios.get('CustomsAgents'); const { data } = await axios.get('CustomsAgents');
customsAgents.value = data; customsAgents.value = data;
@ -61,26 +49,16 @@ const toCustomerConsignees = () => {
}, },
}); });
}; };
function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {};
data.postalCode = code;
data.city = town;
data.provinceFk = provinceFk;
data.countryFk = countryFk;
}
</script> </script>
<template> <template>
<FetchData
@on-fetch="(data) => (postcodesOptions = data)"
auto-load
ref="postcodeFetchDataRef"
url="Postcodes/location"
/>
<FetchData
@on-fetch="(data) => (citiesLocationOptions = data)"
auto-load
ref="townsFetchDataRef"
url="Towns/location"
/>
<FetchData
@on-fetch="(data) => (provincesLocationOptions = data)"
auto-load
url="Provinces/location"
/>
<fetch-data <fetch-data
@on-fetch="(data) => (agencyModes = data)" @on-fetch="(data) => (agencyModes = data)"
auto-load auto-load
@ -113,83 +91,17 @@ const toCustomerConsignees = () => {
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<VnSelectDialog <VnLocation
:label="t('Postcode')"
:options="postcodesOptions"
:roles-allowed-to-create="['deliveryAssistant']"
:rules="validate('Worker.postcode')" :rules="validate('Worker.postcode')"
hide-selected :roles-allowed-to-create="['deliveryAssistant']"
option-label="code" :options="postcodesOptions"
option-value="code" v-model="data.location"
v-model="data.postalCode" @update:model-value="(location) => handleLocation(data, location)"
> ></VnLocation>
<template #form>
<CustomerCreateNewPostcode
@on-data-saved="onPostcodeCreated($event, data)"
/>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection v-if="scope.opt">
<QItemLabel>{{ scope.opt.code }}</QItemLabel>
<QItemLabel caption>
{{ scope.opt.code }} -
{{ scope.opt.town.name }}
({{ scope.opt.town.province.name }},
{{ scope.opt.town.province.country.country }})
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectDialog>
</div>
<div class="col">
<!-- ciudades -->
<VnSelectFilter
:label="t('City')"
:options="citiesLocationOptions"
hide-selected
option-label="name"
option-value="name"
v-model="data.city"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
<QItemLabel caption>
{{
`${scope.opt.name}, ${scope.opt.province.name} (${scope.opt.province.country.country})`
}}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div> </div>
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Province')"
:options="provincesLocationOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.provinceFk"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{
`${scope.opt.name} (${scope.opt.country.country})`
}}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div>
<div class="col"> <div class="col">
<VnSelectFilter <VnSelectFilter
:label="t('Agency')" :label="t('Agency')"

View File

@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import VnLocation from 'src/components/common/VnLocation.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue'; import FormModel from 'components/FormModel.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
@ -17,13 +17,8 @@ import CustomsNewCustomsAgent from 'src/pages/Customer/components/CustomerNewCus
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const townsFetchDataRef = ref(null);
const postcodeFetchDataRef = ref(null);
const urlUpdate = ref(''); const urlUpdate = ref('');
const postcodesOptions = ref([]); const postcodesOptions = ref([]);
const citiesLocationOptions = ref([]);
const provincesLocationOptions = ref([]);
const agencyModes = ref([]); const agencyModes = ref([]);
const incoterms = ref([]); const incoterms = ref([]);
const customsAgents = ref([]); const customsAgents = ref([]);
@ -34,14 +29,6 @@ onBeforeMount(() => {
urlUpdate.value = `Clients/${route.params.id}/updateAddress/${route.params.consigneeId}`; urlUpdate.value = `Clients/${route.params.id}/updateAddress/${route.params.consigneeId}`;
}); });
const onPostcodeCreated = async ({ code, provinceFk, townFk }, formData) => {
await postcodeFetchDataRef.value.fetch();
await townsFetchDataRef.value.fetch();
formData.postalCode = code;
formData.provinceFk = provinceFk;
formData.city = citiesLocationOptions.value.find((town) => town.id === townFk).name;
};
const getData = async (observations) => { const getData = async (observations) => {
observationTypes.value = observations; observationTypes.value = observations;
@ -97,26 +84,16 @@ const onDataSaved = () => {
}; };
axios.post('AddressObservations/crud', payload); axios.post('AddressObservations/crud', payload);
}; };
function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {};
data.postalCode = code;
data.city = town;
data.provinceFk = provinceFk;
data.countryFk = countryFk;
}
</script> </script>
<template> <template>
<FetchData
ref="postcodeFetchDataRef"
@on-fetch="(data) => (postcodesOptions = data)"
auto-load
url="Postcodes/location"
/>
<FetchData
ref="townsFetchDataRef"
@on-fetch="(data) => (citiesLocationOptions = data)"
auto-load
url="Towns/location"
/>
<FetchData
@on-fetch="(data) => (provincesLocationOptions = data)"
auto-load
url="Provinces/location"
/>
<fetch-data <fetch-data
@on-fetch="(data) => (agencyModes = data)" @on-fetch="(data) => (agencyModes = data)"
auto-load auto-load
@ -168,83 +145,17 @@ const onDataSaved = () => {
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<VnSelectDialog <VnLocation
:label="t('Postcode')"
:options="postcodesOptions"
:roles-allowed-to-create="['deliveryAssistant']"
:rules="validate('Worker.postcode')" :rules="validate('Worker.postcode')"
hide-selected :roles-allowed-to-create="['deliveryAssistant']"
option-label="code" :options="postcodesOptions"
option-value="code" v-model="data.location"
v-model="data.postalCode" @update:model-value="(location) => handleLocation(data, location)"
> ></VnLocation>
<template #form>
<CustomerCreateNewPostcode
@on-data-saved="onPostcodeCreated($event, data)"
/>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection v-if="scope.opt">
<QItemLabel>{{ scope.opt.code }}</QItemLabel>
<QItemLabel caption>
{{ scope.opt.code }} -
{{ scope.opt.town.name }}
({{ scope.opt.town.province.name }},
{{ scope.opt.town.province.country.country }})
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectDialog>
</div>
<div class="col">
<!-- ciudades -->
<VnSelectFilter
:label="t('City')"
:options="citiesLocationOptions"
hide-selected
option-label="name"
option-value="name"
v-model="data.city"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{ scope.opt.name }}</QItemLabel>
<QItemLabel caption>
{{
`${scope.opt.name}, ${scope.opt.province.name} (${scope.opt.province.country.country})`
}}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div> </div>
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<div class="col">
<VnSelectFilter
:label="t('Province')"
:options="provincesLocationOptions"
hide-selected
option-label="name"
option-value="id"
v-model="data.provinceFk"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>{{
`${scope.opt.name} (${scope.opt.country.country})`
}}</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelectFilter>
</div>
<div class="col"> <div class="col">
<VnSelectFilter <VnSelectFilter
:label="t('Agency')" :label="t('Agency')"

View File

@ -50,25 +50,23 @@ onMounted(() => {
:key="index" :key="index"
class="row q-gutter-md q-mb-md" class="row q-gutter-md q-mb-md"
> >
<div class="col-3"> <VnSelectFilter
<VnSelectFilter :label="t('entry.notes.observationType')"
:label="t('entry.notes.observationType')" v-model="row.observationTypeFk"
v-model="row.observationTypeFk" :options="entryObservationsOptions"
:options="entryObservationsOptions" :disable="!!row.id"
:disable="!!row.id" option-label="description"
option-label="description" option-value="id"
option-value="id" hide-selected
hide-selected />
/>
</div> <VnInput
<div class="col"> :label="t('globals.description')"
<VnInput v-model="row.description"
:label="t('globals.description')" :rules="validate('EntryObservation.description')"
v-model="row.description" />
:rules="validate('EntryObservation.description')"
/> <div class="row justify-center items-center">
</div>
<div class="col-1 row justify-center items-center">
<QIcon <QIcon
name="delete" name="delete"
size="sm" size="sm"
@ -82,19 +80,17 @@ onMounted(() => {
</QIcon> </QIcon>
</div> </div>
</VnRow> </VnRow>
<VnRow> <QIcon
<QIcon name="add"
name="add" size="sm"
size="sm" class="cursor-pointer"
class="cursor-pointer" color="primary"
color="primary" @click="entryObservationsRef.insert()"
@click="entryObservationsRef.insert()" >
> <QTooltip>
<QTooltip> {{ t('Add note') }}
{{ t('Add note') }} </QTooltip>
</QTooltip> </QIcon>
</QIcon>
</VnRow>
</QCard> </QCard>
</template> </template>
</CrudModel> </CrudModel>

View File

@ -6,7 +6,7 @@ import { useStateStore } from 'stores/useStateStore';
import CardSummary from 'components/ui/CardSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'components/ui/VnLv.vue'; import VnLv from 'components/ui/VnLv.vue';
import ShelvingFilter from 'pages/Shelving/Card/ShelvingFilter.vue'; import ShelvingFilter from 'pages/Shelving/Card/ShelvingFilter.vue';
import VnUserLink from "components/ui/VnUserLink.vue"; import VnUserLink from 'components/ui/VnUserLink.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {

View File

@ -10,6 +10,7 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue'; import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import VnRow from 'components/ui/VnRow.vue'; import VnRow from 'components/ui/VnRow.vue';
import CustomerCreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue'; import CustomerCreateNewPostcode from 'src/components/CreateNewPostcodeForm.vue';
import VnLocation from 'src/components/common/VnLocation.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -55,27 +56,16 @@ onMounted(() => {
updateAddressForm(addressData); updateAddressForm(addressData);
} }
}); });
function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {};
data.postalCode = code;
data.city = town;
data.provinceFk = provinceFk;
data.countryFk = countryFk;
}
</script> </script>
<template> <template>
<FetchData
ref="postcodeFetchDataRef"
url="Postcodes/location"
@on-fetch="(data) => (postcodesOptions = data)"
auto-load
/>
<FetchData
ref="provincesFetchDataRef"
@on-fetch="(data) => (provincesOptions = data)"
auto-load
url="Provinces"
/>
<FetchData
ref="townsFetchDataRef"
@on-fetch="(data) => (townsLocationOptions = data)"
auto-load
url="Towns/location"
/>
<QPage> <QPage>
<FormModel <FormModel
model="supplierAddresses" model="supplierAddresses"
@ -104,59 +94,15 @@ onMounted(() => {
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<VnSelectDialog <VnLocation
v-model="data.postalCode" :rules="validate('Worker.postcode')"
:label="t('supplier.addresses.postcode')"
:rules="validate('supplierAddress.postcode')"
:roles-allowed-to-create="['deliveryAssistant']" :roles-allowed-to-create="['deliveryAssistant']"
:options="postcodesOptions" :options="postcodesOptions"
option-label="code" v-model="data.location"
option-value="code" @update:model-value="
hide-selected (location) => handleLocation(data, location)
> "
<template #form> ></VnLocation>
<CustomerCreateNewPostcode
@on-data-saved="onPostcodeCreated($event)"
/>
</template>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection v-if="scope.opt">
<QItemLabel>{{ scope.opt.code }}</QItemLabel>
<QItemLabel caption
>{{ scope.opt.code }} -
{{ scope.opt.town.name }} ({{
scope.opt.town.province.name
}},
{{
scope.opt.town.province.country.country
}})</QItemLabel
>
</QItemSection>
</QItem>
</template>
</VnSelectDialog>
</div>
<div class="col">
<VnSelectFilter
:label="t('supplier.addresses.city')"
:options="townsLocationOptions"
v-model="data.city"
hide-selected
option-label="name"
option-value="id"
/>
</div>
<div class="col">
<VnSelectFilter
:label="t('supplier.addresses.province')"
:options="provincesOptions"
hide-selected
map-options
option-label="name"
option-value="id"
v-model="data.provinceFk"
/>
</div> </div>
</VnRow> </VnRow>
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">

View File

@ -21,7 +21,7 @@ const postcodesOptions = ref([]);
function handleLocation(data, location) { function handleLocation(data, location) {
const { town, code, provinceFk, countryFk } = location ?? {}; const { town, code, provinceFk, countryFk } = location ?? {};
data.postcode = code; data.postCode = code;
data.city = town; data.city = town;
data.provinceFk = provinceFk; data.provinceFk = provinceFk;
data.countryFk = countryFk; data.countryFk = countryFk;