feat: roles sections
This commit is contained in:
parent
555b5a663c
commit
f9e77596e4
|
@ -27,7 +27,7 @@ function stateColor(code) {
|
|||
function navigate(event, id) {
|
||||
if (event.ctrlKey || event.metaKey)
|
||||
return window.open(`${getApiUrl()}/#/account/${id}/summary`);
|
||||
router.push({ path: `/account/role/${id}` });
|
||||
router.push({ path: `/role/${id}/summary` });
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<script setup>
|
||||
import VnLog from 'src/components/common/VnLog.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnLog model="Account"></VnLog>
|
||||
</template>
|
|
@ -0,0 +1,151 @@
|
|||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { toDate, toPercentage } from 'src/filters';
|
||||
import { useState } from 'src/composables/useState';
|
||||
import CardDescriptor from 'components/ui/CardDescriptor.vue';
|
||||
import VnLv from 'src/components/ui/VnLv.vue';
|
||||
import useCardDescription from 'src/composables/useCardDescription';
|
||||
import VnUserLink from 'src/components/ui/VnUserLink.vue';
|
||||
import { getUrl } from 'src/composables/getUrl';
|
||||
|
||||
const $props = defineProps({
|
||||
id: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: null,
|
||||
},
|
||||
});
|
||||
|
||||
const route = useRoute();
|
||||
const state = useState();
|
||||
const { t } = useI18n();
|
||||
const salixUrl = ref();
|
||||
const entityId = computed(() => {
|
||||
return $props.id || route.params.id;
|
||||
});
|
||||
const filter = {
|
||||
where: { id: entityId },
|
||||
fields: ['id', 'nickname', 'name', 'role'],
|
||||
include: { relation: 'role', scope: { fields: ['id', 'name'] } },
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CardDescriptor
|
||||
ref="descriptor"
|
||||
:url="`VnUsers/preview`"
|
||||
:filter="filter"
|
||||
module="Account"
|
||||
@on-fetch="setData"
|
||||
data-key="accountData"
|
||||
>
|
||||
<template #menu="{ entity }">
|
||||
{{ entity }}
|
||||
</template>
|
||||
<template #body="{ entity }">
|
||||
<VnLv v-if="entity.accountState" :label="t('account.card.state')">
|
||||
<template #value>
|
||||
<QBadge
|
||||
:color="stateColor(entity.accountState.code)"
|
||||
text-color="black"
|
||||
dense
|
||||
>
|
||||
{{ entity.accountState.description }}
|
||||
</QBadge>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('account.card.created')" :value="toDate(entity.created)" />
|
||||
<VnLv :label="t('account.card.commercial')">
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
:name="entity.client?.salesPersonUser?.name"
|
||||
:worker-id="entity.client?.salesPersonFk"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
v-if="entity.worker"
|
||||
:label="t('account.card.attendedBy')"
|
||||
:value="entity.worker.user.name"
|
||||
>
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
:name="entity.worker.user.nickname"
|
||||
:worker-id="entity.worker.id"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('account.card.zone')">
|
||||
<template #value>
|
||||
<span class="link">
|
||||
{{ entity.ticket?.zone?.name }}
|
||||
</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
:label="t('account.card.province')"
|
||||
:value="entity.ticket?.address?.province?.name"
|
||||
/>
|
||||
<VnLv :label="t('account.card.ticketId')">
|
||||
<template #value>
|
||||
<span class="link">
|
||||
{{ entity.ticketFk }}
|
||||
</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
:label="t('accountRate')"
|
||||
:value="toPercentage(entity.client?.accountsRatio?.accountingRate)"
|
||||
/>
|
||||
</template>
|
||||
<template #actions="{ entity }">
|
||||
<QCardActions>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="vn:client"
|
||||
color="primary"
|
||||
:to="{ name: 'CustomerCard', params: { id: entity.clientFk } }"
|
||||
>
|
||||
<QTooltip>{{ t('account.card.customerSummary') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="vn:ticket"
|
||||
color="primary"
|
||||
:to="{ name: 'TicketCard', params: { id: entity.ticketFk } }"
|
||||
>
|
||||
<QTooltip>{{ t('account.card.accountedTicket') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="assignment"
|
||||
color="primary"
|
||||
:href="salixUrl + 'ticket/' + entity.ticketFk + '/sale-tracking'"
|
||||
>
|
||||
<QTooltip>{{ t('account.card.saleTracking') }}</QTooltip>
|
||||
</QBtn>
|
||||
<QBtn
|
||||
size="md"
|
||||
icon="visibility"
|
||||
color="primary"
|
||||
:href="salixUrl + 'ticket/' + entity.ticketFk + '/tracking/index'"
|
||||
>
|
||||
<QTooltip>{{ t('account.card.ticketTracking') }}</QTooltip>
|
||||
</QBtn>
|
||||
</QCardActions>
|
||||
</template>
|
||||
</CardDescriptor>
|
||||
</template>
|
||||
<style scoped>
|
||||
.q-item__label {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
<i18n>
|
||||
en:
|
||||
accountRate: Claming rate
|
||||
es:
|
||||
accountRate: Ratio de reclamación
|
||||
</i18n>
|
|
@ -0,0 +1,6 @@
|
|||
<script setup>
|
||||
import VnLog from 'src/components/common/VnLog.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnLog model="Account"></VnLog>
|
||||
</template>
|
|
@ -27,22 +27,8 @@ const $props = defineProps({
|
|||
});
|
||||
|
||||
const entityId = computed(() => $props.id || route.params.id);
|
||||
const AccountStates = ref([]);
|
||||
const accountUrl = ref();
|
||||
const salixUrl = ref();
|
||||
const accountDmsRef = ref();
|
||||
const accountDmsFilter = ref({
|
||||
include: [
|
||||
{
|
||||
relation: 'dms',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
salixUrl.value = await getUrl('');
|
||||
accountUrl.value = salixUrl.value + `account/${entityId.value}/`;
|
||||
});
|
||||
onMounted(async () => {});
|
||||
|
||||
const detailsColumns = ref([
|
||||
{
|
||||
|
@ -96,347 +82,20 @@ const detailsColumns = ref([
|
|||
sortable: true,
|
||||
},
|
||||
]);
|
||||
|
||||
const STATE_COLOR = {
|
||||
pending: 'warning',
|
||||
incomplete: 'info',
|
||||
resolved: 'positive',
|
||||
canceled: 'negative',
|
||||
};
|
||||
function stateColor(code) {
|
||||
return STATE_COLOR[code];
|
||||
}
|
||||
|
||||
const developmentColumns = ref([
|
||||
{
|
||||
name: 'accountReason',
|
||||
label: 'account.summary.reason',
|
||||
field: (row) => row.accountReason.description,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'accountResult',
|
||||
label: 'account.summary.result',
|
||||
field: (row) => row.accountResult.description,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'accountResponsible',
|
||||
label: 'account.summary.responsible',
|
||||
field: (row) => row.accountResponsible.description,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'worker',
|
||||
label: 'account.summary.worker',
|
||||
field: (row) => row.worker?.user.nickname,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'accountRedelivery',
|
||||
label: 'account.summary.redelivery',
|
||||
field: (row) => row.accountRedelivery.description,
|
||||
sortable: true,
|
||||
},
|
||||
]);
|
||||
const accountDms = ref([]);
|
||||
const multimediaDialog = ref();
|
||||
const multimediaSlide = ref();
|
||||
|
||||
async function getAccountDms() {
|
||||
accountDmsFilter.value.where = { accountFk: entityId.value };
|
||||
await accountDmsRef.value.fetch();
|
||||
}
|
||||
|
||||
function setAccountDms(data) {
|
||||
accountDms.value = [];
|
||||
data.forEach((media) => {
|
||||
accountDms.value.push({
|
||||
isVideo: media.dms.contentType == 'video/mp4',
|
||||
url: `/api/Accounts/${media.dmsFk}/downloadFile?access_token=${token}`,
|
||||
dmsFk: media.dmsFk,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function openDialog(dmsId) {
|
||||
multimediaSlide.value = dmsId;
|
||||
multimediaDialog.value = true;
|
||||
}
|
||||
async function changeState(value) {
|
||||
await axios.patch(`Accounts/updateAccount/${entityId.value}`, {
|
||||
accountStateFk: value,
|
||||
});
|
||||
router.go(route.fullPath);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FetchData
|
||||
url="AccountDms"
|
||||
:filter="accountDmsFilter"
|
||||
@on-fetch="(data) => setAccountDms(data)"
|
||||
ref="accountDmsRef"
|
||||
/>
|
||||
<FetchData
|
||||
url="AccountStates"
|
||||
@on-fetch="(data) => (AccountStates = data)"
|
||||
auto-load
|
||||
/>
|
||||
<CardSummary
|
||||
ref="summary"
|
||||
:url="`Accounts/${entityId}/getSummary`"
|
||||
:url="`VnRoles`"
|
||||
:entity-id="entityId"
|
||||
@on-fetch="getAccountDms"
|
||||
>
|
||||
<template #header="{ entity: { account } }">
|
||||
<!-- <template #header="{ entity: { account } }">
|
||||
{{ account.id }} - {{ account.client.name }} ({{ account.client.id }})
|
||||
</template>
|
||||
<template #header-right>
|
||||
<QBtnDropdown
|
||||
side
|
||||
top
|
||||
color="black"
|
||||
text-color="white"
|
||||
:label="t('ticket.summary.changeState')"
|
||||
>
|
||||
<QList>
|
||||
<QVirtualScroll
|
||||
style="max-height: 300px"
|
||||
:items="AccountStates"
|
||||
separator
|
||||
v-slot="{ item, index }"
|
||||
>
|
||||
<QItem
|
||||
:key="index"
|
||||
dense
|
||||
clickable
|
||||
v-close-popup
|
||||
@click="changeState(item.id)"
|
||||
>
|
||||
<QItemSection>
|
||||
<QItemLabel>{{ item.description }}</QItemLabel>
|
||||
</QItemSection>
|
||||
</QItem>
|
||||
</QVirtualScroll>
|
||||
</QList>
|
||||
</QBtnDropdown>
|
||||
</template>
|
||||
<template #body="{ entity: { account, salesAccounted, developments } }">
|
||||
<QCard class="vn-one">
|
||||
<VnTitle
|
||||
:url="`#/account/${entityId}/basic-data`"
|
||||
:text="t('account.pageTitles.basicData')"
|
||||
/>
|
||||
<VnLv
|
||||
:label="t('account.summary.created')"
|
||||
:value="toDate(account.created)"
|
||||
/>
|
||||
<VnLv :label="t('account.summary.state')">
|
||||
<template #value>
|
||||
<QChip :color="stateColor(account.accountState.code)" dense>
|
||||
{{ account.accountState.description }}
|
||||
</QChip>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('globals.salesPerson')">
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
:name="account.client?.salesPersonUser?.name"
|
||||
:worker-id="account.client?.salesPersonFk"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('account.summary.attendedBy')">
|
||||
<template #value>
|
||||
<VnUserLink
|
||||
:name="account.worker?.user?.nickname"
|
||||
:worker-id="account.workerFk"
|
||||
/>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv :label="t('account.summary.customer')">
|
||||
<template #value>
|
||||
<span class="link cursor-pointer">
|
||||
{{ account.client?.name }}
|
||||
</span>
|
||||
</template>
|
||||
</VnLv>
|
||||
<VnLv
|
||||
:label="t('account.basicData.pickup')"
|
||||
:value="`${dashIfEmpty(account.pickup)}`"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-three">
|
||||
<VnTitle
|
||||
:url="`#/account/${entityId}/notes`"
|
||||
:text="t('account.summary.notes')"
|
||||
/>
|
||||
</QCard>
|
||||
<QCard class="vn-two" v-if="salesAccounted.length > 0">
|
||||
<VnTitle
|
||||
:url="`#/account/${entityId}/lines`"
|
||||
:text="t('account.summary.details')"
|
||||
/>
|
||||
<QTable
|
||||
:columns="detailsColumns"
|
||||
:rows="salesAccounted"
|
||||
flat
|
||||
dense
|
||||
:rows-per-page-options="[0]"
|
||||
hide-bottom
|
||||
>
|
||||
<template #header="props">
|
||||
<QTr :props="props">
|
||||
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
||||
{{ t(col.label) }}
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
<template #body="props">
|
||||
<QTr :props="props">
|
||||
<QTh v-for="col in props.cols" :key="col.name" :props="props">
|
||||
<span v-if="col.name != 'description'">{{
|
||||
t(col.value)
|
||||
}}</span>
|
||||
<QBtn
|
||||
v-if="col.name == 'description'"
|
||||
flat
|
||||
color="blue"
|
||||
>{{ col.value }}</QBtn
|
||||
>
|
||||
|
||||
</QTh>
|
||||
</QTr>
|
||||
</template>
|
||||
</QTable>
|
||||
</QCard>
|
||||
<QCard class="vn-two" v-if="accountDms.length > 0">
|
||||
<VnTitle
|
||||
:url="`#/account/${entityId}/photos`"
|
||||
:text="t('account.summary.photos')"
|
||||
/>
|
||||
<div class="container">
|
||||
<div
|
||||
class="multimedia-container"
|
||||
v-for="(media, index) of accountDms"
|
||||
:key="index"
|
||||
>
|
||||
<div class="relative-position">
|
||||
<QIcon
|
||||
name="play_circle"
|
||||
color="primary"
|
||||
size="xl"
|
||||
class="absolute-center zindex"
|
||||
v-if="media.isVideo"
|
||||
@click.stop="openDialog(media.dmsFk)"
|
||||
>
|
||||
<QTooltip>Video</QTooltip>
|
||||
</QIcon>
|
||||
<QCard class="multimedia relative-position">
|
||||
<QImg
|
||||
:src="media.url"
|
||||
class="rounded-borders cursor-pointer fit"
|
||||
@click="openDialog(media.dmsFk)"
|
||||
v-if="!media.isVideo"
|
||||
>
|
||||
</QImg>
|
||||
<video
|
||||
:src="media.url"
|
||||
class="rounded-borders cursor-pointer fit"
|
||||
muted="muted"
|
||||
v-if="media.isVideo"
|
||||
@click="openDialog(media.dmsFk)"
|
||||
/>
|
||||
</QCard>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</QCard>
|
||||
<QCard class="vn-two" v-if="developments.length > 0">
|
||||
<VnTitle
|
||||
:url="accountUrl + 'development'"
|
||||
:text="t('account.summary.development')"
|
||||
/>
|
||||
<QTable
|
||||
:columns="developmentColumns"
|
||||
:rows="developments"
|
||||
flat
|
||||
dense
|
||||
:rows-per-page-options="[0]"
|
||||
hide-bottom
|
||||
>
|
||||
<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>
|
||||
</QCard>
|
||||
<QCard class="vn-max">
|
||||
<VnTitle
|
||||
:url="accountUrl + 'action'"
|
||||
:text="t('account.summary.actions')"
|
||||
/>
|
||||
<div id="slider-container" class="q-px-xl q-py-md">
|
||||
<QSlider
|
||||
v-model="account.responsibility"
|
||||
label
|
||||
:label-value="t('account.summary.responsibility')"
|
||||
label-always
|
||||
color="var()"
|
||||
markers
|
||||
:marker-labels="[
|
||||
{ value: 1, label: t('account.summary.company') },
|
||||
{ value: 5, label: t('account.summary.person') },
|
||||
]"
|
||||
:min="1"
|
||||
:max="5"
|
||||
readonly
|
||||
/>
|
||||
</div>
|
||||
</QCard>
|
||||
<QDialog
|
||||
v-model="multimediaDialog"
|
||||
transition-show="slide-up"
|
||||
transition-hide="slide-down"
|
||||
>
|
||||
<QToolbar class="absolute zindex close-button">
|
||||
<QSpace />
|
||||
<QBtn icon="close" color="primary" round dense v-close-popup />
|
||||
</QToolbar>
|
||||
<QCarousel
|
||||
swipeable
|
||||
animated
|
||||
v-model="multimediaSlide"
|
||||
arrows
|
||||
class="fit"
|
||||
>
|
||||
<QCarouselSlide
|
||||
v-for="media of accountDms"
|
||||
:key="media.dmsFk"
|
||||
:name="media.dmsFk"
|
||||
>
|
||||
<QImg
|
||||
:src="media.url"
|
||||
class="fit"
|
||||
fit="scale-down"
|
||||
v-if="!media.isVideo"
|
||||
/>
|
||||
<video
|
||||
class="q-ma-none fit"
|
||||
v-if="media.isVideo"
|
||||
controls
|
||||
muted
|
||||
autoplay
|
||||
>
|
||||
<source :src="media.url" type="video/mp4" />
|
||||
</video>
|
||||
</QCarouselSlide>
|
||||
</QCarousel>
|
||||
</QDialog>
|
||||
</template> -->
|
||||
<template #body="{ entity }">
|
||||
{{ entity }}
|
||||
</template>
|
||||
</CardSummary>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<script setup>
|
||||
import VnLog from 'src/components/common/VnLog.vue';
|
||||
</script>
|
||||
<template>
|
||||
<VnLog model="Account"></VnLog>
|
||||
</template>
|
|
@ -53,6 +53,41 @@ export default {
|
|||
icon: 'group',
|
||||
},
|
||||
component: () => import('src/pages/Account/Role/AccountRoles.vue'),
|
||||
// children: [
|
||||
// {
|
||||
// name: 'RoleCard',
|
||||
// path: ':id',
|
||||
// component: () =>
|
||||
// import('src/pages/Account/Role/Card/RoleCard.vue'),
|
||||
// redirect: { name: 'RoleSummary' },
|
||||
// children: [
|
||||
// {
|
||||
// name: 'RoleSummary',
|
||||
// path: 'summary',
|
||||
// meta: {
|
||||
// title: 'summary',
|
||||
// icon: 'launch',
|
||||
// },
|
||||
// component: () =>
|
||||
// import(
|
||||
// 'src/pages/Account/Role/Card/RoleSummary.vue'
|
||||
// ),
|
||||
// },
|
||||
// {
|
||||
// name: 'RoleBasicData',
|
||||
// path: 'basic-data',
|
||||
// meta: {
|
||||
// title: 'basicData',
|
||||
// icon: 'vn:settings',
|
||||
// },
|
||||
// component: () =>
|
||||
// import(
|
||||
// 'src/pages/Account/Role/Card/RoleBasicData.vue'
|
||||
// ),
|
||||
// },
|
||||
// ],
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
{
|
||||
path: 'alias',
|
||||
|
|
|
@ -12,12 +12,12 @@ export default {
|
|||
redirect: { name: 'RoleCard' },
|
||||
menus: {
|
||||
main: [],
|
||||
card: ['RoleBasicData'],
|
||||
card: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
|
||||
},
|
||||
children: [
|
||||
{
|
||||
name: 'RoleCard',
|
||||
path: ':id',
|
||||
path: '/role/:id',
|
||||
component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
|
||||
redirect: { name: 'RoleSummary' },
|
||||
children: [
|
||||
|
@ -41,6 +41,35 @@ export default {
|
|||
component: () =>
|
||||
import('src/pages/Account/Role/Card/RoleBasicData.vue'),
|
||||
},
|
||||
{
|
||||
name: 'SubRoles',
|
||||
path: 'sub-roles',
|
||||
meta: {
|
||||
title: 'subRoles',
|
||||
icon: 'group',
|
||||
},
|
||||
component: () => import('src/pages/Account/Role/Card/SubRoles.vue'),
|
||||
},
|
||||
|
||||
{
|
||||
name: 'InheritedRoles',
|
||||
path: 'inherited-roles',
|
||||
meta: {
|
||||
title: 'inheritedRoles',
|
||||
icon: 'account_tree',
|
||||
},
|
||||
component: () =>
|
||||
import('src/pages/Account/Role/Card/InheritedRoles.vue'),
|
||||
},
|
||||
{
|
||||
name: 'RoleBasicData',
|
||||
path: 'log',
|
||||
meta: {
|
||||
title: 'log',
|
||||
icon: 'history',
|
||||
},
|
||||
component: () => import('src/pages/Account/Role/Card/RoleLog.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue