forked from verdnatura/salix-front
220 lines
6.8 KiB
Vue
220 lines
6.8 KiB
Vue
<script setup>
|
|
import { ref, computed, reactive, watch } from 'vue';
|
|
import { useI18n } from 'vue-i18n';
|
|
|
|
import FetchData from 'components/FetchData.vue';
|
|
import VnSelect from 'src/components/common/VnSelect.vue';
|
|
import VnInputDate from 'src/components/common/VnInputDate.vue';
|
|
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
|
|
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
|
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
|
|
|
import { toDateFormat } from 'src/filters/date.js';
|
|
import { dashIfEmpty } from 'src/filters';
|
|
|
|
const { t } = useI18n();
|
|
|
|
const paginateRef = ref(null);
|
|
const workersActiveOptions = ref([]);
|
|
const clientsOptions = ref([]);
|
|
|
|
const from = ref(Date.vnNew());
|
|
const to = ref(Date.vnNew());
|
|
|
|
const dateRange = computed(() => {
|
|
const minHour = new Date(from.value);
|
|
minHour.setHours(0, 0, 0, 0);
|
|
const maxHour = new Date(to.value);
|
|
maxHour.setHours(23, 59, 59, 59);
|
|
return [minHour, maxHour];
|
|
});
|
|
|
|
const filter = reactive({
|
|
where: {
|
|
'v.stamp': {
|
|
between: dateRange.value,
|
|
},
|
|
},
|
|
});
|
|
|
|
watch(dateRange, (val) => {
|
|
filter.where['v.stamp'].between = val;
|
|
paginateRef.value.fetch();
|
|
});
|
|
|
|
function exprBuilder(param, value) {
|
|
switch (param) {
|
|
case 'clientFk':
|
|
return { [`c.id`]: value };
|
|
case 'salesPersonFk':
|
|
return { [`c.${param}`]: value };
|
|
}
|
|
}
|
|
|
|
const params = reactive({});
|
|
|
|
const applyColumnFilter = async (col) => {
|
|
try {
|
|
const paramKey = col.columnFilter?.filterParamKey || col.field;
|
|
params[paramKey] = col.columnFilter.filterValue;
|
|
await paginateRef.value.addFilter(null, params);
|
|
} catch (err) {
|
|
console.error('Error applying column filter', err);
|
|
}
|
|
};
|
|
|
|
const columns = computed(() => [
|
|
{
|
|
label: t('salesClientsTable.date'),
|
|
name: 'date',
|
|
field: 'dated',
|
|
align: 'left',
|
|
columnFilter: null,
|
|
sortable: true,
|
|
format: (val) => toDateFormat(val),
|
|
},
|
|
{
|
|
label: t('salesClientsTable.hour'),
|
|
name: 'hour',
|
|
field: 'hour',
|
|
align: 'left',
|
|
sortable: true,
|
|
},
|
|
{
|
|
label: t('salesClientsTable.salesPerson'),
|
|
name: 'salesPerson',
|
|
field: 'salesPerson',
|
|
align: 'left',
|
|
sortable: true,
|
|
columnFilter: {
|
|
component: VnSelect,
|
|
filterParamKey: 'salesPersonFk',
|
|
type: 'select',
|
|
filterValue: null,
|
|
attrs: {
|
|
options: workersActiveOptions.value,
|
|
'option-value': 'id',
|
|
'option-label': 'name',
|
|
dense: true,
|
|
},
|
|
},
|
|
format: (val) => dashIfEmpty(val),
|
|
},
|
|
{
|
|
label: t('salesClientsTable.client'),
|
|
field: 'clientName',
|
|
name: 'client',
|
|
align: 'left',
|
|
sortable: true,
|
|
columnFilter: {
|
|
component: VnSelect,
|
|
filterParamKey: 'clientFk',
|
|
type: 'select',
|
|
filterValue: null,
|
|
attrs: {
|
|
options: clientsOptions.value,
|
|
'option-value': 'id',
|
|
'option-label': 'name',
|
|
dense: true,
|
|
},
|
|
},
|
|
format: (val) => dashIfEmpty(val),
|
|
},
|
|
]);
|
|
</script>
|
|
|
|
<template>
|
|
<FetchData
|
|
url="Workers/activeWithInheritedRole"
|
|
:filter="{
|
|
fields: ['id', 'nickname'],
|
|
order: 'nickname ASC',
|
|
where: { role: 'salesPerson' },
|
|
}"
|
|
auto-load
|
|
@on-fetch="(data) => (workersActiveOptions = data)"
|
|
/>
|
|
<FetchData
|
|
url="Clients"
|
|
:filter="{
|
|
fields: ['id', 'name'],
|
|
order: 'name ASC',
|
|
}"
|
|
auto-load
|
|
@on-fetch="(data) => (clientsOptions = data)"
|
|
/>
|
|
<QCard style="max-height: 380px; overflow-y: scroll">
|
|
<VnPaginate
|
|
ref="paginateRef"
|
|
data-key="SalesMonitorClients"
|
|
url="SalesMonitors/clientsFilter"
|
|
:order="['dated DESC', 'hour DESC']"
|
|
:limit="6"
|
|
:expr-builder="exprBuilder"
|
|
:user-params="params"
|
|
:filter="filter"
|
|
:offset="50"
|
|
auto-load
|
|
>
|
|
<template #body="{ rows }">
|
|
<QTable
|
|
:rows="rows"
|
|
:columns="columns"
|
|
row-key="id"
|
|
:pagination="{ rowsPerPage: 0 }"
|
|
class="full-width"
|
|
:no-data-label="t('globals.noResults')"
|
|
>
|
|
<template #top>
|
|
<VnInputDate
|
|
:label="t('salesClientsTable.from')"
|
|
dense
|
|
emit-date-format
|
|
v-model="from"
|
|
class="q-mr-lg"
|
|
style="width: 150px"
|
|
/>
|
|
<VnInputDate
|
|
:label="t('salesClientsTable.to')"
|
|
dense
|
|
emit-date-format
|
|
v-model="to"
|
|
style="width: 150px"
|
|
/>
|
|
</template>
|
|
<template #top-row="{ cols }">
|
|
<QTr>
|
|
<QTd
|
|
v-for="(col, index) in cols"
|
|
:key="index"
|
|
style="max-width: 100px"
|
|
>
|
|
<VnSelect
|
|
:is="col.columnFilter.component"
|
|
v-if="col.columnFilter"
|
|
v-model="col.columnFilter.filterValue"
|
|
v-bind="col.columnFilter.attrs"
|
|
@update:model-value="applyColumnFilter(col)"
|
|
dense
|
|
/>
|
|
</QTd>
|
|
</QTr>
|
|
</template>
|
|
<template #body-cell-salesPerson="{ row }">
|
|
<QTd>
|
|
<span class="link">{{ row.salesPerson }}</span>
|
|
<WorkerDescriptorProxy :id="row.salesPersonFk" dense />
|
|
</QTd>
|
|
</template>
|
|
<template #body-cell-client="{ row }">
|
|
<QTd>
|
|
<span class="link">{{ row.clientName }}</span>
|
|
<CustomerDescriptorProxy :id="row.clientFk" />
|
|
</QTd>
|
|
</template>
|
|
</QTable>
|
|
</template>
|
|
</VnPaginate>
|
|
</QCard>
|
|
</template>
|