Merge branch '4802-searchbar' of https://gitea.verdnatura.es/verdnatura/salix-front into 4802-searchbar
gitea/salix-front/pipeline/head There was a failure building this commit
Details
gitea/salix-front/pipeline/head There was a failure building this commit
Details
This commit is contained in:
commit
9365e93fe8
|
@ -27,3 +27,7 @@ yarn-error.log*
|
||||||
*.ntvs*
|
*.ntvs*
|
||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
|
|
||||||
|
# Cypress directories and files
|
||||||
|
/tests/cypress/videos
|
||||||
|
/tests/cypress/screenshots
|
|
@ -1,6 +1,6 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
singleQuote: true,
|
singleQuote: true,
|
||||||
printWidth: 120,
|
printWidth: 90,
|
||||||
tabWidth: 4,
|
tabWidth: 4,
|
||||||
semi: true,
|
semi: true,
|
||||||
endOfLine: 'auto',
|
endOfLine: 'auto',
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
|
import { onMounted, onUnmounted, computed, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import { useState } from 'src/composables/useState';
|
import { useState } from 'src/composables/useState';
|
||||||
import { useValidator } from 'src/composables/useValidator';
|
import { useValidator } from 'src/composables/useValidator';
|
||||||
import SkeletonForm from 'components/ui/SkeletonForm.vue';
|
import SkeletonForm from 'components/ui/SkeletonForm.vue';
|
||||||
|
@ -44,6 +43,7 @@ const isLoading = ref(false);
|
||||||
const hasChanges = ref(false);
|
const hasChanges = ref(false);
|
||||||
const formData = computed(() => state.get($props.model));
|
const formData = computed(() => state.get($props.model));
|
||||||
const originalData = ref();
|
const originalData = ref();
|
||||||
|
const formUrl = computed(() => $props.url);
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const { data } = await axios.get($props.url, {
|
const { data } = await axios.get($props.url, {
|
||||||
|
@ -91,6 +91,12 @@ function filter(value, update, filterOptions) {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
watch(formUrl, async () => {
|
||||||
|
originalData.value = null;
|
||||||
|
reset();
|
||||||
|
fetch();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<q-banner v-if="hasChanges" class="text-white bg-warning">
|
<q-banner v-if="hasChanges" class="text-white bg-warning">
|
||||||
|
|
|
@ -1,79 +1,106 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useSlots } from 'vue';
|
import { onMounted, useSlots, ref, watch } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import axios from 'axios';
|
||||||
|
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
module: {
|
module: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
}
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const slots = useSlots();
|
const slots = useSlots();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
onMounted(() => fetch());
|
||||||
|
|
||||||
|
const entity = ref();
|
||||||
|
async function fetch() {
|
||||||
|
const params = {};
|
||||||
|
|
||||||
|
if (props.filter) params.filter = props.filter;
|
||||||
|
|
||||||
|
const { data } = await axios.get(props.url, { params });
|
||||||
|
entity.value = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(props, async () => {
|
||||||
|
entity.value = null;
|
||||||
|
await fetch();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="descriptor">
|
<div class="descriptor">
|
||||||
<div class="header bg-primary q-pa-sm">
|
<template v-if="entity">
|
||||||
<router-link :to="{ name: `${module}List` }">
|
<div class="header bg-primary q-pa-sm">
|
||||||
<q-btn round flat dense size="md" icon="view_list" color="white">
|
<router-link :to="{ name: `${module}List` }">
|
||||||
<q-tooltip>{{ t('components.cardDescriptor.mainList') }}</q-tooltip>
|
<q-btn round flat dense size="md" icon="view_list" color="white">
|
||||||
|
<q-tooltip>{{
|
||||||
|
t('components.cardDescriptor.mainList')
|
||||||
|
}}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</router-link>
|
||||||
|
<router-link
|
||||||
|
:to="{ name: `${module}Summary`, params: { id: entity.id } }"
|
||||||
|
>
|
||||||
|
<q-btn round flat dense size="md" icon="launch" color="white">
|
||||||
|
<q-tooltip>{{
|
||||||
|
t('components.cardDescriptor.summary')
|
||||||
|
}}</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</router-link>
|
||||||
|
|
||||||
|
<q-btn
|
||||||
|
v-if="slots.menu"
|
||||||
|
size="md"
|
||||||
|
icon="more_vert"
|
||||||
|
color="white"
|
||||||
|
round
|
||||||
|
flat
|
||||||
|
dense
|
||||||
|
>
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('components.cardDescriptor.moreOptions') }}
|
||||||
|
</q-tooltip>
|
||||||
|
<q-menu>
|
||||||
|
<q-list>
|
||||||
|
<slot name="menu" :entity="entity" />
|
||||||
|
</q-list>
|
||||||
|
</q-menu>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</router-link>
|
|
||||||
<router-link :to="{ name: `${module}Summary`, params: { id: data.id } }">
|
|
||||||
<q-btn round flat dense size="md" icon="launch" color="white">
|
|
||||||
<q-tooltip>{{ t('components.cardDescriptor.summary') }}</q-tooltip>
|
|
||||||
</q-btn>
|
|
||||||
</router-link>
|
|
||||||
|
|
||||||
<q-btn v-if="slots.menu" size="md" icon="more_vert" color="white" round flat dense>
|
|
||||||
<q-tooltip>{{ t('components.cardDescriptor.moreOptions') }}</q-tooltip>
|
|
||||||
<q-menu>
|
|
||||||
<q-list>
|
|
||||||
<slot name="menu" />
|
|
||||||
</q-list>
|
|
||||||
</q-menu>
|
|
||||||
</q-btn>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="$props.data" class="body q-py-sm">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="ellipsis text-h5" :lines="1">
|
|
||||||
{{ $props.description }}
|
|
||||||
<q-tooltip>{{ $props.description }}</q-tooltip>
|
|
||||||
</q-item-label>
|
|
||||||
<q-item dense>
|
|
||||||
<q-item-label class="text-subtitle2" caption>#{{ data.id }}</q-item-label>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
<slot name="body" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Skeleton -->
|
|
||||||
<div id="descriptor-skeleton" v-if="!$props.data">
|
|
||||||
<div class="col q-pl-sm q-pa-sm">
|
|
||||||
<q-skeleton type="text" square height="45px" />
|
|
||||||
<q-skeleton type="text" square height="18px" />
|
|
||||||
<q-skeleton type="text" square height="18px" />
|
|
||||||
<q-skeleton type="text" square height="18px" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="body q-py-sm">
|
||||||
<q-card-actions>
|
<q-list>
|
||||||
<q-skeleton size="40px" />
|
<q-item-label header class="ellipsis text-h5" :lines="1">
|
||||||
<q-skeleton size="40px" />
|
<slot name="description" :entity="entity">
|
||||||
<q-skeleton size="40px" />
|
<span>
|
||||||
<q-skeleton size="40px" />
|
{{ entity.name }}
|
||||||
<q-skeleton size="40px" />
|
<q-tooltip>{{ entity.name }}</q-tooltip>
|
||||||
</q-card-actions>
|
</span>
|
||||||
</div>
|
</slot>
|
||||||
|
</q-item-label>
|
||||||
|
<q-item dense>
|
||||||
|
<q-item-label class="text-subtitle2" caption>
|
||||||
|
#{{ entity.id }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
<slot name="body" :entity="entity" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<!-- Skeleton -->
|
||||||
|
<skeleton-descriptor v-if="!entity" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
<script setup>
|
||||||
|
import { onMounted, ref, watch } from 'vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
||||||
|
onMounted(() => fetch());
|
||||||
|
|
||||||
|
const entity = ref();
|
||||||
|
const props = defineProps({
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
type: Object,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const emit = defineEmits(['onFetch']);
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
entity,
|
||||||
|
fetch,
|
||||||
|
});
|
||||||
|
|
||||||
|
async function fetch() {
|
||||||
|
const params = {};
|
||||||
|
|
||||||
|
if (props.filter) params.filter = props.filter;
|
||||||
|
|
||||||
|
const { data } = await axios.get(props.url, { params });
|
||||||
|
entity.value = data;
|
||||||
|
|
||||||
|
emit('onFetch', data);
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(props, async () => {
|
||||||
|
entity.value = null;
|
||||||
|
fetch();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="summary container">
|
||||||
|
<q-card>
|
||||||
|
<skeleton-summary v-if="!entity" />
|
||||||
|
<template v-if="entity">
|
||||||
|
<div class="header bg-primary q-pa-sm q-mb-md">
|
||||||
|
<slot name="header" :entity="entity">
|
||||||
|
{{ entity.id }} - {{ entity.name }}
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
<div class="body q-pa-md q-mb-md">
|
||||||
|
<slot name="body" :entity="entity" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.summary.container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary {
|
||||||
|
.q-card {
|
||||||
|
width: 100%;
|
||||||
|
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;
|
||||||
|
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>
|
|
@ -28,5 +28,6 @@ $color-spacer: rgba(255, 255, 255, 0.3);
|
||||||
$border-thin-light: 1px solid $color-spacer-light;
|
$border-thin-light: 1px solid $color-spacer-light;
|
||||||
|
|
||||||
$dark-shadow-color: #000;
|
$dark-shadow-color: #000;
|
||||||
|
$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;
|
||||||
|
|
|
@ -1,14 +1,27 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import Navbar from 'src/components/NavBar.vue';
|
import Navbar from 'src/components/NavBar.vue';
|
||||||
|
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
const filterPanel = ref(true);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-layout view="hHh LpR fFf">
|
<q-layout view="hHh LpR fFf">
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
|
<q-drawer
|
||||||
|
v-model="filterPanel"
|
||||||
|
show-if-above
|
||||||
|
side="right"
|
||||||
|
:width="256"
|
||||||
|
:breakpoint="500"
|
||||||
|
>
|
||||||
|
<q-scroll-area class="fit text-grey-8">
|
||||||
|
<div id="rightPanel"></div>
|
||||||
|
</q-scroll-area>
|
||||||
|
</q-drawer>
|
||||||
<q-footer v-if="quasar.platform.is.mobile"></q-footer>
|
<q-footer v-if="quasar.platform.is.mobile"></q-footer>
|
||||||
</q-layout>
|
</q-layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -18,33 +18,4 @@ const state = useState();
|
||||||
<router-view></router-view>
|
<router-view></router-view>
|
||||||
</q-page>
|
</q-page>
|
||||||
</q-page-container>
|
</q-page-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.q-scrollarea__content {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.descriptor {
|
|
||||||
max-width: 256px;
|
|
||||||
|
|
||||||
h5 {
|
|
||||||
margin: 0 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q-card__actions {
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
#descriptor-skeleton .q-card__actions {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,13 +1,12 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, computed, ref } from 'vue';
|
import { 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 axios from 'axios';
|
|
||||||
import TicketDescriptorPopover from 'pages/Ticket/Card/TicketDescriptorPopover.vue';
|
import TicketDescriptorPopover from 'pages/Ticket/Card/TicketDescriptorPopover.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 SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -17,10 +16,6 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await fetch();
|
|
||||||
});
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -28,28 +23,21 @@ const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const claim = ref();
|
const filter = {
|
||||||
async function fetch() {
|
include: [
|
||||||
const filter = {
|
{ relation: 'client' },
|
||||||
include: [
|
{ relation: 'claimState' },
|
||||||
{ relation: 'client' },
|
{
|
||||||
{ relation: 'claimState' },
|
relation: 'claimState',
|
||||||
{
|
},
|
||||||
relation: 'claimState',
|
{
|
||||||
|
relation: 'worker',
|
||||||
|
scope: {
|
||||||
|
include: { relation: 'user' },
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
relation: 'worker',
|
],
|
||||||
scope: {
|
};
|
||||||
include: { relation: 'user' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
const options = { params: { filter } };
|
|
||||||
const { data } = await axios.get(`Claims/${entityId.value}`, options);
|
|
||||||
|
|
||||||
if (data) claim.value = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function stateColor(code) {
|
function stateColor(code) {
|
||||||
if (code === 'pending') return 'green';
|
if (code === 'pending') return 'green';
|
||||||
|
@ -59,40 +47,56 @@ function stateColor(code) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<skeleton-descriptor v-if="!claim" />
|
<card-descriptor
|
||||||
<card-descriptor v-if="claim" module="Claim" :data="claim" :description="claim.client.name">
|
ref="descriptor"
|
||||||
<template #menu>
|
:url="`Claims/${entityId}`"
|
||||||
<claim-descriptor-menu v-if="claim" :claim="claim" />
|
:filter="filter"
|
||||||
|
module="Claim"
|
||||||
|
>
|
||||||
|
<template #menu="{ entity }">
|
||||||
|
<claim-descriptor-menu :claim="entity" />
|
||||||
</template>
|
</template>
|
||||||
<template #body>
|
<template #description="{ entity }">
|
||||||
|
<span>
|
||||||
|
{{ entity.client.name }}
|
||||||
|
<q-tooltip>{{ entity.client.name }}</q-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #body="{ entity }">
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('claim.card.created') }}</q-item-label>
|
<q-item-label caption>{{ t('claim.card.created') }}</q-item-label>
|
||||||
<q-item-label>{{ toDate(claim.created) }}</q-item-label>
|
<q-item-label>{{ toDate(entity.created) }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section v-if="entity.claimState">
|
||||||
<q-item-label caption>{{ t('claim.card.state') }}</q-item-label>
|
<q-item-label caption>{{ t('claim.card.state') }}</q-item-label>
|
||||||
<q-item-label>
|
<q-item-label>
|
||||||
<q-chip :color="stateColor(claim.claimState.code)" dense>
|
<q-chip :color="stateColor(entity.claimState.code)" dense>
|
||||||
{{ claim.claimState.description }}
|
{{ entity.claimState.description }}
|
||||||
</q-chip>
|
</q-chip>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('claim.card.ticketId') }}</q-item-label>
|
<q-item-label caption>
|
||||||
<q-item-label class="link">
|
{{ t('claim.card.ticketId') }}
|
||||||
{{ claim.ticketFk }}
|
</q-item-label>
|
||||||
<q-popup-proxy>
|
<q-item-label>
|
||||||
<ticket-descriptor-popover :id="claim.ticketFk" />
|
<span class="link">
|
||||||
</q-popup-proxy>
|
{{ entity.ticketFk }}
|
||||||
|
<q-popup-proxy>
|
||||||
|
<ticket-descriptor-popover :id="entity.ticketFk" />
|
||||||
|
</q-popup-proxy>
|
||||||
|
</span>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section v-if="entity.worker">
|
||||||
<q-item-label caption>{{ t('claim.card.assignedTo') }}</q-item-label>
|
<q-item-label caption>
|
||||||
<q-item-label>{{ claim.worker.user.name }}</q-item-label>
|
{{ t('claim.card.assignedTo') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.worker.user.name }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
|
@ -102,7 +106,7 @@ function stateColor(code) {
|
||||||
size="md"
|
size="md"
|
||||||
icon="vn:client"
|
icon="vn:client"
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="{ name: 'CustomerCard', params: { id: claim.clientFk } }"
|
:to="{ name: 'CustomerCard', params: { id: entity.clientFk } }"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ t('claim.card.customerSummary') }}</q-tooltip>
|
<q-tooltip>{{ t('claim.card.customerSummary') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
@ -110,7 +114,7 @@ function stateColor(code) {
|
||||||
size="md"
|
size="md"
|
||||||
icon="vn:ticket"
|
icon="vn:ticket"
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="{ name: 'TicketCard', params: { id: claim.ticketFk } }"
|
:to="{ name: 'TicketCard', params: { id: entity.ticketFk } }"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ t('claim.card.claimedTicket') }}</q-tooltip>
|
<q-tooltip>{{ t('claim.card.claimedTicket') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, 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 axios from 'axios';
|
|
||||||
import { toDate, toCurrency } from 'src/filters';
|
import { toDate, toCurrency } from 'src/filters';
|
||||||
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
|
|
||||||
onMounted(() => fetch());
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -20,16 +17,6 @@ const $props = defineProps({
|
||||||
|
|
||||||
const entityId = computed(() => $props.id || route.params.id);
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
|
||||||
const claim = ref(null);
|
|
||||||
const salesClaimed = ref(null);
|
|
||||||
function fetch() {
|
|
||||||
const id = entityId.value;
|
|
||||||
axios.get(`Claims/${id}/getSummary`).then(({ data }) => {
|
|
||||||
claim.value = data.claim;
|
|
||||||
salesClaimed.value = data.salesClaimed;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const detailsColumns = ref([
|
const detailsColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'item',
|
name: 'item',
|
||||||
|
@ -77,7 +64,8 @@ const detailsColumns = ref([
|
||||||
{
|
{
|
||||||
name: 'total',
|
name: 'total',
|
||||||
label: 'claim.summary.total',
|
label: 'claim.summary.total',
|
||||||
field: ({ sale }) => toCurrency(sale.quantity * sale.price * ((100 - sale.discount) / 100)),
|
field: ({ sale }) =>
|
||||||
|
toCurrency(sale.quantity * sale.price * ((100 - sale.discount) / 100)),
|
||||||
sortable: true,
|
sortable: true,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
@ -90,110 +78,95 @@ function stateColor(code) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="summary container">
|
<card-summary ref="summary" :url="`Claims/${entityId}/getSummary`">
|
||||||
<q-card>
|
<template #header="{ entity: { claim } }">
|
||||||
<skeleton-summary v-if="!claim" />
|
{{ claim.id }} - {{ claim.client.name }}
|
||||||
<template v-if="claim">
|
</template>
|
||||||
<div class="header bg-primary q-pa-sm q-mb-md">{{ claim.id }} - {{ claim.client.name }}</div>
|
<template #body="{ entity: { claim, salesClaimed } }">
|
||||||
<q-list>
|
<q-card-section class="row q-pa-none q-col-gutter-md">
|
||||||
<q-item>
|
<div class="col">
|
||||||
<q-item-section>
|
<q-list>
|
||||||
<q-item-label caption>{{ t('claim.summary.created') }}</q-item-label>
|
<q-item>
|
||||||
<q-item-label>{{ toDate(claim.created) }}</q-item-label>
|
<q-item-section>
|
||||||
</q-item-section>
|
<q-item-label caption>
|
||||||
<q-item-section>
|
{{ t('claim.summary.created') }}
|
||||||
<q-item-label caption>{{ t('claim.summary.state') }}</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label>
|
<q-item-label>{{ toDate(claim.created) }}</q-item-label>
|
||||||
<q-chip :color="stateColor(claim.claimState.code)" dense>
|
</q-item-section>
|
||||||
{{ claim.claimState.description }}
|
<q-item-section v-if="claim.claimState">
|
||||||
</q-chip>
|
<q-item-label caption>{{
|
||||||
</q-item-label>
|
t('claim.summary.state')
|
||||||
</q-item-section>
|
}}</q-item-label>
|
||||||
</q-item>
|
<q-item-label>
|
||||||
<q-item>
|
<q-chip
|
||||||
<q-item-section>
|
:color="stateColor(claim.claimState.code)"
|
||||||
<q-item-label caption>{{ t('claim.summary.assignedTo') }}</q-item-label>
|
dense
|
||||||
<q-item-label>{{ claim.worker.user.nickname }}</q-item-label>
|
>
|
||||||
</q-item-section>
|
{{ claim.claimState.description }}
|
||||||
<q-item-section>
|
</q-chip>
|
||||||
<q-item-label caption>{{ t('claim.summary.attendedBy') }}</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label>{{ claim.client.salesPersonUser.name }}</q-item-label>
|
</q-item-section>
|
||||||
</q-item-section>
|
</q-item>
|
||||||
</q-item>
|
<q-item>
|
||||||
</q-list>
|
<q-item-section v-if="claim.worker && claim.worker.user">
|
||||||
<q-card-section class="q-pa-md">
|
<q-item-label caption>{{
|
||||||
<h6>{{ t('claim.summary.details') }}</h6>
|
t('claim.summary.assignedTo')
|
||||||
<q-table :columns="detailsColumns" :rows="salesClaimed" flat>
|
}}</q-item-label>
|
||||||
<template #header="props">
|
<q-item-label>{{
|
||||||
<q-tr :props="props">
|
claim.worker.user.nickname
|
||||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
}}</q-item-label>
|
||||||
{{ t(col.label) }}
|
</q-item-section>
|
||||||
</q-th>
|
<q-item-section
|
||||||
</q-tr>
|
v-if="claim.client && claim.client.salesPersonUser"
|
||||||
</template>
|
>
|
||||||
</q-table>
|
<q-item-label caption>{{
|
||||||
</q-card-section>
|
t('claim.summary.attendedBy')
|
||||||
<q-card-section class="q-pa-md">
|
}}</q-item-label>
|
||||||
<h6>{{ t('claim.summary.actions') }}</h6>
|
<q-item-label>{{
|
||||||
<q-separator />
|
claim.client.salesPersonUser.name
|
||||||
<div id="slider-container">
|
}}</q-item-label>
|
||||||
<q-slider
|
</q-item-section>
|
||||||
v-model="claim.responsibility"
|
</q-item>
|
||||||
label
|
</q-list>
|
||||||
:label-value="t('claim.summary.responsibility')"
|
</div>
|
||||||
label-always
|
</q-card-section>
|
||||||
color="primary"
|
<q-card-section class="q-pa-md">
|
||||||
markers
|
<h6>{{ t('claim.summary.details') }}</h6>
|
||||||
:marker-labels="[
|
<q-table :columns="detailsColumns" :rows="salesClaimed" flat>
|
||||||
{ value: 1, label: t('claim.summary.company') },
|
<template #header="props">
|
||||||
{ value: 5, label: t('claim.summary.person') },
|
<q-tr :props="props">
|
||||||
]"
|
<q-th
|
||||||
:min="1"
|
v-for="col in props.cols"
|
||||||
:max="5"
|
:key="col.name"
|
||||||
readonly
|
:props="props"
|
||||||
/>
|
>
|
||||||
</div>
|
{{ t(col.label) }}
|
||||||
</q-card-section>
|
</q-th>
|
||||||
</template>
|
</q-tr>
|
||||||
</q-card>
|
</template>
|
||||||
</div>
|
</q-table>
|
||||||
</template>
|
</q-card-section>
|
||||||
|
<q-card-section class="q-pa-md">
|
||||||
<style lang="scss" scoped>
|
<h6>{{ t('claim.summary.actions') }}</h6>
|
||||||
.container {
|
<q-separator />
|
||||||
display: flex;
|
<div id="slider-container">
|
||||||
justify-content: center;
|
<q-slider
|
||||||
}
|
v-model="claim.responsibility"
|
||||||
|
label
|
||||||
.q-card {
|
:label-value="t('claim.summary.responsibility')"
|
||||||
width: 100%;
|
label-always
|
||||||
max-width: 950px;
|
color="primary"
|
||||||
}
|
markers
|
||||||
|
:marker-labels="[
|
||||||
.summary {
|
{ value: 1, label: t('claim.summary.company') },
|
||||||
.header {
|
{ value: 5, label: t('claim.summary.person') },
|
||||||
text-align: center;
|
]"
|
||||||
font-size: 18px;
|
:min="1"
|
||||||
}
|
:max="5"
|
||||||
|
readonly
|
||||||
#slider-container {
|
/>
|
||||||
max-width: 80%;
|
</div>
|
||||||
margin: 0 auto;
|
</q-card-section>
|
||||||
|
</template>
|
||||||
.q-slider {
|
</card-summary>
|
||||||
.q-slider__marker-labels:nth-child(1) {
|
</template>
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
.q-slider__marker-labels:nth-child(2) {
|
|
||||||
transform: none;
|
|
||||||
left: auto !important;
|
|
||||||
right: 0%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.q-dialog .summary {
|
|
||||||
max-width: 1200px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,11 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed } from 'vue';
|
import { 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 axios from 'axios';
|
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -15,75 +13,98 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await fetch();
|
|
||||||
});
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const entityId = computed(() => {
|
const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const customer = ref();
|
|
||||||
async function fetch() {
|
|
||||||
const { data } = await axios.get(`Clients/${entityId.value}/getCard`);
|
|
||||||
|
|
||||||
if (data) customer.value = data;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<skeleton-descriptor v-if="!customer" />
|
<card-descriptor module="Customer" :url="`Clients/${entityId}/getCard`">
|
||||||
<card-descriptor v-if="customer" module="Customer" :data="customer" :description="customer.name">
|
<template #body="{ entity }">
|
||||||
<!-- <template #menu>
|
<q-list dense>
|
||||||
<q-item clickable v-ripple>Option 1</q-item>
|
<q-item v-if="entity.salesPersonUser" class="row">
|
||||||
<q-item clickable v-ripple>Option 2</q-item>
|
<q-item-label class="col" caption>
|
||||||
</template> -->
|
{{ t('customer.card.salesPerson') }}
|
||||||
<template #body>
|
</q-item-label>
|
||||||
<q-list>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
<q-item v-if="customer.salesPersonUser">
|
{{ entity.salesPersonUser.name }}
|
||||||
<q-item-section>
|
</q-item-label>
|
||||||
<q-item-label caption>{{ t('customer.card.salesPerson') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.salesPersonUser.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item class="row">
|
||||||
<q-item-section>
|
<q-item-label class="col" caption>
|
||||||
<q-item-label caption>{{ t('customer.card.credit') }}</q-item-label>
|
{{ t('customer.card.credit') }}
|
||||||
<q-item-label>{{ toCurrency(customer.credit) }}</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
<q-item-section>
|
{{ toCurrency(entity.credit) }}
|
||||||
<q-item-label caption>{{ t('customer.card.securedCredit') }}</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label>{{ toCurrency(customer.creditInsurance) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item class="row">
|
||||||
<q-item-section v-if="customer.payMethod">
|
<q-item-label class="col" caption>
|
||||||
<q-item-label caption>{{ t('customer.card.payMethod') }}</q-item-label>
|
{{ t('customer.card.securedCredit') }}
|
||||||
<q-item-label>{{ customer.payMethod.name }}</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
<q-item-section>
|
{{ toCurrency(entity.creditInsurance) }}
|
||||||
<q-item-label caption>{{ t('customer.card.debt') }}</q-item-label>
|
</q-item-label>
|
||||||
<q-item-label>{{ toCurrency(customer.debt) }}</q-item-label>
|
</q-item>
|
||||||
</q-item-section>
|
<q-item v-if="entity.payMethod" class="row">
|
||||||
|
<q-item-label class="col" caption>
|
||||||
|
{{ t('customer.card.payMethod') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label class="col text-right q-ma-none">
|
||||||
|
{{ entity.payMethod.name }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item>
|
||||||
|
<q-item class="row">
|
||||||
|
<q-item-label class="col" caption>
|
||||||
|
{{ t('customer.card.debt') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label class="col text-right q-ma-none">
|
||||||
|
{{ toCurrency(entity.debt) }}
|
||||||
|
</q-item-label>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
<q-card-actions class="q-gutter-md">
|
<q-card-actions class="q-gutter-md">
|
||||||
<q-icon v-if="customer.isActive == false" name="vn:disabled" size="xs" color="primary">
|
<q-icon
|
||||||
|
v-if="entity.isActive == false"
|
||||||
|
name="vn:disabled"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('customer.card.isDisabled') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.card.isDisabled') }}</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-icon v-if="customer.isFreezed == true" name="vn:frozen" size="xs" color="primary">
|
<q-icon
|
||||||
|
v-if="entity.isFreezed == true"
|
||||||
|
name="vn:frozen"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('customer.card.isFrozen') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.card.isFrozen') }}</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-icon v-if="customer.debt > customer.credit" name="vn:risk" size="xs" color="primary">
|
<q-icon
|
||||||
|
v-if="entity.debt > entity.credit"
|
||||||
|
name="vn:risk"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('customer.card.hasDebt') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.card.hasDebt') }}</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-icon v-if="customer.isTaxDataChecked == false" name="vn:no036" size="xs" color="primary">
|
<q-icon
|
||||||
|
v-if="entity.isTaxDataChecked == false"
|
||||||
|
name="vn:no036"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('customer.card.notChecked') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.card.notChecked') }}</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
<q-icon v-if="customer.account.active == false" name="vn:noweb" size="xs" color="primary">
|
<q-icon
|
||||||
|
v-if="entity.account && entity.account.active == false"
|
||||||
|
name="vn:noweb"
|
||||||
|
size="xs"
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('customer.card.noWebAccess') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.card.noWebAccess') }}</q-tooltip>
|
||||||
</q-icon>
|
</q-icon>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
|
|
|
@ -1,13 +1,9 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, computed } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import axios from 'axios';
|
|
||||||
import { toCurrency, toPercentage, toDate } from 'src/filters';
|
import { toCurrency, toPercentage, toDate } from 'src/filters';
|
||||||
import SkeletonSummary from 'components/ui/SkeletonSummary.vue';
|
import CardSummary from 'components/ui/CardSummary.vue';
|
||||||
import { useArrayDataStore } from 'stores/useArrayDataStore';
|
|
||||||
|
|
||||||
onMounted(() => fetch());
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
@ -20,37 +16,29 @@ const $props = defineProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
const entityId = computed(() => $props.id || route.params.id);
|
const entityId = computed(() => $props.id || route.params.id);
|
||||||
|
const summary = ref();
|
||||||
const customer = ref(null);
|
const customer = computed(() => summary.value.entity);
|
||||||
function fetch() {
|
|
||||||
const id = entityId.value;
|
|
||||||
axios.get(`Clients/${id}/summary`).then(({ data }) => {
|
|
||||||
customer.value = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const balanceDue = computed(() => {
|
const balanceDue = computed(() => {
|
||||||
return customer.value.defaulters.length && customer.value.defaulters[0].amount;
|
return (
|
||||||
|
customer.value &&
|
||||||
|
customer.value.defaulters.length &&
|
||||||
|
customer.value.defaulters[0].amount
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
const balanceDueWarning = computed(() => (balanceDue.value ? 'negative' : ''));
|
const balanceDueWarning = computed(() => (balanceDue.value ? 'negative' : ''));
|
||||||
|
|
||||||
const claimRate = computed(() => {
|
const claimRate = computed(() => {
|
||||||
const data = customer.value;
|
return customer.value.claimsRatio.claimingRate * 100;
|
||||||
|
|
||||||
return data.claimsRatio.claimingRate * 100;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const priceIncreasingRate = computed(() => {
|
const priceIncreasingRate = computed(() => {
|
||||||
const data = customer.value;
|
return customer.value.claimsRatio.priceIncreasing / 100;
|
||||||
|
|
||||||
return data.claimsRatio.priceIncreasing / 100;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const debtWarning = computed(() => {
|
const debtWarning = computed(() => {
|
||||||
const data = customer.value;
|
return customer.value.debt.debt > customer.value.credit ? 'negative' : '';
|
||||||
|
|
||||||
return data.debt.debt > data.credit ? 'negative' : '';
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const creditWarning = computed(() => {
|
const creditWarning = computed(() => {
|
||||||
|
@ -60,438 +48,485 @@ const creditWarning = computed(() => {
|
||||||
|
|
||||||
return tooMuchInsurance || noCreditInsurance ? 'negative' : '';
|
return tooMuchInsurance || noCreditInsurance ? 'negative' : '';
|
||||||
});
|
});
|
||||||
|
|
||||||
const arrayDataStore = useArrayDataStore();
|
|
||||||
const d = arrayDataStore.get('test');
|
|
||||||
console.log(d);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="summary container">
|
<card-summary ref="summary" :url="`Clients/${entityId}/summary`">
|
||||||
<q-card>
|
<template #body="{ entity }">
|
||||||
<skeleton-summary v-if="!customer" />
|
<q-card-section class="row q-pa-none q-col-gutter-md">
|
||||||
<template v-if="customer">
|
<div class="col">
|
||||||
<div class="header bg-primary q-pa-sm q-mb-md">{{ customer.id }} - {{ customer.name }}</div>
|
<q-list dense>
|
||||||
<div class="row q-pa-md q-col-gutter-md q-mb-md">
|
<q-item-label header class="text-h6">
|
||||||
<div class="col">
|
{{ t('customer.summary.basicData') }}
|
||||||
<q-list>
|
<router-link
|
||||||
<q-item-label header class="text-h6">
|
:to="{
|
||||||
{{ t('customer.summary.basicData') }}
|
name: 'CustomerBasicData',
|
||||||
<router-link
|
params: { id: entity.id },
|
||||||
:to="{ name: 'CustomerBasicData', params: { id: entityId } }"
|
}"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<q-icon name="open_in_new" />
|
<q-icon name="open_in_new" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
|
<q-separator class="q-mb-md" />
|
||||||
|
|
||||||
<q-item>
|
<q-item class="row col">
|
||||||
<q-item-section>
|
<q-item-label class="col" caption>
|
||||||
<q-item-label caption>{{ t('customer.summary.customerId') }}</q-item-label>
|
{{ t('customer.summary.customerId') }}:
|
||||||
<q-item-label>{{ customer.id }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.name') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.contact') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.contact }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.salesPersonUser">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.salesPerson') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.salesPersonUser.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.phone') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.phone }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.mobile') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.mobile }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.email') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.email }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.contactChannel">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.contactChannel') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.contactChannel.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.fiscalAddress') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
<q-item-section>
|
{{ entity.id }}
|
||||||
<q-item-label caption>{{ t('customer.summary.socialName') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.socialName }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.fiscalId') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.fi }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.postcode') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.postcode }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.province">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.province') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.province.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.country">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.country') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.country.country }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.street') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.street }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.fiscalData') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item dense>
|
</q-item>
|
||||||
<q-checkbox
|
<q-item class="row col">
|
||||||
v-model="customer.isEqualizated"
|
<q-item-label class="col" caption>
|
||||||
:label="t('customer.summary.isEqualizated')"
|
{{ t('customer.summary.name') }}:
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.isActive"
|
|
||||||
:label="t('customer.summary.isActive')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.hasToInvoiceByAddress"
|
|
||||||
:label="t('customer.summary.invoiceByAddress')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.isTaxDataChecked"
|
|
||||||
:label="t('customer.summary.verifiedData')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.hasToInvoice"
|
|
||||||
:label="t('customer.summary.hasToInvoice')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.isToBeMailed"
|
|
||||||
:label="t('customer.summary.notifyByEmail')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox v-model="customer.isVies" :label="t('customer.summary.vies')" disable />
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.billingData') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item>
|
<q-item-label class="col text-right q-ma-none">{{
|
||||||
<q-item-section>
|
entity.name
|
||||||
<q-item-label caption>{{ t('customer.summary.payMethod') }}</q-item-label>
|
}}</q-item-label>
|
||||||
<q-item-label>{{ customer.payMethod.name }}</q-item-label>
|
</q-item>
|
||||||
</q-item-section>
|
<q-item class="row col">
|
||||||
</q-item>
|
<q-item-label class="col" caption>
|
||||||
<q-item>
|
{{ t('customer.summary.contact') }}:
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.bankAccount') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.iban }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.dueDay') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.dueDay }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox v-model="customer.hasLcr" :label="t('customer.summary.hasLcr')" disable />
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.hasCoreVnl"
|
|
||||||
:label="t('customer.summary.hasCoreVnl')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.hasSepaVnl"
|
|
||||||
:label="t('customer.summary.hasB2BVnl')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col" v-if="customer.defaultAddress">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.consignee') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item>
|
<q-item-label class="col text-right q-ma-none">{{
|
||||||
<q-item-section>
|
entity.contact
|
||||||
<q-item-label caption>{{ t('customer.summary.addressName') }}</q-item-label>
|
}}</q-item-label>
|
||||||
<q-item-label>{{ customer.defaultAddress.nickname }}</q-item-label>
|
</q-item>
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
<q-item v-if="entity.salesPersonUser" class="row col">
|
||||||
<q-item>
|
<q-item-label class="col" caption>
|
||||||
<q-item-section>
|
{{ t('customer.summary.salesPerson') }}:
|
||||||
<q-item-label caption>{{ t('customer.summary.addressCity') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.defaultAddress.city }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.addressStreet') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.defaultAddress.street }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col" v-if="customer.account">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.webAccess') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
<q-item-section>
|
{{ entity.salesPersonUser.name }}
|
||||||
<q-item-label caption>{{ t('customer.summary.username') }}</q-item-label>
|
|
||||||
<q-item-label>{{ customer.account.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item dense>
|
|
||||||
<q-checkbox
|
|
||||||
v-model="customer.account.active"
|
|
||||||
:label="t('customer.summary.webAccess')"
|
|
||||||
disable
|
|
||||||
/>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.businessData') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item>
|
</q-item>
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.totalGreuge') }}</q-item-label>
|
<q-item class="row col">
|
||||||
<q-item-label>{{ toCurrency(customer.totalGreuge) }}</q-item-label>
|
<q-item-label class="col" caption>
|
||||||
</q-item-section>
|
{{ t('customer.summary.phone') }}:
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.mana">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.mana') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toCurrency(customer.mana.mana) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.claimsRatio">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>
|
|
||||||
{{ t('customer.summary.priceIncreasingRate') }}
|
|
||||||
</q-item-label>
|
|
||||||
<q-item-label>{{ toPercentage(priceIncreasingRate) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.averageInvoiced">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.averageInvoiced') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toCurrency(customer.averageInvoiced.invoiced) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.claimsRatio">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.claimRate') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toPercentage(claimRate) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<q-list>
|
|
||||||
<q-item-label header class="text-h6">
|
|
||||||
{{ t('customer.summary.financialData') }}
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
<q-item v-if="customer.debt">
|
<q-item-label class="col text-right q-ma-none">{{
|
||||||
<q-item-section>
|
entity.phone
|
||||||
<q-item-label caption>{{ t('customer.summary.risk') }}</q-item-label>
|
}}</q-item-label>
|
||||||
<q-item-label :class="debtWarning">
|
</q-item>
|
||||||
{{ toCurrency(customer.debt.debt) }}
|
|
||||||
</q-item-label>
|
<q-item class="row col">
|
||||||
</q-item-section>
|
<q-item-label class="col" caption>
|
||||||
<q-item-section side>
|
{{ t('customer.summary.mobile') }}:
|
||||||
<q-icon name="vn:info">
|
</q-item-label>
|
||||||
<q-tooltip>{{ t('customer.summary.riskInfo') }}</q-tooltip>
|
<q-item-label class="col text-right q-ma-none">{{
|
||||||
</q-icon>
|
entity.mobile
|
||||||
</q-item-section>
|
}}</q-item-label>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
<q-item v-if="entity.contactChannel" class="row col">
|
||||||
<q-item-label caption>{{ t('customer.summary.credit') }}</q-item-label>
|
<q-item-label class="col" caption>
|
||||||
<q-item-label :class="creditWarning">
|
{{ t('customer.summary.contactChannel') }}
|
||||||
{{ toCurrency(customer.credit) }}
|
</q-item-label>
|
||||||
</q-item-label>
|
<q-item-label class="col text-right q-ma-none">
|
||||||
</q-item-section>
|
{{ entity.contactChannel.name }}
|
||||||
<q-item-section side>
|
</q-item-label>
|
||||||
<q-icon name="vn:info">
|
</q-item>
|
||||||
<q-tooltip>{{ t('customer.summary.creditInfo') }}</q-tooltip>
|
|
||||||
</q-icon>
|
<q-item>
|
||||||
</q-item-section>
|
<q-item-section>
|
||||||
</q-item>
|
<q-item-label caption>
|
||||||
<q-item v-if="customer.creditInsurance">
|
{{ t('customer.summary.email') }}
|
||||||
<q-item-section>
|
</q-item-label>
|
||||||
<q-item-label caption>{{ t('customer.summary.securedCredit') }}</q-item-label>
|
<q-item-label>{{ entity.email }}</q-item-label>
|
||||||
<q-item-label>{{ toCurrency(customer.creditInsurance) }}</q-item-label>
|
</q-item-section>
|
||||||
</q-item-section>
|
</q-item>
|
||||||
<q-item-section side>
|
</q-list>
|
||||||
<q-icon name="vn:info">
|
|
||||||
<q-tooltip>{{ t('customer.summary.securedCreditInfo') }}</q-tooltip>
|
|
||||||
</q-icon>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.balance') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toCurrency(customer.sumRisk) || toCurrency(0) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section side>
|
|
||||||
<q-icon name="vn:info">
|
|
||||||
<q-tooltip>{{ t('customer.summary.balanceInfo') }}</q-tooltip>
|
|
||||||
</q-icon>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.defaulters">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.balanceDue') }}</q-item-label>
|
|
||||||
<q-item-label :class="balanceDueWarning">
|
|
||||||
{{ toCurrency(balanceDue) }}
|
|
||||||
</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section side>
|
|
||||||
<q-icon name="vn:info">
|
|
||||||
<q-tooltip>{{ t('customer.summary.balanceDueInfo') }}</q-tooltip>
|
|
||||||
</q-icon>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item v-if="customer.recovery">
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('customer.summary.recoverySince') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toDate(customer.recovery.started) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
</q-list>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<div class="col">
|
||||||
</q-card>
|
<q-list>
|
||||||
</div>
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.fiscalAddress') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.socialName') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.socialName }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.fiscalId') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.fi }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.postcode') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.postcode }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.province">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.province') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.province.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.country">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.country') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.country.country }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.street') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.street }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.fiscalData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.isEqualizated"
|
||||||
|
:label="t('customer.summary.isEqualizated')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.isActive"
|
||||||
|
:label="t('customer.summary.isActive')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.hasToInvoiceByAddress"
|
||||||
|
:label="t('customer.summary.invoiceByAddress')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.isTaxDataChecked"
|
||||||
|
:label="t('customer.summary.verifiedData')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.hasToInvoice"
|
||||||
|
:label="t('customer.summary.hasToInvoice')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.isToBeMailed"
|
||||||
|
:label="t('customer.summary.notifyByEmail')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.isVies"
|
||||||
|
:label="t('customer.summary.vies')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.billingData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.payMethod') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.payMethod.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.bankAccount') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.iban }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.dueDay') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.dueDay }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.hasLcr"
|
||||||
|
:label="t('customer.summary.hasLcr')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.hasCoreVnl"
|
||||||
|
:label="t('customer.summary.hasCoreVnl')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.hasSepaVnl"
|
||||||
|
:label="t('customer.summary.hasB2BVnl')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col" v-if="entity.defaultAddress">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.consignee') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.addressName') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ entity.defaultAddress.nickname }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.addressCity') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{
|
||||||
|
entity.defaultAddress.city
|
||||||
|
}}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.addressStreet') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ entity.defaultAddress.street }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col" v-if="entity.account">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.webAccess') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.username') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ entity.account.name }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item dense>
|
||||||
|
<q-checkbox
|
||||||
|
v-model="entity.account.active"
|
||||||
|
:label="t('customer.summary.webAccess')"
|
||||||
|
disable
|
||||||
|
/>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.businessData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.totalGreuge') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toCurrency(entity.totalGreuge) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.mana">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.mana') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toCurrency(entity.mana.mana) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.claimsRatio">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.priceIncreasingRate') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toPercentage(priceIncreasingRate) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.averageInvoiced">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.averageInvoiced') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toCurrency(entity.averageInvoiced.invoiced) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.claimsRatio">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.claimRate') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ toPercentage(claimRate) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-list>
|
||||||
|
<q-item-label header class="text-h6">
|
||||||
|
{{ t('customer.summary.financialData') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item v-if="entity.debt">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.risk') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label :class="debtWarning">
|
||||||
|
{{ toCurrency(entity.debt.debt) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon name="vn:info">
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('customer.summary.riskInfo') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.credit') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label :class="creditWarning">
|
||||||
|
{{ toCurrency(entity.credit) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon name="vn:info">
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('customer.summary.creditInfo') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.creditInsurance">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.securedCredit') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toCurrency(entity.creditInsurance) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon name="vn:info">
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('customer.summary.securedCreditInfo') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.balance') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toCurrency(entity.sumRisk) || toCurrency(0) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon name="vn:info">
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('customer.summary.balanceInfo') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.defaulters">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.balanceDue') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label :class="balanceDueWarning">
|
||||||
|
{{ toCurrency(balanceDue) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section side>
|
||||||
|
<q-icon name="vn:info">
|
||||||
|
<q-tooltip>
|
||||||
|
{{ t('customer.summary.balanceDueInfo') }}
|
||||||
|
</q-tooltip>
|
||||||
|
</q-icon>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item v-if="entity.recovery">
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('customer.summary.recoverySince') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ toDate(entity.recovery.started) }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
</q-list>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</template>
|
||||||
|
</card-summary>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.container {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q-card {
|
<style lang="scss">
|
||||||
width: 100%;
|
.q-item__label + .q-item__label {
|
||||||
max-width: 1200px;
|
margin: 0;
|
||||||
}
|
|
||||||
|
|
||||||
.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>
|
</style>
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import Paginate from 'src/components/PaginateData.vue';
|
import Paginate from 'src/components/PaginateData.vue';
|
||||||
import CustomerSummaryDialog from './Card/CustomerSummaryDialog.vue';
|
import CustomerSummaryDialog from './Card/CustomerSummaryDialog.vue';
|
||||||
|
import TeleportSlot from 'components/ui/TeleportSlot.vue';
|
||||||
|
import FetchData from 'components/FetchData.vue';
|
||||||
|
|
||||||
|
import { useArrayData } from 'composables/useArrayData';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const quasar = useQuasar();
|
const quasar = useQuasar();
|
||||||
|
@ -21,27 +26,189 @@ function viewSummary(id) {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const arrayData = useArrayData('customers');
|
||||||
|
|
||||||
|
const userParams = ref({});
|
||||||
|
async function search() {
|
||||||
|
//const params = userParams;
|
||||||
|
const params = userParams.value;
|
||||||
|
await arrayData.apply({ params });
|
||||||
|
// searchPanel.value.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
const provinces = ref([]);
|
||||||
|
const workers = ref([]);
|
||||||
|
const workersCopy = ref([]);
|
||||||
|
const zones = ref([]);
|
||||||
|
|
||||||
|
function setWorkers(data) {
|
||||||
|
workers.value = data;
|
||||||
|
workersCopy.value = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const tags = computed(() => {
|
||||||
|
const params = [];
|
||||||
|
|
||||||
|
for (const param in userParams.value) {
|
||||||
|
params.push({
|
||||||
|
label: param,
|
||||||
|
value: userParams.value[param],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return params;
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<fetch-data url="Provinces" @on-fetch="(data) => (provinces = data)" auto-load />
|
||||||
|
<fetch-data url="Zones" @on-fetch="(data) => (zones = data)" auto-load />
|
||||||
|
<fetch-data
|
||||||
|
url="Workers/activeWithInheritedRole"
|
||||||
|
:filter="{ where: { role: 'salesPerson' } }"
|
||||||
|
@on-fetch="setWorkers"
|
||||||
|
auto-load
|
||||||
|
/>
|
||||||
|
<teleport-slot to="#rightPanel">
|
||||||
|
<!-- <q-list>
|
||||||
|
<q-item-label header class="text-uppercase">Filter</q-item-label>
|
||||||
|
</q-list> -->
|
||||||
|
<q-form @submit="search">
|
||||||
|
<div class="row q-pa-md truncate-chip-labels">
|
||||||
|
<q-chip
|
||||||
|
v-for="chip of tags"
|
||||||
|
:key="chip.label"
|
||||||
|
@remove="log('Icecream')"
|
||||||
|
icon="label"
|
||||||
|
color="primary"
|
||||||
|
size="sm"
|
||||||
|
removable
|
||||||
|
>
|
||||||
|
<strong>{{ chip.label }}: </strong>
|
||||||
|
<span>"{{ chip.value }}"</span>
|
||||||
|
</q-chip>
|
||||||
|
</div>
|
||||||
|
<div class="q-pa-md q-gutter-y-md">
|
||||||
|
<q-input
|
||||||
|
v-model="userParams.search"
|
||||||
|
label="Search by id or name"
|
||||||
|
lazy-rules
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
|
||||||
|
<q-btn
|
||||||
|
label="Search"
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
class="full-width"
|
||||||
|
rounded
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<q-separator />
|
||||||
|
|
||||||
|
<div class="q-px-md">
|
||||||
|
<q-input label="Fiscal ID" v-model="userParams.fi" lazy-rules />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-gutter-md q-px-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-input label="Name" v-model="userParams.name" lazy-rules />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-input
|
||||||
|
label="Social name"
|
||||||
|
v-model="userParams.socialName"
|
||||||
|
lazy-rules
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="q-px-md">
|
||||||
|
<q-select
|
||||||
|
v-model="userParams.salesPersonFk"
|
||||||
|
:options="workers"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
emit-value
|
||||||
|
label="Salesperson"
|
||||||
|
map-options
|
||||||
|
use-input
|
||||||
|
:input-debounce="0"
|
||||||
|
>
|
||||||
|
</q-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-gutter-md q-px-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-input label="Phone" v-model="userParams.phone" lazy-rules />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-input label="Email" v-model="userParams.email" lazy-rules />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-gutter-md q-px-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-select
|
||||||
|
label="Province"
|
||||||
|
v-model="userParams.provinceFk"
|
||||||
|
:options="provinces"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-input label="City" v-model="userParams.city" lazy-rules />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row q-gutter-md q-px-md">
|
||||||
|
<div class="col">
|
||||||
|
<q-select
|
||||||
|
label="Zone"
|
||||||
|
v-model="userParams.zoneFk"
|
||||||
|
:options="zones"
|
||||||
|
option-value="id"
|
||||||
|
option-label="name"
|
||||||
|
emit-value
|
||||||
|
map-options
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<q-input label="Postcode" v-model="userParams.postcode" lazy-rules />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-form>
|
||||||
|
</teleport-slot>
|
||||||
<q-page class="q-pa-md">
|
<q-page class="q-pa-md">
|
||||||
<paginate url="/Clients/filter" order="id DESC" auto-load>
|
<paginate url="/Clients/filter" order="id DESC" auto-load>
|
||||||
<template #body="{ rows }">
|
<template #body="{ rows }">
|
||||||
<q-card class="card" v-for="row of rows" :key="row.id">
|
<q-card class="card" v-for="row of rows" :key="row.id">
|
||||||
<q-item class="q-pa-none items-start cursor-pointer q-hoverable" v-ripple clickable>
|
<q-item
|
||||||
|
class="q-pa-none items-start cursor-pointer q-hoverable"
|
||||||
|
v-ripple
|
||||||
|
clickable
|
||||||
|
>
|
||||||
<q-item-section class="q-pa-md" @click="navigate(row.id)">
|
<q-item-section class="q-pa-md" @click="navigate(row.id)">
|
||||||
<div class="text-h6">{{ row.name }}</div>
|
<div class="text-h6">{{ row.name }}</div>
|
||||||
<q-item-label caption>#{{ row.id }}</q-item-label>
|
<q-item-label caption>#{{ row.id }}</q-item-label>
|
||||||
|
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item class="q-pa-none">
|
<q-item class="q-pa-none">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('customer.list.email') }}</q-item-label>
|
<q-item-label caption>
|
||||||
|
{{ t('customer.list.email') }}
|
||||||
|
</q-item-label>
|
||||||
<q-item-label>{{ row.email }}</q-item-label>
|
<q-item-label>{{ row.email }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item class="q-pa-none">
|
<q-item class="q-pa-none">
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('customer.list.phone') }}</q-item-label>
|
<q-item-label caption>{{
|
||||||
|
t('customer.list.phone')
|
||||||
|
}}</q-item-label>
|
||||||
<q-item-label>{{ row.phone }}</q-item-label>
|
<q-item-label>{{ row.phone }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
|
@ -69,11 +236,27 @@ function viewSummary(id) {
|
||||||
</q-menu>
|
</q-menu>
|
||||||
</q-btn> -->
|
</q-btn> -->
|
||||||
|
|
||||||
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
|
<q-btn
|
||||||
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
|
flat
|
||||||
|
round
|
||||||
|
color="orange"
|
||||||
|
icon="arrow_circle_right"
|
||||||
|
@click="navigate(row.id)"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{
|
||||||
|
t('components.smartCard.openCard')
|
||||||
|
}}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn flat round color="grey-7" icon="preview" @click="viewSummary(row.id)">
|
<q-btn
|
||||||
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
|
flat
|
||||||
|
round
|
||||||
|
color="grey-7"
|
||||||
|
icon="preview"
|
||||||
|
@click="viewSummary(row.id)"
|
||||||
|
>
|
||||||
|
<q-tooltip>{{
|
||||||
|
t('components.smartCard.openSummary')
|
||||||
|
}}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<!-- <q-btn flat round color="grey-7" icon="vn:ticket">
|
<!-- <q-btn flat round color="grey-7" icon="vn:ticket">
|
||||||
<q-tooltip>{{ t('customer.list.customerOrders') }}</q-tooltip>
|
<q-tooltip>{{ t('customer.list.customerOrders') }}</q-tooltip>
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, ref, 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, toDate } from 'src/filters';
|
import { toCurrency, toDate } from 'src/filters';
|
||||||
import axios from 'axios';
|
|
||||||
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
|
||||||
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
||||||
|
|
||||||
|
@ -15,86 +14,104 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await fetch();
|
|
||||||
});
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const entityId = computed(() => {
|
const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
const descriptor = ref();
|
||||||
|
|
||||||
const invoiceOut = ref();
|
const filter = {
|
||||||
async function fetch() {
|
include: [
|
||||||
const filter = {
|
{
|
||||||
include: [
|
relation: 'company',
|
||||||
{
|
scope: {
|
||||||
relation: 'company',
|
fields: ['id', 'code'],
|
||||||
scope: {
|
|
||||||
fields: ['id', 'code'],
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
},
|
||||||
relation: 'client',
|
{
|
||||||
scope: {
|
relation: 'client',
|
||||||
fields: ['id', 'name', 'email'],
|
scope: {
|
||||||
},
|
fields: ['id', 'name', 'email'],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
};
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const options = { params: { filter } };
|
function ticketFilter(invoice) {
|
||||||
const { data } = await axios.get(`InvoiceOuts/${entityId.value}`, options);
|
return JSON.stringify({ refFk: invoice.ref });
|
||||||
if (data) invoiceOut.value = data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const filter = computed(() => {
|
|
||||||
return invoiceOut.value ? JSON.stringify({ refFk: invoiceOut.value.ref }) : null;
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<card-descriptor v-if="invoiceOut" module="InvoiceOut" :data="invoiceOut" :description="invoiceOut.ref">
|
<card-descriptor
|
||||||
<template #body>
|
ref="descriptor"
|
||||||
|
module="InvoiceOut"
|
||||||
|
:url="`InvoiceOuts/${entityId}`"
|
||||||
|
:filter="filter"
|
||||||
|
>
|
||||||
|
<template #description="{ entity }">
|
||||||
|
<span>
|
||||||
|
{{ entity.ref }}
|
||||||
|
<q-tooltip>{{ entity.ref }}</q-tooltip>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #body="{ entity }">
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('invoiceOut.card.issued') }}</q-item-label>
|
<q-item-label caption>
|
||||||
<q-item-label>{{ toDate(invoiceOut.issued) }}</q-item-label>
|
{{ t('invoiceOut.card.issued') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(entity.issued) }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('invoiceOut.card.amount') }}</q-item-label>
|
<q-item-label caption>
|
||||||
<q-item-label>{{ toCurrency(invoiceOut.amount) }}</q-item-label>
|
{{ t('invoiceOut.card.amount') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ toCurrency(entity.amount) }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section v-if="invoiceOut.company">
|
<q-item-section v-if="entity.client">
|
||||||
<q-item-label caption>{{ t('invoiceOut.card.client') }}</q-item-label>
|
<q-item-label caption>
|
||||||
|
{{ t('invoiceOut.card.client') }}
|
||||||
|
</q-item-label>
|
||||||
<q-item-label class="link">
|
<q-item-label class="link">
|
||||||
{{ invoiceOut.client.name }}
|
{{ entity.client.name }}
|
||||||
<q-popup-proxy>
|
<q-popup-proxy>
|
||||||
<customer-descriptor-popover :id="invoiceOut.client.id" />
|
<customer-descriptor-popover :id="entity.client.id" />
|
||||||
</q-popup-proxy>
|
</q-popup-proxy>
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
<q-item-section v-if="invoiceOut.company">
|
<q-item-section v-if="entity.company">
|
||||||
<q-item-label caption>{{ t('invoiceOut.card.company') }}</q-item-label>
|
<q-item-label caption>{{
|
||||||
<q-item-label>{{ invoiceOut.company.code }}</q-item-label>
|
t('invoiceOut.card.company')
|
||||||
|
}}</q-item-label>
|
||||||
|
<q-item-label>{{ entity.company.code }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
<q-card-actions>
|
<q-card-actions>
|
||||||
<q-btn
|
<q-btn
|
||||||
|
v-if="entity.client"
|
||||||
size="md"
|
size="md"
|
||||||
icon="vn:client"
|
icon="vn:client"
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="{ name: 'CustomerCard', params: { id: invoiceOut.client.id } }"
|
:to="{ name: 'CustomerCard', params: { id: entity.client.id } }"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ t('invoiceOut.card.customerCard') }}</q-tooltip>
|
<q-tooltip>{{ t('invoiceOut.card.customerCard') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-btn size="md" icon="vn:ticket" color="primary" :to="{ name: 'TicketList', params: { q: filter } }">
|
<q-btn
|
||||||
|
size="md"
|
||||||
|
icon="vn:ticket"
|
||||||
|
color="primary"
|
||||||
|
:to="{
|
||||||
|
name: 'TicketList',
|
||||||
|
query: { q: ticketFilter(entity) },
|
||||||
|
}"
|
||||||
|
>
|
||||||
<q-tooltip>{{ t('invoiceOut.card.ticketList') }}</q-tooltip>
|
<q-tooltip>{{ t('invoiceOut.card.ticketList') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
</q-card-actions>
|
</q-card-actions>
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, computed, ref } from 'vue';
|
import { 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 axios from 'axios';
|
|
||||||
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
import CustomerDescriptorPopover from 'src/pages/Customer/Card/CustomerDescriptorPopover.vue';
|
||||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||||
import SkeletonDescriptor from 'components/ui/SkeletonDescriptor.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
id: {
|
id: {
|
||||||
|
@ -16,10 +14,6 @@ const $props = defineProps({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
await fetch();
|
|
||||||
});
|
|
||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
@ -27,12 +21,35 @@ const entityId = computed(() => {
|
||||||
return $props.id || route.params.id;
|
return $props.id || route.params.id;
|
||||||
});
|
});
|
||||||
|
|
||||||
const ticket = ref();
|
const filter = {
|
||||||
async function fetch() {
|
include: [
|
||||||
const { data } = await axios.get(`Tickets/${entityId.value}/summary`);
|
{
|
||||||
|
relation: 'client',
|
||||||
if (data) ticket.value = data;
|
scope: {
|
||||||
}
|
fields: ['id', 'name', 'salesPersonFk'],
|
||||||
|
include: { relation: 'salesPersonUser' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'ticketState',
|
||||||
|
scope: {
|
||||||
|
include: { relation: 'state' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'warehouse',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
relation: 'agencyMode',
|
||||||
|
scope: {
|
||||||
|
fields: ['id', 'name'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
function stateColor(state) {
|
function stateColor(state) {
|
||||||
if (state.code === 'OK') return 'text-green';
|
if (state.code === 'OK') return 'text-green';
|
||||||
|
@ -43,55 +60,64 @@ function stateColor(state) {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<skeleton-descriptor v-if="!ticket" />
|
<card-descriptor module="Ticket" :url="`Tickets/${entityId}`" :filter="filter">
|
||||||
<card-descriptor v-if="ticket" module="Ticket" :data="ticket" :description="ticket.client.name">
|
<template #description="{ entity }">
|
||||||
<!-- <template #menu>
|
<span>
|
||||||
<q-item clickable v-ripple>Option 1</q-item>
|
{{ entity.client.name }}
|
||||||
<q-item clickable v-ripple>Option 2</q-item>
|
<q-tooltip>{{ entity.client.name }}</q-tooltip>
|
||||||
</template> -->
|
</span>
|
||||||
<template #body>
|
</template>
|
||||||
|
<template #body="{ entity }">
|
||||||
<q-list>
|
<q-list>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section v-if="entity.ticketState">
|
||||||
<q-item-label caption>{{ t('ticket.card.ticketId') }}</q-item-label>
|
|
||||||
<q-item-label>#{{ ticket.id }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('ticket.card.state') }}</q-item-label>
|
<q-item-label caption>{{ t('ticket.card.state') }}</q-item-label>
|
||||||
<q-item-label :class="stateColor(ticket.ticketState.state)">
|
<q-item-label :class="stateColor(entity.ticketState.state)">
|
||||||
{{ ticket.ticketState.state.name }}
|
{{ entity.ticketState.state.name }}
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('ticket.card.shipped') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>{{ toDate(entity.shipped) }}</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
</q-item>
|
||||||
|
<q-item>
|
||||||
|
<q-item-section>
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('ticket.card.customerId') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
<span class="link">
|
||||||
|
{{ entity.clientFk }}
|
||||||
|
<q-popup-proxy>
|
||||||
|
<customer-descriptor-popover :id="entity.client.id" />
|
||||||
|
</q-popup-proxy>
|
||||||
|
</span>
|
||||||
|
</q-item-label>
|
||||||
|
</q-item-section>
|
||||||
|
<q-item-section v-if="entity.client && entity.client.salesPersonUser">
|
||||||
|
<q-item-label caption>
|
||||||
|
{{ t('ticket.card.salesPerson') }}
|
||||||
|
</q-item-label>
|
||||||
|
<q-item-label>
|
||||||
|
{{ entity.client.salesPersonUser.name }}
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item>
|
||||||
<q-item-section>
|
<q-item-section v-if="entity.warehouse">
|
||||||
<q-item-label caption>{{ t('ticket.card.customerId') }}</q-item-label>
|
<q-item-label caption>
|
||||||
<q-item-label class="link">
|
{{ t('ticket.card.warehouse') }}
|
||||||
{{ ticket.clientFk }}
|
|
||||||
<q-popup-proxy>
|
|
||||||
<customer-descriptor-popover :id="ticket.client.id" />
|
|
||||||
</q-popup-proxy>
|
|
||||||
</q-item-label>
|
</q-item-label>
|
||||||
</q-item-section>
|
<q-item-label>{{ entity.warehouse.name }}</q-item-label>
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('ticket.card.salesPerson') }}</q-item-label>
|
|
||||||
<q-item-label>{{ ticket.client.salesPersonUser.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
<q-item>
|
<q-item v-if="entity.agencyMode">
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('ticket.card.warehouse') }}</q-item-label>
|
|
||||||
<q-item-label>{{ ticket.warehouse.name }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
<q-item-section>
|
|
||||||
<q-item-label caption>{{ t('ticket.card.shipped') }}</q-item-label>
|
|
||||||
<q-item-label>{{ toDate(ticket.shipped) }}</q-item-label>
|
|
||||||
</q-item-section>
|
|
||||||
</q-item>
|
|
||||||
<q-item>
|
|
||||||
<q-item-section>
|
<q-item-section>
|
||||||
<q-item-label caption>{{ t('ticket.card.agency') }}</q-item-label>
|
<q-item-label caption>{{ t('ticket.card.agency') }}</q-item-label>
|
||||||
<q-item-label>{{ ticket.agencyMode.name }}</q-item-label>
|
<q-item-label>{{ entity.agencyMode.name }}</q-item-label>
|
||||||
</q-item-section>
|
</q-item-section>
|
||||||
</q-item>
|
</q-item>
|
||||||
</q-list>
|
</q-list>
|
||||||
|
@ -101,7 +127,7 @@ function stateColor(state) {
|
||||||
size="md"
|
size="md"
|
||||||
icon="vn:client"
|
icon="vn:client"
|
||||||
color="primary"
|
color="primary"
|
||||||
:to="{ name: 'CustomerCard', params: { id: ticket.clientFk } }"
|
:to="{ name: 'CustomerCard', params: { id: entity.clientFk } }"
|
||||||
>
|
>
|
||||||
<q-tooltip>{{ t('ticket.card.customerCard') }}</q-tooltip>
|
<q-tooltip>{{ t('ticket.card.customerCard') }}</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
|
|
|
@ -29,6 +29,7 @@ const entityId = computed(() => $props.id || route.params.id);
|
||||||
const ticket = ref();
|
const ticket = ref();
|
||||||
const salesLines = ref(null);
|
const salesLines = ref(null);
|
||||||
const editableStates = ref([]);
|
const editableStates = ref([]);
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
const { data } = await axios.get(`Tickets/${entityId.value}/summary`);
|
const { data } = await axios.get(`Tickets/${entityId.value}/summary`);
|
||||||
if (data) {
|
if (data) {
|
||||||
|
|
Loading…
Reference in New Issue