Merge branch 'dev' into 6076-2FA
gitea/salix-front/pipeline/head This commit looks good Details

This commit is contained in:
Alex Moreno 2023-08-09 13:01:11 +00:00
commit 87d6304218
13 changed files with 371 additions and 338 deletions

View File

@ -4,7 +4,7 @@ import { useI18n } from 'vue-i18n';
import axios from 'axios'; import axios from 'axios';
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue'; import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
const props = defineProps({ const $props = defineProps({
url: { url: {
type: String, type: String,
default: '', default: '',
@ -17,6 +17,14 @@ const props = defineProps({
type: String, type: String,
required: true, required: true,
}, },
title: {
type: String,
default: '',
},
subtitle: {
type: Number,
default: 0,
},
}); });
const slots = useSlots(); const slots = useSlots();
@ -30,15 +38,15 @@ const entity = ref();
async function fetch() { async function fetch() {
const params = {}; const params = {};
if (props.filter) params.filter = JSON.stringify(props.filter); if ($props.filter) params.filter = JSON.stringify($props.filter);
const { data } = await axios.get(props.url, { params }); const { data } = await axios.get($props.url, { params });
entity.value = data; entity.value = data;
emit('onFetch', data); emit('onFetch', data);
} }
watch(props, async () => { watch($props, async () => {
entity.value = null; entity.value = null;
await fetch(); await fetch();
}); });
@ -49,14 +57,30 @@ watch(props, async () => {
<template v-if="entity"> <template v-if="entity">
<div class="header bg-primary q-pa-sm"> <div class="header bg-primary q-pa-sm">
<RouterLink :to="{ name: `${module}List` }"> <RouterLink :to="{ name: `${module}List` }">
<QBtn round flat dense size="md" icon="view_list" color="white"> <QBtn
round
flat
dense
size="md"
icon="view_list"
color="white"
class="link"
>
<QTooltip> <QTooltip>
{{ t('components.cardDescriptor.mainList') }} {{ t('components.cardDescriptor.mainList') }}
</QTooltip> </QTooltip>
</QBtn> </QBtn>
</RouterLink> </RouterLink>
<RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }"> <RouterLink :to="{ name: `${module}Summary`, params: { id: entity.id } }">
<QBtn round flat dense size="md" icon="launch" color="white"> <QBtn
round
flat
dense
size="md"
icon="launch"
color="white"
class="link"
>
<QTooltip> <QTooltip>
{{ t('components.cardDescriptor.summary') }} {{ t('components.cardDescriptor.summary') }}
</QTooltip> </QTooltip>
@ -86,20 +110,34 @@ watch(props, async () => {
<div class="body q-py-sm"> <div class="body q-py-sm">
<QList dense> <QList dense>
<QItemLabel header class="ellipsis text-h5" :lines="1"> <QItemLabel header class="ellipsis text-h5" :lines="1">
<slot name="description" :entity="entity"> <div class="title">
<span> <span v-if="$props.title">
{{ entity.name }} {{ $props.title }}
<QTooltip>{{ entity.name }}</QTooltip> <QTooltip>{{ $props.title }}</QTooltip>
</span> </span>
</slot> <slot v-else name="description" :entity="entity">
<span>
{{ entity.name }}
<QTooltip>{{ entity.name }}</QTooltip>
</span>
</slot>
</div>
</QItemLabel> </QItemLabel>
<QItem dense> <QItem dense>
<QItemLabel class="text-subtitle2" caption> <QItemLabel class="subtitle text-white" caption>
#{{ entity.id }} #{{ $props.subtitle ?? entity.id }}
</QItemLabel> </QItemLabel>
</QItem> </QItem>
</QList> </QList>
<slot name="body" :entity="entity" /> <div class="list-box">
<slot name="body" :entity="entity" />
</div>
</div>
<div class="icons">
<slot name="icons" :entity="entity" />
</div>
<div class="actions">
<slot name="actions" :entity="entity" />
</div> </div>
<slot name="after" /> <slot name="after" />
</template> </template>
@ -110,24 +148,77 @@ watch(props, async () => {
<style lang="scss"> <style lang="scss">
.body { .body {
.q-card__actions {
justify-content: center;
}
.text-h5 { .text-h5 {
padding-top: 5px; padding-top: 5px;
padding-bottom: 5px; padding-bottom: 5px;
} }
.q-item {
min-height: 20px;
.link {
margin-left: 5px;
}
}
.vn-label-value {
display: flex;
padding: 2px 16px;
.label {
color: $label-color;
font-size: 12px;
width: 47%;
}
.value {
font-size: 14px;
margin-left: 12px;
width: 47%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.info {
margin-left: 5px;
}
}
} }
</style> </style>
<style lang="scss" scoped> <style lang="scss" scoped>
.title {
span {
color: $primary;
font-weight: bold;
}
}
.subtitle {
font-size: 16px;
}
.list-box {
width: 90%;
background-color: rgba(87, 86, 86, 0.2);
margin: 20px 10px 0 10px;
padding: 10px 5px 10px 0px;
border-radius: 8px;
.q-item__label {
color: $label-color;
}
}
.descriptor { .descriptor {
width: 256px; width: 256px;
.header { .header {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: stretch; align-items: stretch;
} }
.icons {
margin: 0 10px;
display: flex;
justify-content: center;
.q-icon {
margin-right: 5px;
}
}
.actions {
margin: 0 5px;
}
} }
</style> </style>

View File

@ -13,7 +13,9 @@ const isBooleanValue = computed(() => typeof $props.value === 'boolean');
<template> <template>
<div class="vn-label-value"> <div class="vn-label-value">
<div v-if="$props.label || $slots.label" class="label"> <div v-if="$props.label || $slots.label" class="label">
<slot name="label"> {{ $props.label }}</slot> <slot name="label">
<span>{{ $props.label }}</span>
</slot>
</div> </div>
<div v-if="$props.value || $slots.value" class="value"> <div v-if="$props.value || $slots.value" class="value">
<span v-if="isBooleanValue"> <span v-if="isBooleanValue">
@ -22,9 +24,9 @@ const isBooleanValue = computed(() => typeof $props.value === 'boolean');
:color="$props.value ? `positive` : `negative`" :color="$props.value ? `positive` : `negative`"
/> />
</span> </span>
<span v-else> <slot v-else name="value">
<slot name="value">{{ $props.value }}</slot> <span :title="$props.value">{{ $props.value }}</span>
</span> </slot>
</div> </div>
<div class="info" v-if="$props.info"> <div class="info" v-if="$props.info">
<QIcon name="info"> <QIcon name="info">

View File

@ -0,0 +1,8 @@
export default function useCardDescription(title, subtitle) {
const getTitle = (title) => title;
const getSubtitle = (subtitle) => subtitle;
return {
title: getTitle(title),
subtitle: getSubtitle(subtitle),
};
}

View File

@ -21,6 +21,23 @@ $negative: #c10015;
$info: #31ccec; $info: #31ccec;
$warning: #f2c037; $warning: #f2c037;
// Pendiente de cuadrar con la base de datos
$success: $positive;
$alert: $negative;
.bg-success {
background-color: $positive;
}
.bg-notice {
background-color: $info;
}
.text-notice {
color: $info;
}
.bg-alert {
background-color: $negative;
}
$color-spacer-light: rgba(255, 255, 255, 0.12); $color-spacer-light: rgba(255, 255, 255, 0.12);
$color-spacer: rgba(255, 255, 255, 0.3); $color-spacer: rgba(255, 255, 255, 0.3);
$border-thin-light: 1px solid $color-spacer-light; $border-thin-light: 1px solid $color-spacer-light;
@ -29,3 +46,5 @@ $dark-shadow-color: #000;
$dark: #292929; $dark: #292929;
$layout-shadow-dark: 0 0 10px 2px rgba(0, 0, 0, 0.2), 0 0px 10px rgba(0, 0, 0, 0.24); $layout-shadow-dark: 0 0 10px 2px rgba(0, 0, 0, 0.2), 0 0px 10px rgba(0, 0, 0, 0.24);
$spacing-md: 16px; $spacing-md: 16px;
$label-color: rgba(255, 255, 255, 0.6);

View File

@ -281,6 +281,9 @@ export default {
ticketId: 'Ticket ID', ticketId: 'Ticket ID',
customerSummary: 'Customer summary', customerSummary: 'Customer summary',
claimedTicket: 'Claimed ticket', claimedTicket: 'Claimed ticket',
commercial: 'Commercial',
province: 'Province',
zone: 'Zone',
}, },
summary: { summary: {
customer: 'Customer', customer: 'Customer',

View File

@ -280,6 +280,9 @@ export default {
ticketId: 'ID ticket', ticketId: 'ID ticket',
customerSummary: 'Resumen del cliente', customerSummary: 'Resumen del cliente',
claimedTicket: 'Ticket reclamado', claimedTicket: 'Ticket reclamado',
commercial: 'Comercial',
province: 'Provincia',
zone: 'Zona',
}, },
summary: { summary: {
customer: 'Cliente', customer: 'Cliente',

View File

@ -1,12 +1,14 @@
<script setup> <script setup>
import { computed } from 'vue'; import { ref, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue'; import TicketDescriptorProxy from 'pages/Ticket/Card/TicketDescriptorProxy.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue'; import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -25,11 +27,29 @@ const entityId = computed(() => {
const filter = { const filter = {
include: [ include: [
{ relation: 'client' }, {
{ relation: 'claimState' }, relation: 'client',
scope: {
include: { relation: 'salesPersonUser' },
},
},
{ {
relation: 'claimState', relation: 'claimState',
}, },
{
relation: 'ticket',
scope: {
include: [
{ relation: 'zone' },
{
relation: 'address',
scope: {
include: { relation: 'province' },
},
},
],
},
},
{ {
relation: 'worker', relation: 'worker',
scope: { scope: {
@ -40,10 +60,14 @@ const filter = {
}; };
function stateColor(code) { function stateColor(code) {
if (code === 'pending') return 'green'; if (code === 'pending') return 'positive';
if (code === 'managed') return 'orange'; if (code === 'managed') return 'warning';
if (code === 'resolved') return 'red'; if (code === 'resolved') return 'negative';
} }
const data = ref(useCardDescription());
const setData = (entity) => {
data.value = useCardDescription(entity.client.name, entity.id);
};
</script> </script>
<template> <template>
@ -52,54 +76,58 @@ function stateColor(code) {
:url="`Claims/${entityId}`" :url="`Claims/${entityId}`"
:filter="filter" :filter="filter"
module="Claim" module="Claim"
:title="data.title"
:subtitle="data.subtitle"
@on-fetch="setData"
> >
<template #menu="{ entity }"> <template #menu="{ entity }">
<ClaimDescriptorMenu :claim="entity" /> <ClaimDescriptorMenu :claim="entity" />
</template> </template>
<template #description="{ entity }">
<span>
{{ entity.client.name }}
<QTooltip>{{ entity.client.name }}</QTooltip>
</span>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<QList> <VnLv :label="t('claim.card.created')" :value="toDate(entity.created)" />
<QItem> <VnLv v-if="entity.claimState" :label="t('claim.card.state')">
<QItemSection> <template #value>
<QItemLabel caption>{{ t('claim.card.created') }}</QItemLabel> <QBadge :color="stateColor(entity.claimState.code)" dense>
<QItemLabel>{{ toDate(entity.created) }}</QItemLabel> {{ entity.claimState.description }}
</QItemSection> </QBadge>
<QItemSection v-if="entity.claimState"> </template>
<QItemLabel caption>{{ t('claim.card.state') }}</QItemLabel> </VnLv>
<QItemLabel> <VnLv :label="t('claim.card.ticketId')">
<QBadge :color="stateColor(entity.claimState.code)" dense> <template #value>
{{ entity.claimState.description }} <span class="link">
</QBadge> {{ entity.ticketFk }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('claim.card.ticketId') }}
</QItemLabel>
<QItemLabel>
<span class="link">
{{ entity.ticketFk }}
<TicketDescriptorProxy :id="entity.ticketFk" />
</span>
</QItemLabel>
</QItemSection>
<QItemSection v-if="entity.worker">
<QItemLabel caption>
{{ t('claim.card.assignedTo') }}
</QItemLabel>
<QItemLabel>{{ entity.worker.user.name }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
<TicketDescriptorProxy :id="entity.ticketFk" />
</span>
</template>
</VnLv>
<VnLv
v-if="entity.worker"
:label="t('claim.card.assignedTo')"
:value="entity.worker.user.name"
>
<template #value>
<span class="link">
{{ entity.worker.user.name }}
<WorkerDescriptorProxy :id="entity.worker.userFk" />
</span>
</template>
</VnLv>
<VnLv :label="t('claim.card.commercial')">
<template #value>
<span class="link">
{{ entity.client.salesPersonUser.name }}
<WorkerDescriptorProxy :id="entity.client.salesPersonFk" />
</span>
</template>
</VnLv>
<VnLv
:label="t('claim.card.province')"
:value="entity.ticket.address.province.name"
/>
<VnLv :label="t('claim.card.zone')" :value="entity.ticket.zone.name" />
</template>
<template #actions="{ entity }">
<QCardActions> <QCardActions>
<QBtn <QBtn
size="md" size="md"
@ -121,3 +149,8 @@ function stateColor(code) {
</template> </template>
</CardDescriptor> </CardDescriptor>
</template> </template>
<style scoped>
.q-item__label {
margin-top: 0;
}
</style>

View File

@ -1,10 +1,12 @@
<script setup> <script setup>
import { computed } from 'vue'; import { ref, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { toCurrency } from 'src/filters'; import { toCurrency } from 'src/filters';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -20,57 +22,38 @@ const { t } = useI18n();
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.name, entity.id));
</script> </script>
<template> <template>
<CardDescriptor module="Customer" :url="`Clients/${entityId}/getCard`"> <CardDescriptor
module="Customer"
:url="`Clients/${entityId}/getCard`"
:title="data.title"
:subtitle="data.subtitle"
@on-fetch="setData"
>
<template #body="{ entity }"> <template #body="{ entity }">
<QList dense> <VnLv v-if="entity.salesPersonUser" :label="t('customer.card.salesPerson')">
<QItem v-if="entity.salesPersonUser" class="row"> <template #value>
<QItemLabel class="col" caption> <span class="link">
{{ t('customer.card.salesPerson') }} {{ entity.salesPersonUser.name }}
</QItemLabel> <WorkerDescriptorProxy :id="entity.salesPersonFk" />
<QItemLabel class="col q-ma-none"> </span>
<span class="link"> </template>
{{ entity.salesPersonUser.name }} </VnLv>
<WorkerDescriptorProxy :id="entity.salesPersonFk" /> <VnLv :label="t('customer.card.credit')" :value="toCurrency(entity.credit)" />
</span> <VnLv
</QItemLabel> :label="t('customer.card.securedCredit')"
</QItem> :value="toCurrency(entity.creditInsurance)"
<QItem class="row"> />
<QItemLabel class="col" caption> <VnLv :label="t('customer.card.payMethod')" :value="entity.payMethod.name" />
{{ t('customer.card.credit') }} <VnLv :label="t('customer.card.debt')" :value="toCurrency(entity.debt)" />
</QItemLabel> </template>
<QItemLabel class="col q-ma-none"> <template #icons="{ entity }">
{{ toCurrency(entity.credit) }} <QCardActions>
</QItemLabel>
</QItem>
<QItem class="row">
<QItemLabel class="col" caption>
{{ t('customer.card.securedCredit') }}
</QItemLabel>
<QItemLabel class="col q-ma-none">
{{ toCurrency(entity.creditInsurance) }}
</QItemLabel>
</QItem>
<QItem v-if="entity.payMethod" class="row">
<QItemLabel class="col" caption>
{{ t('customer.card.payMethod') }}
</QItemLabel>
<QItemLabel class="col q-ma-none">
{{ entity.payMethod.name }}
</QItemLabel>
</QItem>
<QItem class="row">
<QItemLabel class="col" caption>
{{ t('customer.card.debt') }}
</QItemLabel>
<QItemLabel class="col q-ma-none">
{{ toCurrency(entity.debt) }}
</QItemLabel>
</QItem>
</QList>
<QCardActions class="q-gutter-md">
<QIcon <QIcon
v-if="entity.isActive == false" v-if="entity.isActive == false"
name="vn:disabled" name="vn:disabled"
@ -103,15 +86,9 @@ const entityId = computed(() => {
> >
<QTooltip>{{ t('customer.card.notChecked') }}</QTooltip> <QTooltip>{{ t('customer.card.notChecked') }}</QTooltip>
</QIcon> </QIcon>
<QIcon
v-if="entity.account && entity.account.active == false"
name="vn:noweb"
size="xs"
color="primary"
>
<QTooltip>{{ t('customer.card.noWebAccess') }}</QTooltip>
</QIcon>
</QCardActions> </QCardActions>
</template>
<template #actions="{ entity }">
<QCardActions> <QCardActions>
<QBtn <QBtn
:to="{ :to="{
@ -135,23 +112,10 @@ const entityId = computed(() => {
> >
<QTooltip>{{ t('invoiceOutList') }}</QTooltip> <QTooltip>{{ t('invoiceOutList') }}</QTooltip>
</QBtn> </QBtn>
<!--
<QBtn size="md" icon="vn:basketadd" color="primary">
<QTooltip>Order list</QTooltip>
</QBtn>
<QBtn size="md" icon="face" color="primary">
<QTooltip>View user</QTooltip>
</QBtn>
<QBtn size="md" icon="expand_more" color="primary">
<QTooltip>More options</QTooltip>
</QBtn> -->
</QCardActions> </QCardActions>
</template> </template>
</CardDescriptor> </CardDescriptor>
</template> </template>
<i18n> <i18n>
{ {
"en": { "en": {

View File

@ -5,6 +5,8 @@ import { useI18n } from 'vue-i18n';
import { toCurrency, toDate } from 'src/filters'; import { toCurrency, toDate } from 'src/filters';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -42,6 +44,8 @@ const filter = {
function ticketFilter(invoice) { function ticketFilter(invoice) {
return JSON.stringify({ refFk: invoice.ref }); return JSON.stringify({ refFk: invoice.ref });
} }
const data = ref(useCardDescription());
const setData = (entity) => (data.value = useCardDescription(entity.ref, entity.id));
</script> </script>
<template> <template>
@ -50,47 +54,31 @@ function ticketFilter(invoice) {
module="InvoiceOut" module="InvoiceOut"
:url="`InvoiceOuts/${entityId}`" :url="`InvoiceOuts/${entityId}`"
:filter="filter" :filter="filter"
:title="data.title"
:subtitle="data.subtitle"
@on-fetch="setData"
> >
<template #description="{ entity }">
<span>
{{ entity.ref }}
<QTooltip>{{ entity.ref }}</QTooltip>
</span>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<QList> <VnLv :label="t('invoiceOut.card.issued')" :value="toDate(entity.issued)" />
<QItem> <VnLv
<QItemSection> :label="t('invoiceOut.card.amount')"
<QItemLabel caption> :value="toCurrency(entity.amount)"
{{ t('invoiceOut.card.issued') }} />
</QItemLabel> <VnLv v-if="entity.client" :label="t('invoiceOut.card.client')">
<QItemLabel>{{ toDate(entity.issued) }}</QItemLabel> <template #value>
</QItemSection> <span class="link">
<QItemSection> {{ entity.client.name }}
<QItemLabel caption> <CustomerDescriptorProxy :id="entity.client.id" />
{{ t('invoiceOut.card.amount') }} </span>
</QItemLabel> </template>
<QItemLabel>{{ toCurrency(entity.amount) }}</QItemLabel> </VnLv>
</QItemSection> <VnLv
</QItem> v-if="entity.company"
<QItem> :label="t('invoiceOut.card.company')"
<QItemSection v-if="entity.client"> :value="entity.company.code"
<QItemLabel caption> />
{{ t('invoiceOut.card.client') }} </template>
</QItemLabel> <template #actions="{ entity }">
<QItemLabel class="link">
{{ entity.client.name }}
<CustomerDescriptorProxy :id="entity.client.id" />
</QItemLabel>
</QItemSection>
<QItemSection v-if="entity.company">
<QItemLabel caption>{{
t('invoiceOut.card.company')
}}</QItemLabel>
<QItemLabel>{{ entity.company.code }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
<QCardActions> <QCardActions>
<QBtn <QBtn
v-if="entity.client" v-if="entity.client"

View File

@ -1,11 +1,13 @@
<script setup> <script setup>
import { computed } from 'vue'; import { ref, computed } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { toDate } from 'src/filters'; import { toDate } from 'src/filters';
import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'pages/Customer/Card/CustomerDescriptorProxy.vue';
import CardDescriptor from 'components/ui/CardDescriptor.vue'; import CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue'; import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
@ -66,78 +68,58 @@ const filter = {
], ],
}; };
function stateColor(state) { const data = ref(useCardDescription());
if (state.code === 'OK') return 'text-green'; const setData = (entity) =>
if (state.code === 'FREE') return 'text-blue-3'; (data.value = useCardDescription(entity.client.name, entity.id));
if (state.alertLevel === 1) return 'text-primary';
if (state.alertLevel === 0) return 'text-red';
}
</script> </script>
<template> <template>
<CardDescriptor module="Ticket" :url="`Tickets/${entityId}`" :filter="filter"> <CardDescriptor
module="Ticket"
:url="`Tickets/${entityId}`"
:filter="filter"
:title="data.title"
:subtitle="data.subtitle"
@on-fetch="setData"
>
<template #menu="{ entity }"> <template #menu="{ entity }">
<TicketDescriptorMenu :ticket="entity" /> <TicketDescriptorMenu :ticket="entity" />
</template> </template>
<template #description="{ entity }">
<span>
{{ entity.client.name }}
<QTooltip>{{ entity.client.name }}</QTooltip>
</span>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<QList> <VnLv v-if="entity.ticketState" :label="t('ticket.card.state')">
<QItem> <template #value>
<QItemSection v-if="entity.ticketState"> <QBadge :color="entity.ticketState.state.classColor ?? 'dark'">
<QItemLabel caption>{{ t('ticket.card.state') }}</QItemLabel> {{ entity.ticketState.state.name }}
<QItemLabel :class="stateColor(entity.ticketState.state)"> </QBadge>
{{ entity.ticketState.state.name }} </template>
</QItemLabel> </VnLv>
</QItemSection> <VnLv :label="t('ticket.card.shipped')" :value="toDate(entity.shipped)" />
<QItemSection> <VnLv :label="t('ticket.card.customerId')">
<QItemLabel caption> <template #value>
{{ t('ticket.card.shipped') }} <span class="link">
</QItemLabel> {{ entity.clientFk }}
<QItemLabel>{{ toDate(entity.shipped) }}</QItemLabel> <CustomerDescriptorProxy :id="entity.client.id" />
</QItemSection> </span>
</QItem> </template>
<QItem> </VnLv>
<QItemSection> <VnLv
<QItemLabel caption> v-if="entity.client && entity.client.salesPersonUser"
{{ t('ticket.card.customerId') }} :label="t('ticket.card.salesPerson')"
</QItemLabel> :value="entity.client.salesPersonUser.name"
<QItemLabel> />
<span class="link"> <VnLv
{{ entity.clientFk }} v-if="entity.warehouse"
<CustomerDescriptorProxy :id="entity.client.id" /> :label="t('ticket.card.warehouse')"
</span> :value="entity.warehouse.name"
</QItemLabel> />
</QItemSection> <VnLv
<QItemSection v-if="entity.client && entity.client.salesPersonUser"> v-if="entity.agencyMode"
<QItemLabel caption> :label="t('ticket.card.agency')"
{{ t('ticket.card.salesPerson') }} :value="entity.agencyMode.name"
</QItemLabel> />
<QItemLabel> </template>
{{ entity.client.salesPersonUser.name }} <template #icons="{ entity }">
</QItemLabel> <QCardActions>
</QItemSection>
</QItem>
<QItem>
<QItemSection v-if="entity.warehouse">
<QItemLabel caption>
{{ t('ticket.card.warehouse') }}
</QItemLabel>
<QItemLabel>{{ entity.warehouse.name }}</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.agencyMode">
<QItemSection>
<QItemLabel caption>{{ t('ticket.card.agency') }}</QItemLabel>
<QItemLabel>{{ entity.agencyMode.name }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
<QCardActions class="q-gutter-md">
<QIcon <QIcon
v-if="entity.isDeleted == true" v-if="entity.isDeleted == true"
name="vn:deletedTicket" name="vn:deletedTicket"
@ -147,7 +129,8 @@ function stateColor(state) {
<QTooltip>{{ t('This ticket is deleted') }}</QTooltip> <QTooltip>{{ t('This ticket is deleted') }}</QTooltip>
</QIcon> </QIcon>
</QCardActions> </QCardActions>
</template>
<template #actions="{ entity }">
<QCardActions> <QCardActions>
<QBtn <QBtn
size="md" size="md"

View File

@ -135,10 +135,16 @@ async function changeState(value) {
<QItemLabel caption> <QItemLabel caption>
{{ t('ticket.summary.state') }} {{ t('ticket.summary.state') }}
</QItemLabel> </QItemLabel>
<QItemLabel <QItemLabel>
:class="stateColor(ticket.ticketState.state)" <QBadge
> :color="
{{ ticket.ticketState.state.name }} ticket.ticketState.state.classColor
? ticket.ticketState.state.classColor
: 'dark'
"
>
{{ ticket.ticketState.state.name }}
</QBadge>
</QItemLabel> </QItemLabel>
</QItemSection> </QItemSection>
</QItem> </QItem>

View File

@ -18,34 +18,6 @@ const stateStore = useStateStore();
onMounted(() => (stateStore.rightDrawer = true)); onMounted(() => (stateStore.rightDrawer = true));
onUnmounted(() => (stateStore.rightDrawer = false)); onUnmounted(() => (stateStore.rightDrawer = false));
const filter = {
include: [
{
relation: 'client',
scope: {
include: {
relation: 'salesPersonUser',
scope: {
fields: ['name'],
},
},
},
},
{
relation: 'ticketState',
scope: {
fields: ['stateFk', 'code', 'alertLevel'],
include: {
relation: 'state',
scope: {
fields: ['name'],
},
},
},
},
],
};
const from = Date.vnNew(); const from = Date.vnNew();
const to = Date.vnNew(); const to = Date.vnNew();
to.setDate(to.getDate() + 1); to.setDate(to.getDate() + 1);
@ -55,14 +27,6 @@ const userParams = {
to: toDateString(to), to: toDateString(to),
}; };
function stateColor(row) {
if (row.alertLevelCode === 'OK') return 'green';
if (row.alertLevelCode === 'FREE') return 'blue-3';
if (row.alertLevel === 1) return 'orange';
if (row.alertLevel === 0) return 'red';
return 'red';
}
function navigate(id) { function navigate(id) {
router.push({ path: `/ticket/${id}` }); router.push({ path: `/ticket/${id}` });
} }
@ -112,7 +76,6 @@ function viewSummary(id) {
<VnPaginate <VnPaginate
data-key="TicketList" data-key="TicketList"
url="Tickets/filter" url="Tickets/filter"
:filter="filter"
:user-params="userParams" :user-params="userParams"
order="id DESC" order="id DESC"
auto-load auto-load
@ -143,7 +106,7 @@ function viewSummary(id) {
</QItemLabel> </QItemLabel>
<QItemLabel> <QItemLabel>
<QBadge <QBadge
:color="stateColor(row)" :color="row.classColor ?? 'dark'"
class="q-ma-none" class="q-ma-none"
dense dense
> >

View File

@ -4,7 +4,8 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useSession } from 'src/composables/useSession'; import { useSession } from 'src/composables/useSession';
import CardDescriptor from 'src/components/ui/CardDescriptor.vue'; import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
@ -52,13 +53,22 @@ function getWorkerAvatar() {
const token = getToken(); const token = getToken();
return `/api/Images/user/160x160/${route.params.id}/download?access_token=${token}`; return `/api/Images/user/160x160/${route.params.id}/download?access_token=${token}`;
} }
const data = ref(useCardDescription());
const setData = (entity) =>
(data.value = useCardDescription(entity.user.nickname, entity.id));
</script> </script>
<template> <template>
<CardDescriptor <CardDescriptor
module="Worker" module="Worker"
:url="`Workers/${entityId}`" :url="`Workers/${entityId}`"
:filter="filter" :filter="filter"
@on-fetch="(data) => (worker = data)" :title="data.title"
@on-fetch="
(data) => {
worker = data;
setData(data);
}
"
> >
<template #before> <template #before>
<QImg :src="getWorkerAvatar()" class="photo"> <QImg :src="getWorkerAvatar()" class="photo">
@ -78,55 +88,15 @@ function getWorkerAvatar() {
</template> </template>
</QImg> </QImg>
</template> </template>
<template #description="{ entity }">
<span>
{{ entity.user.nickname }}
<QTooltip>{{ entity.user.nickname }}</QTooltip>
</span>
</template>
<template #body="{ entity }"> <template #body="{ entity }">
<QList> <VnLv :label="t('worker.card.name')" :value="entity.user.nickname" />
<QItem> <VnLv :label="t('worker.card.email')" :value="entity.user.email"> </VnLv>
<QItemSection> <VnLv
<QItemLabel caption> {{ t('worker.card.name') }} </QItemLabel> :label="t('worker.list.department')"
<QItemLabel>{{ entity.user.nickname }}</QItemLabel> :value="entity.department ? entity.department.department.name : null"
</QItemSection> />
</QItem> <VnLv :label="t('worker.card.phone')" :value="entity.phone" />
<QItem> <VnLv :label="t('worker.summary.sipExtension')" :value="sip" />
<QItemSection>
<QItemLabel caption>
{{ t('worker.card.email') }}
</QItemLabel>
<QItemLabel>{{ entity.user.email }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('worker.list.department') }}
</QItemLabel>
<QItemLabel>
{{ entity.department.department.name }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('worker.card.phone') }}
</QItemLabel>
<QItemLabel>{{ entity.phone }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.summary.sipExtension') }}
</QItemLabel>
<QItemLabel>{{ sip }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</template> </template>
</CardDescriptor> </CardDescriptor>
</template> </template>