Merge pull request 'refactor: refs #8316 used VnSection and VnCardBeta' (!1149) from 8316-orderCardWithVnCardBeta into dev
gitea/salix-front/pipeline/head This commit looks good Details

Reviewed-on: #1149
Reviewed-by: Alex Moreno <alexm@verdnatura.es>
This commit is contained in:
Alex Moreno 2025-01-15 11:41:35 +00:00
commit c6d7008ed5
12 changed files with 272 additions and 299 deletions

View File

@ -80,7 +80,6 @@ onBeforeMount(() => {
/> />
<div :id="searchbarId"></div> <div :id="searchbarId"></div>
</slot> </slot>
<RightMenu> <RightMenu>
<template #right-panel v-if="$slots['rightMenu'] || rightFilter"> <template #right-panel v-if="$slots['rightMenu'] || rightFilter">
<slot name="rightMenu"> <slot name="rightMenu">

View File

@ -18,8 +18,7 @@ const $props = defineProps({
}, },
columns: { columns: {
type: Number, type: Number,
required: false, default: 3,
default: null,
}, },
}); });

View File

@ -579,27 +579,6 @@ parking:
searchBar: searchBar:
info: You can search by parking code info: You can search by parking code
label: Search parking... label: Search parking...
order:
field:
salesPersonFk: Sales Person
form:
clientFk: Client
addressFk: Address
agencyModeFk: Agency
list:
newOrder: New Order
summary:
basket: Basket
notConfirmed: Not confirmed
created: Created
createdFrom: Created From
address: Address
total: Total
items: Items
orderTicketList: Order Ticket List
amount: Amount
confirm: Confirm
confirmLines: Confirm lines
department: department:
chat: Chat chat: Chat
bossDepartment: Boss Department bossDepartment: Boss Department

View File

@ -563,30 +563,6 @@ invoiceOut:
comercial: Comercial comercial: Comercial
errors: errors:
downloadCsvFailed: Error al descargar CSV downloadCsvFailed: Error al descargar CSV
order:
field:
salesPersonFk: Comercial
form:
clientFk: Cliente
addressFk: Dirección
agencyModeFk: Agencia
list:
newOrder: Nuevo Pedido
summary:
basket: Cesta
notConfirmed: No confirmada
created: Creado
createdFrom: Creado desde
address: Dirección
total: Total
vat: IVA
state: Estado
alias: Alias
items: Artículos
orderTicketList: Tickets del pedido
amount: Monto
confirm: Confirmar
confirmLines: Confirmar lineas
shelving: shelving:
list: list:
parking: Parking parking: Parking

View File

@ -391,7 +391,7 @@ onBeforeMount(async () => {
{{ row?.subName.toUpperCase() }} {{ row?.subName.toUpperCase() }}
</div> </div>
</div> </div>
<FetchedTags :item="row" :columns="3" /> <FetchedTags :item="row" />
</template> </template>
<template #more-create-dialog="{ data }"> <template #more-create-dialog="{ data }">
<VnInput <VnInput

View File

@ -1,38 +1,12 @@
<script setup> <script setup>
import { computed } from 'vue'; import VnCardBeta from 'components/common/VnCardBeta.vue';
import { useRoute } from 'vue-router';
import VnCard from 'components/common/VnCard.vue';
import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue'; import OrderDescriptor from 'pages/Order/Card/OrderDescriptor.vue';
import OrderFilter from './OrderFilter.vue';
import OrderSearchbar from './OrderSearchbar.vue';
import OrderCatalogFilter from './OrderCatalogFilter.vue';
const config = {
OrderCatalog: OrderCatalogFilter,
};
const route = useRoute();
const routeName = computed(() => route.name);
const customRouteRedirectName = computed(() => {
const route = config[routeName.value];
if (route) return null;
return 'OrderList';
});
const customFilterPanel = computed(() => {
const filterPanel = config[routeName.value] ?? OrderFilter;
return filterPanel;
});
</script> </script>
<template> <template>
<VnCard <VnCardBeta
data-key="Order" data-key="Order"
base-url="Orders" base-url="Orders"
:descriptor="OrderDescriptor" :descriptor="OrderDescriptor"
:filter-panel="customFilterPanel" />
:search-data-key="customRouteRedirectName"
>
<template #searchbar>
<OrderSearchbar />
</template>
</VnCard>
</template> </template>

View File

@ -15,15 +15,18 @@ const router = useRouter();
const stateStore = useStateStore(); const stateStore = useStateStore();
const { t } = useI18n(); const { t } = useI18n();
const dataKey = 'OrderCatalogList'; const dataKey = 'OrderCatalogList';
const arrayData = useArrayData(dataKey); const catalogParams = {
const store = arrayData.store;
const tags = ref([]);
const itemRefs = ref({});
let catalogParams = {
orderFk: route.params.id, orderFk: route.params.id,
orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }), orderBy: JSON.stringify({ field: 'relevancy DESC, name', way: 'ASC', isTag: false }),
}; };
const arrayData = useArrayData(dataKey, {
url: 'Orders/CatalogFilter',
limit: 50,
userParams: catalogParams,
});
const store = arrayData.store;
const tags = ref([]);
const itemRefs = ref({});
onMounted(() => { onMounted(() => {
stateStore.rightDrawer = true; stateStore.rightDrawer = true;
@ -66,7 +69,6 @@ function extractValueTags(items) {
); );
tagValue.value = resultValueTags; tagValue.value = resultValueTags;
} }
const autoLoad = computed(() => !!JSON.parse(route?.query.table ?? '{}')?.categoryFk);
watch( watch(
() => store.data, () => store.data,
@ -78,16 +80,15 @@ watch(
</script> </script>
<template> <template>
<VnSearchbar <Teleport to="#section-searchbar" v-if="stateStore.isHeaderMounted()">
:data-key="dataKey" <VnSearchbar
:user-params="catalogParams" :data-key="dataKey"
:static-params="['orderFk', 'orderBy']" :redirect="false"
:redirect="false" :label="t('Search items')"
url="Orders/CatalogFilter" :info="t('You can search items by name or id')"
:label="t('Search items')" :search-remove-params="false"
:info="t('You can search items by name or id')" />
:search-remove-params="false" </Teleport>
/>
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()"> <Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
<OrderCatalogFilter <OrderCatalogFilter
:data-key="dataKey" :data-key="dataKey"
@ -98,13 +99,7 @@ watch(
</Teleport> </Teleport>
<QPage class="column items-center q-pa-md" data-cy="orderCatalogPage"> <QPage class="column items-center q-pa-md" data-cy="orderCatalogPage">
<div class="full-width"> <div class="full-width">
<VnPaginate <VnPaginate :data-key="dataKey">
:data-key="dataKey"
url="Orders/CatalogFilter"
:limit="50"
:user-params="catalogParams"
:auto-load="autoLoad"
>
<template #body="{ rows }"> <template #body="{ rows }">
<div class="catalog-list"> <div class="catalog-list">
<div v-if="rows && !rows?.length" class="no-result"> <div v-if="rows && !rows?.length" class="no-result">

View File

@ -1,22 +0,0 @@
<script setup>
import { useI18n } from 'vue-i18n';
import VnSearchbar from 'components/ui/VnSearchbar.vue';
const { t } = useI18n();
</script>
<template>
<VnSearchbar
data-key="OrderList"
url="Orders/filter"
:label="t('Search order')"
:info="t('Search orders by ticket id')"
/>
</template>
<style scoped lang="scss"></style>
<i18n>
es:
Search order: Buscar orden
Search orders by ticket id: Buscar pedido por id ticket
</i18n>

View File

@ -8,15 +8,14 @@ import { useRoute } from 'vue-router';
import axios from 'axios'; import axios from 'axios';
import OrderSummary from 'pages/Order/Card/OrderSummary.vue'; import OrderSummary from 'pages/Order/Card/OrderSummary.vue';
import OrderSearchbar from './Card/OrderSearchbar.vue';
import OrderFilter from './Card/OrderFilter.vue'; import OrderFilter from './Card/OrderFilter.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import VnTable from 'src/components/VnTable/VnTable.vue'; import VnTable from 'src/components/VnTable/VnTable.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue'; import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnSelect from 'src/components/common/VnSelect.vue'; import VnSelect from 'src/components/common/VnSelect.vue';
import VnSection from 'src/components/common/VnSection.vue';
const { t } = useI18n(); const { t } = useI18n();
const { viewSummary } = useSummaryDialog(); const { viewSummary } = useSummaryDialog();
@ -24,6 +23,8 @@ const tableRef = ref();
const agencyList = ref([]); const agencyList = ref([]);
const route = useRoute(); const route = useRoute();
const addressOptions = ref([]); const addressOptions = ref([]);
const dataKey = 'OrderList';
const columns = computed(() => [ const columns = computed(() => [
{ {
align: 'left', align: 'left',
@ -178,117 +179,126 @@ const getDateColor = (date) => {
if (difference < 0) return 'bg-success'; if (difference < 0) return 'bg-success';
}; };
</script> </script>
<template> <template>
<OrderSearchbar /> <VnSection
<RightMenu> :data-key="dataKey"
<template #right-panel> :columns="columns"
prefix="order"
:array-data-props="{
url: 'Orders/filter',
order: ['landed DESC', 'clientFk ASC', 'id DESC'],
}"
>
<template #rightMenu>
<OrderFilter data-key="OrderList" /> <OrderFilter data-key="OrderList" />
</template> </template>
</RightMenu> <template #body>
<VnTable <VnTable
ref="tableRef" ref="tableRef"
data-key="OrderList" :data-key="dataKey"
url="Orders/filter" :create="{
:order="['landed DESC', 'clientFk ASC', 'id DESC']" urlCreate: 'Orders/new',
:create="{ title: t('module.cerateOrder'),
urlCreate: 'Orders/new', onDataSaved: (url) => {
title: t('module.cerateOrder'), tableRef.redirect(`${url}/catalog`);
onDataSaved: (url) => { },
tableRef.redirect(`${url}/catalog`); formInitialData: {
}, active: true,
formInitialData: { addressId: null,
active: true, clientFk: null,
addressId: null, },
clientFk: null, }"
}, :user-params="{ showEmpty: false }"
}" :columns="columns"
:user-params="{ showEmpty: false }" :right-search="false"
:columns="columns" redirect="order"
:right-search="false"
redirect="order"
>
<template #column-clientFk="{ row }">
<span class="link" @click.stop>
{{ row?.clientName }}
<CustomerDescriptorProxy :id="row?.clientFk" />
</span>
</template>
<template #column-salesPersonFk="{ row }">
<span class="link" @click.stop>
{{ row?.name }}
<WorkerDescriptorProxy :id="row?.salesPersonFk" />
</span>
</template>
<template #column-landed="{ row }">
<span v-if="getDateColor(row.landed)">
<QChip :class="getDateColor(row.landed)" dense square>
{{ toDate(row?.landed) }}
</QChip>
</span>
</template>
<template #more-create-dialog="{ data }">
<VnSelect
url="Clients"
:include="{ relation: 'addresses' }"
v-model="data.clientFk"
:label="t('module.customer')"
@update:model-value="(id) => fetchClientAddress(id, data)"
> >
<template #option="scope"> <template #column-clientFk="{ row }">
<QItem v-bind="scope.itemProps"> <span class="link" @click.stop>
<QItemSection> {{ row?.clientName }}
<QItemLabel> <CustomerDescriptorProxy :id="row?.clientFk" />
{{ scope.opt.name }} </span>
</QItemLabel>
<QItemLabel caption>
{{ `#${scope.opt.id}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template> </template>
</VnSelect> <template #column-salesPersonFk="{ row }">
<VnSelect <span class="link" @click.stop>
v-model="data.addressId" {{ row?.name }}
:options="addressOptions" <WorkerDescriptorProxy :id="row?.salesPersonFk" />
:label="t('module.address')" </span>
option-value="id"
option-label="nickname"
@update:model-value="() => fetchAgencies(data)"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
:class="{
'color-vn-label': !scope.opt?.isActive,
}"
>
{{
`${
!scope.opt?.isActive
? t('basicData.inactive')
: ''
} `
}}
{{ scope.opt?.nickname }}: {{ scope.opt?.street }},
{{ scope.opt?.city }}
</QItemLabel>
</QItemSection>
</QItem>
</template> </template>
</VnSelect> <template #column-landed="{ row }">
<VnInputDate <span v-if="getDateColor(row.landed)">
v-model="data.landed" <QChip :class="getDateColor(row.landed)" dense square>
:label="t('module.landed')" {{ toDate(row?.landed) }}
@update:model-value="() => fetchAgencies(data)" </QChip>
/> </span>
<VnSelect </template>
v-model="data.agencyModeId" <template #more-create-dialog="{ data }">
:label="t('module.agency')" <VnSelect
:options="agencyList" url="Clients"
option-value="agencyModeFk" :include="{ relation: 'addresses' }"
option-label="agencyMode" v-model="data.clientFk"
/> :label="t('module.customer')"
@update:model-value="(id) => fetchClientAddress(id, data)"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel>
{{ scope.opt.name }}
</QItemLabel>
<QItemLabel caption>
{{ `#${scope.opt.id}` }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnSelect
v-model="data.addressId"
:options="addressOptions"
:label="t('module.address')"
option-value="id"
option-label="nickname"
@update:model-value="() => fetchAgencies(data)"
>
<template #option="scope">
<QItem v-bind="scope.itemProps">
<QItemSection>
<QItemLabel
:class="{
'color-vn-label': !scope.opt?.isActive,
}"
>
{{
`${
!scope.opt?.isActive
? t('basicData.inactive')
: ''
} `
}}
{{ scope.opt?.nickname }}:
{{ scope.opt?.street }},
{{ scope.opt?.city }}
</QItemLabel>
</QItemSection>
</QItem>
</template>
</VnSelect>
<VnInputDate
v-model="data.landed"
:label="t('module.landed')"
@update:model-value="() => fetchAgencies(data)"
/>
<VnSelect
v-model="data.agencyModeId"
:label="t('module.agency')"
:options="agencyList"
option-value="agencyModeFk"
option-label="agencyMode"
/>
</template>
</VnTable>
</template> </template>
</VnTable> </VnSection>
</template> </template>

View File

@ -21,3 +21,26 @@ lines:
image: Image image: Image
params: params:
tagGroups: Tags tagGroups: Tags
order:
field:
salesPersonFk: Sales Person
form:
clientFk: Client
addressFk: Address
agencyModeFk: Agency
list:
newOrder: New Order
summary:
basket: Basket
notConfirmed: Not confirmed
created: Created
createdFrom: Created From
address: Address
total: Total
items: Items
orderTicketList: Order Ticket List
amount: Amount
confirm: Confirm
confirmLines: Confirm lines
search: Search orders
searchInfo: You can search orders by ticket id

View File

@ -21,3 +21,29 @@ lines:
image: Imagen image: Imagen
params: params:
tagGroups: Tags tagGroups: Tags
order:
field:
salesPersonFk: Comercial
form:
clientFk: Cliente
addressFk: Dirección
agencyModeFk: Agencia
list:
newOrder: Nuevo Pedido
summary:
basket: Cesta
notConfirmed: No confirmada
created: Creado
createdFrom: Creado desde
address: Dirección
total: Total
vat: IVA
state: Estado
alias: Alias
items: Artículos
orderTicketList: Tickets del pedido
amount: Monto
confirm: Confirmar
confirmLines: Confirmar lineas
search: Buscar pedido
searchInfo: Buscar pedidos por el número de ticket

View File

@ -1,35 +1,102 @@
import { RouterView } from 'vue-router'; import { RouterView } from 'vue-router';
const orderCard = {
name: 'OrderCard',
path: ':id',
component: () => import('src/pages/Order/Card/OrderCard.vue'),
redirect: { name: 'OrderSummary' },
meta: {
menu: [
'OrderBasicData',
'OrderCatalog',
'OrderVolume',
'OrderLines',
],
},
children: [
{
path: 'summary',
name: 'OrderSummary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () => import('src/pages/Order/Card/OrderSummary.vue'),
},
{
path: 'basic-data',
name: 'OrderBasicData',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
},
{
path: 'catalog',
name: 'OrderCatalog',
meta: {
title: 'catalog',
icon: 'vn:basket',
},
component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
},
{
path: 'volume',
name: 'OrderVolume',
meta: {
title: 'volume',
icon: 'vn:volume',
},
component: () => import('src/pages/Order/Card/OrderVolume.vue'),
},
{
path: 'line',
name: 'OrderLines',
meta: {
title: 'lines',
icon: 'vn:lines',
},
component: () => import('src/pages/Order/Card/OrderLines.vue'),
},
],
};
export default { export default {
path: '/order',
name: 'Order', name: 'Order',
path: '/order',
meta: { meta: {
title: 'order', title: 'order',
icon: 'vn:basket', icon: 'vn:basket',
moduleName: 'Order', moduleName: 'Order',
keyBinding: 'o', keyBinding: 'o',
menu: ['OrderList'],
}, },
component: RouterView, component: RouterView,
redirect: { name: 'OrderMain' }, redirect: { name: 'OrderMain' },
menus: {
main: ['OrderList'],
card: ['OrderBasicData', 'OrderCatalog', 'OrderVolume', 'OrderLines'],
},
children: [ children: [
{ {
path: '',
name: 'OrderMain', name: 'OrderMain',
path: '',
component: () => import('src/components/common/VnModule.vue'), component: () => import('src/components/common/VnModule.vue'),
redirect: { name: 'OrderList' }, redirect: { name: 'OrderIndexMain' },
children: [ children: [
{ {
path: 'list', path: '',
name: 'OrderList', name: 'OrderIndexMain',
meta: { redirect: { name: 'OrderList' },
title: 'orderList',
icon: 'view_list',
},
component: () => import('src/pages/Order/OrderList.vue'), component: () => import('src/pages/Order/OrderList.vue'),
children: [
{
name: 'OrderList',
path: 'list',
meta: {
title: 'orderList',
icon: 'view_list',
},
},
orderCard,
],
}, },
{ {
path: 'create', path: 'create',
@ -42,58 +109,5 @@ export default {
}, },
], ],
}, },
{
name: 'OrderCard',
path: ':id',
component: () => import('src/pages/Order/Card/OrderCard.vue'),
redirect: { name: 'OrderSummary' },
children: [
{
name: 'OrderSummary',
path: 'summary',
meta: {
title: 'summary',
icon: 'launch',
},
component: () => import('src/pages/Order/Card/OrderSummary.vue'),
},
{
name: 'OrderBasicData',
path: 'basic-data',
meta: {
title: 'basicData',
icon: 'vn:settings',
},
component: () => import('src/pages/Order/Card/OrderBasicData.vue'),
},
{
name: 'OrderCatalog',
path: 'catalog',
meta: {
title: 'catalog',
icon: 'vn:basket',
},
component: () => import('src/pages/Order/Card/OrderCatalog.vue'),
},
{
name: 'OrderVolume',
path: 'volume',
meta: {
title: 'volume',
icon: 'vn:volume',
},
component: () => import('src/pages/Order/Card/OrderVolume.vue'),
},
{
name: 'OrderLines',
path: 'line',
meta: {
title: 'lines',
icon: 'vn:lines',
},
component: () => import('src/pages/Order/Card/OrderLines.vue'),
},
],
},
], ],
}; };