fix: refs #8388 update VnSelect component to handle option rendering based on optionLabel type
gitea/salix-front/pipeline/pr-dev This commit is unstable Details

This commit is contained in:
Jorge Penadés 2025-04-23 16:38:34 +02:00
parent 587f106818
commit 6c49c9ea82
2 changed files with 96 additions and 188 deletions

View File

@ -407,7 +407,12 @@ function getCaption(opt) {
</template> </template>
<template #option="{ opt, itemProps }"> <template #option="{ opt, itemProps }">
<QItem v-bind="itemProps"> <QItem v-bind="itemProps">
<QItemSection v-if="typeof opt !== 'object'"> {{ opt }}</QItemSection> <QItemSection v-if="typeof optionLabel === 'function'">{{
optionLabel(opt)
}}</QItemSection>
<QItemSection v-else-if="typeof opt !== 'object'">
{{ opt }}</QItemSection
>
<QItemSection v-else-if="opt[optionValue] == opt[optionLabel]"> <QItemSection v-else-if="opt[optionValue] == opt[optionLabel]">
<QItemLabel>{{ opt[optionLabel] }}</QItemLabel> <QItemLabel>{{ opt[optionLabel] }}</QItemLabel>
</QItemSection> </QItemSection>

View File

@ -3,71 +3,85 @@ import { computed, ref } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { getTotal } from 'src/composables/getTotal'; import { getTotal } from 'src/composables/getTotal';
import CrudModel from 'src/components/CrudModel.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const invoceInIntrastat = ref([]);
const rowsSelected = ref([]); const rowsSelected = ref([]);
const countries = ref([]); const countries = ref([]);
const intrastats = ref([]); const intrastats = ref([]);
const invoiceInFormRef = ref(); const invoiceInIntrastatRef = ref();
const invoiceInId = computed(() => +route.params.id); const invoiceInId = computed(() => +route.params.id);
const filter = { where: { invoiceInFk: invoiceInId.value } }; const filter = computed(() => ({ where: { invoiceInFk: invoiceInId.value } }));
const columns = computed(() => [ const columns = computed(() => [
{ {
name: 'code', name: 'intrastatFk',
label: t('Code'), label: t('Code'),
field: (row) => row.intrastatFk, component: 'select',
columnFilter: false,
attrs: {
options: intrastats.value, options: intrastats.value,
model: 'intrastatFk',
optionValue: 'id', optionValue: 'id',
optionLabel: (row) => `${row.id}: ${row.description}`, optionLabel: (row) => `${row.id}: ${row.description}`,
sortable: true, 'data-cy': 'intrastat-code',
tabIndex: 1, sortBy: 'id',
align: 'left', fields: ['id', 'description'],
},
format: getCode,
create: true,
isEditable: true,
}, },
{ {
name: 'amount', name: 'amount',
label: t('amount'), label: t('amount'),
field: (row) => row.amount, component: 'number',
sortable: true, create: true,
tabIndex: 2, isEditable: true,
align: 'left', columnFilter: false,
width: '30px',
}, },
{ {
name: 'net', name: 'net',
label: t('net'), label: t('net'),
field: (row) => row.net, component: 'number',
sortable: true, create: true,
tabIndex: 3, isEditable: true,
align: 'left', columnFilter: false,
width: '30px',
}, },
{ {
name: 'stems', name: 'stems',
label: t('stems'), label: t('stems'),
field: (row) => row.stems, component: 'number',
sortable: true, create: true,
tabIndex: 4, isEditable: true,
align: 'left', columnFilter: false,
width: '30px',
}, },
{ {
name: 'country', name: 'countryFk',
label: t('country'), label: t('country'),
field: (row) => row.countryFk, component: 'select',
attrs: {
options: countries.value, options: countries.value,
model: 'countryFk',
optionValue: 'id',
optionLabel: 'code', optionLabel: 'code',
sortable: true, },
tabIndex: 5, create: true,
align: 'left', isEditable: true,
columnFilter: false,
width: '30px',
}, },
]); ]);
const tableRows = computed(
() => invoiceInIntrastatRef.value?.CrudModelRef?.formData || [],
);
function getCode(row) {
const { id, description } = intrastats.value.find(({ id }) => id === row.intrastatFk);
return `${id}: ${description}`;
}
</script> </script>
<template> <template>
<FetchData <FetchData
@ -82,164 +96,51 @@ const columns = computed(() => [
auto-load auto-load
@on-fetch="(data) => (intrastats = data)" @on-fetch="(data) => (intrastats = data)"
/> />
<div class="invoiceIn-intrastat"> <div class="invoice-in-intrastat">
<CrudModel <VnTable
ref="invoiceInFormRef" ref="invoiceInIntrastatRef"
data-key="InvoiceInIntrastats" data-key="InvoiceInIntrastats"
url="InvoiceInIntrastats" url="InvoiceInIntrastats"
save-url="InvoiceInIntrastats/crud"
search-url="InvoiceInIntrastats"
auto-load auto-load
:data-required="{ invoiceInFk: invoiceInId }" :filter
:filter="filter" :user-filter
v-model:selected="rowsSelected" v-model:selected="rowsSelected"
@on-fetch="(data) => (invoceInIntrastat = data)" :columns
:is-editable="true"
:table="{ selection: 'multiple', 'row-key': '$index' }"
:create="{
urlCreate: 'InvoiceInIntrastats',
title: t('Create Intrastat Line'),
formInitialData: { invoiceInFk: invoiceInId },
onDataSaved: () => invoiceInIntrastatRef.reload(),
}"
footer
data-cy="invoice-in-intrastat-table"
:right-search="false"
:disable-option="{ card: true }"
> >
<template #body="{ rows }"> <template #column-footer-amount>
<QTable {{ getTotal(tableRows, 'amount', { currency: 'default' }) }}
v-model:selected="rowsSelected"
selection="multiple"
:columns="columns"
:rows="rows"
row-key="$index"
:grid="$q.screen.lt.sm"
>
<template #body-cell="{ row, col }">
<QTd>
<VnInputNumber v-model="row[col.name]" />
</QTd>
</template> </template>
<template #body-cell-code="{ row, col }"> <template #column-footer-net>
<QTd> {{ getTotal(tableRows, 'net') }}
<VnSelect
v-model="row[col.model]"
:options="col.options"
:option-value="col.optionValue"
:option-label="col.optionLabel"
:filter-options="['id', 'description']"
data-cy="intrastat-code"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
{{ `${scope.opt.id}: ${scope.opt.description}` }}
</QItem>
</template> </template>
</VnSelect> <template #column-footer-stems>
</QTd> {{ getTotal(tableRows, 'stems', { decimalPlaces: 0 }) }}
</template> </template>
<template #body-cell-country="{ row, col }"> </VnTable>
<QTd>
<VnSelect
v-model="row[col.model]"
:options="col.options"
:option-value="col.optionValue"
:option-label="col.optionLabel"
/>
</QTd>
</template>
<template #bottom-row>
<QTr class="bg">
<QTd />
<QTd />
<QTd>
{{ getTotal(rows, 'amount', { currency: 'default' }) }}
</QTd>
<QTd>
{{ getTotal(rows, 'net') }}
</QTd>
<QTd>
{{ getTotal(rows, 'stems', { decimalPlaces: 0 }) }}
</QTd>
<QTd />
</QTr>
</template>
<template #item="props">
<div class="q-pa-xs col-xs-12 col-sm-6 grid-style-transition">
<QCard>
<QCardSection>
<QCheckbox v-model="props.selected" dense />
</QCardSection>
<QSeparator />
<QList>
<QItem>
<VnSelect
:label="t('Code')"
class="full-width"
v-model="props.row['intrastatFk']"
:options="intrastats"
option-value="id"
:option-label="
(row) => `${row.id}:${row.description}`
"
:filter-options="['id', 'description']"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
{{
`${scope.opt.id}: ${scope.opt.description}`
}}
</QItem>
</template>
</VnSelect>
</QItem>
<QItem
v-for="(value, index) of [
'amount',
'net',
'stems',
]"
:key="index"
>
<VnInputNumber
:label="t(value)"
class="full-width"
v-model="props.row[value]"
clearable
clear-icon="close"
/>
</QItem>
<QItem>
<VnSelect
:label="t('country')"
class="full-width"
v-model="props.row['countryFk']"
:options="countries"
option-value="id"
option-label="code"
/>
</QItem>
</QList>
</QCard>
</div> </div>
</template>
</QTable>
</template>
</CrudModel>
</div>
<QPageSticky position="bottom-right" :offset="[25, 25]">
<QBtn
color="primary"
icon="add"
v-shortcut="'+'"
size="lg"
round
@click="invoiceInFormRef.insert()"
/>
</QPageSticky>
</template> </template>
<style lang="scss"> <style lang="scss" scoped>
.invoiceIn-intrastat { .invoice-in-intrastat {
> .q-card {
.vn-label-value {
display: flex; display: flex;
gap: 1em; flex-direction: column;
align-items: center;
.label { }
flex: 1; :deep(.full-width) {
} max-width: 900px;
.value {
flex: 0.5;
}
}
}
} }
</style> </style>
<i18n> <i18n>
@ -248,6 +149,7 @@ const columns = computed(() => [
net: Net net: Net
stems: Stems stems: Stems
country: Country country: Country
Create Intrastat Line: Create Intrastat Line
es: es:
Code: Código Code: Código
amount: Valor mercancía amount: Valor mercancía
@ -257,4 +159,5 @@ const columns = computed(() => [
Total amount: Total importe Total amount: Total importe
Total net: Total neto Total net: Total neto
Total stems: Total tallos Total stems: Total tallos
Create Intrastat Line: Crear Línea Intrastat
</i18n> </i18n>