feat: refs #6897 add tabs and string checkbox
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Pablo Natek 2024-10-26 10:02:12 +02:00
parent 54ace8c682
commit 11e570360d
8 changed files with 245 additions and 215 deletions

View File

@ -8,7 +8,6 @@ const props = defineProps({
validator: (value) => value.length <= 3,
},
});
const sectionHeight = computed(() => `${100 / props.colors.length}%`);
</script>
<template>
<div class="color-div">
@ -17,18 +16,16 @@ const sectionHeight = computed(() => `${100 / props.colors.length}%`);
:key="index"
:style="{
backgroundColor: color,
height: sectionHeight,
width: '100%',
flexShrink: 0,
height: '10px',
}"
/>
>
&nbsp;
</div>
</div>
</template>
<style scoped>
.color-div {
display: flex;
flex-direction: column;
height: 100vh;
width: 100%;
}
</style>

View File

@ -327,7 +327,6 @@ const editingRow = ref(null);
const editingField = ref(null);
const handleClick = (event) => {
console.log('event: ', event);
const clickedElement = event.target.closest('td');
if (!clickedElement) return;
@ -341,7 +340,6 @@ const handleClick = (event) => {
};
const vnEditableCell = ref(null);
const startEditing = async (rowId, field) => {
console.log('entrando a startEditing');
const col = $props.columns.find((col) => col.name === field);
if (col?.isEditable === false) return;
editingRow.value = rowId;
@ -359,48 +357,23 @@ const stopEditing = (rowIndex, field) => {
editingField.value = null;
};
const findNextEditableColumnIndex = (columns, startIndex) => {
let index = startIndex;
console.log('columns: ', columns);
console.log('index: ', index);
console.log(
'columns[index]?.isVisible === false || columns[index]?.isEditable === false: ',
columns[index]?.isVisible === false || columns[index]?.isEditable === false
);
while (columns[index]?.isVisible === false && columns[index]?.isEditable === false) {
index++;
if (index >= columns.length) {
index = 0;
}
if (index === startIndex) {
return -1;
}
}
console.log('index: ', index);
return index;
};
const handleTab = async (rowIndex, colName) => {
console.log('colName: ', colName);
console.log('rowIndex: ', rowIndex);
const columns = $props.columns;
console.log('columns: ', columns);
if (!Array.isArray(columns) || columns.length === 0) return;
let currentColumnIndex = columns.findIndex((col) => col.name === colName);
if (currentColumnIndex === -1) return;
currentColumnIndex++;
if (currentColumnIndex >= columns.length) {
currentColumnIndex = 0;
rowIndex++;
let newColumnIndex = currentColumnIndex + 1;
while (
columns[newColumnIndex]?.visible === false ||
columns[newColumnIndex]?.isEditable === false ||
!columns[newColumnIndex]?.component
) {
newColumnIndex++;
if (newColumnIndex >= columns.length) newColumnIndex = 0;
}
currentColumnIndex = findNextEditableColumnIndex(columns, currentColumnIndex);
if (currentColumnIndex === -1) return;
if (currentColumnIndex >= newColumnIndex) rowIndex++;
await startEditing(rowIndex, columns[currentColumnIndex].name);
await startEditing(rowIndex, columns[newColumnIndex].name);
};
const handleShiftTab = async (rowIndex, colName) => {
@ -438,19 +411,25 @@ const handleShiftTab = async (rowIndex, colName) => {
await startEditing(prevRowIndex, columns[prevColumnIndex]?.name);
console.log('finishHandleShiftTab');
};
const handleTabKey = async (event, rowIndex, colName) => {
console.log('colName: ', colName);
console.log('rowIndex: ', rowIndex);
console.log('event: ', event);
if (event.shiftKey) await handleShiftTab(rowIndex, colName);
else await handleTab(rowIndex, colName);
};
function getCheckboxIcon(value) {
switch (value) {
case true:
return 'check';
case false:
return 'close';
switch (typeof value) {
case 'boolean':
return value ? 'check' : 'close';
case 'string':
return value.toLowerCase() === 'partial'
? 'indeterminate_check_box'
: 'unknown_med';
case 'number':
return value > 0 ? 'check' : 'close';
case 'object':
return value === null ? 'help_outline' : 'unknown_med';
case 'undefined':
return 'help_outline';
default:
return 'unknown_med';
}
@ -458,7 +437,7 @@ function getCheckboxIcon(value) {
function shouldDisplayReadonly(col, rowIndex) {
return (
col?.isEditable === false ||
!col?.component ||
editingRow.value !== rowIndex ||
editingField.value !== col?.name
);
@ -549,7 +528,11 @@ function shouldDisplayReadonly(col, rowIndex) {
<template #body="{ rows }">
<QTable
v-bind="table"
:class="['vnTable', table ? 'selection-cell' : '']"
:class="[
'vnTable',
table ? 'selection-cell' : '',
$props.footer ? 'last-row-sticky' : '',
]"
wrap-cells
:columns="splittedColumns.columns"
:rows="rows"
@ -571,12 +554,6 @@ function shouldDisplayReadonly(col, rowIndex) {
@click="handleClick"
>
<template #top-left v-if="!$props.withoutHeader">
<QIcon
v-if="$props.isEditable"
name="edit"
color="primary"
size="sm"
/>
<slot name="top-left"> </slot>
</template>
<template #top-right v-if="!$props.withoutHeader">
@ -667,7 +644,6 @@ function shouldDisplayReadonly(col, rowIndex) {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
vertical-align: middle;
"
>
<slot
@ -682,15 +658,18 @@ function shouldDisplayReadonly(col, rowIndex) {
style="color: var(--vn-text-color)"
size="var(--font-size)"
:class="
isEditable && (col?.isEditable ?? 'editable-text')
isEditable &&
(col?.component ? 'editable-text' : '')
"
/>
<span
v-else
:class="
isEditable && (col?.isEditable ?? 'editable-text')
isEditable &&
(col?.component ? 'editable-text' : '')
"
:style="col?.style ? col.style(row) : null"
style="bottom: 0"
>
{{
col?.format
@ -700,7 +679,7 @@ function shouldDisplayReadonly(col, rowIndex) {
</span>
</slot>
</div>
<div v-else-if="isEditable">
<div v-else>
<VnTableColumn
ref="vnEditableCell"
:column="col"
@ -1073,6 +1052,9 @@ es:
table tbody th {
position: relative;
}
}
.last-row-sticky {
tbody:nth-last-child(1) {
@extend .bg-header;
position: sticky;

View File

@ -88,28 +88,28 @@ const columns = [
width: '35px',
},
{
align: 'center',
label: 'Pack',
name: 'packing',
component: 'number',
width: '35px',
style: (row) => {
if (row.groupingMode === 'grouping') {
if (row.groupingMode === 'grouping')
return { color: 'var(--vn-label-color)' };
}
},
},
{
align: 'center',
label: 'Group',
name: 'grouping',
component: 'number',
width: '35px',
style: (row) => {
if (row.groupingMode === 'packing') {
return { color: 'var(--vn-label-color)' };
}
if (row.groupingMode === 'packing') return { color: 'var(--vn-label-color)' };
},
},
{
align: 'center',
label: t('Quantity'),
name: 'quantity',
component: 'number',
@ -120,18 +120,30 @@ const columns = [
},
},
{
label: t('Amount'),
name: 'amount',
align: 'center',
label: 'Cost.',
name: 'buyingValue',
component: 'number',
width: '50px',
},
{
align: 'center',
label: t('Amount'),
name: 'amount',
width: '50px',
style: () => {
return { color: 'var(--vn-label-color)' };
},
},
{
align: 'center',
label: t('Package'),
name: 'price2',
component: 'number',
width: '35px',
},
{
align: 'center',
label: t('Box'),
name: 'price3',
component: 'number',
@ -144,12 +156,12 @@ const columns = [
component: 'number',
width: '35px',
style: (row) => {
if (row?.hasMinPrice) {
if (row?.hasMinPrice)
return { backgroundColor: 'var(--q-positive)', color: 'black' };
}
},
},
{
align: 'center',
label: t('P.Sen'),
name: 'packingOut',
component: 'number',
@ -163,10 +175,13 @@ const columns = [
width: '55px',
},
{
align: 'center',
label: 'Prod.',
name: 'subName',
component: 'input',
width: '45px',
style: () => {
return { color: 'var(--vn-label-color)' };
},
},
{
align: 'center',
@ -174,13 +189,11 @@ const columns = [
name: 'tags',
width: '120px',
columnSearch: false,
isEditable: false,
},
{
align: 'center',
label: 'Comp.',
name: 'company_name',
component: 'input',
width: '35px',
},
];
@ -195,6 +208,11 @@ onMounted(() => {
data-key="EntryBuys"
:url="`Entries/${route.params.id}/getBuys`"
:disable-option="{ card: true }"
v-model:selected="selectedRows"
:table="{
'row-key': 'id',
selection: 'multiple',
}"
:right-search="false"
:row-click="false"
:columns="columns"
@ -230,7 +248,7 @@ onMounted(() => {
</style>
<i18n>
es:
Article: Artículo
Article: Artículo3
Size: Med.
Sti.: Eti.
Bucket: Cubo

View File

@ -1,11 +1,12 @@
<script setup>
import { ref, computed, watch, onMounted } from 'vue';
import { ref, computed, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import TravelDescriptorProxy from 'src/pages/Travel/Card/TravelDescriptorProxy.vue';
import { useState } from 'src/composables/useState';
import { toDate } from 'src/filters';
@ -101,8 +102,6 @@ const getEntryRedirectionFilter = (entry) => {
const showEntryReport = () => {
openReport(`Entries/${route.params.id}/entry-order-pdf`);
};
watch;
</script>
<template>
@ -122,16 +121,14 @@ watch;
</QItem>
</template>
<template #body="{ entity }">
<VnLv
:label="t('entry.descriptor.agency')"
:value="entity.travel?.agency?.name"
/>
<VnLv :label="t('shipped')" :value="toDate(entity.travel?.shipped)" />
<VnLv :label="t('landed')" :value="toDate(entity.travel?.landed)" />
<VnLv
:label="t('entry.descriptor.warehouseOut')"
:value="entity.travel?.warehouseOut?.name"
/>
<VnLv :label="t('invoiceInFk')" :value="entity?.invoiceInFk" />
<VnLv :label="t('supplierFk')" :value="entity?.supplier?.name" />
<VnLv :label="t('travelFk')" :value="entity.travel?.id">
<template #value>
<span class="link">{{ entity.travel?.agency?.name }}</span>
<TravelDescriptorProxy :id="entity.travel?.id" />
</template>
</VnLv>
</template>
<template #icons>
<QCardActions class="q-gutter-x-md">
@ -204,4 +201,6 @@ es:
Go to module index: Ir al índice del modulo
Inventory entry: Es inventario
Virtual entry: Es una redada
shipped: Enviado
landed: Recibido
</i18n>

View File

@ -184,58 +184,67 @@ const fetchEntryBuys = async () => {
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnLv :label="t('entry.summary.commission')" :value="entry.commission" />
<VnLv
:label="t('entry.summary.currency')"
:value="entry.currency?.name"
/>
<VnLv :label="t('entry.summary.company')" :value="entry.company.code" />
<VnLv :label="t('entry.summary.reference')" :value="entry.reference" />
<VnLv
:label="t('entry.summary.invoiceNumber')"
:value="entry.invoiceNumber"
/>
</QCard>
<QCard class="vn-one">
<router-link
:to="{ name: 'EntryBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnLv :label="t('entry.summary.travelReference')">
<template #value>
<span class="link">
{{ entry.travel.ref }}
<TravelDescriptorProxy :id="entry.travel.id" />
</span>
</template>
</VnLv>
<VnLv
:label="t('entry.summary.travelAgency')"
:value="entry.travel.agency?.name"
/>
<VnLv :label="t('shipped')" :value="toDate(entry.travel.shipped)" />
<VnLv
:label="t('entry.summary.travelWarehouseOut')"
:value="entry.travel.warehouseOut?.name"
/>
<QCheckbox
:label="t('entry.summary.travelDelivered')"
v-model="entry.travel.isDelivered"
:disable="true"
/>
<VnLv :label="t('landed')" :value="toDate(entry.travel.landed)" />
<VnLv
:label="t('entry.summary.travelWarehouseIn')"
:value="entry.travel.warehouseIn?.name"
/>
<QCheckbox
:label="t('entry.summary.travelReceived')"
v-model="entry.travel.isReceived"
:disable="true"
/>
<div class="card-group">
<div class="card-content">
<VnLv
:label="t('entry.summary.commission')"
:value="entry.commission"
/>
<VnLv
:label="t('entry.summary.currency')"
:value="entry.currency?.name"
/>
<VnLv
:label="t('entry.summary.company')"
:value="entry.company.code"
/>
<VnLv
:label="t('entry.summary.reference')"
:value="entry.reference"
/>
<VnLv
:label="t('entry.summary.invoiceNumber')"
:value="entry.invoiceNumber"
/>
</div>
<div class="card-content">
<VnLv :label="t('entry.summary.travelReference')">
<template #value>
<span class="link">
{{ entry.travel.ref }}
<TravelDescriptorProxy :id="entry.travel.id" />
</span>
</template>
</VnLv>
<VnLv
:label="t('entry.summary.travelAgency')"
:value="entry.travel.agency?.name"
/>
<VnLv
:label="t('shipped')"
:value="toDate(entry.travel.shipped)"
/>
<VnLv
:label="t('entry.summary.travelWarehouseOut')"
:value="entry.travel.warehouseOut?.name"
/>
<VnLv :label="t('landed')" :value="toDate(entry.travel.landed)" />
<VnLv
:label="t('entry.summary.travelWarehouseIn')"
:value="entry.travel.warehouseIn?.name"
/>
<QCheckbox
:label="t('entry.summary.travelDelivered')"
v-model="entry.travel.isDelivered"
:disable="true"
/>
<QCheckbox
:label="t('entry.summary.travelReceived')"
v-model="entry.travel.isReceived"
:disable="true"
/>
</div>
</div>
</QCard>
<QCard class="vn-one">
<router-link
@ -279,6 +288,24 @@ const fetchEntryBuys = async () => {
.separation-row {
background-color: var(--vn-section-color) !important;
}
.card-group {
display: flex;
flex-direction: column;
}
.card-content {
margin-bottom: 16px; /* Para dar espacio entre las secciones */
}
@media (min-width: 1010px) {
.card-group {
flex-direction: row; /* Coloca los contenidos en fila cuando el ancho es mayor a 600px */
}
.card-content {
flex: 1; /* Haz que las secciones ocupen el mismo espacio */
margin-right: 16px; /* Espaciado entre las dos primeras tarjetas */
}
}
</style>
<i18n>

View File

@ -69,8 +69,9 @@ const columns = computed(() => [
format: (row) => row?.name,
},
{
align: 'left',
align: 'center',
name: 'isConfirmed',
component: 'checkbox',
label: t('module.isConfirmed'),
},
{
@ -93,7 +94,9 @@ const columns = computed(() => [
columnField: {
component: null,
},
style: 'color="positive"',
style: () => {
return { color: 'positive' };
},
},
{
align: 'left',

View File

@ -3,7 +3,7 @@ import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useQuasar } from 'quasar';
import { toDate } from 'src/filters';
import { toDate, toHour } from 'src/filters';
import { useRouter } from 'vue-router';
import { usePrintService } from 'src/composables/usePrintService';
@ -38,7 +38,7 @@ const routeFilter = {
};
const columns = computed(() => [
{
align: 'left',
align: 'center',
name: 'id',
label: 'Id',
chip: {
@ -48,7 +48,7 @@ const columns = computed(() => [
columnFilter: false,
},
{
align: 'left',
align: 'center',
name: 'workerFk',
label: t('route.Worker'),
create: true,
@ -71,7 +71,7 @@ const columns = computed(() => [
format: (row, dashIfEmpty) => dashIfEmpty(row.travelRef),
},
{
align: 'left',
align: 'center',
name: 'agencyModeFk',
label: t('route.Agency'),
isTitle: true,
@ -89,7 +89,7 @@ const columns = computed(() => [
columnClass: 'expand',
},
{
align: 'left',
align: 'center',
name: 'vehicleFk',
label: t('route.Vehicle'),
cardVisible: true,
@ -110,27 +110,27 @@ const columns = computed(() => [
},
},
{
align: 'left',
align: 'center',
name: 'created',
label: t('route.Date'),
columnFilter: false,
cardVisible: true,
create: true,
component: 'date',
format: ({ date }) => toDate(date),
format: ({ created }) => toDate(created),
},
{
align: 'left',
align: 'center',
name: 'from',
label: t('route.From'),
visible: false,
cardVisible: true,
create: true,
component: 'date',
format: ({ date }) => toDate(date),
format: ({ from }) => toDate(from),
},
{
align: 'left',
align: 'center',
name: 'to',
label: t('route.To'),
visible: false,
@ -147,18 +147,20 @@ const columns = computed(() => [
columnClass: 'shrink',
},
{
align: 'left',
align: 'center',
name: 'started',
label: t('route.hourStarted'),
component: 'time',
columnFilter: false,
format: ({ hourStarted }) => toHour(hourStarted),
},
{
align: 'left',
align: 'center',
name: 'finished',
label: t('route.hourFinished'),
component: 'time',
columnFilter: false,
format: ({ hourFinished }) => toHour(hourFinished),
},
{
align: 'center',
@ -177,7 +179,7 @@ const columns = computed(() => [
visible: false,
},
{
align: 'left',
align: 'center',
name: 'description',
label: t('route.Description'),
isTitle: true,
@ -186,7 +188,7 @@ const columns = computed(() => [
field: 'description',
},
{
align: 'left',
align: 'center',
name: 'isOk',
label: t('route.Served'),
component: 'checkbox',
@ -301,60 +303,62 @@ const openTicketsDialog = (id) => {
<RouteFilter data-key="RouteList" />
</template>
</RightMenu>
<VnTable
class="route-list"
ref="tableRef"
data-key="RouteList"
url="Routes/filter"
:columns="columns"
:right-search="false"
:is-editable="true"
:filter="routeFilter"
redirect="route"
:row-click="false"
:create="{
urlCreate: 'Routes',
title: t('route.createRoute'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
save-url="Routes/crud"
:disable-option="{ card: true }"
table-height="85vh"
v-model:selected="selectedRows"
:table="{
'row-key': 'id',
selection: 'multiple',
}"
>
<template #moreBeforeActions>
<QBtn
icon="vn:clone"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="confirmationDialog = true"
>
<QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
</QBtn>
<QBtn
icon="cloud_download"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="showRouteReport"
>
<QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
</QBtn>
<QBtn
icon="check"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="markAsServed()"
>
<QTooltip>{{ t('route.Mark as served') }}</QTooltip>
</QBtn>
</template>
</VnTable>
<QPage class="q-px-md">
<VnTable
class="route-list"
ref="tableRef"
data-key="RouteList"
url="Routes/filter"
:columns="columns"
:right-search="false"
:is-editable="true"
:filter="routeFilter"
redirect="route"
:row-click="false"
:create="{
urlCreate: 'Routes',
title: t('route.createRoute'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {},
}"
save-url="Routes/crud"
:disable-option="{ card: true }"
table-height="85vh"
v-model:selected="selectedRows"
:table="{
'row-key': 'id',
selection: 'multiple',
}"
>
<template #moreBeforeActions>
<QBtn
icon="vn:clone"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="confirmationDialog = true"
>
<QTooltip>{{ t('route.Clone Selected Routes') }}</QTooltip>
</QBtn>
<QBtn
icon="cloud_download"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="showRouteReport"
>
<QTooltip>{{ t('route.Download selected routes as PDF') }}</QTooltip>
</QBtn>
<QBtn
icon="check"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="markAsServed()"
>
<QTooltip>{{ t('route.Mark as served') }}</QTooltip>
</QBtn>
</template>
</VnTable>
</QPage>
</template>

View File

@ -252,7 +252,7 @@ const getLink = (param) => `#/travel/${entityId.value}/${param}`;
data-key="TravelSummary"
>
<template #header>
<span>{{ travel.ref }} - {{ travel.id }}</span>
<span>{{ travel.id }} - {{ travel.ref }}</span>
</template>
<template #body>