salix-front/src/pages/Item/ItemFixedPrice.vue

403 lines
12 KiB
Vue

<script setup>
import { onMounted, ref, onUnmounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useStateStore } from 'stores/useStateStore';
import { beforeSave } from 'src/composables/updateMinPriceBeforeSave';
import FetchedTags from 'components/ui/FetchedTags.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import EditFixedPriceForm from 'src/pages/Item/components/EditFixedPriceForm.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnColor from 'src/components/common/VnColor.vue';
import { toDate } from 'src/filters';
import { isLower, isBigger } from 'src/filters/date.js';
import ItemFixedPriceFilter from './ItemFixedPriceFilter.vue';
import ItemDescriptorProxy from './Card/ItemDescriptorProxy.vue';
import CloneFixedPriceForm from 'src/pages/Item/components/CloneFixedPriceForm.vue';
const stateStore = useStateStore();
const { t } = useI18n();
const tableRef = ref();
const editFixedPriceForm = ref(null);
const cloneFixedPriceForm = ref(null);
const cloneRow = ref({});
const selectedRows = ref([]);
const hasSelectedRows = computed(() => selectedRows.value.length > 0);
const dateColor = 'var(--vn-label-text-color)';
onMounted(async () => {
stateStore.rightDrawer = true;
});
onUnmounted(() => (stateStore.rightDrawer = false));
const columns = computed(() => [
{
name: 'itemFk',
label: t('item.fixedPrice.itemFk'),
labelAbbreviation: 'Id',
toolTip: t('item.fixedPrice.itemFk'),
component: 'select',
attrs: {
url: 'Items',
fields: ['id', 'name', 'subName'],
optionLabel: 'name',
optionValue: 'id',
uppercase: false,
},
columnFilter: {
inWhere: true,
},
width: '55px',
},
{
labelAbbreviation: '',
name: 'hex',
columnSearch: false,
isEditable: false,
width: '10px',
component: 'select',
attrs: {
url: 'Inks',
fields: ['id', 'name'],
},
},
{
align: 'left',
label: t('globals.name'),
name: 'name',
create: true,
component: 'input',
isEditable: false,
},
{
label: t('item.fixedPrice.groupingPrice'),
labelAbbreviation: 'Group.',
toolTip: t('item.fixedPrice.groupingPrice'),
name: 'rate2',
component: 'number',
create: true,
createOrder: 3,
width: '40px',
},
{
label: t('item.fixedPrice.packingPrice'),
labelAbbreviation: 'Pack.',
toolTip: t('item.fixedPrice.packingPrice'),
name: 'rate3',
component: 'number',
create: true,
createOrder: 4,
width: '40px',
},
{
name: 'hasMinPrice',
label: t('item.fixedPrice.hasMinPrice'),
labelAbbreviation: t('item.fixedPrice.MP'),
toolTip: t('item.fixedPrice.hasMinPrice'),
label: t('Has min price'),
component: 'checkbox',
attrs: {
toggleIndeterminate: false,
},
width: '50px',
},
{
label: t('item.fixedPrice.minPrice'),
labelAbbreviation: 'Min.P',
toolTip: t('item.fixedPrice.minPrice'),
name: 'minPrice',
component: 'number',
width: '45px',
style: (row) => {
if (!row?.hasMinPrice) return { color: 'var(--vn-label-color)' };
},
format: (row) => parseFloat(row['minPrice']).toFixed(2),
},
{
label: t('item.fixedPrice.started'),
name: 'started',
component: 'date',
columnFilter: {
component: 'date',
},
create: true,
createOrder: 5,
width: '55px',
},
{
label: t('item.fixedPrice.ended'),
name: 'ended',
component: 'date',
columnFilter: {
component: 'date',
},
create: true,
createOrder: 6,
width: '55px',
},
{
align: 'center',
label: t('globals.warehouse'),
name: 'warehouseFk',
component: 'select',
attrs: {
url: 'Warehouses',
fields: ['id', 'name'],
optionLabel: 'name',
optionValue: 'id',
},
create: true,
format: (row, dashIfEmpty) => dashIfEmpty(row.warehouseName),
width: '80px',
},
{
align: 'right',
name: 'tableActions',
actions: [
{
title: t('globals.clone'),
icon: 'vn:clone',
action: (row) => openCloneFixedPriceForm(row),
isPrimary: true,
},
],
},
]);
const openEditFixedPriceForm = () => {
editFixedPriceForm.value.show();
};
const openCloneFixedPriceForm = (row) => {
cloneRow.value = (({ itemFk, rate2, rate3, started, ended, warehouseFk }) => ({
itemFk,
rate2,
rate3,
started,
ended,
warehouseFk,
}))(JSON.parse(JSON.stringify(row)));
cloneFixedPriceForm.value.show();
};
const dateStyle = (date) =>
date
? {
color: 'var(--vn-black-text-color)',
}
: { color: dateColor, 'background-color': 'transparent' };
</script>
<template>
<RightMenu>
<template #right-panel>
<ItemFixedPriceFilter data-key="ItemFixedPrices" />
</template>
</RightMenu>
<VnSubToolbar />
<Teleport to="#st-data" v-if="stateStore?.isSubToolbarShown()">
<QBtnGroup push style="column-gap: 10px">
<QBtn
:disable="!hasSelectedRows"
@click="openEditFixedPriceForm()"
color="primary"
icon="vn:wand"
flat
:label="t('globals.edit')"
data-cy="FixedPriceToolbarEditBtn"
>
<QTooltip>
{{ t('Edit fixed price(s)') }}
</QTooltip>
</QBtn>
</QBtnGroup>
</Teleport>
<VnTable
ref="tableRef"
data-key="ItemFixedPrices"
url="FixedPrices/filter"
:order="'name DESC'"
save-url="FixedPrices/crud"
:columns="columns"
:is-editable="true"
:right-search="false"
:table="{
'row-key': 'id',
selection: 'multiple',
}"
v-model:selected="selectedRows"
:create="{
urlCreate: 'FixedPrices',
title: t('Create fixed price'),
formInitialData: {},
onDataSaved: () => tableRef.reload(),
showSaveAndContinueBtn: true,
}"
:disable-option="{ card: true }"
auto-load
:beforeSaveFn="(data, getChanges) => beforeSave(data, getChanges, 'FixedPrices')"
>
<template #column-hex="{ row }">
<VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
</template>
<template #column-name="{ row }">
<span class="link">
{{ row.name }}
</span>
<span class="subName">{{ row.subName }}</span>
<ItemDescriptorProxy :id="row.itemFk" />
<FetchedTags :item="row" :columns="6" />
</template>
<template #column-started="{ row }">
<div class="editable-text q-pb-xxs">
<QBadge class="badge" :style="dateStyle(isLower(row?.ended))">
{{ toDate(row?.started) }}
</QBadge>
</div>
</template>
<template #column-ended="{ row }">
<div class="editable-text q-pb-xxs">
<QBadge class="badge" :style="dateStyle(isBigger(row?.ended))">
{{ toDate(row?.ended) }}
</QBadge>
</div>
</template>
<template #column-create-name="{ data }">
<VnSelect
url="Items/search"
v-model="data.itemFk"
:label="t('item.fixedPrice.itemName')"
:fields="['id', 'name']"
:filter-options="['id', 'name']"
option-label="name"
option-value="id"
:required="true"
sort-by="name ASC"
data-cy="FixedPriceCreateNameSelect"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt.name }}
</QItemLabel>
<QItemLabel caption> #{{ scope.opt.id }} </QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</template>
<template #column-create-warehouseFk="{ data }">
<VnSelect
:label="t('globals.warehouse')"
url="Warehouses"
v-model="data.warehouseFk"
:fields="['id', 'name']"
option-label="name"
option-value="id"
hide-selected
:required="true"
sort-by="name ASC"
data-cy="FixedPriceCreateWarehouseSelect"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt.name }}
</QItemLabel>
<QItemLabel caption> #{{ scope.opt.id }} </QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
</template>
</VnTable>
<QDialog ref="editFixedPriceForm">
<EditFixedPriceForm
edit-url="FixedPrices/editFixedPrice"
:rows="selectedRows"
:fields-options="
columns.filter(
({ isEditable, component, name }) =>
isEditable !== false && component && name !== 'itemFk',
)
"
:beforeSave="beforeSave"
@on-data-saved="tableRef.CrudModelRef.saveChanges()"
/>
</QDialog>
<QDialog ref="cloneFixedPriceForm">
<CloneFixedPriceForm :row="cloneRow" @on-data-saved="tableRef.reload()" />
</QDialog>
</template>
<style lang="scss">
.q-table th,
.q-table td {
padding-inline: 5px !important;
}
.q-table tr td {
font-size: 10pt;
border-top: none;
border-collapse: collapse;
}
.q-table tbody td {
max-width: none;
.q-td.col {
& .vnInputDate {
min-width: 90px;
}
& div.row {
& .q-checkbox {
& .q-checkbox__inner {
position: relative !important;
&.q-checkbox__inner--truthy {
color: var(--q-primary);
}
}
}
}
}
}
.q-field__after,
.q-field__append {
padding: 0;
}
tbody tr.highlight .q-td {
animation: highlight-animation 4s ease-in-out;
}
@keyframes highlight-animation {
0% {
background-color: $primary-light;
}
100% {
background-color: transparent;
}
}
.subName {
margin-left: 5%;
font-size: 0.75rem;
text-transform: uppercase;
color: var(--vn-label-color);
}
</style>
<style lang="scss" scoped>
.badge {
background-color: $warning;
}
</style>
<i18n>
es:
Add fixed price: Añadir precio fijado
Edit fixed price(s): Editar precio(s) fijado(s)
Create fixed price: Crear precio fijado
</i18n>