refactor: refs #8684 refs #8363 multiple refactor on item sections

This commit is contained in:
Pablo Natek 2025-04-24 13:24:46 +02:00
parent f01eb6c49c
commit 2cbbd92021
17 changed files with 169 additions and 221 deletions

View File

@ -162,7 +162,6 @@ async function fetch() {
align-items: start;
.label {
color: var(--vn-label-color);
width: 9em;
overflow: hidden;
white-space: wrap;
text-overflow: ellipsis;

View File

@ -247,10 +247,6 @@ const toModule = computed(() => {
.label {
color: var(--vn-label-color);
font-size: 14px;
&:not(:has(a))::after {
content: ':';
}
}
.value {
color: var(--vn-text-color);

View File

@ -63,7 +63,6 @@ defineExpose({
spinner-color="primary"
:error-src="`/no_image${getDarkSuffix()}.png`"
/>
{{ console.log(getDarkSuffix()) }}
<QDialog v-if="$props.zoom" v-model="show">
<QImg
:draggable="true"

View File

@ -40,10 +40,10 @@ const val = computed(() => $props.value);
<template v-else>
<div v-if="label || $slots.label" class="label">
<slot name="label">
<span style="color: var(--vn-label-color)">{{ label }}</span>
<span style="color: var(--vn-label-color)">{{ label }}:</span>
</slot>
</div>
<div class="value" v-if="value || $slots.value">
<div class="value">
<slot name="value">
<span :title="value" style="text-overflow: ellipsis">
{{ dash ? dashIfEmpty(value) : value }}
@ -71,21 +71,13 @@ const val = computed(() => $props.value);
visibility: visible;
cursor: pointer;
}
.label,
.value {
white-space: pre-line;
word-wrap: break-word;
}
.copy {
visibility: hidden;
}
.info {
margin-left: 5px;
}
}
:deep(.q-checkbox.disabled) {
opacity: 1 !important;
}

View File

@ -498,26 +498,6 @@ entry:
isRaid: Raid
invoiceNumber: Invoice
reference: Ref/Alb/Guide
params:
isExcludedFromAvailable: Excluir del inventario
isOrdered: Pedida
isConfirmed: Lista para etiquetar
isReceived: Recibida
isRaid: Redada
landed: Fecha
supplierFk: Proveedor
invoiceNumber: Nº Factura
reference: Ref/Alb/Guía
agencyModeId: Agencia
isBooked: Asentado
companyFk: Empresa
travelFk: Envio
evaNotes: Notas
warehouseOutFk: Origen
warehouseInFk: Destino
entryTypeDescription: Tipo entrada
invoiceAmount: Importe
dated: Fecha
ticket:
params:
ticketFk: Ticket ID

View File

@ -230,7 +230,7 @@ const onIntrastatCreated = (response, formData) => {
/>
<VnInput
type="textarea"
:label="t('globals.comment')"
:label="t('item.basicData.photoMotivation')"
v-model="data.photoMotivation"
fill-input
/>

View File

@ -102,20 +102,21 @@ const columns = computed(() => [
label: t('itemDiary.in'),
field: 'invalue',
name: 'in',
align: 'left',
align: 'right',
format: (val) => dashIfEmpty(val),
},
{
label: t('itemDiary.out'),
field: 'out',
name: 'out',
align: 'left',
align: 'right',
format: (val) => dashIfEmpty(val),
},
{
label: t('itemDiary.balance'),
name: 'balance',
align: 'left',
align: 'right',
class: 'q-px-sm',
},
]);
@ -217,7 +218,8 @@ async function updateWarehouse(warehouseFk) {
<QTable
:rows="itemBalances"
:columns="columns"
class="full-width q-mt-md"
class="full-width q-mt-md q-px-md"
style="background-color: var(--vn-section-color)"
:no-data-label="t('globals.noResults')"
>
<template #body-cell-claim="{ row }">
@ -294,14 +296,14 @@ async function updateWarehouse(warehouseFk) {
</QTd>
</template>
<template #body-cell-in="{ row }">
<QTd @click.stop>
<QTd @click.stop class="text-right">
<span :class="{ 'is-in': row.invalue }">
{{ dashIfEmpty(row.invalue) }}
</span>
</QTd>
</template>
<template #body-cell-balance="{ row }">
<QTd @click.stop>
<QTd @click.stop class="text-right">
<QBadge
class="balance-negative"
:color="

View File

@ -48,7 +48,7 @@ const columns = computed(() => [
label: t('itemDiary.warehouse'),
name: 'warehouse',
field: 'warehouse',
align: 'center',
align: 'left',
},
{
label: t('lastEntries.landed'),
@ -60,7 +60,7 @@ const columns = computed(() => [
label: t('lastEntries.entry'),
name: 'entry',
field: 'stateName',
align: 'center',
align: 'right',
format: (val) => dashIfEmpty(val),
},
{
@ -75,14 +75,14 @@ const columns = computed(() => [
label: t('lastEntries.printedStickers'),
name: 'printedStickers',
field: 'printedStickers',
align: 'center',
align: 'right',
format: (val) => dashIfEmpty(val),
},
{
label: t('lastEntries.label'),
name: 'stickers',
field: 'stickers',
align: 'center',
align: 'right',
format: (val) => dashIfEmpty(val),
style: (row) => highlightedRow(row),
},
@ -90,39 +90,39 @@ const columns = computed(() => [
label: 'Packing',
name: 'packing',
field: 'packing',
align: 'center',
align: 'right',
},
{
label: t('lastEntries.grouping'),
name: 'grouping',
field: 'grouping',
align: 'center',
align: 'right',
},
{
label: t('itemBasicData.stems'),
name: 'stems',
field: 'stems',
align: 'center',
align: 'right',
style: (row) => highlightedRow(row),
},
{
label: t('lastEntries.quantity'),
name: 'quantity',
field: 'quantity',
align: 'center',
align: 'right',
style: (row) => highlightedRow(row),
},
{
label: t('lastEntries.cost'),
name: 'cost',
field: 'cost',
align: 'center',
field: 'right',
align: 'right',
},
{
label: 'Kg',
name: 'weight',
field: 'weight',
align: 'center',
align: 'right',
style: (row) => highlightedRow(row),
},
{
@ -136,7 +136,7 @@ const columns = computed(() => [
label: t('lastEntries.supplier'),
name: 'supplier',
field: 'supplier',
align: 'center',
align: 'left',
},
]);
@ -269,7 +269,7 @@ function highlightedRow(row) {
</template>
<template #body-cell-entry="{ row }">
<QTd @click.stop :style="highlightedRow(row)">
<div class="full-width flex justify-center">
<div class="full-width text-right">
<EntryDescriptorProxy :id="row.entryFk" class="q-ma-none" dense />
<span class="link">{{ row.entryFk }}</span>
</div>
@ -282,16 +282,16 @@ function highlightedRow(row) {
</QTd>
</template>
<template #body-cell-printedStickers="{ row }">
<QTd @click.stop class="text-center" :style="highlightedRow(row)">
<QTd @click.stop class="text-right" :style="highlightedRow(row)">
<span style="color: var(--vn-label-color)">
{{ row.printedStickers }}</span
>
</QTd>
</template>
<template #body-cell-packing="{ row }">
<QTd @click.stop :style="highlightedRow(row)">
<QTd @click.stop :style="highlightedRow(row)" class="text-right">
<QBadge
class="center-content"
class="grouping-badge"
:class="getBadgeClass(row.groupingMode, 'packing')"
rounded
>
@ -301,9 +301,9 @@ function highlightedRow(row) {
</QTd>
</template>
<template #body-cell-grouping="{ row }">
<QTd @click.stop :style="highlightedRow(row)">
<QTd @click.stop :style="highlightedRow(row)" class="text-right">
<QBadge
class="center-content"
class="grouping-badge"
:class="getBadgeClass(row.groupingMode, 'grouping')"
rounded
>
@ -313,7 +313,7 @@ function highlightedRow(row) {
</QTd>
</template>
<template #body-cell-cost="{ row }">
<QTd @click.stop class="text-center" :style="highlightedRow(row)">
<QTd @click.stop class="text-right" :style="highlightedRow(row)">
<span>
{{ toCurrency(row.cost, 'EUR', 3) }}
<QTooltip>
@ -357,10 +357,7 @@ function highlightedRow(row) {
.q-badge--rounded {
border-radius: 50%;
}
.center-content {
display: flex;
max-width: max-content;
margin: auto;
.grouping-badge {
padding: 0 11px;
height: 28px;
}

View File

@ -58,7 +58,7 @@ const columns = computed(() => [
{
label: t('shelvings.item'),
name: 'itemFk',
align: 'left',
align: 'right',
columnFilter: false,
},
{
@ -102,19 +102,20 @@ const columns = computed(() => [
name: 'label',
align: 'left',
columnFilter: { inWhere: true },
component: 'number',
format: (row) => (row.stock / row.packing).toFixed(2),
},
{
label: t('shelvings.packing'),
name: 'packing',
attrs: { inWhere: true },
align: 'left',
component: 'number',
},
{
label: t('globals.visible'),
name: 'stock',
attrs: { inWhere: true },
align: 'left',
component: 'number',
},
]);
@ -138,21 +139,12 @@ watchEffect(selectedRows);
<template>
<template v-if="stateStore.isHeaderMounted()">
<Teleport to="#st-data">
<div class="q-pa-md q-mr-lg q-ma-xs" style="border: 2px solid #222">
<QCardSection horizontal>
<span class="text-weight-bold text-subtitle1 text-center full-width">
{{ t('shelvings.total') }}
</span>
</QCardSection>
<QCardSection class="column items-center" horizontal>
<div>
<span class="details-label"
>{{ t('shelvings.totalLabels') }}
</span>
<span class="details-label">{{ t('shelvings.totalLabels') }} </span>
<span>: {{ totalLabels }}</span>
</div></QCardSection
>
</div>
</QCardSection>
</Teleport>
<Teleport to="#st-actions">
<QBtn

View File

@ -2,6 +2,7 @@
import { computed } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import { dashIfEmpty } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
@ -48,7 +49,7 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
<ItemDescriptorMenu :entity-id="entityId" :warehouse-fk="warehouseFk" />
</template>
<template #body="{ entity: { item, tags, visible, available, botanical } }">
<QCard class="vn-one photo">
<QCard class="vn-one photo" v-if="$route.name != 'ItemSummary'">
<ItemDescriptorImage
:entity-id="entityId"
:visible="visible"
@ -56,14 +57,22 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
:show-edit-button="false"
/>
</QCard>
<QCard class="vn-one">
<QCard class="vn-three">
<VnTitle
:url="getUrl(entityId, 'basic-data')"
:text="t('globals.summary.basicData')"
/>
<div class="vn-card-group">
<div class="vn-card-content">
<VnLv :label="t('globals.name')" :value="item.name" />
<VnLv :label="t('item.summary.completeName')" :value="item.longName" />
<VnLv :label="t('item.summary.family')" :value="item.itemType.name" />
<VnLv
:label="t('item.summary.completeName')"
:value="item.longName"
/>
<VnLv
:label="t('item.summary.family')"
:value="item.itemType.name"
/>
<VnLv :label="t('globals.size')" :value="item.size" />
<VnLv :label="t('globals.origin')" :value="item.origin.name" />
<VnLv :label="t('item.summary.stems')" :value="item.stems" />
@ -86,15 +95,24 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
:label="t('item.summary.doPhoto')"
v-model="item.isPhotoRequested"
:disable="true"
size="xs"
/>
</template>
</VnLv>
</QCard>
<QCard class="vn-one">
<VnTitle
:url="getUrl(entityId, 'basic-data')"
:text="t('item.summary.otherData')"
<VnLv :label="t('globals.description')">
<template #value>
<span
style="
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
"
v-text="dashIfEmpty(item.description)"
/>
</template>
</VnLv>
</div>
<div class="vn-card-content">
<VnLv
:label="t('item.summary.intrastatCode')"
:value="item.intrastat.id"
@ -104,11 +122,23 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
:value="item.intrastat.description"
/>
<VnLv :label="t('item.summary.ref')" :value="item.comment" />
<VnLv :label="t('item.summary.relevance')" :value="item.relevancy" />
<VnLv :label="t('item.summary.weight')" :value="item.weightByPiece" />
<VnLv
:label="t('item.summary.relevance')"
:value="item.relevancy"
/>
<VnLv
:label="t('item.summary.weight')"
:value="item.weightByPiece"
/>
<VnLv :label="t('item.summary.units')" :value="item.packingOut" />
<VnLv :label="t('item.summary.expense')" :value="item.expense.name" />
<VnLv :label="t('item.summary.generic')" :value="item.genericFk" />
<VnLv
:label="t('item.summary.expense')"
:value="item.expense.name"
/>
<VnLv
:label="t('item.summary.generic')"
:value="item.genericFk"
/>
<VnLv
:label="t('item.summary.recycledPlastic')"
:value="item.recycledPlastic"
@ -117,23 +147,18 @@ const getUrl = (id, param) => `#/Item/${id}/${param}`;
:label="t('item.summary.nonRecycledPlastic')"
:value="item.nonRecycledPlastic"
/>
</div>
</div>
</QCard>
<QCard class="vn-one">
<VnTitle :url="getUrl(entityId, 'tags')" :text="t('globals.tags')" />
<VnLv
v-for="(tag, index) in tags"
:key="index"
:label="`${tag.priority} ${tag.tag.name}:`"
:label="`${tag.priority} ${tag.tag.name}`"
:value="tag.value"
/>
</QCard>
<QCard class="vn-one" v-if="item.description">
<VnTitle
:url="getUrl(entityId, 'basic-data')"
:text="t('globals.description')"
/>
<p v-text="item.description" />
</QCard>
<QCard class="vn-one">
<VnTitle :url="getUrl(entityId, 'tax')" :text="t('item.summary.tax')" />
<VnLv

View File

@ -76,15 +76,7 @@ const insertTag = (rows) => {
model="ItemTags"
url="ItemTags"
:data-required="{
$index: undefined,
itemFk: route.params.id,
priority: undefined,
tag: {
isFree: undefined,
value: undefined,
name: undefined,
},
tagFk: undefined,
}"
:default-remove="false"
:user-filter="{
@ -106,7 +98,7 @@ const insertTag = (rows) => {
<VnRow
v-for="(row, index) in rows"
:key="index"
class="items-center"
class="items-center q-py-sm"
>
<VnSelect
:label="t('itemTags.tag')"
@ -132,9 +124,7 @@ const insertTag = (rows) => {
emit-value
use-input
class="col"
:is-clearable="false"
:required="false"
:rules="validate('itemTag.tagFk')"
:use-like="false"
sort-by="value"
/>
@ -145,7 +135,6 @@ const insertTag = (rows) => {
v-model="row.value"
:label="t('itemTags.value')"
:is-clearable="false"
@keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
:data-cy="`tag${row?.tag?.name}Value`"
/>
<VnInput
@ -154,7 +143,7 @@ const insertTag = (rows) => {
v-model="row.priority"
:required="true"
:rules="validate('itemTag.priority')"
@keyup.enter.stop="(data) => itemTagsRef.onSubmit(data)"
style="max-width: 60%"
/>
<div class="row justify-center" style="flex: 0">
<QIcon
@ -181,11 +170,8 @@ const insertTag = (rows) => {
v-shortcut="'+'"
fab
data-cy="createNewTag"
>
<QTooltip>
{{ t('itemTags.addTag') }}
</QTooltip>
</QBtn>
:title="t('globals.add')"
/>
</QPageSticky>
</template>
</CrudModel>

View File

@ -64,6 +64,7 @@ const submitTaxes = async (data) => {
auto-load
>
<template #body="{ rows }">
<div style="display: flex; justify-content: center">
<QCard class="q-px-lg q-py-md">
<VnRow
v-for="(row, index) in rows"
@ -85,6 +86,7 @@ const submitTaxes = async (data) => {
/>
</VnRow>
</QCard>
</div>
</template>
</CrudModel>
</template>

View File

@ -1,7 +1,6 @@
<script setup>
import { ref, computed, onBeforeMount } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import VnImg from 'src/components/ui/VnImg.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import { toDate } from 'src/filters';
@ -18,17 +17,13 @@ import VnSelect from 'src/components/common/VnSelect.vue';
import axios from 'axios';
import VnSection from 'src/components/common/VnSection.vue';
const entityId = computed(() => route.params.id);
const { openCloneDialog } = cloneItem();
const { viewSummary } = useSummaryDialog();
const { t } = useI18n();
const tableRef = ref();
const route = useRoute();
const dataKey = 'ItemList';
const validPriorities = ref([]);
const defaultTag = ref();
const defaultPriority = ref();
const defaultItem = ref();
const defaultItem = ref(null);
const itemFilter = {
include: [
@ -305,9 +300,7 @@ const columns = computed(() => [
onBeforeMount(async () => {
const { data } = await axios.get('ItemConfigs/findOne');
defaultItem.value = data;
console.log('defaultItem.value: ', defaultItem.value);
});
const dafaultComputed = computed(() => defaultItem.value);
</script>
<template>
<VnSection
@ -325,6 +318,7 @@ const dafaultComputed = computed(() => defaultItem.value);
</template>
<template #body>
<VnTable
v-if="defaultItem"
:data-key="dataKey"
ref="tableRef"
search-url="ItemList"
@ -335,8 +329,8 @@ const dafaultComputed = computed(() => defaultItem.value);
title: t('item.list.newItem'),
onDataSaved: ({ id }) => tableRef.redirect(`${id}/basic-data`),
formInitialData: {
tag: 1,
priority: 1,
tag: defaultItem?.defaultTag,
priority: defaultItem?.defaultPriority,
},
}"
:columns="columns"
@ -380,7 +374,6 @@ const dafaultComputed = computed(() => defaultItem.value);
</span>
</template>
<template #more-create-dialog="{ data }">
{{ data }}
<VnInput
v-model="data.provisionalName"
:label="t('Provisional name')"
@ -388,7 +381,7 @@ const dafaultComputed = computed(() => defaultItem.value);
/>
<VnSelect
url="Tags"
v-model="data.defaultTag"
v-model="data.tag"
:label="t('globals.tag')"
:fields="['id', 'name']"
option-label="name"
@ -487,8 +480,5 @@ const dafaultComputed = computed(() => defaultItem.value);
</style>
<i18n>
es:
New item: Nuevo artículo
Create Item: Crear artículo
You can search by id: Puedes buscar por id
Provisional name: Nombre provisional
</i18n>

View File

@ -7,7 +7,7 @@ import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
import { useArrayData } from 'composables/useArrayData';
import { useValidator } from 'src/composables/useValidator';
import axios from 'axios';

View File

@ -99,9 +99,6 @@ item:
concept: Concept
denyOptions: Deny
scopeDays: Scope days
searchbar:
label: Search item
info: You can search by id
descriptor:
item: Item
buyer: Buyer
@ -158,6 +155,7 @@ item:
isPhotoRequestedTooltip: This item does need a photo
isCustomInspectionRequired: Needs physical inspection (PIF)
description: Description
fotoMotivation: Comment for the photographer
fixedPrice:
itemFk: Item ID
groupingPrice: Grouping price
@ -216,7 +214,7 @@ item:
genus: Genus
specie: Specie
search: 'Search item'
searchInfo: 'You can search by id'
searchInfo: 'You can search by id or barcode'
regularizeStock: Regularize stock
itemProposal: Items proposal
proposal:

View File

@ -148,15 +148,16 @@ item:
weightByPiece: Peso (gramos)/tallo
boxUnits: Unidades/caja
recycledPlastic: Plastico reciclado
nonRecycledPlastic: Plático no reciclado
nonRecycledPlastic: Plástico no reciclado
isActive: Activo
hasKgPrice: Precio en kg
isFragile: Frágil
isFragileTooltip: Se muestra en la web, app que este artículo no puede viajar (coronas, palmas, ...)
isPhotoRequested: Hacer foto
isPhotoRequestedTooltip: Este artículo necesita una foto
isCustomInspectionRequired: Necesita inspección física (PIF)
isCustomInspectionRequired: Necesita insp. física (PIF)
description: Descripción
photoMotivation: Comentario para el fotógrafo
fixedPrice:
itemFk: ID Artículo
groupingPrice: Precio grouping
@ -203,6 +204,8 @@ item:
minSalesQuantity: Cantidad mínima de venta
genus: Genus
specie: Specie
search: 'Buscar artículo'
searchInfo: 'Puedes buscar por id de artículo o código de barras'
regularizeStock: Regularizar stock
buyRequest:
ticketId: 'ID Ticket'

View File

@ -203,19 +203,6 @@ export default {
},
component: () => import('src/pages/Item/ItemRequest.vue'),
},
{
path: 'waste-breakdown',
name: 'WasteBreakdown',
meta: {
title: 'wasteBreakdown',
icon: 'vn:claims',
},
beforeEnter: (to, from, next) => {
next({ name: 'ItemList' });
window.location.href =
'https://grafana.verdnatura.es/d/TTNXQAxVk';
},
},
{
path: 'fixed-price',
name: 'ItemFixedPrice',