5990-reStyle_summary #82

Merged
alexm merged 7 commits from 5990-reStyle_summary into dev 2023-08-17 05:44:50 +00:00
13 changed files with 947 additions and 1640 deletions

View File

@ -31,7 +31,7 @@ function findMatches(search, item) {
const matches = []; const matches = [];
function findRoute(search, item) { function findRoute(search, item) {
for (const child of item.children) { for (const child of item.children) {
if (search.indexOf(child.name) > -1) { if (search?.indexOf(child.name) > -1) {
matches.push(child); matches.push(child);
} else if (child.children) { } else if (child.children) {
findRoute(search, child); findRoute(search, child);

View File

@ -2,6 +2,8 @@
import { onMounted, ref, watch } from 'vue'; import { onMounted, ref, watch } from 'vue';
import axios from 'axios'; import axios from 'axios';
import SkeletonSummary from 'components/ui/SkeletonSummary.vue'; import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
onMounted(() => fetch()); onMounted(() => fetch());
const entity = ref(); const entity = ref();
@ -41,15 +43,21 @@ watch(props, async () => {
<template> <template>
<div class="summary container"> <div class="summary container">
<QCard> <QCard class="cardSummary">
<SkeletonSummary v-if="!entity" /> <SkeletonSummary v-if="!entity" />
<template v-if="entity"> <template v-if="entity">
<div class="header bg-primary q-pa-sm q-mb-md"> <div class="summaryHeader bg-primary q-pa-md text-weight-bolder">
<slot name="header-left">
<span></span>
</slot>
<slot name="header" :entity="entity"> <slot name="header" :entity="entity">
{{ entity.id }} - {{ entity.name }} <VnLv :label="`${entity.id} -`" :value="entity.name" />
</slot>
<slot name="header-right">
<span></span>
</slot> </slot>
</div> </div>
<div class="body q-pa-md q-mb-md"> <div class="summaryBody row q-mb-md">
<slot name="body" :entity="entity" /> <slot name="body" :entity="entity" />
</div> </div>
</template> </template>
@ -63,57 +71,84 @@ watch(props, async () => {
justify-content: center; justify-content: center;
} }
.summary { .cardSummary {
.q-card { width: 100%;
width: 100%; .summaryHeader {
max-width: 1200px;
}
.negative {
color: red;
}
.q-list {
.q-item__label--header {
display: flex;
justify-content: space-between;
a {
color: $primary;
}
}
}
.body > .q-card__section.row {
flex-wrap: wrap;
& > .col {
min-width: 250px;
}
}
.header {
text-align: center; text-align: center;
font-size: 18px; font-size: 20px;
display: flex;
justify-content: space-between;
} }
.summaryBody {
display: flex;
flex-direction: row;
justify-content: space-evenly;
gap: 15px;
padding: 15px;
#slider-container { > .q-card.vn-one {
max-width: 80%; flex: 1;
margin: 0 auto; }
> .q-card.vn-two {
flex: 2;
}
> .q-card.vn-three {
flex: 3;
}
> .q-card.vn-max {
width: 100%;
}
.q-slider { > .q-card {
.q-slider__marker-labels:nth-child(1) { width: 100%;
transform: none; background-color: var(--vn-gray);
padding: 15px;
font-size: 16px;
min-width: 275px;
.vn-label-value {
display: flex;
flex-direction: row;
margin-top: 5px;
.label {
color: var(--vn-label);
width: 10em;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
margin-right: 10px;
}
.value {
color: var(--vn-text);
width: max-content;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
} }
.q-slider__marker-labels:nth-child(2) { .header {
transform: none; color: $primary;
left: auto !important; font-weight: bold;
right: 0%; margin-bottom: 25px;
font-size: 20px;
display: inline-block;
}
.header.link:hover {
color: lighten($primary, 20%);
} }
} }
} }
}
.q-dialog .summary { @media (max-width: $breakpoint-xs) {
max-width: 1200px; .summaryBody {
padding: 0;
}
}
}
</style>
<style lang="scss" scoped>
.summaryHeader .vn-label-value {
display: flex;
flex-direction: row;
} }
</style> </style>

View File

@ -1,5 +1,7 @@
<script setup> <script setup>
import { computed } from 'vue'; import { computed } from 'vue';
import { dashIfEmpty } from 'src/filters';
const $props = defineProps({ const $props = defineProps({
label: { type: String, default: null }, label: { type: String, default: null },
value: { value: {
@ -7,6 +9,7 @@ const $props = defineProps({
default: null, default: null,
}, },
info: { type: String, default: null }, info: { type: String, default: null },
dash: { type: Boolean, default: true },
}); });
const isBooleanValue = computed(() => typeof $props.value === 'boolean'); const isBooleanValue = computed(() => typeof $props.value === 'boolean');
</script> </script>
@ -17,15 +20,18 @@ const isBooleanValue = computed(() => typeof $props.value === 'boolean');
<span>{{ $props.label }}</span> <span>{{ $props.label }}</span>
</slot> </slot>
</div> </div>
<div v-if="$props.value || $slots.value" class="value"> <div class="value">
<span v-if="isBooleanValue"> <span v-if="isBooleanValue">
<QIcon <QIcon
:name="$props.value ? `check` : `close`" :name="$props.value ? `check` : `close`"
:color="$props.value ? `positive` : `negative`" :color="$props.value ? `positive` : `negative`"
size="sm"
/> />
</span> </span>
<slot v-else name="value"> <slot v-else name="value">
<span :title="$props.value">{{ $props.value }}</span> <span :title="$props.value">
{{ $props.dash ? dashIfEmpty($props.value) : $props.value }}
</span>
</slot> </slot>
</div> </div>
<div class="info" v-if="$props.info"> <div class="info" v-if="$props.info">

View File

@ -35,4 +35,13 @@ body.body--light {
color: white; color: white;
} }
} }
--vn-text: #000000;
Review

He vist que de esta manera pots difinir variables que canvien segons el modo de color

He vist que de esta manera pots difinir variables que canvien segons el modo de color
--vn-gray: #dddddd;
--vn-label: #5f5f5f;
}
body.body--dark {
--vn-text: #ffffff;
--vn-gray: #313131;
--vn-label: #a8a8a8;
} }

View File

@ -47,4 +47,4 @@ $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); $label-color: #ffffff99;

View File

@ -33,6 +33,9 @@ export default {
rowRemoved: 'Row removed', rowRemoved: 'Row removed',
pleaseWait: 'Please wait...', pleaseWait: 'Please wait...',
noPinnedModules: 'You have dont have any pinned modules', noPinnedModules: 'You have dont have any pinned modules',
summary: {
basicData: 'Basic data',
},
}, },
errors: { errors: {
statusUnauthorized: 'Access denied', statusUnauthorized: 'Access denied',
@ -154,6 +157,8 @@ export default {
balanceDue: 'Balance due', balanceDue: 'Balance due',
balanceDueInfo: 'Deviated invoices minus payments', balanceDueInfo: 'Deviated invoices minus payments',
recoverySince: 'Recovery since', recoverySince: 'Recovery since',
businessType: 'Business Type',
city: 'City',
}, },
basicData: { basicData: {
socialName: 'Fiscal name', socialName: 'Fiscal name',
@ -175,6 +180,7 @@ export default {
basicData: 'Basic Data', basicData: 'Basic Data',
boxing: 'Boxing', boxing: 'Boxing',
sms: 'Sms', sms: 'Sms',
notes: 'Notes',
}, },
list: { list: {
nickname: 'Nickname', nickname: 'Nickname',
@ -244,6 +250,7 @@ export default {
requester: 'Requester', requester: 'Requester',
atender: 'Atender', atender: 'Atender',
request: 'Request', request: 'Request',
weight: 'Weight',
goTo: 'Go to', goTo: 'Go to',
}, },
}, },
@ -411,6 +418,7 @@ export default {
userId: 'User ID', userId: 'User ID',
role: 'Role', role: 'Role',
sipExtension: 'Extension', sipExtension: 'Extension',
locker: 'Locker',
}, },
notificationsManager: { notificationsManager: {
activeNotifications: 'Active notifications', activeNotifications: 'Active notifications',

View File

@ -33,6 +33,9 @@ export default {
rowRemoved: 'Fila eliminada', rowRemoved: 'Fila eliminada',
pleaseWait: 'Por favor, espera...', pleaseWait: 'Por favor, espera...',
noPinnedModules: 'No has fijado ningún módulo', noPinnedModules: 'No has fijado ningún módulo',
summary: {
basicData: 'Datos básicos',
},
}, },
errors: { errors: {
statusUnauthorized: 'Acceso denegado', statusUnauthorized: 'Acceso denegado',
@ -119,7 +122,7 @@ export default {
province: 'Provincia', province: 'Provincia',
country: 'País', country: 'País',
street: 'Calle', street: 'Calle',
isEqualizated: 'Equalizado', isEqualizated: 'Recargo de equivalencia',
isActive: 'Activo', isActive: 'Activo',
invoiceByAddress: 'Facturar por consignatario', invoiceByAddress: 'Facturar por consignatario',
verifiedData: 'Datos verificados', verifiedData: 'Datos verificados',
@ -153,6 +156,8 @@ export default {
balanceDue: 'Saldo vencido', balanceDue: 'Saldo vencido',
balanceDueInfo: 'Facturas fuera de plazo menos recibos', balanceDueInfo: 'Facturas fuera de plazo menos recibos',
recoverySince: 'Recobro desde', recoverySince: 'Recobro desde',
businessType: 'Tipo de negocio',
city: 'Población',
}, },
basicData: { basicData: {
socialName: 'Nombre fiscal', socialName: 'Nombre fiscal',
@ -174,6 +179,7 @@ export default {
basicData: 'Datos básicos', basicData: 'Datos básicos',
boxing: 'Encajado', boxing: 'Encajado',
sms: 'Sms', sms: 'Sms',
notes: 'Notas',
}, },
list: { list: {
nickname: 'Alias', nickname: 'Alias',
@ -243,6 +249,7 @@ export default {
requester: 'Solicitante', requester: 'Solicitante',
atender: 'Comprador', atender: 'Comprador',
request: 'Petición de compra', request: 'Petición de compra',
weight: 'Peso',
goTo: 'Ir a', goTo: 'Ir a',
}, },
}, },
@ -411,6 +418,7 @@ export default {
userId: 'ID del usuario', userId: 'ID del usuario',
role: 'Rol', role: 'Rol',
sipExtension: 'Extensión', sipExtension: 'Extensión',
locker: 'Taquilla',
}, },
notificationsManager: { notificationsManager: {
activeNotifications: 'Notificaciones activas', activeNotifications: 'Notificaciones activas',

View File

@ -1,12 +1,14 @@
<script setup> <script setup>
import { ref, computed } from 'vue'; import { onMounted, 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, toCurrency } from 'src/filters'; import { toDate, toCurrency } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import WorkerDescriptorProxy from 'pages/Worker/Card/WorkerDescriptorProxy.vue';
import FetchData from 'components/FetchData.vue'; import FetchData from 'components/FetchData.vue';
import { getUrl } from 'src/composables/getUrl';
import { useSession } from 'src/composables/useSession'; import { useSession } from 'src/composables/useSession';
import WorkerDescriptorProxy from 'pages/Worker/Card/WorkerDescriptorProxy.vue';
import VnLv from 'src/components/ui/VnLv.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -22,6 +24,14 @@ const $props = defineProps({
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const claimUrl = ref();
const salixUrl = ref();
onMounted(async () => {
salixUrl.value = await getUrl('');
claimUrl.value = salixUrl.value + `claim/${entityId.value}/`;
});
const detailsColumns = ref([ const detailsColumns = ref([
{ {
name: 'item', name: 'item',
@ -155,78 +165,52 @@ function openDialog(dmsId) {
<template #header="{ entity: { claim } }"> <template #header="{ entity: { claim } }">
{{ claim.id }} - {{ claim.client.name }} {{ claim.id }} - {{ claim.client.name }}
</template> </template>
<template #body="{ entity: { developments, observations, claim, salesClaimed } }"> <template #body="{ entity: { claim, salesClaimed, developments } }">
<QCardSection class="row q-pa-none q-col-gutter-md"> <QCard class="vn-one">
<div class="col"> <a class="header" :href="`#/claim/${entityId}/basic-data`">
<QList> {{ t('claim.pageTitles.basicData') }}
<QItem> <QIcon name="open_in_new" color="primary" />
<QItemSection> </a>
<QItemLabel caption> <VnLv
{{ t('claim.summary.created') }} :label="t('claim.summary.created')"
</QItemLabel> :value="toDate(claim.created)"
<QItemLabel>{{ toDate(claim.created) }}</QItemLabel> />
</QItemSection> <VnLv :label="t('claim.summary.state')">
<QItemSection v-if="claim.claimState"> <template #value>
<QItemLabel caption> <QChip :color="stateColor(claim.claimState.code)" dense>
{{ t('claim.summary.state') }} {{ claim.claimState.description }}
</QItemLabel> </QChip>
<QItemLabel> </template>
<QChip </VnLv>
:color="stateColor(claim.claimState.code)" <VnLv :label="t('claim.summary.assignedTo')">
dense <template #value>
> <span class="link">
{{ claim.claimState.description }} {{ claim.worker.user.nickname }}
</QChip> <WorkerDescriptorProxy :id="claim.workerFk" />
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection v-if="claim.worker && claim.worker.user">
<QItemLabel caption>
{{ t('claim.summary.assignedTo') }}
</QItemLabel>
<QItemLabel>
<span class="link">
{{ claim.worker.user.nickname }}
<WorkerDescriptorProxy :id="claim.workerFk" />
</span>
</QItemLabel>
</QItemSection>
<QItemSection
v-if="claim.client && claim.client.salesPersonUser"
>
<QItemLabel caption>
{{ t('claim.summary.attendedBy') }}
</QItemLabel>
<QItemLabel>
<span class="link">
{{ claim.client.salesPersonUser.name }}
<WorkerDescriptorProxy
:id="claim.client.salesPersonFk"
/>
</span>
</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
</QCardSection>
<QCardSection class="q-pa-md" v-if="observations.length > 0">
<h6>{{ t('claim.summary.notes') }}</h6>
<div class="note-list" v-for="note in observations" :key="note.id">
<div class="note-caption">
<span
>{{ note.worker.firstName }} {{ note.worker.lastName }}
</span> </span>
<span>{{ toDate(note.created) }}</span> </template>
</div> </VnLv>
<div class="note-text"> <VnLv :label="t('claim.summary.attendedBy')">
<span>{{ note.text }}</span> <template #value>
</div> <span class="link">
</div> {{ claim.client.salesPersonUser.name }}
</QCardSection> <WorkerDescriptorProxy :id="claim.client.salesPersonFk" />
<QCardSection class="q-pa-md" v-if="salesClaimed.length > 0"> </span>
<h6>{{ t('claim.summary.details') }}</h6> </template>
</VnLv>
</QCard>
<QCard class="vn-one">
<a class="header" :href="claimUrl + 'note/index'">
{{ t('claim.summary.notes') }}
<QIcon name="open_in_new" color="primary" />
</a>
<!-- Use VnNotes and maybe VirtualScroll-->
</QCard>
<QCard class="vn-max" v-if="salesClaimed.length > 0">
<a class="header" :href="claimUrl + 'note/index'">
{{ t('claim.summary.details') }}
<QIcon name="open_in_new" color="primary" />
</a>
<QTable :columns="detailsColumns" :rows="salesClaimed" flat> <QTable :columns="detailsColumns" :rows="salesClaimed" flat>
<template #header="props"> <template #header="props">
<QTr :props="props"> <QTr :props="props">
@ -236,16 +220,19 @@ function openDialog(dmsId) {
</QTr> </QTr>
</template> </template>
</QTable> </QTable>
</QCardSection> </QCard>
<QCardSection class="q-pa-md" v-if="claimDms.length > 0"> <QCard class="vn-max" v-if="claimDms.length > 0">
<h6>{{ t('claim.summary.photos') }}</h6> <a class="header" :href="`#/claim/${entityId}/photos`">
{{ t('claim.summary.photos') }}
<QIcon name="open_in_new" color="primary" />
</a>
<div class="container"> <div class="container">
<div class="multimediaParent bg-transparent"> <div
<div class="multimedia-container"
v-for="(media, index) of claimDms" v-for="(media, index) of claimDms"
:key="index" :key="index"
class="relative-position" >
> <div class="relative-position">
<QIcon <QIcon
name="play_circle" name="play_circle"
color="primary" color="primary"
@ -275,9 +262,12 @@ function openDialog(dmsId) {
</div> </div>
</div> </div>
</div> </div>
</QCardSection> </QCard>
<QCardSection class="q-pa-md" v-if="developments.length > 0"> <QCard class="vn-two" v-if="developments.length > 0">
<h6>{{ t('claim.summary.development') }}</h6> <a class="header" :href="claimUrl + 'development'">
{{ t('claim.summary.development') }}
<QIcon name="open_in_new" color="primary" />
</a>
<QTable :columns="developmentColumns" :rows="developments" flat> <QTable :columns="developmentColumns" :rows="developments" flat>
<template #header="props"> <template #header="props">
<QTr :props="props"> <QTr :props="props">
@ -287,11 +277,13 @@ function openDialog(dmsId) {
</QTr> </QTr>
</template> </template>
</QTable> </QTable>
</QCardSection> </QCard>
<QCardSection class="q-pa-md"> <QCard class="vn-max" v-if="developments.length > 0">
<h6>{{ t('claim.summary.actions') }}</h6> <a class="header" :href="claimUrl + 'action'">
<QSeparator /> {{ t('claim.summary.actions') }}
<div id="slider-container"> <QIcon name="open_in_new" color="primary" />
</a>
<div id="slider-container" class="q-px-xl q-py-md">
<QSlider <QSlider
v-model="claim.responsibility" v-model="claim.responsibility"
label label
@ -308,7 +300,21 @@ function openDialog(dmsId) {
readonly readonly
/> />
</div> </div>
</QCardSection> </QCard>
<!-- <QCardSection class="q-pa-md" v-if="observations.length > 0">
<h6>{{ t('claim.summary.notes') }}</h6>
<div class="note-list" v-for="note in observations" :key="note.id">
<div class="note-caption">
<span
>{{ note.worker.firstName }} {{ note.worker.lastName }}
</span>
<span>{{ toDate(note.created) }}</span>
</div>
<div class="note-text">
<span>{{ note.text }}</span>
</div>
</div>
</QCardSection> -->
<QDialog <QDialog
v-model="multimediaDialog" v-model="multimediaDialog"
transition-show="slide-up" transition-show="slide-up"
@ -352,22 +358,19 @@ function openDialog(dmsId) {
</CardSummary> </CardSummary>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.container {
min-width: 80%;
}
.q-dialog__inner--minimized > div { .q-dialog__inner--minimized > div {
max-width: 80%; max-width: 80%;
} }
.container {
.multimediaParent { display: flex;
display: grid; flex-direction: row;
grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); flex-wrap: wrap;
gap: 15px;
grid-auto-rows: auto; flex-basis: 30%;
}
grid-gap: 1rem; .multimedia-container {
flex: 1 0 21%;
} }
.multimedia { .multimedia {
transition: all 0.5s; transition: all 0.5s;
opacity: 1; opacity: 1;
@ -395,18 +398,4 @@ function openDialog(dmsId) {
.zindex { .zindex {
z-index: 1; z-index: 1;
} }
.note-list {
width: 100%;
border: 0.1rem solid $grey-7;
padding: 0.5rem;
margin-bottom: 0.5rem;
}
.note-caption {
display: flex;
justify-content: space-between;
margin-bottom: 0.5rem;
color: $grey-7;
}
</style> </style>

View File

@ -1,9 +1,11 @@
<script setup> <script setup>
import { computed, ref } from 'vue'; import { computed, ref, onMounted } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { toCurrency, toPercentage, toDate } from 'src/filters'; import { toCurrency, toPercentage, toDate } from 'src/filters';
import CardSummary from 'components/ui/CardSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import { getUrl } from 'src/composables/getUrl';
import VnLv from 'src/components/ui/VnLv.vue';
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -16,8 +18,13 @@ const $props = defineProps({
}); });
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const summary = ref();
const customer = computed(() => summary.value.entity); const customer = computed(() => summary.value.entity);
const summary = ref();
const clientUrl = ref();
onMounted(async () => {
clientUrl.value = (await getUrl('client/')) + entityId.value + '/';
});
const balanceDue = computed(() => { const balanceDue = computed(() => {
return ( return (
@ -38,7 +45,7 @@ const priceIncreasingRate = computed(() => {
}); });
const debtWarning = computed(() => { const debtWarning = computed(() => {
return customer.value.debt.debt > customer.value.credit ? 'negative' : ''; return customer.value?.debt?.debt > customer.value.credit ? 'negative' : '';
}); });
const creditWarning = computed(() => { const creditWarning = computed(() => {
@ -53,478 +60,212 @@ const creditWarning = computed(() => {
<template> <template>
<CardSummary ref="summary" :url="`Clients/${entityId}/summary`"> <CardSummary ref="summary" :url="`Clients/${entityId}/summary`">
<template #body="{ entity }"> <template #body="{ entity }">
<QCardSection class="row q-pa-none QCol-gutter-md"> <QCard class="vn-one">
<div class="col"> <a class="header" :href="clientUrl + `basic-data`">
<QList dense> {{ t('customer.summary.basicData') }}
<QItemLabel header class="text-h6"> <QIcon name="open_in_new" color="primary" />
{{ t('customer.summary.basicData') }} </a>
<RouterLink <VnLv :label="t('customer.summary.customerId')" :value="entity.id" />
:to="{ <VnLv :label="t('customer.summary.name')" :value="entity.name" />
name: 'CustomerBasicData', <VnLv :label="t('customer.summary.contact')" :value="entity.contact" />
params: { id: entity.id }, <VnLv :label="t('customer.summary.phone')" :value="entity.phone" />
}" <VnLv :label="t('customer.summary.mobile')" :value="entity.mobile" />
target="_blank" <VnLv :label="t('customer.summary.email')" :value="entity.email" />
> <VnLv
<QIcon name="open_in_new" /> :label="t('customer.summary.salesPerson')"
</RouterLink> :value="entity?.salesPersonUser?.name"
</QItemLabel> />
<QSeparator class="q-mb-md" /> <VnLv
:label="t('customer.summary.contactChannel')"
:value="entity?.contactChannel?.name"
/>
<VnLv
:label="t('customer.summary.businessType')"
:value="entity.businessType.description"
/>
</QCard>
<QCard class="vn-one">
<a class="header" :href="clientUrl + `fiscal-data`">
{{ t('customer.summary.fiscalAddress') }}
<QIcon name="open_in_new" color="primary" />
</a>
<VnLv
:label="t('customer.summary.socialName')"
:value="entity.socialName"
/>
<VnLv :label="t('customer.summary.fiscalId')" :value="entity.fi" />
<VnLv :label="t('customer.summary.city')" :value="entity.city" />
<VnLv :label="t('customer.summary.postcode')" :value="entity.postcode" />
<QItem class="row col"> <VnLv
<QItemLabel class="col" caption> v-if="entity.province"
{{ t('customer.summary.customerId') }} :label="t('customer.summary.province')"
</QItemLabel> :value="entity.province.name"
<QItemLabel class="col q-ma-none"> />
{{ entity.id }} <VnLv
</QItemLabel> v-if="entity.country"
</QItem> :label="t('customer.summary.country')"
<QItem class="row col"> :value="entity.country.country"
<QItemLabel class="col" caption> />
{{ t('customer.summary.name') }} <VnLv :label="t('customer.summary.street')" :value="entity.street" />
</QItemLabel> </QCard>
<QItemLabel class="col q-ma-none"> <QCard class="vn-one">
{{ entity.name }} <a class="header link" :href="clientUrl + `fiscal-data`" link>
</QItemLabel> {{ t('customer.summary.fiscalAddress') }}
</QItem> <QIcon name="open_in_new" color="primary" />
<QItem class="row col"> </a>
<QItemLabel class="col" caption> <VnLv
{{ t('customer.summary.contact') }} :label="t('customer.summary.isEqualizated')"
</QItemLabel> :value="entity.isEqualizated"
<QItemLabel class="col q-ma-none"> />
{{ entity.contact }} <VnLv :label="t('customer.summary.isActive')" :value="entity.isActive" />
</QItemLabel> <VnLv
</QItem> :label="t('customer.summary.invoiceByAddress')"
:value="entity.hasToInvoiceByAddress"
/>
<VnLv
:label="t('customer.summary.verifiedData')"
:value="entity.isTaxDataChecked"
/>
<VnLv
:label="t('customer.summary.hasToInvoice')"
:value="entity.hasToInvoice"
/>
<VnLv
:label="t('customer.summary.notifyByEmail')"
:value="entity.isToBeMailed"
/>
<VnLv :label="t('customer.summary.vies')" :value="entity.isVies" />
</QCard>
<QCard class="vn-one">
<a class="header link" :href="clientUrl + `billing-data`" link>
{{ t('customer.summary.billingData') }}
<QIcon name="open_in_new" color="primary" />
</a>
<VnLv
:label="t('customer.summary.payMethod')"
:value="entity.payMethod.name"
/>
<VnLv :label="t('customer.summary.bankAccount')" :value="entity.iban" />
<VnLv :label="t('customer.summary.dueDay')" :value="entity.dueDay" />
<VnLv :label="t('customer.summary.hasLcr')" :value="entity.hasLcr" />
<VnLv
:label="t('customer.summary.hasCoreVnl')"
:value="entity.hasCoreVnl"
/>
<VnLv
:label="t('customer.summary.hasB2BVnl')"
:value="entity.hasSepaVnl"
/>
</QCard>
<QCard class="vn-one" v-if="entity.defaultAddress">
<a class="header link" :href="clientUrl + `address/index`" link>
{{ t('customer.summary.consignee') }}
<QIcon name="open_in_new" color="primary" />
</a>
<VnLv
:label="t('customer.summary.addressName')"
:value="entity.defaultAddress.nickname"
/>
<VnLv
:label="t('customer.summary.addressCity')"
:value="entity.defaultAddress.city"
/>
<VnLv
:label="t('customer.summary.addressStreet')"
:value="entity.defaultAddress.street"
/>
</QCard>
<QCard class="vn-one" v-if="entity.account">
<a class="header link" :href="clientUrl + `web-access`">
{{ t('customer.summary.webAccess') }}
<QIcon name="open_in_new" color="primary" />
</a>
<VnLv
:label="t('customer.summary.username')"
:value="entity.account.name"
/>
<VnLv
:label="t('customer.summary.webAccess')"
:value="entity.account.active"
/>
</QCard>
<QCard class="vn-one" v-if="entity.account">
<div class="header">
{{ t('customer.summary.businessData') }}
</div>
<VnLv
:label="t('customer.summary.totalGreuge')"
:value="toCurrency(entity.totalGreuge)"
/>
<VnLv
:label="t('customer.summary.mana')"
:value="toCurrency(entity?.mana?.mana)"
/>
<VnLv
v-if="entity.claimsRatio"
:label="t('customer.summary.priceIncreasingRate')"
:value="toPercentage(priceIncreasingRate)"
/>
<VnLv
:label="t('customer.summary.averageInvoiced')"
:value="toCurrency(entity?.averageInvoiced?.invoiced)"
/>
<VnLv
v-if="entity.claimsRatio"
:label="t('customer.summary.claimRate')"
:value="toPercentage(claimRate)"
/>
</QCard>
<QCard class="vn-one" v-if="entity.account">
<a
class="header link"
:href="`https://grafana.verdnatura.es/d/40buzE4Vk/comportamiento-pagos-clientes?orgId=1&var-clientFk=${entityId}`"
link
>
{{ t('customer.summary.financialData') }}
<QIcon name="vn:grafana" color="primary" />
</a>
<VnLv
:label="t('customer.summary.risk')"
:value="toCurrency(entity?.debt?.debt)"
:class="debtWarning"
:info="t('customer.summary.riskInfo')"
/>
<QItem v-if="entity.salesPersonUser" class="row col"> <VnLv
<QItemLabel class="col" caption> :label="t('customer.summary.credit')"
{{ t('customer.summary.salesPerson') }} :value="toCurrency(entity.credit)"
</QItemLabel> :class="creditWarning"
<QItemLabel class="col q-ma-none"> :info="t('customer.summary.creditInfo')"
{{ entity.salesPersonUser.name }} />
</QItemLabel>
</QItem>
<QItem class="row col"> <VnLv
<QItemLabel class="col" caption> v-if="entity.creditInsurance"
{{ t('customer.summary.phone') }} :label="t('customer.summary.securedCredit')"
</QItemLabel> :value="toCurrency(entity.creditInsurance)"
<QItemLabel class="col q-ma-none"> :info="t('customer.summary.securedCreditInfo')"
{{ entity.phone }} />
</QItemLabel>
</QItem>
<QItem class="row col"> <VnLv
<QItemLabel class="col" caption> :label="t('customer.summary.balance')"
{{ t('customer.summary.mobile') }} :value="toCurrency(entity.sumRisk) || toCurrency(0)"
</QItemLabel> :info="t('customer.summary.balanceInfo')"
<QItemLabel class="col q-ma-none">{{ />
entity.mobile
}}</QItemLabel>
</QItem>
<QItem v-if="entity.contactChannel" class="row col"> <VnLv
<QItemLabel class="col" caption> v-if="entity.defaulters"
{{ t('customer.summary.contactChannel') }} :label="t('customer.summary.balanceDue')"
</QItemLabel> :value="toCurrency(balanceDue)"
<QItemLabel class="col q-ma-none"> :class="balanceDueWarning"
{{ entity.contactChannel.name }} :info="t('customer.summary.balanceDueInfo')"
</QItemLabel> />
</QItem> <VnLv
v-if="entity.recovery"
<QItem> :label="t('customer.summary.recoverySince')"
<QItemSection> :value="toDate(entity.recovery.started)"
<QItemLabel caption> />
{{ t('customer.summary.email') }} </QCard>
</QItemLabel>
<QItemLabel>{{ entity.email }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.fiscalAddress') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.socialName') }}
</QItemLabel>
<QItemLabel>{{ entity.socialName }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.fiscalId') }}
</QItemLabel>
<QItemLabel>{{ entity.fi }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.postcode') }}
</QItemLabel>
<QItemLabel>{{ entity.postcode }}</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.province">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.province') }}
</QItemLabel>
<QItemLabel>{{ entity.province.name }}</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.country">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.country') }}
</QItemLabel>
<QItemLabel>{{ entity.country.country }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.street') }}
</QItemLabel>
<QItemLabel>{{ entity.street }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.fiscalData') }}
</QItemLabel>
<QItem dense>
<QCheckbox
v-model="entity.isEqualizated"
:label="t('customer.summary.isEqualizated')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.isActive"
:label="t('customer.summary.isActive')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.hasToInvoiceByAddress"
:label="t('customer.summary.invoiceByAddress')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.isTaxDataChecked"
:label="t('customer.summary.verifiedData')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.hasToInvoice"
:label="t('customer.summary.hasToInvoice')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.isToBeMailed"
:label="t('customer.summary.notifyByEmail')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.isVies"
:label="t('customer.summary.vies')"
disable
/>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.billingData') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.payMethod') }}
</QItemLabel>
<QItemLabel>{{ entity.payMethod.name }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.bankAccount') }}
</QItemLabel>
<QItemLabel>{{ entity.iban }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.dueDay') }}
</QItemLabel>
<QItemLabel>{{ entity.dueDay }}</QItemLabel>
</QItemSection>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.hasLcr"
:label="t('customer.summary.hasLcr')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.hasCoreVnl"
:label="t('customer.summary.hasCoreVnl')"
disable
/>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.hasSepaVnl"
:label="t('customer.summary.hasB2BVnl')"
disable
/>
</QItem>
</QList>
</div>
<div class="col" v-if="entity.defaultAddress">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.consignee') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.addressName') }}
</QItemLabel>
<QItemLabel>
{{ entity.defaultAddress.nickname }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.addressCity') }}
</QItemLabel>
<QItemLabel>{{ entity.defaultAddress.city }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.addressStreet') }}
</QItemLabel>
<QItemLabel>
{{ entity.defaultAddress.street }}
</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
<div class="col" v-if="entity.account">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.webAccess') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.username') }}
</QItemLabel>
<QItemLabel>{{ entity.account.name }}</QItemLabel>
</QItemSection>
</QItem>
<QItem dense>
<QCheckbox
v-model="entity.account.active"
:label="t('customer.summary.webAccess')"
disable
/>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.businessData') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.totalGreuge') }}
</QItemLabel>
<QItemLabel>
{{ toCurrency(entity.totalGreuge) }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.mana">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.mana') }}
</QItemLabel>
<QItemLabel>
{{ toCurrency(entity.mana.mana) }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.claimsRatio">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.priceIncreasingRate') }}
</QItemLabel>
<QItemLabel>
{{ toPercentage(priceIncreasingRate) }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.averageInvoiced">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.averageInvoiced') }}
</QItemLabel>
<QItemLabel>
{{ toCurrency(entity.averageInvoiced.invoiced) }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem v-if="entity.claimsRatio">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.claimRate') }}
</QItemLabel>
<QItemLabel>{{ toPercentage(claimRate) }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('customer.summary.financialData') }}
</QItemLabel>
<QItem v-if="entity.debt">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.risk') }}
</QItemLabel>
<QItemLabel :class="debtWarning">
{{ toCurrency(entity.debt.debt) }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QIcon name="vn:info">
<QTooltip>
{{ t('customer.summary.riskInfo') }}
</QTooltip>
</QIcon>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.credit') }}
</QItemLabel>
<QItemLabel :class="creditWarning">
{{ toCurrency(entity.credit) }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QIcon name="vn:info">
<QTooltip>
{{ t('customer.summary.creditInfo') }}
</QTooltip>
</QIcon>
</QItemSection>
</QItem>
<QItem v-if="entity.creditInsurance">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.securedCredit') }}
</QItemLabel>
<QItemLabel>
{{ toCurrency(entity.creditInsurance) }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QIcon name="vn:info">
<QTooltip>
{{ t('customer.summary.securedCreditInfo') }}
</QTooltip>
</QIcon>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.balance') }}
</QItemLabel>
<QItemLabel>
{{ toCurrency(entity.sumRisk) || toCurrency(0) }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QIcon name="vn:info">
<QTooltip>
{{ t('customer.summary.balanceInfo') }}
</QTooltip>
</QIcon>
</QItemSection>
</QItem>
<QItem v-if="entity.defaulters">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.balanceDue') }}
</QItemLabel>
<QItemLabel :class="balanceDueWarning">
{{ toCurrency(balanceDue) }}
</QItemLabel>
</QItemSection>
<QItemSection side>
<QIcon name="vn:info">
<QTooltip>
{{ t('customer.summary.balanceDueInfo') }}
</QTooltip>
</QIcon>
</QItemSection>
</QItem>
<QItem v-if="entity.recovery">
<QItemSection>
<QItemLabel caption>
{{ t('customer.summary.recoverySince') }}
</QItemLabel>
<QItemLabel>
{{ toDate(entity.recovery.started) }}
</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
</QCardSection>
</template> </template>
</CardSummary> </CardSummary>
</template> </template>
<style lang="scss">
.q-item__label + .q-item__label {
margin: 0;
}
</style>

View File

@ -4,8 +4,15 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import axios from 'axios'; import axios from 'axios';
import { toCurrency, toDate } from 'src/filters'; import { toCurrency, toDate } from 'src/filters';
import SkeletonSummary from 'components/ui/SkeletonSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
onMounted(() => fetch()); import VnLv from 'src/components/ui/VnLv.vue';
import { getUrl } from 'src/composables/getUrl';
onMounted(async () => {
fetch();
salixUrl.value = await getUrl('');
invoiceOutUrl.value = salixUrl.value + `invoiceOut/${entityId.value}/`;
});
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -19,20 +26,13 @@ const $props = defineProps({
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const invoiceOut = ref(null); const salixUrl = ref();
const tax = ref(null); const invoiceOutUrl = ref();
const tikets = ref(null); const tickets = ref(null);
function fetch() { function fetch() {
const id = entityId.value; axios.get(`InvoiceOuts/${entityId.value}/getTickets`).then(({ data }) => {
tickets.value = data;
axios.get(`InvoiceOuts/${id}/summary`).then(({ data }) => {
invoiceOut.value = data.invoiceOut;
tax.value = data.invoiceOut.taxesBreakdown;
});
axios.get(`InvoiceOuts/${id}/getTickets`).then(({ data }) => {
tikets.value = data;
}); });
} }
@ -95,124 +95,64 @@ const ticketsColumns = ref([
</script> </script>
<template> <template>
<div class="summary container"> <CardSummary ref="summary" :url="`InvoiceOuts/${entityId}/summary`">
<QCard> <template #header="{ entity: { invoiceOut } }">
<SkeletonSummary v-if="!invoiceOut" /> <div>{{ invoiceOut.ref }} - {{ invoiceOut.client?.socialName }}</div>
<template v-if="invoiceOut"> </template>
<div class="header bg-primary q-pa-sm q-mb-md"> <template #body="{ entity: { invoiceOut } }">
{{ invoiceOut.ref }} - {{ invoiceOut.client.socialName }} <QCard class="vn-one">
<div class="header">
{{ t('invoiceOut.pageTitles.basicData') }}
</div> </div>
<QList> <VnLv
<QItem> :label="t('invoiceOut.summary.issued')"
<QItemSection> :value="toDate(invoiceOut.issued)"
<QItemLabel caption>{{ />
t('invoiceOut.summary.issued') <VnLv
}}</QItemLabel> :label="t('invoiceOut.summary.dued')"
<QItemLabel>{{ toDate(invoiceOut.issued) }}</QItemLabel> :value="toDate(invoiceOut.dued)"
</QItemSection> />
<QItemSection> <VnLv
<QItemLabel caption>{{ :label="t('invoiceOut.summary.created')"
t('invoiceOut.summary.dued') :value="toDate(invoiceOut.created)"
}}</QItemLabel> />
<QItemLabel>{{ toDate(invoiceOut.dued) }}</QItemLabel> <VnLv
</QItemSection> :label="t('invoiceOut.summary.booked')"
</QItem> :value="toDate(invoiceOut.booked)"
<QItem> />
<QItemSection> <VnLv
<QItemLabel caption>{{ :label="t('invoiceOut.summary.company')"
t('invoiceOut.summary.created') :value="invoiceOut.company.code"
}}</QItemLabel> />
<QItemLabel>{{ toDate(invoiceOut.created) }}</QItemLabel> </QCard>
</QItemSection> <QCard class="vn-three">
<QItemSection> <div class="header">
<QItemLabel caption>{{ {{ t('invoiceOut.summary.taxBreakdown') }}
t('invoiceOut.summary.booked') </div>
}}</QItemLabel> <QTable :columns="taxColumns" :rows="invoiceOut.taxesBreakdown" flat>
<QItemLabel>{{ toDate(invoiceOut.booked) }}</QItemLabel> <template #header="props">
</QItemSection> <QTr :props="props">
</QItem> <QTh v-for="col in props.cols" :key="col.name" :props="props">
<QItem> {{ t(col.label) }}
<QItemSection> </QTh>
<QItemLabel caption>{{ </QTr>
t('invoiceOut.summary.company') </template>
}}</QItemLabel> </QTable>
<QItemLabel>{{ invoiceOut.company.code }}</QItemLabel> </QCard>
</QItemSection> <QCard class="vn-three">
</QItem> <div class="header">
</QList> {{ t('invoiceOut.summary.tickets') }}
<QCardSection class="q-pa-md"> </div>
<h6>{{ t('invoiceOut.summary.taxBreakdown') }}</h6> <QTable :columns="ticketsColumns" :rows="tickets" flat>
<QTable :columns="taxColumns" :rows="tax" flat> <template #header="props">
<template #header="props"> <QTr :props="props">
<QTr :props="props"> <QTh v-for="col in props.cols" :key="col.name" :props="props">
<QTh {{ t(col.label) }}
v-for="col in props.cols" </QTh>
:key="col.name" </QTr>
:props="props" </template>
> </QTable>
{{ t(col.label) }} </QCard>
</QTh> </template>
</QTr> </CardSummary>
</template>
</QTable>
</QCardSection>
<QCardSection class="q-pa-md">
<h6>{{ t('invoiceOut.summary.tickets') }}</h6>
<QTable :columns="ticketsColumns" :rows="tikets" flat>
<template #header="props">
<QTr :props="props">
<QTh
v-for="col in props.cols"
:key="col.name"
:props="props"
>
{{ t(col.label) }}
</QTh>
</QTr>
</template>
</QTable>
</QCardSection>
</template>
</QCard>
</div>
</template> </template>
<style lang="scss" scoped>
.container {
display: flex;
justify-content: center;
}
.q-card {
width: 100%;
min-width: 950px;
max-width: 950px;
}
.summary {
.header {
text-align: center;
font-size: 18px;
}
#slider-container {
max-width: 80%;
margin: 0 auto;
.q-slider {
.q-slider__marker-labels:nth-child(1) {
transform: none;
}
.q-slider__marker-labels:nth-child(2) {
transform: none;
left: auto !important;
right: 0%;
}
}
}
}
.q-dialog .summary {
max-width: 1200px;
}
</style>

File diff suppressed because it is too large Load Diff

View File

@ -3,11 +3,11 @@ import axios from 'axios';
import { ref, onMounted, computed, onUpdated } from 'vue'; import { ref, onMounted, computed, onUpdated } from 'vue';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import SkeletonSummary from 'components/ui/SkeletonSummary.vue'; import CardSummary from 'components/ui/CardSummary.vue';
import { getUrl } from 'src/composables/getUrl';
import VnLv from 'src/components/ui/VnLv.vue';
import WorkerDescriptorProxy from './WorkerDescriptorProxy.vue'; import WorkerDescriptorProxy from './WorkerDescriptorProxy.vue';
import { dashIfEmpty } from 'src/filters';
onMounted(() => fetch());
onUpdated(() => fetch());
const route = useRoute(); const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
@ -20,8 +20,11 @@ const $props = defineProps({
}); });
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => $props.id || route.params.id);
const workerUrl = ref();
const worker = ref(null); onMounted(async () => {
workerUrl.value = (await getUrl('')) + `worker/${entityId.value}/`;
});
const filter = { const filter = {
include: [ include: [
@ -59,230 +62,59 @@ const filter = {
}, },
], ],
}; };
function fetch() {
const id = entityId.value;
axios.get(`/Workers/${id}`, { params: { filter } }).then((response) => {
worker.value = response.data;
});
}
function sipExtension() {
if (worker.value.sip) return worker.value.sip.extension;
return '-';
}
</script> </script>
<template> <template>
<div class="summary container"> <CardSummary ref="summary" :url="`Workers/${entityId}`" :filter="filter">
<QCard> <template #header="{ entity }">
<SkeletonSummary v-if="!worker" /> <div>{{ entity.id }} - {{ entity.firstName }} {{ entity.lastName }}</div>
<template v-if="worker"> </template>
<div class="header bg-primary q-pa-sm q-mb-md"> <template #body="{ entity: worker }">
{{ worker.id }} - {{ worker.firstName }} {{ worker.lastName }} <QCard class="vn-one">
</div> <a class="header" :href="workerUrl + `basic-data`">
<div class="row q-pa-md q-col-gutter-md q-mb-md"> {{ t('worker.summary.basicData') }}
<div class="col"> <QIcon name="open_in_new" color="primary" />
<QList> </a>
<QItemLabel header class="text-h6"> <VnLv :label="t('worker.card.name')" :value="worker.user.nickname" />
{{ t('worker.summary.basicData') }} <VnLv
</QItemLabel> :label="t('worker.list.department')"
<QItem> :value="worker.department.department.name"
<QItemSection> />
<QItemLabel caption> ID </QItemLabel> <VnLv :label="t('worker.list.email')" :value="worker.user.email" />
<QItemLabel>{{ worker.id }}</QItemLabel> <VnLv :label="t('worker.summary.boss')" link>
</QItemSection> <template #value>
</QItem> <span class="link">
<QItem> {{ dashIfEmpty(worker.boss?.name) }}
<QItemSection> <WorkerDescriptorProxy
<QItemLabel caption :id="worker.bossFk"
>{{ t('worker.card.name') }}
</QItemLabel>
<QItemLabel>
{{ worker.user.nickname }}
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.list.department') }}
</QItemLabel>
<QItemLabel>{{
worker.department.department.name
}}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.list.email') }}
</QItemLabel>
<QItemLabel>{{ worker.user.email }}</QItemLabel>
</QItemSection>
</QItem>
<QItem
class="items-start cursor-pointer q-hoverable"
v-if="worker.boss" v-if="worker.boss"
> />
<QItemSection> </span>
<QItemLabel caption> </template>
{{ t('worker.summary.boss') }} </VnLv>
</QItemLabel> <VnLv
<QItemLabel> :label="t('worker.summary.phoneExtension')"
<span class="link"> :value="worker.mobileExtension"
{{ worker.boss.name }} />
<WorkerDescriptorProxy :id="worker.bossFk" /> <VnLv :label="t('worker.summary.entPhone')" :value="worker.phone" />
</span> <VnLv
</QItemLabel> :label="t('worker.summary.personalPhone')"
</QItemSection> :value="worker.client.phone"
</QItem> />
<QItem> <VnLv :label="t('worker.summary.locker')" :value="worker.locker" />
<QItemSection> </QCard>
<QItemLabel caption <QCard class="vn-one">
>{{ t('worker.summary.phoneExtension') }} <div class="header">
</QItemLabel> {{ t('worker.summary.userData') }}
<QItemLabel>
{{
worker.mobileExtension == ''
? worker.mobileExtension
: '-'
}}
</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.summary.entPhone') }}
</QItemLabel>
<QItemLabel>{{
worker.phone == '' ? worker.phone : '-'
}}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.summary.personalPhone') }}
</QItemLabel>
<QItemLabel>{{
worker.client.phone == ''
? worker.client.phone
: '-'
}}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
<div class="col">
<QList>
<QItemLabel header class="text-h6">
{{ t('worker.summary.userData') }}
</QItemLabel>
<QItem>
<QItemSection>
<QItemLabel caption>
{{ t('worker.summary.userId') }}
</QItemLabel>
<QItemLabel>{{ worker.user.id }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.card.name') }}
</QItemLabel>
<QItemLabel>{{ worker.user.nickname }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.summary.role') }}
</QItemLabel>
<QItemLabel>{{ worker.user.role.name }}</QItemLabel>
</QItemSection>
</QItem>
<QItem>
<QItemSection>
<QItemLabel caption
>{{ t('worker.summary.sipExtension') }}
</QItemLabel>
<QItemLabel>{{ sipExtension() }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</div>
</div> </div>
</template> <VnLv :label="t('worker.summary.userId')" :value="worker.user.id" />
</QCard> <VnLv :label="t('worker.card.name')" :value="worker.user.nickname" />
</div> <VnLv :label="t('worker.summary.role')" :value="worker.user.role.name" />
<VnLv
:label="t('worker.summary.sipExtension')"
:value="worker?.sip?.extension"
/>
</QCard>
</template>
</CardSummary>
</template> </template>
<style lang="scss" scoped>
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.container {
display: flex;
justify-content: center;
}
.q-card {
width: 100%;
max-width: 1200px;
}
.negative {
color: red;
}
.summary {
.q-list {
.q-item__label--header {
display: flex;
justify-content: space-between;
a {
color: $primary;
}
}
}
.row {
flex-wrap: wrap;
.col {
min-width: 250px;
}
}
.header {
text-align: center;
font-size: 18px;
}
#slider-container {
max-width: 80%;
margin: 0 auto;
.q-slider {
.q-slider__marker-labels:nth-child(1) {
transform: none;
}
.q-slider__marker-labels:nth-child(2) {
transform: none;
left: auto !important;
right: 0%;
}
}
}
}
.q-dialog .summary {
max-width: 1200px;
}
</style>

View File

@ -1,15 +1,15 @@
describe('WorkerSummary', () => { describe('WorkerSummary', () => {
beforeEach(() => { beforeEach(() => {
cy.viewport(1280, 720) cy.viewport(1280, 720);
cy.login('developer') cy.login('developer');
cy.visit('/#/worker/19/summary'); cy.visit('/#/worker/19/summary');
}); });
it('should load worker summary', () => { it('should load worker summary', () => {
cy.get('div[class="header bg-primary q-pa-sm q-mb-md"').should('have.text', '19 - salesBoss salesBoss'); cy.get('.summaryHeader > div').should('have.text', '19 - salesBoss salesBoss');
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(0).should('have.text', 'Basic data'); cy.get(':nth-child(1) > :nth-child(2) > .value > span').should(
cy.get('div[class="q-item__label q-item__label--header text-h6"]').eq(1).should('have.text', 'User data'); 'have.text',
cy.get('div[class="q-item__section column q-item__section--main justify-center"]').eq(0).should('have.text', 'NamesalesBossNick'); 'salesBossNick'
);
}); });
}); });