0
0
Fork 0

Merge branch 'dev' into 6897-entryMigration2

This commit is contained in:
Carlos Satorres 2024-07-03 10:02:28 +00:00
commit 885decc700
59 changed files with 549 additions and 755 deletions

View File

@ -10,6 +10,7 @@ import VnPaginate from 'components/ui/VnPaginate.vue';
import VnConfirm from 'components/ui/VnConfirm.vue'; import VnConfirm from 'components/ui/VnConfirm.vue';
import SkeletonTable from 'components/ui/SkeletonTable.vue'; import SkeletonTable from 'components/ui/SkeletonTable.vue';
import { tMobile } from 'src/composables/tMobile'; import { tMobile } from 'src/composables/tMobile';
import VnSubToolbar from './ui/VnSubToolbar.vue';
const { push } = useRouter(); const { push } = useRouter();
const quasar = useQuasar(); const quasar = useQuasar();
@ -67,7 +68,7 @@ const $props = defineProps({
default: '', default: '',
description: 'It is used for redirect on click "save and continue"', description: 'It is used for redirect on click "save and continue"',
}, },
hasSubtoolbar: { hasSubToolbar: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
@ -313,8 +314,11 @@ watch(formUrl, async () => {
></slot> ></slot>
</template> </template>
</VnPaginate> </VnPaginate>
<SkeletonTable v-if="!formData" :columns="$attrs.columns?.length" /> <SkeletonTable
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown() && hasSubtoolbar"> v-if="!formData && $attrs.autoLoad"
:columns="$attrs.columns?.length"
/>
<Teleport to="#st-actions" v-if="stateStore?.isSubToolbarShown() && hasSubToolbar">
<QBtnGroup push style="column-gap: 10px"> <QBtnGroup push style="column-gap: 10px">
<slot name="moreBeforeActions" /> <slot name="moreBeforeActions" />
<QBtn <QBtn

View File

@ -21,7 +21,7 @@ const itemComputed = computed(() => {
</script> </script>
<template> <template>
<QItem <QItem
active-class="bg-hover" active-class="bg-vn-hover"
class="min-height" class="min-height"
:to="{ name: itemComputed.name }" :to="{ name: itemComputed.name }"
clickable clickable

View File

@ -138,7 +138,7 @@ const col = computed(() => {
const components = computed(() => $props.components ?? defaultComponents); const components = computed(() => $props.components ?? defaultComponents);
</script> </script>
<template> <template>
<div class="row no-wrap fit"> <div class="row no-wrap">
<VnComponent <VnComponent
v-if="col.before" v-if="col.before"
:prop="col.before" :prop="col.before"

View File

@ -59,10 +59,14 @@ const $props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
hasSubtoolbar: { hasSubToolbar: {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
disableOption: {
type: Object,
default: () => ({ card: false, table: false }),
},
}); });
const { t } = useI18n(); const { t } = useI18n();
const stateStore = useStateStore(); const stateStore = useStateStore();
@ -84,11 +88,13 @@ const tableModes = [
icon: 'view_column', icon: 'view_column',
title: t('table view'), title: t('table view'),
value: TABLE_MODE, value: TABLE_MODE,
disable: $props.disableOption?.table,
}, },
{ {
icon: 'grid_view', icon: 'grid_view',
title: t('grid view'), title: t('grid view'),
value: DEFAULT_MODE, value: DEFAULT_MODE,
disable: $props.disableOption?.card,
}, },
]; ];
@ -232,7 +238,7 @@ defineExpose({
:search-url="searchUrl" :search-url="searchUrl"
:disable-infinite-scroll="mode == TABLE_MODE" :disable-infinite-scroll="mode == TABLE_MODE"
@save-changes="reload" @save-changes="reload"
:has-subtoolbar="$attrs['hasSubtoolbar'] ?? isEditable" :has-sub-toolbar="$attrs['hasSubToolbar'] ?? isEditable"
> >
<template <template
v-for="(_, slotName) in $slots" v-for="(_, slotName) in $slots"
@ -418,9 +424,9 @@ defineExpose({
> >
<VnLv <VnLv
:label=" :label="
!col.component && !col.component && col.label
col.label && ? `${col.label}:`
`${col.label}:` : ''
" "
> >
<template #value> <template #value>

View File

@ -12,7 +12,7 @@ const $props = defineProps({
default: () => {}, default: () => {},
}, },
value: { value: {
type: [Object, Number, String], type: [Object, Number, String, Boolean],
default: () => {}, default: () => {},
}, },
}); });

View File

@ -49,6 +49,7 @@ const filter = {
'changedModelId', 'changedModelId',
'changedModelValue', 'changedModelValue',
'description', 'description',
'summaryId',
], ],
include: [ include: [
{ {
@ -459,12 +460,12 @@ onUnmounted(() => {
:style="{ :style="{
backgroundColor: useColor(modelLog.model), backgroundColor: useColor(modelLog.model),
}" }"
:title="modelLog.model" :title="`${modelLog.model} #${modelLog.id}`"
> >
{{ t(modelLog.modelI18n) }} {{ t(modelLog.modelI18n) }}
</QChip> </QChip>
<span class="model-id" v-if="modelLog.id" <span class="model-id" v-if="modelLog.summaryId"
>#{{ modelLog.id }}</span >#{{ modelLog.summaryId }}</span
> >
<span class="model-value" :title="modelLog.showValue"> <span class="model-value" :title="modelLog.showValue">
{{ modelLog.showValue }} {{ modelLog.showValue }}

View File

@ -93,13 +93,36 @@ function getValueFromPath(path) {
} }
const emit = defineEmits(['onFetch']); const emit = defineEmits(['onFetch']);
const iconModule = computed(() => route.matched[1].meta.icon);
const toModule = computed(() =>
route.matched[1].path.split('/').length > 2
? route.matched[1].redirect
: route.matched[1].children[0].redirect
);
</script> </script>
<template> <template>
<div class="descriptor"> <div class="descriptor">
<template v-if="entity && !isLoading"> <template v-if="entity && !isLoading">
<div class="header bg-primary q-pa-sm justify-between"> <div class="header bg-primary q-pa-sm justify-between">
<slot name="header-extra-action" /> <slot name="header-extra-action"
><QBtn
round
flat
dense
size="md"
:icon="iconModule"
color="white"
class="link"
:to="toModule"
>
<QTooltip>
{{ t('globals.goToModuleIndex') }}
</QTooltip>
</QBtn></slot
>
<QBtn <QBtn
@click.stop="viewSummary(entity.id, $props.summary)" @click.stop="viewSummary(entity.id, $props.summary)"
round round

View File

@ -1,6 +1,7 @@
<script setup> <script setup>
import { onMounted, onUnmounted, ref } from 'vue'; import { onMounted, onBeforeUnmount, ref, nextTick } from 'vue';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
const stateStore = useStateStore(); const stateStore = useStateStore();
const actions = ref(null); const actions = ref(null);
const data = ref(null); const data = ref(null);
@ -24,9 +25,7 @@ onMounted(() => {
if (data.value) observer.observe(data.value, opts); if (data.value) observer.observe(data.value, opts);
}); });
onUnmounted(() => { onBeforeUnmount(() => stateStore.toggleSubToolbar());
stateStore.toggleSubToolbar();
});
</script> </script>
<template> <template>

View File

@ -19,7 +19,6 @@ export function useArrayData(key = useRoute().meta.moduleName, userOptions) {
onMounted(() => { onMounted(() => {
setOptions(); setOptions();
store.skip = 0; store.skip = 0;
const query = route.query; const query = route.query;
const searchUrl = store.searchUrl; const searchUrl = store.searchUrl;
if (query[searchUrl]) { if (query[searchUrl]) {

View File

@ -5,6 +5,7 @@
body.body--light { body.body--light {
--font-color: black; --font-color: black;
--vn-section-color: #e0e0e0; --vn-section-color: #e0e0e0;
--vn-section-hover-color: #b9b9b9;
--vn-page-color: #ffffff; --vn-page-color: #ffffff;
--vn-text-color: var(--font-color); --vn-text-color: var(--font-color);
--vn-label-color: #5f5f5f; --vn-label-color: #5f5f5f;
@ -19,6 +20,7 @@ body.body--light {
body.body--dark { body.body--dark {
--vn-page-color: #222; --vn-page-color: #222;
--vn-section-color: #3d3d3d; --vn-section-color: #3d3d3d;
--vn-section-hover-color: #747474;
--vn-text-color: white; --vn-text-color: white;
--vn-label-color: #a8a8a8; --vn-label-color: #a8a8a8;
--vn-accent-color: #424242; --vn-accent-color: #424242;
@ -71,8 +73,9 @@ select:-webkit-autofill {
.bg-vn-section-color { .bg-vn-section-color {
background-color: var(--vn-section-color); background-color: var(--vn-section-color);
} }
.bg-hover {
background-color: #666666; .bg-vn-hover {
background-color: var(--vn-section-hover-color);
} }
.color-vn-label { .color-vn-label {
@ -183,8 +186,6 @@ select:-webkit-autofill {
justify-content: center; justify-content: center;
} }
/* q-notification row items-stretch q-notification--standard bg-negative text-white */
.q-card, .q-card,
.q-table, .q-table,
.q-table__bottom, .q-table__bottom,

View File

@ -90,6 +90,7 @@ globals:
send: Send send: Send
code: Code code: Code
pageTitles: pageTitles:
logIn: Login
summary: Summary summary: Summary
basicData: Basic data basicData: Basic data
log: Logs log: Logs
@ -244,6 +245,7 @@ globals:
new: New new: New
comment: Comment comment: Comment
observations: Observations observations: Observations
goToModuleIndex: Go to module index
errors: errors:
statusUnauthorized: Access denied statusUnauthorized: Access denied
statusInternalServerError: An internal server error has ocurred statusInternalServerError: An internal server error has ocurred
@ -262,8 +264,6 @@ login:
loginError: Invalid username or password loginError: Invalid username or password
fieldRequired: This field is required fieldRequired: This field is required
twoFactorRequired: Two-factor verification required twoFactorRequired: Two-factor verification required
pageTitles:
logIn: Login
twoFactor: twoFactor:
code: Code code: Code
validate: Validate validate: Validate
@ -1026,6 +1026,19 @@ wagon:
maxWagonHeight: 'The maximum height of the wagon is ' maxWagonHeight: 'The maximum height of the wagon is '
uncompleteTrays: There are incomplete trays uncompleteTrays: There are incomplete trays
route: route:
pageTitles:
agency: Agency List
routes: Routes
cmrsList: CMRs list
RouteList: List
routeCreate: New route
basicData: Basic Data
summary: Summary
RouteRoadmap: Roadmaps
RouteRoadmapCreate: Create roadmap
tickets: Tickets
log: Log
autonomous: Autonomous
cmr: cmr:
list: list:
results: results results: results
@ -1144,6 +1157,16 @@ supplier:
date: Date date: Date
reference: Reference reference: Reference
travel: travel:
travelList:
tableVisibleColumns:
id: Id
ref: Reference
agency: Agency
shipped: Shipped
landed: Landed
warehouseIn: Warehouse in
warehouseOut: Warehouse out
totalEntries: Total entries
summary: summary:
confirmed: Confirmed confirmed: Confirmed
entryId: Entry Id entryId: Entry Id

View File

@ -90,6 +90,7 @@ globals:
send: Enviar send: Enviar
code: Código code: Código
pageTitles: pageTitles:
logIn: Inicio de sesión
summary: Resumen summary: Resumen
basicData: Datos básicos basicData: Datos básicos
log: Historial log: Historial
@ -245,6 +246,7 @@ globals:
new: Nuevo new: Nuevo
comment: Comentario comment: Comentario
observations: Observaciones observations: Observaciones
goToModuleIndex: Ir al índice del módulo
errors: errors:
statusUnauthorized: Acceso denegado statusUnauthorized: Acceso denegado
statusInternalServerError: Ha ocurrido un error interno del servidor statusInternalServerError: Ha ocurrido un error interno del servidor
@ -263,8 +265,6 @@ login:
loginError: Nombre de usuario o contraseña incorrectos loginError: Nombre de usuario o contraseña incorrectos
fieldRequired: Este campo es obligatorio fieldRequired: Este campo es obligatorio
twoFactorRequired: Verificación de doble factor requerida twoFactorRequired: Verificación de doble factor requerida
pageTitles:
logIn: Inicio de sesión
twoFactor: twoFactor:
code: Código code: Código
validate: Validar validate: Validar
@ -1016,7 +1016,7 @@ route:
list: list:
results: resultados results: resultados
cmrFk: Id CMR cmrFk: Id CMR
hasCmrDms: Adjuntado en gestdoc hasCmrDms: Gestdoc
'true': 'true':
'false': 'No' 'false': 'No'
ticketFk: Id ticket ticketFk: Id ticket
@ -1130,6 +1130,16 @@ supplier:
date: Fecha date: Fecha
reference: Referencia reference: Referencia
travel: travel:
travelList:
tableVisibleColumns:
id: Id
ref: Referencia
agency: Agencia
shipped: Enviado
landed: Llegada
warehouseIn: Almacén de salida
warehouseOut: Almacén de entrada
totalEntries: Total de entradas
summary: summary:
confirmed: Confirmado confirmed: Confirmado
entryId: Id entrada entryId: Id entrada

View File

@ -49,20 +49,6 @@ const hasAccount = ref(false);
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
> >
<template #header-extra-action>
<QBtn
round
flat
size="md"
color="white"
icon="face"
:to="{ name: 'AccountList' }"
>
<QTooltip>
{{ t('Go to module index') }}
</QTooltip>
</QBtn>
</template>
<template #menu> <template #menu>
<AccountDescriptorMenu :has-account="hasAccount" /> <AccountDescriptorMenu :has-account="hasAccount" />
</template> </template>

View File

@ -1,72 +0,0 @@
<script setup>
import VnPaginate from 'src/components/ui/VnPaginate.vue';
import CardList from 'src/components/ui/CardList.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
const { t } = useI18n();
const router = useRouter();
function navigate(id) {
router.push({ path: `/agency/${id}` });
}
function exprBuilder(param, value) {
if (!value) return;
if (param !== 'search') return;
if (!isNaN(value)) return { id: value };
return { name: { like: `%${value}%` } };
}
</script>
<template>
<VnSearchbar
:info="t('You can search by name')"
:label="t('Search agency')"
data-key="AgencyList"
url="Agencies"
/>
<QPage class="column items-center q-pa-md">
<div class="vn-card-list">
<VnPaginate
data-key="AgencyList"
url="Agencies"
order="name"
:expr-builder="exprBuilder"
>
<template #body="{ rows }">
<CardList
:id="row.id"
:key="row.id"
:title="row.name"
@click="navigate(row.id)"
v-for="row of rows"
>
<template #list-items>
<QCheckbox
:label="t('isOwn')"
v-model="row.isOwn"
:disable="true"
/>
<QCheckbox
:label="t('isAnyVolumeAllowed')"
v-model="row.isAnyVolumeAllowed"
:disable="true"
/>
</template>
</CardList>
</template>
</VnPaginate>
</div>
</QPage>
</template>
<i18n>
es:
isOwn: Tiene propietario
isAnyVolumeAllowed: Permite cualquier volumen
Search agency: Buscar agencia
You can search by name: Puedes buscar por nombre
en:
isOwn: Has owner
isAnyVolumeAllowed: Allows any volume
</i18n>

View File

@ -69,7 +69,7 @@ const filterOptions = {
<template #form="{ data, validate, filter }"> <template #form="{ data, validate, filter }">
<VnRow class="row q-gutter-md q-mb-md"> <VnRow class="row q-gutter-md q-mb-md">
<VnInput <VnInput
:label="t('Comercial name')" :label="t('globals.name')"
:rules="validate('client.socialName')" :rules="validate('client.socialName')"
autofocus autofocus
clearable clearable

View File

@ -45,20 +45,6 @@ const setData = (entity) => (data.value = useCardDescription(entity.name, entity
:summary="$props.summary" :summary="$props.summary"
data-key="customerData" data-key="customerData"
> >
<template #header-extra-action>
<QBtn
round
flat
size="sm"
icon="vn:Person"
color="white"
:to="{ name: 'CustomerList' }"
>
<QTooltip>
{{ t('Go to module index') }}
</QTooltip>
</QBtn>
</template>
<template #menu="{ entity }"> <template #menu="{ entity }">
<CustomerDescriptorMenu :customer="entity" /> <CustomerDescriptorMenu :customer="entity" />
</template> </template>

View File

@ -73,7 +73,7 @@ const creditWarning = computed(() => {
:text="t('customer.summary.basicData')" :text="t('customer.summary.basicData')"
/> />
<VnLv :label="t('customer.summary.customerId')" :value="entity.id" /> <VnLv :label="t('customer.summary.customerId')" :value="entity.id" />
<VnLv :label="t('customer.summary.name')" :value="entity.name" /> <VnLv :label="t('globals.name')" :value="entity.name" />
<VnLv :label="t('customer.summary.contact')" :value="entity.contact" /> <VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
<VnLv :value="entity.phone"> <VnLv :value="entity.phone">
<template #label> <template #label>

View File

@ -38,7 +38,7 @@ const columns = computed(() => [
}, },
{ {
align: 'left', align: 'left',
label: t('customer.extendedList.tableVisibleColumns.name'), label: t('globals.name'),
name: 'name', name: 'name',
isTitle: true, isTitle: true,
create: true, create: true,
@ -408,6 +408,7 @@ function handleLocation(data, location) {
default-mode="table" default-mode="table"
redirect="customer" redirect="customer"
auto-load auto-load
:disable-option="{ card: true }"
> >
<template #more-create-dialog="{ data }"> <template #more-create-dialog="{ data }">
<VnLocation <VnLocation

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import { ref, computed, watch } from 'vue'; import { ref, computed, watch, onMounted } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
@ -10,6 +10,7 @@ import useCardDescription from 'src/composables/useCardDescription';
import { useState } from 'src/composables/useState'; import { useState } from 'src/composables/useState';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import { usePrintService } from 'composables/usePrintService'; import { usePrintService } from 'composables/usePrintService';
import { getUrl } from 'src/composables/getUrl';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -17,10 +18,6 @@ const $props = defineProps({
required: false, required: false,
default: null, default: null,
}, },
summary: {
type: Object,
default: null,
},
}); });
const route = useRoute(); const route = useRoute();
@ -28,6 +25,7 @@ const { t } = useI18n();
const { openReport } = usePrintService(); const { openReport } = usePrintService();
const state = useState(); const state = useState();
const entryDescriptorRef = ref(null); const entryDescriptorRef = ref(null);
const url = ref();
const entryFilter = { const entryFilter = {
include: [ include: [
@ -69,6 +67,9 @@ const entryFilter = {
const entityId = computed(() => { const entityId = computed(() => {
return $props.id || route.params.id; return $props.id || route.params.id;
}); });
onMounted(async () => {
url.value = await getUrl('');
});
const data = ref(useCardDescription()); const data = ref(useCardDescription());
const setData = (entity) => const setData = (entity) =>
@ -114,6 +115,7 @@ watch;
:subtitle="data.subtitle" :subtitle="data.subtitle"
@on-fetch="setData" @on-fetch="setData"
data-key="entry" data-key="entry"
:summary="$attrs"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<QItem v-ripple clickable @click="showEntryReport(entity)"> <QItem v-ripple clickable @click="showEntryReport(entity)">

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import EntryDescriptor from './EntryDescriptor.vue'; import EntryDescriptor from './EntryDescriptor.vue';
import EntrySummary from './EntrySummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -11,6 +12,6 @@ const $props = defineProps({
<template> <template>
<QPopupProxy> <QPopupProxy>
<EntryDescriptor v-if="$props.id" :id="$props.id" /> <EntryDescriptor v-if="$props.id" :id="$props.id" :summary="EntrySummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import InvoiceInDescriptor from "pages/InvoiceIn/Card/InvoiceInDescriptor.vue"; import InvoiceInDescriptor from 'pages/InvoiceIn/Card/InvoiceInDescriptor.vue';
import InvoiceInSummary from './InvoiceInSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -10,6 +11,10 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy>
<InvoiceInDescriptor v-if="$props.id" :id="$props.id" /> <InvoiceInDescriptor
v-if="$props.id"
:id="$props.id"
:summary="InvoiceInSummary"
/>
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -51,20 +51,6 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
@on-fetch="setData" @on-fetch="setData"
data-key="entry" data-key="entry"
> >
<template #header-extra-action>
<QBtn
round
flat
size="sm"
icon="vn:item"
color="white"
:to="{ name: 'ItemTypeList' }"
>
<QTooltip>
{{ t('Go to module index') }}
</QTooltip>
</QBtn>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('shared.code')" :value="entity.code" /> <VnLv :label="t('shared.code')" :value="entity.code" />
<VnLv :label="t('shared.name')" :value="entity.name" /> <VnLv :label="t('shared.name')" :value="entity.name" />

View File

@ -0,0 +1,92 @@
<script setup>
import { computed } from 'vue';
import { useRouter } from 'vue-router';
import { useI18n } from 'vue-i18n';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import VnTable from 'components/VnTable/VnTable.vue';
const { t } = useI18n();
const router = useRouter();
function navigate(id) {
router.push({ path: `/agency/${id}` });
}
const exprBuilder = (param, value) => {
if (!value) return;
if (param !== 'search') return;
if (!isNaN(value)) return { id: value };
return { name: { like: `%${value}%` } };
};
const columns = computed(() => [
{
align: 'left',
name: 'id',
label: 'Id',
chip: {
condition: () => true,
},
isId: true,
},
{
align: 'left',
label: t('globals.name'),
name: 'name',
isTitle: true,
},
{
align: 'left',
label: t('isOwn'),
name: 'isOwn',
component: 'checkbox',
cardVisible: true,
},
{
align: 'left',
label: t('isAnyVolumeAllowed'),
name: 'isAnyVolumeAllowed',
component: 'checkbox',
cardVisible: true,
disable: true,
},
{
align: 'right',
label: '',
name: 'tableActions',
actions: [
{
title: t('Client ticket list'),
icon: 'preview',
action: (row) => navigate(row.id),
},
],
},
]);
</script>
<template>
<VnSearchbar
:info="t('You can search by name')"
:label="t('Search agency')"
data-key="AgencyList"
:expr-builder="exprBuilder"
/>
<VnTable
ref="tableRef"
data-key="AgencyList"
url="Agencies"
order="name"
:columns="columns"
:right-search="false"
:use-model="true"
/>
</template>
<i18n>
es:
isOwn: Tiene propietario
isAnyVolumeAllowed: Permite cualquier volumen
Search agency: Buscar agencia
You can search by name: Puedes buscar por nombre
en:
isOwn: Has owner
isAnyVolumeAllowed: Allows any volume
</i18n>

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
import AgencyDescriptor from 'pages/Agency/Card/AgencyDescriptor.vue'; import AgencyDescriptor from 'pages/Route/Agency/Card/AgencyDescriptor.vue';
import VnCard from 'components/common/VnCard.vue'; import VnCard from 'components/common/VnCard.vue';
</script> </script>
<template> <template>

View File

@ -18,12 +18,10 @@ const entityId = computed(() => $props.id || useRoute().params.id);
<template #header="{ entity: agency }">{{ agency.name }}</template> <template #header="{ entity: agency }">{{ agency.name }}</template>
<template #body="{ entity: agency }"> <template #body="{ entity: agency }">
<QCard class="vn-one"> <QCard class="vn-one">
<QCardSection class="q-pa-none"> <VnTitle
<VnTitle :url="`#/agency/${entityId}/basic-data`"
:url="`#/agency/${entityId}/basic-data`" :text="t('globals.pageTitles.basicData')"
:text="t('globals.pageTitles.basicData')" />
/>
</QCardSection>
<VnLv :label="t('globals.name')" :value="agency.name" /> <VnLv :label="t('globals.name')" :value="agency.name" />
<QCheckbox <QCheckbox
:label="t('agency.isOwn')" :label="t('agency.isOwn')"

View File

@ -74,8 +74,9 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
:filter="filter" :filter="filter"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
data-key="Routes" data-key="routeData"
@on-fetch="setData" @on-fetch="setData"
:summary="$attrs"
> >
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('Date')" :value="toDate(entity?.created)" /> <VnLv :label="t('Date')" :value="toDate(entity?.created)" />

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue'; import RouteDescriptor from 'pages/Route/Card/RouteDescriptor.vue';
import RouteSummary from './RouteSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -10,6 +11,6 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy>
<RouteDescriptor v-if="$props.id" :id="$props.id" /> <RouteDescriptor v-if="$props.id" :id="$props.id" :summary="RouteSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -9,7 +9,6 @@ const { t } = useI18n();
data-key="RouteList" data-key="RouteList"
:label="t('Search route')" :label="t('Search route')"
:info="t('You can search by route reference')" :info="t('You can search by route reference')"
custom-route-redirect-name="RouteList"
/> />
</template> </template>

View File

@ -154,7 +154,7 @@ const warehouses = ref();
es: es:
params: params:
cmrFk: Id cmr cmrFk: Id cmr
hasCmrDms: Adjuntado en gestdoc hasCmrDms: Gestdoc
ticketFk: Id ticket ticketFk: Id ticket
country: País country: País
clientFk: Id cliente clientFk: Id cliente

View File

@ -12,6 +12,8 @@ import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import { useStateStore } from 'src/stores/useStateStore'; import { useStateStore } from 'src/stores/useStateStore';
import VnTable from 'components/VnTable/VnTable.vue';
const { t } = useI18n(); const { t } = useI18n();
const { getTokenMultimedia } = useSession(); const { getTokenMultimedia } = useSession();
const token = getTokenMultimedia(); const token = getTokenMultimedia();
@ -107,88 +109,15 @@ function downloadPdfs() {
} }
</script> </script>
<template> <template>
<RightMenu> <VnTable
<template #right-panel> ref="tableRef"
<CmrFilter data-key="CmrList" /> data-key="CmrList"
</template> url="Routes/cmrs"
</RightMenu> order="cmrFk DESC"
<div class="column items-center"> :columns="columns"
<div class="list"> :right-search="true"
<VnPaginate data-key="CmrList" :url="`Routes/cmrs`" order="cmrFk DESC"> :use-model="true"
<template #body="{ rows }"> />
<QTable
:columns="columns"
:rows="rows"
:dense="$q.screen.lt.md"
row-key="cmrFk"
selection="multiple"
v-model:selected="selected"
:grid="$q.screen.lt.md"
auto-load
>
<template #top>
<div style="width: 100%; display: table">
<div style="float: right; color: lightgray">
{{ `${rows.length} ${t('route.cmr.list.results')}` }}
</div>
</div>
</template>
<template #body-cell-hasCmrDms="{ value }">
<QTd align="center">
<QBadge
text-color="black"
:id="value ? 'true' : 'false'"
:label="
value
? t('route.cmr.list.true')
: t('route.cmr.list.false')
"
/>
</QTd>
</template>
<template #body-cell-ticketFk="{ value }">
<QTd align="right" class="text-primary">
<span class="text-primary link">{{ value }}</span>
<TicketDescriptorProxy :id="value" />
</QTd>
</template>
<template #body-cell-clientFk="{ value }">
<QTd align="right" class="text-primary">
<span class="text-primary link">{{ value }}</span>
<CustomerDescriptorProxy :id="value" />
</QTd>
</template>
<template #body-cell-warehouseFk="{ value }">
<QTd align="center">
{{ warehouses.find(({ id }) => id === value)?.name }}
</QTd>
</template>
<template #body-cell-icons="{ value }">
<QTd align="center">
<a :href="getCmrUrl(value)" target="_blank">
<QIcon
name="visibility"
color="primary"
size="md"
class="q-mr-sm q-ml-sm"
/>
<QTooltip>
{{ t('route.cmr.list.viewCmr') }}
</QTooltip>
</a>
</QTd>
</template>
</QTable>
</template>
</VnPaginate>
</div>
<QPageSticky :offset="[20, 20]">
<QBtn @click="downloadPdfs" fab icon="cloud_download" color="primary" />
<QTooltip>
{{ t('route.cmr.list.downloadCmrs') }}
</QTooltip>
</QPageSticky>
</div>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.list { .list {

View File

@ -1,29 +1,32 @@
<script setup> <script setup>
import { useI18n } from 'vue-i18n'; import { useArrayData } from 'composables/useArrayData';
import { computed, onMounted, ref } from 'vue';
import { dashIfEmpty, toHour } from 'src/filters'; import { dashIfEmpty, toHour } from 'src/filters';
import { computed, onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useValidator } from 'composables/useValidator'; import { useValidator } from 'composables/useValidator';
import { useSession } from 'composables/useSession'; import { useSession } from 'composables/useSession';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { useArrayData } from 'composables/useArrayData';
import { useQuasar } from 'quasar'; import { useQuasar } from 'quasar';
import axios from 'axios'; import axios from 'axios';
import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue'; import RouteSearchbar from 'pages/Route/Card/RouteSearchbar.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import RouteListTicketsDialog from 'pages/Route/Card/RouteListTicketsDialog.vue'; import RouteListTicketsDialog from 'pages/Route/Card/RouteListTicketsDialog.vue';
import { useRouter } from 'vue-router';
import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue'; import RightMenu from 'src/components/common/RightMenu.vue';
import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import VnPaginate from 'components/ui/VnPaginate.vue'; import VnPaginate from 'components/ui/VnPaginate.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInput from 'components/common/VnInput.vue'; import VnInput from 'components/common/VnInput.vue';
import VnInputTime from 'components/common/VnInputTime.vue'; import VnInputTime from 'components/common/VnInputTime.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnSelect from 'components/common/VnSelect.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue'; import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import { useStateStore } from 'src/stores/useStateStore';
const { t } = useI18n(); const { t } = useI18n();
const { validate } = useValidator(); const { validate } = useValidator();
@ -40,90 +43,100 @@ const allColumnNames = ref([]);
const confirmationDialog = ref(false); const confirmationDialog = ref(false);
const startingDate = ref(null); const startingDate = ref(null);
const refreshKey = ref(0); const refreshKey = ref(0);
const router = useRouter();
const stateStore = useStateStore();
const columns = computed(() => [ const columns = computed(() => [
{ {
name: 'Id', align: 'left',
label: t('Id'), name: 'id',
field: (row) => row.id, label: 'Id',
sortable: true, chip: {
align: 'center', condition: () => true,
},
isId: true,
columnFilter: {
name: 'search',
},
}, },
{ {
align: 'left',
name: 'worker', name: 'worker',
label: t('Worker'), label: t('Worker'),
field: (row) => row.workerUserName, create: true,
sortable: true, component: 'select',
align: 'left', attrs: {
url: 'payrollComponents',
fields: ['id', 'name'],
},
cardVisible: true,
}, },
{ {
name: 'agency', name: 'agency',
label: t('Agency'), label: t('Agency'),
field: (row) => row.agencyName,
sortable: true,
align: 'left', align: 'left',
isTitle: true,
cardVisible: true,
create: true,
}, },
{ {
name: 'vehicle', name: 'vehicle',
label: t('Vehicle'), label: t('Vehicle'),
field: (row) => row.vehiclePlateNumber,
sortable: true,
align: 'left', align: 'left',
cardVisible: true,
create: true,
}, },
{ {
name: 'date', name: 'date',
label: t('Date'), label: t('Date'),
field: (row) => row.created,
sortable: true,
align: 'left', align: 'left',
cardVisible: true,
create: true,
}, },
{ {
name: 'volume', name: 'volume',
label: 'm³', label: 'm³',
field: (row) => dashIfEmpty(row.m3),
sortable: true,
align: 'center', align: 'center',
cardVisible: true,
}, },
{ {
name: 'description', name: 'description',
label: t('Description'), label: t('Description'),
field: (row) => row.description,
sortable: true,
align: 'left', align: 'left',
isTitle: true,
create: true,
}, },
{ {
name: 'started', name: 'started',
label: t('hourStarted'), label: t('hourStarted'),
field: (row) => toHour(row.started),
sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'finished', name: 'finished',
label: t('hourFinished'), label: t('hourFinished'),
field: (row) => toHour(row.finished),
sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'isServed', name: 'isServed',
label: t('Served'), label: t('Served'),
field: (row) => Boolean(row.isOk),
sortable: true,
align: 'left', align: 'left',
}, },
{ {
name: 'actions',
label: '',
sortable: false,
align: 'right', align: 'right',
label: 'asdasd',
name: 'tableActions',
actions: [
{
title: t('Client ticket list'),
icon: 'preview',
action: (row) => navigate(row.id),
},
],
}, },
]); ]);
const arrayData = useArrayData('EntryLatestBuys', { function navigate(id) {
url: 'Buys/latestBuysFilter', router.push({ path: `/route/${id}` });
order: ['itemFk DESC'], }
});
const updateRoute = async (route) => { const updateRoute = async (route) => {
try { try {
@ -181,20 +194,10 @@ const openTicketsDialog = (id) => {
}) })
.onOk(() => refreshKey.value++); .onOk(() => refreshKey.value++);
}; };
onMounted(async () => {
allColumnNames.value = columns.value.map((col) => col.name);
await arrayData.fetch({ append: false });
});
</script> </script>
<template> <template>
<RouteSearchbar /> <RouteSearchbar />
<RightMenu>
<template #right-panel>
<RouteFilter data-key="RouteList" />
</template>
</RightMenu>
<QDialog v-model="confirmationDialog"> <QDialog v-model="confirmationDialog">
<QCard style="min-width: 350px"> <QCard style="min-width: 350px">
<QCardSection> <QCardSection>
@ -227,256 +230,53 @@ onMounted(async () => {
/> />
<FetchData url="AgencyModes" @on-fetch="(data) => (agencyList = data)" auto-load /> <FetchData url="AgencyModes" @on-fetch="(data) => (agencyList = data)" auto-load />
<FetchData url="Vehicles" @on-fetch="(data) => (vehicleList = data)" auto-load /> <FetchData url="Vehicles" @on-fetch="(data) => (vehicleList = data)" auto-load />
<QPage class="column items-center"> <VnSubToolbar />
<VnSubToolbar> <VnTable
<template #st-data> ref="tableRef"
<TableVisibleColumns data-key="RouteList"
class="LeftIcon" url="Routes/filter"
:all-columns="allColumnNames" :columns="columns"
table-code="routesList" :right-search="true"
labels-traductions-path="route.columnLabels" default-mode="table"
@on-config-saved="visibleColumns = [...$event]" :is-editable="true"
/> :create="{
</template> urlCreate: 'Routes',
<template #st-actions> title: t('Create route'),
<QBtn onDataSaved: () => tableRef.reload(),
icon="vn:clone" }"
color="primary" save-url="routes"
class="q-mr-sm" :disable-option="{ card: true }"
:disable="!selectedRows?.length" >
@click="confirmationDialog = true" <template #moreBeforeActions>
> <QBtn
<QTooltip>{{ t('Clone Selected Routes') }}</QTooltip> icon="vn:clone"
</QBtn> color="primary"
<QBtn class="q-mr-sm"
icon="cloud_download" :disable="!selectedRows?.length"
color="primary" @click="confirmationDialog = true"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="showRouteReport"
>
<QTooltip>{{ t('Download selected routes as PDF') }}</QTooltip>
</QBtn>
<QBtn
icon="check"
color="primary"
class="q-mr-sm"
:disable="!selectedRows?.length"
@click="markAsServed()"
>
<QTooltip>{{ t('Mark as served') }}</QTooltip>
</QBtn>
</template>
</VnSubToolbar>
<div class="route-list">
<VnPaginate
:key="refreshKey"
data-key="RouteList"
url="Routes/filter"
:order="['created ASC', 'started ASC', 'id ASC']"
:limit="20"
> >
<template #body="{ rows }"> <QTooltip>{{ t('Clone Selected Routes') }}</QTooltip>
<div class="q-pa-md route-table"> </QBtn>
<QTable <QBtn
v-model:selected="selectedRows" icon="cloud_download"
:columns="columns" color="primary"
:rows="rows" class="q-mr-sm"
flat :disable="!selectedRows?.length"
row-key="id" @click="showRouteReport"
selection="multiple" >
:rows-per-page-options="[0]" <QTooltip>{{ t('Download selected routes as PDF') }}</QTooltip>
:visible-columns="visibleColumns" </QBtn>
hide-pagination <QBtn
:no-data-label="t('globals.noResults')" icon="check"
style="max-height: 82vh" color="primary"
> class="q-mr-sm"
<template #body-cell-worker="{ row }"> :disable="!selectedRows?.length"
<QTd class="table-input-cell"> @click="markAsServed()"
<VnSelect >
:label="t('Worker')" <QTooltip>{{ t('Mark as served') }}</QTooltip>
v-model="row.workerFk" </QBtn>
:options="workers" </template>
option-value="id" </VnTable>
option-label="nickname"
hide-selected
dense
:emit-value="false"
:rules="validate('Route.workerFk')"
:is-clearable="false"
@update:model-value="updateRoute(row)"
>
<template #option="{ opt, itemProps }">
<QItem
v-bind="itemProps"
class="q-pa-xs row items-center"
>
<QItemSection
class="col-9 justify-center"
>
<span>{{ opt.name }}</span>
<span class="text-grey">{{
opt.nickname
}}</span>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QTd>
</template>
<template #body-cell-agency="{ row }">
<QTd class="table-input-cell">
<VnSelect
:label="t('Agency')"
v-model="row.agencyModeFk"
:options="agencyList"
option-value="id"
option-label="name"
hide-selected
dense
:emit-value="false"
:rules="validate('route.agencyFk')"
:is-clearable="false"
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-vehicle="{ row }">
<QTd class="table-input-cell small-column">
<VnSelect
:label="t('Vehicle')"
v-model="row.vehicleFk"
:options="vehicleList"
option-value="id"
option-label="numberPlate"
hide-selected
dense
:emit-value="false"
:rules="validate('route.vehicleFk')"
:is-clearable="false"
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-date="{ row }">
<QTd class="table-input-cell small-column">
<VnInputDate
v-model="row.created"
hide-bottom-space
dense
:label="t('Date')"
:rules="validate('route.created')"
:is-clearable="false"
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-description="{ row }">
<QTd class="table-input-cell">
<VnInput
v-model="row.description"
:label="t('Description')"
:rules="validate('route.description')"
:is-clearable="false"
dense
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-started="{ row }">
<QTd class="table-input-cell small-column">
<VnInputTime
v-model="row.started"
:label="t('hourStarted')"
:rules="validate('route.started')"
:is-clearable="false"
hide-bottom-space
dense
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-finished="{ row }">
<QTd class="table-input-cell small-column">
<VnInputTime
v-model="row.finished"
autofocus
:label="t('hourFinished')"
:rules="validate('route.finished')"
:is-clearable="false"
hide-bottom-space
dense
@update:model-value="updateRoute(row)"
/>
</QTd>
</template>
<template #body-cell-isServed="props">
<QTd class="table-input-cell small-column">
<QCheckbox v-model="props.value" disable>
<QTooltip>
{{
props.value
? t('Route is closed')
: t('Route is not served')
}}
</QTooltip>
</QCheckbox>
</QTd>
</template>
<template #body-cell-actions="props">
<QTd :props="props">
<div class="flex items-center no-wrap table-actions">
<QIcon
name="vn:ticketAdd"
size="sm"
color="primary"
class="cursor-pointer"
@click="openTicketsDialog(props?.row?.id)"
>
<QTooltip>{{ t('Add ticket') }}</QTooltip>
</QIcon>
<QIcon
name="preview"
size="sm"
color="primary"
@click="
viewSummary(props?.row?.id, RouteSummary)
"
class="cursor-pointer"
>
<QTooltip>{{ t('Preview') }}</QTooltip>
</QIcon>
<RouterLink
:to="{
name: 'RouteSummary',
params: { id: props?.row?.id },
}"
>
<QIcon
name="vn:eye"
size="xs"
color="primary"
>
<QTooltip>{{ t('Summary') }}</QTooltip>
</QIcon>
</RouterLink>
</div>
</QTd>
</template>
</QTable>
</div>
</template>
</VnPaginate>
</div>
<QPageSticky :offset="[20, 20]">
<RouterLink :to="{ name: 'RouteCreate' }">
<QBtn fab icon="add" color="primary" />
<QTooltip>
{{ t('newRoute') }}
</QTooltip>
</RouterLink>
</QPageSticky>
</QPage>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -2,7 +2,7 @@
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'src/components/LeftMenu.vue'; import LeftMenu from 'src/components/LeftMenu.vue';
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
const stateStore = useStateStore(); const stateStore = useStateStore();
onMounted(() => (stateStore.leftDrawer = false)); onMounted(() => (stateStore.leftDrawer = false));
</script> </script>

View File

@ -51,6 +51,7 @@ const setData = (entity) => (data.value = useCardDescription(entity.code, entity
:subtitle="data.subtitle" :subtitle="data.subtitle"
data-key="Shelvings" data-key="Shelvings"
@on-fetch="setData" @on-fetch="setData"
:summary="$attrs"
> >
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('shelving.summary.code')" :value="entity.code" /> <VnLv :label="t('shelving.summary.code')" :value="entity.code" />

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import ShelvingDescriptor from "pages/Shelving/Card/ShelvingDescriptor.vue"; import ShelvingDescriptor from 'pages/Shelving/Card/ShelvingDescriptor.vue';
import ShelvingSummary from './ShelvingSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -10,6 +11,6 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy>
<ShelvingDescriptor v-if="$props.id" :id="$props.id" /> <ShelvingDescriptor v-if="$props.id" :id="$props.id" :summary="ShelvingSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -112,22 +112,6 @@ const getEntryQueryParams = (supplier) => {
data-key="supplier" data-key="supplier"
:summary="$props.summary" :summary="$props.summary"
> >
<template #header-extra-action>
<QBtn
round
flat
dense
size="md"
icon="vn:supplier"
color="white"
class="link"
:to="{ name: 'SupplierList' }"
>
<QTooltip>
{{ t('Go to module index') }}
</QTooltip>
</QBtn>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="t('supplier.summary.taxNumber')" :value="entity.nif" /> <VnLv :label="t('supplier.summary.taxNumber')" :value="entity.nif" />
<VnLv label="Alias" :value="entity.nickname" /> <VnLv label="Alias" :value="entity.nickname" />

View File

@ -70,8 +70,6 @@ const filter = {
}; };
const data = ref(useCardDescription()); const data = ref(useCardDescription());
const setData = (entity) =>
(data.value = useCardDescription(entity.client?.name, entity.id));
</script> </script>
<template> <template>
@ -82,7 +80,6 @@ const setData = (entity) =>
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
data-key="ticketData" data-key="ticketData"
@on-fetch="setData"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<TicketDescriptorMenu :ticket="entity" /> <TicketDescriptorMenu :ticket="entity" />
@ -153,4 +150,5 @@ const setData = (entity) =>
<i18n> <i18n>
es: es:
This ticket is deleted: Este ticket está eliminado This ticket is deleted: Este ticket está eliminado
Go to module index: Ir al índice del modulo
</i18n> </i18n>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import TicketDescriptor from './TicketDescriptor.vue'; import TicketDescriptor from './TicketDescriptor.vue';
import TicketSummary from './TicketSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -10,6 +11,6 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy>
<TicketDescriptor v-if="$props.id" :id="$props.id" /> <TicketDescriptor v-if="$props.id" :id="$props.id" :summary="TicketSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -33,8 +33,12 @@ const filter = {
<template> <template>
<VnCard <VnCard
data-key="Travel" data-key="Travel"
:filter="filter"
base-url="Travels" base-url="Travels"
search-data-key="TravelList"
searchbar-label="Search travel"
searchbar-info="You can search by travel id or name"
search-url="Travels"
:filter="filter"
:descriptor="TravelDescriptor" :descriptor="TravelDescriptor"
/> />
</template> </template>

View File

@ -1,10 +1,11 @@
<script setup> <script setup>
import { computed } from 'vue'; 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 CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue'; import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue'; import TravelDescriptorMenuItems from './TravelDescriptorMenuItems.vue';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
@ -51,32 +52,22 @@ const filter = {
const entityId = computed(() => { const entityId = computed(() => {
return $props.id || route.params.id; return $props.id || route.params.id;
}); });
const data = ref(useCardDescription());
const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.id));
</script> </script>
<template> <template>
<CardDescriptor <CardDescriptor
module="Travel" module="Travel"
:url="`Travels/${entityId}`" :url="`Travels/${entityId}`"
title="ref" :title="data.title"
:subtitle="data.subtitle"
:filter="filter" :filter="filter"
data-key="Travel" data-key="travelData"
:summary="$attrs"
@on-fetch="setData"
> >
<template #header-extra-action>
<QBtn
round
flat
dense
size="md"
icon="local_airport"
color="white"
class="link"
:to="{ name: 'TravelList' }"
>
<QTooltip>
{{ t('Go to module index') }}
</QTooltip>
</QBtn>
</template>
<template #menu="{ entity }"> <template #menu="{ entity }">
<TravelDescriptorMenuItems :travel="entity" /> <TravelDescriptorMenuItems :travel="entity" />
</template> </template>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import TravelDescriptor from './TravelDescriptor.vue'; import TravelDescriptor from './TravelDescriptor.vue';
import TravelSummary from './TravelSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -11,6 +12,6 @@ const $props = defineProps({
<template> <template>
<QPopupProxy> <QPopupProxy>
<TravelDescriptor v-if="$props.id" :id="$props.id" /> <TravelDescriptor v-if="$props.id" :id="$props.id" :summary="TravelSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -12,8 +12,6 @@ import FetchData from 'src/components/FetchData.vue';
import { toDate, toCurrency } from 'src/filters'; import { toDate, toCurrency } from 'src/filters';
import axios from 'axios'; import axios from 'axios';
onUpdated(() => summaryRef.value.fetch());
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,

View File

@ -2,31 +2,27 @@
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import VnPaginate from 'src/components/ui/VnPaginate.vue'; import { useRoute } from 'vue-router';
import CardList from 'src/components/ui/CardList.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import TravelSummary from './Card/TravelSummary.vue';
import TravelFilter from './TravelFilter.vue';
import FetchData from 'components/FetchData.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
import { useStateStore } from 'stores/useStateStore'; import { useStateStore } from 'stores/useStateStore';
import { toDate } from 'src/filters/index'; import VnTable from 'components/VnTable/VnTable.vue';
import { useSummaryDialog } from 'src/composables/useSummaryDialog'; import { useSummaryDialog } from 'src/composables/useSummaryDialog';
import { getDateQBadgeColor } from 'src/composables/getDateQBadgeColor.js'; import { computed } from 'vue';
import RightMenu from 'src/components/common/RightMenu.vue'; import TravelSummary from './Card/TravelSummary.vue';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
import { dashIfEmpty, toDate } from 'src/filters';
const { viewSummary } = useSummaryDialog();
const router = useRouter(); const router = useRouter();
const { t } = useI18n(); const { t } = useI18n();
const stateStore = useStateStore(); const stateStore = useStateStore();
const { viewSummary } = useSummaryDialog(); const route = useRoute();
const tableRef = ref();
const warehouses = ref([]); const $props = defineProps({
id: {
const navigateToTravelId = (id) => { type: Number,
router.push({ path: `/travel/${id}` }); default: 0,
}; },
});
const entityId = computed(() => $props.id || route.params.id);
const cloneTravel = (travelData) => { const cloneTravel = (travelData) => {
const stringifiedTravelData = JSON.stringify(travelData); const stringifiedTravelData = JSON.stringify(travelData);
redirectToCreateView(stringifiedTravelData); redirectToCreateView(stringifiedTravelData);
@ -40,125 +36,170 @@ const redirectCreateEntryView = (travelData) => {
router.push({ name: 'EntryCreate', query: { travelFk: travelData.id } }); router.push({ name: 'EntryCreate', query: { travelFk: travelData.id } });
}; };
const getWarehouseName = (id) => {
return warehouses.value.find((warehouse) => warehouse.id === id).name;
};
onMounted(async () => { onMounted(async () => {
stateStore.rightDrawer = true; stateStore.rightDrawer = true;
}); });
const columns = computed(() => [
{
align: 'left',
name: 'id',
label: t('travel.travelList.tableVisibleColumns.id'),
isId: true,
field: 'id',
cardVisible: true,
},
{
align: 'left',
name: 'ref',
label: t('travel.travelList.tableVisibleColumns.ref'),
field: 'ref',
component: 'input',
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{
align: 'left',
name: 'agencyModeFk',
label: t('travel.travelList.tableVisibleColumns.agency'),
field: 'agencyModeFk',
component: 'select',
attrs: {
url: 'agencyModes',
fields: ['id', 'name'],
},
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{
align: 'left',
name: 'shipped',
label: t('travel.travelList.tableVisibleColumns.shipped'),
field: 'shipped',
component: 'date',
columnField: {
component: null,
},
cardVisible: true,
create: true,
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.shipped)),
},
{
align: 'left',
name: 'landed',
label: t('travel.travelList.tableVisibleColumns.landed'),
field: 'landed',
component: 'date',
columnField: {
component: null,
},
cardVisible: true,
create: true,
format: (row, dashIfEmpty) => dashIfEmpty(toDate(row.landed)),
},
{
align: 'left',
name: 'warehouseInFk',
label: t('travel.travelList.tableVisibleColumns.warehouseIn'),
field: 'warehouseInFk',
component: 'select',
attrs: {
url: 'warehouses',
fields: ['id', 'name'],
},
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{
align: 'left',
name: 'warehouseOutFk',
label: t('travel.travelList.tableVisibleColumns.warehouseOut'),
field: 'warehouseOutFk',
component: 'select',
attrs: {
url: 'warehouses',
fields: ['id', 'name'],
},
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{
align: 'left',
name: 'totalEntries',
label: t('travel.travelList.tableVisibleColumns.totalEntries'),
field: 'totalEntries',
component: 'input',
columnField: {
component: null,
},
cardVisible: true,
create: true,
},
{
align: 'right',
label: '',
name: 'tableActions',
actions: [
{
title: t('Clone'),
icon: 'vn:clone',
action: cloneTravel,
isPrimary: true,
},
{
title: t('Add entry'),
icon: 'contact_support',
action: redirectCreateEntryView,
},
{
title: t('View Summary'),
icon: 'preview',
action: (row) => viewSummary(row.id, TravelSummary),
},
],
},
]);
</script> </script>
<template> <template>
<FetchData <VnSearchbar
url="Warehouses" :info="t('You can search by travel id or name')"
:filter="{ fields: ['id', 'name'] }" :label="t('Search travel')"
order="name" data-key="TravelList"
@on-fetch="(data) => (warehouses = data)" />
auto-load <VnTable
ref="tableRef"
data-key="TravelList"
url="Travels"
:create="{
urlCreate: 'Travels',
title: t('Create Travels'),
onDataSaved: ({ id }) => tableRef.redirect(id),
formInitialData: {
editorFk: entityId,
},
}"
order="landed DESC"
:columns="columns"
default-mode="table"
auto-load
redirect="travel"
:right-search="false"
:is-editable="false"
:use-model="true"
/> />
<VnSearchbar data-key="TravelList" :limit="20" :label="t('searchByIdOrReference')" />
<RightMenu>
<template #right-panel>
<TravelFilter data-key="TravelList" />
</template>
</RightMenu>
<QPage class="column items-center q-pa-md">
<div class="vn-card-list">
<VnPaginate
data-key="TravelList"
url="Travels/filter"
auto-load
order="shipped DESC, landed DESC"
>
<template #body="{ rows }">
<CardList
v-for="row of rows"
:key="row.id"
:title="row.ref"
:id="row.id"
@click="navigateToTravelId(row.id)"
>
<template #list-items>
<VnLv
:label="t('globals.agency')"
:value="row.agencyModeName"
/>
<VnLv
v-if="warehouses.length > 0"
:label="t('globals.wareHouseOut')"
:value="getWarehouseName(row.warehouseOutFk)"
/>
<VnLv :label="t('globals.shipped')">
<template #value>
<QBadge
text-color="black"
v-if="getDateQBadgeColor(row.shipped)"
:color="getDateQBadgeColor(row.shipped)"
class="q-ma-none"
dense
style="font-size: 14px"
>
{{ toDate(row.shipped) }}
</QBadge>
<span v-else>{{ toDate(row.shipped) }}</span>
</template>
</VnLv>
<VnLv :label="t('globals.landed')">
<template #value>
<QBadge
text-color="black"
v-if="getDateQBadgeColor(row.landed)"
:color="getDateQBadgeColor(row.landed)"
class="q-ma-none"
dense
style="font-size: 14px"
>
{{ toDate(row.landed) }}
</QBadge>
<span v-else>{{ toDate(row.landed) }}</span>
</template>
</VnLv>
<VnLv
v-if="warehouses.length > 0"
:label="t('globals.wareHouseIn')"
:value="getWarehouseName(row.warehouseInFk)"
/>
<VnLv
:label="t('globals.totalEntries')"
:value="row.totalEntries"
/>
</template>
<template #actions>
<QBtn
:label="t('components.smartCard.clone')"
@click.stop="cloneTravel(row)"
outline
/>
<QBtn
:label="t('addEntry')"
@click.stop="redirectCreateEntryView(row)"
outline
style="margin-top: 15px"
/>
<QBtn
:label="t('components.smartCard.openSummary')"
@click.stop="viewSummary(row.id, TravelSummary)"
color="primary"
style="margin-top: 15px"
/>
</template>
</CardList>
</template>
</VnPaginate>
</div>
<QPageSticky :offset="[20, 20]">
<QBtn fab icon="add" color="primary" @click="redirectToCreateView()" />
<QTooltip>
{{ t('supplier.list.newSupplier') }}
</QTooltip>
</QPageSticky>
</QPage>
</template> </template>
<i18n> <i18n>
@ -169,4 +210,6 @@ en:
es: es:
addEntry: Añadir entrada addEntry: Añadir entrada
searchByIdOrReference: Buscar por ID o por referencia searchByIdOrReference: Buscar por ID o por referencia
You can search by travel id or name: Buscar por envio por id o nombre
Search travel: Buscar envio
</i18n> </i18n>

View File

@ -17,10 +17,6 @@ const $props = defineProps({
required: false, required: false,
default: null, default: null,
}, },
summary: {
type: Object,
default: null,
},
}); });
const route = useRoute(); const route = useRoute();
@ -115,7 +111,7 @@ const refetch = async () => await cardDescriptorRef.value.getData();
:filter="filter" :filter="filter"
:title="data.title" :title="data.title"
:subtitle="data.subtitle" :subtitle="data.subtitle"
:summary="$props.summary" :summary="$attrs"
@on-fetch=" @on-fetch="
(data) => { (data) => {
worker = data; worker = data;

View File

@ -38,7 +38,6 @@ const entityId = computed(() => {
}); });
const data = ref(useCardDescription()); const data = ref(useCardDescription());
const setData = (entity) => { const setData = (entity) => {
data.value = useCardDescription(entity.ref, entity.id); data.value = useCardDescription(entity.ref, entity.id);
}; };
@ -53,23 +52,8 @@ const setData = (entity) => {
:filter="filter" :filter="filter"
@on-fetch="setData" @on-fetch="setData"
data-key="zoneData" data-key="zoneData"
:summary="$attrs"
> >
<template #header-extra-action>
<QBtn
round
flat
dense
size="md"
icon="vn:zone"
color="white"
class="link"
:to="{ name: 'ZoneList' }"
>
<QTooltip>
{{ t('Summary') }}
</QTooltip>
</QBtn>
</template>
<template #menu="{ entity }"> <template #menu="{ entity }">
<ZoneDescriptorMenuItems :zone="entity" /> <ZoneDescriptorMenuItems :zone="entity" />
</template> </template>
@ -82,3 +66,8 @@ const setData = (entity) => {
</template> </template>
</CardDescriptor> </CardDescriptor>
</template> </template>
<i18n>
es:
Go to module index: Ir al índice del módulo
</i18n>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import ZoneDescriptor from './ZoneDescriptor.vue'; import ZoneDescriptor from './ZoneDescriptor.vue';
import ZoneSummary from './ZoneSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -11,6 +12,6 @@ const $props = defineProps({
<template> <template>
<QPopupProxy> <QPopupProxy>
<ZoneDescriptor v-if="$props.id" :id="$props.id" /> <ZoneDescriptor v-if="$props.id" :id="$props.id" :summary="ZoneSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -18,7 +18,7 @@ export default {
{ {
path: '/agency/:id', path: '/agency/:id',
name: 'AgencyCard', name: 'AgencyCard',
component: () => import('src/pages/Agency/Card/AgencyCard.vue'), component: () => import('src/pages/Route/Agency/Card/AgencyCard.vue'),
redirect: { name: 'AgencySummary' }, redirect: { name: 'AgencySummary' },
children: [ children: [
{ {
@ -28,7 +28,8 @@ export default {
title: 'summary', title: 'summary',
icon: 'view_list', icon: 'view_list',
}, },
component: () => import('src/pages/Agency/Card/AgencySummary.vue'), component: () =>
import('src/pages/Route/Agency/Card/AgencySummary.vue'),
}, },
{ {
name: 'AgencyBasicData', name: 'AgencyBasicData',
@ -37,7 +38,8 @@ export default {
title: 'basicData', title: 'basicData',
icon: 'vn:settings', icon: 'vn:settings',
}, },
component: () => import('pages/Agency/Card/AgencyBasicData.vue'), component: () =>
import('pages/Route/Agency/Card/AgencyBasicData.vue'),
}, },
{ {
path: 'workCenter', path: 'workCenter',
@ -52,7 +54,9 @@ export default {
title: 'workCenters', title: 'workCenters',
}, },
component: () => component: () =>
import('src/pages/Agency/Card/AgencyWorkcenter.vue'), import(
'src/pages/Route/Agency/Card/AgencyWorkcenter.vue'
),
}, },
], ],
}, },
@ -69,7 +73,7 @@ export default {
title: 'modes', title: 'modes',
}, },
component: () => component: () =>
import('src/pages/Agency/Card/AgencyModes.vue'), import('src/pages/Route/Agency/Card/AgencyModes.vue'),
}, },
], ],
}, },
@ -80,7 +84,7 @@ export default {
title: 'log', title: 'log',
icon: 'history', icon: 'history',
}, },
component: () => import('src/pages/Agency/Card/AgencyLog.vue'), component: () => import('src/pages/Route/Agency/Card/AgencyLog.vue'),
}, },
], ],
}, },

View File

@ -86,7 +86,8 @@ export default {
title: 'agencyList', title: 'agencyList',
icon: 'view_list', icon: 'view_list',
}, },
component: () => import('src/pages/Agency/AgencyList.vue'), component: () =>
import('src/pages/Route/Agency/AgencyList.vue'),
}, },
], ],
}, },