0
0
Fork 0

Claim summary

This commit is contained in:
Joan Sanchez 2022-10-19 12:22:05 +02:00
parent 01a2728862
commit 17b3e73d21
5 changed files with 290 additions and 50 deletions

View File

@ -19,6 +19,7 @@ const session = useSession();
const token = session.getToken(); const token = session.getToken();
const claim = ref(null); const claim = ref(null);
const claimCopy = ref(null);
function fetch() { function fetch() {
const id = route.params.id; const id = route.params.id;
const filter = { const filter = {
@ -32,39 +33,76 @@ function fetch() {
], ],
}; };
const options = { params: { filter } }; const options = { params: { filter } };
axios.get(`Claims/${id}`, options).then((response) => { axios.get(`Claims/${id}`, options).then(({ data }) => {
// const { data } = response; claim.value = data;
claimCopy.value = Object.assign({}, data);
// data.created = new Date(data.created);
claim.value = response.data;
}); });
} }
const workers = ref([]); const workers = ref([]);
const workersCopy = ref([]);
function fetchWorkers() { function fetchWorkers() {
axios.get(`Workers`).then((response) => (workers.value = response.data)); const filter = {
} where: {
role: 'employee',
function filterFn(val, update) { },
console.log(val, update); };
const options = { params: { filter } };
// if (val === '') { axios.get(`Workers/activeWithRole`, options).then(({ data }) => {
// update(() => { workers.value = data;
// workers.value = workersCopy.value; workersCopy.value = data;
// }); });
// return;
// }
// update(() => {
// const needle = val.toLowerCase();
// workers.value = workers.value.filter((v) => v.firstName.toLowerCase().indexOf(needle) > -1);
// });
} }
const claimStates = ref([]); const claimStates = ref([]);
const claimStatesCopy = ref([]);
function fetchClaimStates() { function fetchClaimStates() {
axios.get(`ClaimStates`).then((response) => (claimStates.value = response.data)); axios.get(`ClaimStates`).then(({ data }) => {
claimStates.value = data;
claimStatesCopy.value = data;
});
}
function filter(value, update, options, originalOptions, filter) {
update(
() => {
if (value === '') {
options.value = originalOptions.value;
return;
}
options.value = options.value.filter(filter);
},
(ref) => {
ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true);
}
);
}
function filterWorkers(value, update) {
const search = value.toLowerCase();
filter(value, update, workers, workersCopy, (row) => {
const id = row.id;
const name = row.name.toLowerCase();
const idMatch = id == search;
const nameMatch = name.indexOf(search) > -1;
return idMatch || nameMatch;
});
}
function filterStates(value, update) {
const search = value.toLowerCase();
filter(value, update, claimStates, claimStatesCopy, (row) => {
const description = row.description.toLowerCase();
return description.indexOf(search) > -1;
});
} }
function save() { function save() {
@ -74,15 +112,15 @@ function save() {
axios.patch(`Claims/${id}`, formData); axios.patch(`Claims/${id}`, formData);
} }
const vRule = { function onReset() {
mounted: (element, binding) => console.log(binding.value), claim.value = claimCopy.value;
}; }
</script> </script>
<template> <template>
<q-page class="q-pa-md"> <q-page class="q-pa-md">
<div class="container"> <div class="container">
<q-card class="q-pa-md"> <q-card class="q-pa-md">
<q-form v-if="claim" @submit="save"> <q-form v-if="claim" @submit="save" @reset="onReset" greedy>
<div class="row q-gutter-md q-mb-md"> <div class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<q-input v-model="claim.client.name" label="Client" disable /> <q-input v-model="claim.client.name" label="Client" disable />
@ -109,34 +147,24 @@ const vRule = {
v-model="claim.workerFk" v-model="claim.workerFk"
:options="workers" :options="workers"
option-value="id" option-value="id"
option-label="firstName" option-label="name"
emit-value emit-value
label="Assigned" label="Assigned"
map-options map-options
use-input use-input
@filter="filterFn" @filter="filterWorkers"
:rules="validate('claim.claimStateFk')" :rules="validate('claim.claimStateFk')"
:input-debounce="0"
> >
<template #before> <template #before>
<q-avatar color="orange"> <q-avatar color="orange">
<q-img <q-img
:if="claim.workerFk" v-if="claim.workerFk"
:src="`/api/Images/user/160x160/${claim.workerFk}/download?access_token=${token}`" :src="`/api/Images/user/160x160/${claim.workerFk}/download?access_token=${token}`"
spinner-color="white" spinner-color="white"
/> />
</q-avatar> </q-avatar>
</template> </template>
<template #selected-item="scope">
{{ scope.opt.firstName }} {{ scope.opt.lastName }}
</template>
<template #option="scope">
<q-item v-bind="scope.itemProps">
<q-item-section
>{{ scope.opt.firstName }} {{ scope.opt.lastName }}</q-item-section
>
</q-item>
</template>
</q-select> </q-select>
</div> </div>
<div class="col"> <div class="col">
@ -149,14 +177,16 @@ const vRule = {
label="State" label="State"
map-options map-options
use-input use-input
@filter="filterStates"
:rules="validate('claim.claimStateFk')" :rules="validate('claim.claimStateFk')"
:input-debounce="0"
> >
</q-select> </q-select>
</div> </div>
</div> </div>
<div class="row q-gutter-md q-mb-md"> <div class="row q-gutter-md q-mb-md">
<div class="col"> <div class="col">
<q-input v-model="claim.packages" label="Packages" v-rule="`claim.packages`" /> <q-input v-model="claim.packages" label="Packages" :rules="validate('claim.packages')" />
</div> </div>
</div> </div>
<div class="row q-gutter-md q-mb-md"> <div class="row q-gutter-md q-mb-md">
@ -166,7 +196,7 @@ const vRule = {
</div> </div>
<div> <div>
<q-btn :label="t('globals.save')" type="submit" color="primary" /> <q-btn :label="t('globals.save')" type="submit" color="primary" />
<q-btn :label="t('globals.reset')" type="reset" color="primary" flat class="q-ml-sm" /> <q-btn :label="t('globals.reset')" type="reset" class="q-ml-sm" color="primary" flat />
</div> </div>
</q-form> </q-form>
</q-card> </q-card>

View File

@ -53,7 +53,7 @@ function stateColor(code) {
<q-tooltip>Claim list</q-tooltip> <q-tooltip>Claim list</q-tooltip>
</q-btn> </q-btn>
</router-link> </router-link>
<router-link :to="{ path: '/claim/list' }"> <router-link :to="{ name: 'ClaimSummary', params: { id: route.params.id } }">
<q-btn round flat dense size="md" icon="launch" color="white"> <q-btn round flat dense size="md" icon="launch" color="white">
<q-tooltip>Claim preview</q-tooltip> <q-tooltip>Claim preview</q-tooltip>
</q-btn> </q-btn>
@ -146,7 +146,7 @@ function stateColor(code) {
<q-list> <q-list>
<q-item :to="{ name: 'ClaimBasicData' }" clickable v-ripple active-class="text-orange"> <q-item :to="{ name: 'ClaimBasicData' }" clickable v-ripple active-class="text-orange">
<q-item-section avatar> <q-item-section avatar>
<q-icon name="person" /> <q-icon name="vn:settings" />
</q-item-section> </q-item-section>
<q-item-section>Basic data</q-item-section> <q-item-section>Basic data</q-item-section>
</q-item> </q-item>

View File

@ -0,0 +1,186 @@
<script setup>
import { onMounted, defineProps, ref, computed } from 'vue';
import { useRoute } from 'vue-router';
// import { useI18n } from 'vue-i18n';
import axios from 'axios';
import { toDate } from 'src/filters';
onMounted(() => {
fetch();
});
const route = useRoute();
const $props = defineProps({
claimId: {
type: Number,
default: 0,
},
});
const entityId = computed(() => $props.claimId || 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 = [
{
name: 'item',
label: 'Item',
field: (row) => row.sale.itemFk,
sortable: true,
},
{
name: 'landed',
label: 'Landed',
field: (row) => row.sale.ticket.landed,
format: (value) => toDate(value),
sortable: true,
},
{
name: 'quantity',
label: 'Quantity',
field: (row) => row.sale.quantity,
sortable: true,
},
{
name: 'claimed',
label: 'Claimed',
field: (row) => row.quantity,
sortable: true,
},
{
name: 'description',
label: 'Description',
field: (row) => row.sale.concept,
},
{
name: 'price',
label: 'Price',
field: (row) => row.sale.price,
sortable: true,
},
{
name: 'discount',
label: 'Discount',
field: (row) => row.sale.discount,
format: (value) => `${value} %`,
sortable: true,
},
{
name: 'total',
label: 'Total',
field: ({ sale }) => sale.quantity * sale.price * ((100 - sale.discount) / 100),
sortable: true,
},
];
function stateColor(code) {
if (code === 'pending') return 'green';
if (code === 'managed') return 'orange';
if (code === 'resolved') return 'red';
}
</script>
<template>
<q-page class="q-pa-md">
<div class="summary container">
<q-card v-if="claim">
<div class="header bg-orange q-pa-sm q-mb-md">{{ claim.id }} - {{ claim.client.name }}</div>
<q-list>
<q-item>
<q-item-section>
<q-item-label caption>Created</q-item-label>
<q-item-label>{{ toDate(claim.created) }}</q-item-label>
</q-item-section>
<q-item-section>
<q-item-label caption>State</q-item-label>
<q-item-label>
<q-chip :color="stateColor(claim.claimState.code)" dense>
{{ claim.claimState.description }}
</q-chip>
</q-item-label>
</q-item-section>
</q-item>
<q-item>
<q-item-section>
<q-item-label caption>Assigned</q-item-label>
<q-item-label>{{ claim.worker.user.nickname }}</q-item-label>
</q-item-section>
<q-item-section>
<q-item-label caption>Attended by</q-item-label>
<q-item-label>{{ claim.client.salesPersonUser.name }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
<q-card-section class="q-pa-md">
<h6>Details</h6>
<q-table :columns="detailsColumns" :rows="salesClaimed" flat></q-table>
</q-card-section>
<q-card-section class="q-pa-md">
<h6>Action</h6>
<q-separator />
<div id="slider-container">
<q-slider
v-model="claim.responsibility"
label
:label-value="'Responsibility'"
label-always
color="primary"
markers
:marker-labels="[
{ value: 1, label: 'Company' },
{ value: 5, label: 'Person' },
]"
:min="1"
:max="5"
readonly
/>
</div>
</q-card-section>
</q-card>
</div>
</q-page>
</template>
<style lang="scss" scoped>
.container {
display: flex;
justify-content: center;
}
.q-card {
width: 100%;
max-width: 950px;
}
.summary {
.header {
text-align: center;
font-size: 18px;
}
#slider-container {
max-width: 80%;
margin: 0 auto;
.q-slider {
.q-slider__marker-labels:nth-child(1) {
transform: none;
}
.q-slider__marker-labels:nth-child(2) {
transform: none;
left: auto !important;
right: 0%;
}
}
}
}
</style>

View File

@ -1,8 +1,10 @@
<script setup> <script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import SmartCard from 'src/components/SmartCard.vue'; import SmartCard from 'src/components/SmartCard.vue';
import { toDate } from 'src/filters/index'; import { toDate } from 'src/filters/index';
import ClaimSummary from './Card/ClaimSummary.vue';
const router = useRouter(); const router = useRouter();
const { t } = useI18n(); const { t } = useI18n();
@ -33,6 +35,16 @@ function stateColor(code) {
function navigate(id) { function navigate(id) {
router.push({ path: `/claim/${id}` }); router.push({ path: `/claim/${id}` });
} }
const preview = ref({
shown: false,
});
function showPreview(id) {
preview.value.shown = true;
preview.value.data = {
claimId: id,
};
}
</script> </script>
<template> <template>
@ -90,10 +102,13 @@ function navigate(id) {
<q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)"> <q-btn flat round color="orange" icon="arrow_circle_right" @click="navigate(row.id)">
<q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip> <q-tooltip>{{ t('components.smartCard.openCard') }}</q-tooltip>
</q-btn> </q-btn>
<q-btn flat round color="grey-7" icon="preview"> <q-btn flat round color="grey-7" icon="preview" @click="showPreview(row.id)">
<q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip> <q-tooltip>{{ t('components.smartCard.openSummary') }}</q-tooltip>
</q-btn> </q-btn>
</template> </template>
</smart-card> </smart-card>
</q-page> </q-page>
<q-dialog v-model="preview.shown">
<claim-summary :claim-id="preview.data.claimId" />
</q-dialog>
</template> </template>

View File

@ -4,7 +4,6 @@ export default {
name: 'Claim', name: 'Claim',
path: '/claim', path: '/claim',
meta: { meta: {
roles: ['developer'],
title: 'claims', title: 'claims',
icon: 'vn:claims' icon: 'vn:claims'
}, },
@ -38,15 +37,25 @@ export default {
] ]
}, },
{ {
name: 'ClaimCard',
path: ':id', path: ':id',
component: () => import('src/pages/Claim/Card/ClaimCard.vue'), component: () => import('src/pages/Claim/Card/ClaimCard.vue'),
redirect: { name: 'ClaimBasicData' }, redirect: { name: 'ClaimSummary' },
children: [ children: [
{
name: 'ClaimSummary',
path: 'summary',
meta: {
title: 'summary'
},
component: () => import('src/pages/Claim/Card/ClaimSummary.vue'),
},
{ {
name: 'ClaimBasicData', name: 'ClaimBasicData',
path: 'basic-data', path: 'basic-data',
meta: { meta: {
title: 'basicData' title: 'basicData',
roles: ['salesPerson']
}, },
component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'), component: () => import('src/pages/Claim/Card/ClaimBasicData.vue'),
} }