<script setup> import { onMounted, ref, computed, reactive, onUnmounted } from 'vue'; import { useI18n } from 'vue-i18n'; import { useRouter } from 'vue-router'; import FetchData from 'components/FetchData.vue'; import FetchedTags from 'components/ui/FetchedTags.vue'; import EntryDescriptorProxy from './Card/EntryDescriptorProxy.vue'; import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue'; import EditTableCellValueForm from 'src/components/EditTableCellValueForm.vue'; import VnInput from 'src/components/common/VnInput.vue'; import VnSelect from 'src/components/common/VnSelect.vue'; import EntryLatestBuysFilter from './EntryLatestBuysFilter.vue'; import ItemDescriptorProxy from '../Item/Card/ItemDescriptorProxy.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import { useStateStore } from 'stores/useStateStore'; import { toDate, toCurrency } from 'src/filters'; // import { useSession } from 'composables/useSession'; import { dashIfEmpty } from 'src/filters'; import { useArrayData } from 'composables/useArrayData'; import RightMenu from 'src/components/common/RightMenu.vue'; import VnImg from 'src/components/ui/VnImg.vue'; const router = useRouter(); // const { getTokenMultimedia } = useSession(); // const token = getTokenMultimedia(); const stateStore = useStateStore(); const { t } = useI18n(); const rowsFetchDataRef = ref(null); const itemTypesOptions = ref([]); const originsOptions = ref([]); const itemFamiliesOptions = ref([]); const intrastatOptions = ref([]); const packagingsOptions = ref([]); const editTableCellDialogRef = ref(null); const visibleColumns = ref([]); const allColumnNames = ref([]); const exprBuilder = (param, value) => { switch (param) { case 'id': case 'size': case 'weightByPiece': case 'isActive': case 'family': case 'minPrice': case 'packingOut': return { [`i.${param}`]: value }; case 'name': case 'description': return { [`i.${param}`]: { like: `%${value}%` } }; case 'code': return { 'it.code': value }; case 'intrastat': return { 'intr.description': value }; case 'origin': return { 'ori.code': value }; case 'landing': return { [`lb.${param}`]: value }; case 'packing': case 'grouping': case 'quantity': case 'entryFk': case 'buyingValue': case 'freightValue': case 'comissionValue': case 'packageValue': case 'isIgnored': case 'price2': case 'price3': case 'ektFk': case 'weight': case 'packagingFk': return { [`b.${param}`]: value }; } }; const params = reactive({}); const arrayData = useArrayData('EntryLatestBuys', { url: 'Buys/latestBuysFilter', order: ['itemFk DESC'], exprBuilder: exprBuilder, }); const store = arrayData.store; const rows = computed(() => store.data); const rowsSelected = ref([]); const getInputEvents = (col) => { return col.columnFilter.type === 'select' ? { 'update:modelValue': () => applyColumnFilter(col) } : { 'keyup.enter': () => applyColumnFilter(col), }; }; const columns = computed(() => [ { label: t('entry.latestBuys.picture'), name: 'picture', align: 'left', }, { label: t('entry.latestBuys.itemFk'), name: 'itemFk', field: 'itemFk', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.packing'), field: 'packing', name: 'packing', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.grouping'), field: 'grouping', name: 'grouping', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.quantity'), field: 'quantity', name: 'quantity', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.description'), field: 'description', name: 'description', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.size'), field: 'size', name: 'size', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.tags'), name: 'tags', align: 'left', columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.type'), field: 'code', name: 'type', align: 'left', sortable: true, columnFilter: { component: VnSelect, type: 'select', filterValue: null, event: getInputEvents, attrs: { options: itemTypesOptions.value, 'option-value': 'code', 'option-label': 'code', dense: true, }, }, }, { label: t('entry.latestBuys.intrastat'), field: 'intrastat', name: 'intrastat', align: 'left', sortable: true, columnFilter: { component: VnSelect, type: 'select', filterValue: null, event: getInputEvents, attrs: { options: intrastatOptions.value, 'option-value': 'description', 'option-label': 'description', dense: true, }, }, }, { label: t('entry.latestBuys.origin'), field: 'origin', name: 'origin', align: 'left', sortable: true, columnFilter: { component: VnSelect, type: 'select', filterValue: null, event: getInputEvents, attrs: { options: originsOptions.value, 'option-value': 'code', 'option-label': 'code', dense: true, }, }, }, { label: t('entry.latestBuys.weightByPiece'), field: 'weightByPiece', name: 'weightByPiece', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.isActive'), field: 'isActive', name: 'isActive', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.family'), field: 'family', name: 'family', align: 'left', sortable: true, columnFilter: { component: VnSelect, type: 'select', filterValue: null, event: getInputEvents, attrs: { options: itemFamiliesOptions.value, 'option-value': 'code', 'option-label': 'code', dense: true, }, }, }, { label: t('entry.latestBuys.entryFk'), field: 'entryFk', name: 'entryFk', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.buyingValue'), field: 'buyingValue', name: 'buyingValue', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.freightValue'), field: 'freightValue', name: 'freightValue', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.comissionValue'), field: 'comissionValue', name: 'comissionValue', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.packageValue'), field: 'packageValue', name: 'packageValue', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.isIgnored'), field: 'isIgnored', name: 'isIgnored', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.price2'), field: 'price2', name: 'price2', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.price3'), field: 'price3', name: 'price3', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.minPrice'), field: 'minPrice', name: 'minPrice', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toCurrency(val), }, { label: t('entry.latestBuys.ektFk'), field: 'ektFk', name: 'ektFk', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.weight'), field: 'weight', name: 'weight', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, }, { label: t('entry.latestBuys.packagingFk'), field: 'packagingFk', name: 'packagingFk', align: 'left', sortable: true, columnFilter: { component: VnSelect, type: 'select', filterValue: null, event: getInputEvents, attrs: { options: packagingsOptions.value, 'option-value': 'id', 'option-label': 'id', dense: true, }, }, }, { label: t('entry.latestBuys.packingOut'), field: 'packingOut', name: 'packingOut', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => dashIfEmpty(val), }, { label: t('entry.latestBuys.landing'), field: 'landing', name: 'landing', align: 'left', sortable: true, columnFilter: { component: VnInput, type: 'text', filterValue: null, event: getInputEvents, attrs: { dense: true, }, }, format: (val) => toDate(val), }, ]); const editTableCellFormFieldsOptions = [ { field: 'packing', label: t('entry.latestBuys.packing') }, { field: 'grouping', label: t('entry.latestBuys.grouping') }, { field: 'packageValue', label: t('entry.latestBuys.packageValue') }, { field: 'weight', label: t('entry.latestBuys.weight') }, { field: 'description', label: t('globals.description') }, { field: 'size', label: t('entry.latestBuys.size') }, { field: 'weightByPiece', label: t('entry.latestBuys.weightByPiece') }, { field: 'packingOut', label: t('entry.latestBuys.packingOut') }, { field: 'landing', label: t('entry.latestBuys.landing') }, ]; const openEditTableCellDialog = () => { editTableCellDialogRef.value.show(); }; const onEditCellDataSaved = async () => { rowsSelected.value = []; await rowsFetchDataRef.value.fetch(); }; const redirectToEntryBuys = (entryFk) => { router.push({ name: 'EntryBuys', params: { id: entryFk } }); }; const applyColumnFilter = async (col) => { try { params[col.field] = col.columnFilter.filterValue; await arrayData.addFilter({ params }); } catch (err) { console.error('Error applying column filter', err); } }; onMounted(async () => { stateStore.rightDrawer = true; const filteredColumns = columns.value.filter((col) => col.name !== 'picture'); allColumnNames.value = filteredColumns.map((col) => col.name); await arrayData.fetch({ append: false }); }); onUnmounted(() => (stateStore.rightDrawer = false)); </script> <template> <FetchData url="ItemTypes" :filter="{ fields: ['code'], order: 'code ASC', limit: 30 }" auto-load @on-fetch="(data) => (itemTypesOptions = data)" /> <FetchData url="Origins" :filter="{ fields: ['code'], order: 'code ASC', limit: 30 }" auto-load @on-fetch="(data) => (originsOptions = data)" /> <FetchData url="ItemFamilies" :filter="{ fields: ['code'], order: 'code ASC', limit: 30 }" auto-load @on-fetch="(data) => (itemFamiliesOptions = data)" /> <FetchData url="Packagings" :filter="{ fields: ['id'], order: 'id ASC', limit: 30 }" auto-load @on-fetch="(data) => (packagingsOptions = data)" /> <FetchData url="Intrastats" :filter="{ fields: ['description'], order: 'description ASC', limit: 30 }" auto-load @on-fetch="(data) => (intrastatOptions = data)" /> <VnSubToolbar> <template #st-data> <TableVisibleColumns :all-columns="allColumnNames" table-code="latestBuys" labels-traductions-path="entry.latestBuys" @on-config-saved="visibleColumns = ['picture', ...$event]" /> </template> </VnSubToolbar> <RightMenu> <template #right-panel> <EntryLatestBuysFilter data-key="EntryLatestBuys" /> </template> </RightMenu> <Teleport to="#actions-append"> <div class="row q-gutter-x-sm"> <QBtn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu"> <QTooltip bottom anchor="bottom right"> {{ t('globals.collapseMenu') }} </QTooltip> </QBtn> </div> </Teleport> <QPage class="column items-center q-pa-md"> <QTable :rows="rows" :columns="columns" selection="multiple" row-key="id" class="full-width q-mt-md" :visible-columns="visibleColumns" v-model:selected="rowsSelected" :no-data-label="t('globals.noResults')" @row-click="(_, row) => redirectToEntryBuys(row.entryFk)" > <template #top-row="{ cols }"> <QTr> <QTd /> <QTd v-for="(col, index) in cols" :key="index" style="max-width: 100px" > <component :is="col.columnFilter.component" v-if="col.name !== 'picture'" v-model="col.columnFilter.filterValue" v-bind="col.columnFilter.attrs" v-on="col.columnFilter.event(col)" dense /> </QTd> </QTr> </template> <template #body-cell-picture="{ row }"> <QTd> <VnImg :id="row.itemFk" size="50x50" class="image" /> </QTd> </template> <template #body-cell-itemFk="{ row }"> <QTd @click.stop> <QBtn flat color="primary"> {{ row.itemFk }} </QBtn> <ItemDescriptorProxy :id="row.itemFk" /> </QTd> </template> <template #body-cell-tags="{ row }"> <QTd> <FetchedTags :item="row" :max-length="6" /> </QTd> </template> <template #body-cell-entryFk="{ row }"> <QTd @click.stop> <QBtn flat color="primary"> <EntryDescriptorProxy :id="row.entryFk" /> {{ row.entryFk }} </QBtn> </QTd> </template> <template #body-cell-isIgnored="{ row }"> <QTd> <QIcon :name="row.isIgnored ? `check` : `close`" :color="row.isIgnored ? `positive` : `negative`" size="sm" /> </QTd> </template> <template #body-cell-isActive="{ row }"> <QTd> <QIcon :name="row.isActive ? `check` : `close`" :color="row.isActive ? `positive` : `negative`" size="sm" /> </QTd> </template> </QTable> <QPageSticky v-if="rowsSelected.length > 0" :offset="[20, 20]"> <QBtn @click="openEditTableCellDialog()" color="primary" fab icon="edit" /> <QTooltip> {{ t('Edit buy(s)') }} </QTooltip> </QPageSticky> <QDialog ref="editTableCellDialogRef"> <EditTableCellValueForm edit-url="Buys/editLatestBuys" :rows="rowsSelected" :fields-options="editTableCellFormFieldsOptions" @on-data-saved="onEditCellDataSaved()" /> </QDialog> </QPage> </template> <i18n> es: Edit buy(s): Editar compra(s) </i18n>