0
0
Fork 0

feat: refs #6825 create vnTable and add in CustomerExtendedList

This commit is contained in:
Alex Moreno 2024-04-26 15:17:03 +02:00
parent 8f064e3338
commit 161922da09
3 changed files with 877 additions and 58 deletions

View File

@ -0,0 +1,243 @@
<script setup>
import { ref, onMounted, markRaw } from 'vue';
import VnPaginate from 'components/ui/VnPaginate.vue';
import VnBreadcrumbs from 'components/common/VnBreadcrumbs.vue';
import { useI18n } from 'vue-i18n';
/* basic input */
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import { QCheckbox } from 'quasar';
// import VnLv from 'src/components/ui/VnLv.vue';
const $props = defineProps({
columns: {
type: Array,
required: true,
},
columnsTable: {
type: Array,
default: () => [],
},
defaultMode: {
type: String, // 'table', 'list', 'card 2/3'
default: 'list',
},
reponsive: {
type: Boolean,
default: true,
},
columnSearch: {
type: Boolean,
default: true,
},
rightSearch: {
type: Boolean,
default: true,
},
});
const { t } = useI18n();
const mode = ref('list');
const selected = ref([]);
const tableModes = [
{
icon: 'view_column',
title: t('table view'),
class: 'q-mr-lg',
value: 'table',
},
{
icon: 'lists',
title: t('list view'),
value: 'list',
},
{
icon: 'apps',
title: t('grid view'),
value: 'card',
},
];
const basicInputs = {
input: markRaw(VnInput),
number: markRaw(VnInput),
date: markRaw(VnInputDate),
checkbox: markRaw(QCheckbox),
select: markRaw(VnSelect),
};
// {
// isId: Boolean
// align: 'left',
// field: 'hasFile',
// label: t('globals.original'),
// name: 'hasFile',
// component: QCheckbox ?? span,
// cardVisible: Boolean
// props: (prop) => ({
// disable: true,
// 'model-value': Boolean(prop.value),
// }),
// },
onMounted(() => {
mode.value = $props.defaultMode;
});
</script>
<template>
<VnPaginate v-bind="$attrs" class="q-px-md">
<template #body="{ rows }">
<QTable
class="vnTable"
:columns="columns"
:rows="rows"
row-key="$index"
selection="multiple"
v-model:selected="selected"
:grid="($q.screen.lt.md && reponsive) || mode != 'table'"
table-header-class="bg-grey-8"
flat
:virtual-scroll-item-size="48"
:pagination="pagination"
:rows-per-page-options="[0]"
style="height: 85vh"
:card-container-class="mode == 'list' ? 'grid-one' : 'grid-three'"
>
<template #top-left>
<VnBreadcrumbs />
</template>
<template #top-right>
<QBtn icon="visibility" title="asd" class="bg-dark q-mr-lg" dense />
<QBtnToggle
v-model="mode"
toggle-color="primary"
class="bg-dark"
dense
:options="tableModes"
/>
<QBtn icon="filter_alt" title="asd" class="bg-dark q-ml-lg" dense />
</template>
<!-- VnTableColumn¿?-->
<template #header-cell="{ col }">
<QTh auto-width :class="`text-${col.align ?? 'left'}`">
<span>{{ col.label }}</span>
<QInput
v-if="columnSearch"
dense
outlined
:type="col.component == 'number' ? 'number' : 'text'"
/>
</QTh>
</template>
<template #body-cell="{ props, row, col }">
<QTd auto-width :class="`text-${col.align ?? 'left'}`">
<!-- {{ row[col.field] }} -->
<component
v-if="col.component"
class="col-content"
:is="basicInputs[col.component] ?? col.component"
v-bind="col.props && col.props(props)"
@click="col.event && col.event(props)"
/>
<span v-else> {{ row[col.field] }}</span>
</QTd>
</template>
<template #item="{ row, cols }">
<QCard bordered flat>
<QCardSection horizontal>
<QChip color="primary">1234123</QChip>
</QCardSection>
<QCardSection class="q-pa-md">
<div
v-for="(prop, index) of Object.entries(row)"
:key="index"
>
<div
v-if="cols[index]?.cardVisible && !cols[index]?.isId"
>
<component
v-if="cols[index]?.component"
class="cols[index]-content"
:is="
basicInputs[cols[index]?.component] ??
cols[index]?.component
"
v-bind="
cols[index]?.props && cols[index]?.props(row)
"
@click="
cols[index]?.event && cols[index]?.event(row)
"
/>
<span v-else> {{ prop[0] }} : {{ prop[1] }}</span>
</div>
</div>
</QCardSection>
</QCard>
</template>
</QTable>
</template>
</VnPaginate>
</template>
<style lang="scss">
.q-checkbox {
& .q-checkbox__label {
color: #f5b351; /* use global*/
}
& .q-checkbox__inner {
color: #f5b351; /* use global*/
}
}
.q-table--dark .q-table__bottom,
.q-table--dark thead,
.q-table--dark tr,
.q-table--dark th,
.q-table--dark td {
border-color: #222222; /* use global*/
}
.q-table__container > div:first-child {
background-color: #222222;
}
/* Works on Firefox */
* {
scrollbar-width: thin;
scrollbar-color: #f5b351 transparent;
}
/* Works on Chrome, Edge, and Safari */
*::-webkit-scrollbar {
width: 12px;
}
*::-webkit-scrollbar-track {
background: transparent;
}
*::-webkit-scrollbar-thumb {
background-color: transparent;
border-radius: 20px;
border: 3px solid #f5b351;
}
.grid-one {
display: grid;
grid-template-columns: repeat(1, 1fr);
grid-gap: 10px;
}
.grid-three {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 10px;
}
/*.vnTable {
thead tr th {
position: sticky;
z-index: 1;
}
thead tr:first-child th {
top: 0;
}
}*/
</style>

View File

@ -2,6 +2,8 @@
import { ref, computed, onBeforeMount, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import VnInput from 'src/components/common/VnInput.vue';
import VnTable from 'components/common/VnTable.vue';
import { QBtn, QIcon } from 'quasar';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
@ -266,28 +268,30 @@ const tableColumnComponents = {
const columns = computed(() => [
{
align: 'left',
field: '',
label: '',
field: 'customerStatus',
label: 'customerStatus',
name: 'customerStatus',
format: () => ' ',
},
{
align: 'left',
field: 'id',
label: t('customer.extendedList.tableVisibleColumns.id'),
name: 'id',
isId: true,
},
{
align: 'left',
field: 'name',
label: t('customer.extendedList.tableVisibleColumns.name'),
name: 'name',
cardVisible: true,
},
{
align: 'left',
field: 'fi',
label: t('customer.extendedList.tableVisibleColumns.fi'),
name: 'fi',
cardVisible: true,
},
{
align: 'left',
@ -494,7 +498,7 @@ const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
/>
</QScrollArea>
</QDrawer>
<VnSubToolbar>
<!-- <VnSubToolbar>
<template #st-actions>
<TableVisibleColumns
:all-columns="allColumnNames"
@ -505,10 +509,10 @@ const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
"
/>
</template>
</VnSubToolbar>
</VnSubToolbar> -->
<QPage class="column items-center q-pa-md">
<QTable
<VnTable
data-key="CustomerExtendedList"
:columns="columns"
:rows="rows"
class="full-width q-mt-md"
@ -516,6 +520,8 @@ const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
:visible-columns="visibleColumns"
@row-click="(evt, row, id) => navigateToTravelId(row.id)"
>
<!--
default-mode="table"
<template #body-cell="{ col, value }">
<QTd @click="stopEventPropagation($event, col)">
{{ value }}
@ -558,9 +564,8 @@ const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
@click="tableColumnComponents[props.col.name].event(props)"
/>
</QTd>
</template>
</QTable>
</QPage>
</template> -->
</VnTable>
</template>
<style lang="scss" scoped>

View File

@ -0,0 +1,571 @@
<script setup>
import { ref, computed, onBeforeMount, onMounted } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRouter } from 'vue-router';
import { QBtn, QIcon } from 'quasar';
import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import CustomerExtendedListActions from './CustomerExtendedListActions.vue';
import CustomerExtendedListFilter from './CustomerExtendedListFilter.vue';
import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import { useArrayData } from 'composables/useArrayData';
import { useStateStore } from 'stores/useStateStore';
import { toDate } from 'src/filters';
const { t } = useI18n();
const router = useRouter();
const stateStore = useStateStore();
const arrayData = ref(null);
onBeforeMount(async () => {
arrayData.value = useArrayData('CustomerExtendedList', {
url: 'Clients/extendedListFilter',
limit: 0,
});
await arrayData.value.fetch({ append: false });
stateStore.rightDrawer = true;
});
onMounted(() => {
const filteredColumns = columns.value.filter(
(col) => col.name !== 'actions' && col.name !== 'customerStatus'
);
allColumnNames.value = filteredColumns.map((col) => col.name);
});
const rows = computed(() => arrayData.value.store.data);
const selectedCustomerId = ref(0);
const selectedSalesPersonId = ref(0);
const allColumnNames = ref([]);
const visibleColumns = ref([]);
const tableColumnComponents = {
customerStatus: {
component: QIcon,
props: (prop) => ({
name: !prop.row.isActive
? 'vn:disabled'
: prop.row.isActive && prop.row.isFreezed
? 'vn:frozen'
: '',
color: 'primary',
size: 'sm',
}),
event: () => {},
},
id: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: (prop) => {
selectCustomerId(prop.row.id);
},
},
name: {
component: 'span',
props: () => {},
event: () => {},
},
fi: {
component: 'span',
props: () => {},
event: () => {},
},
salesPersonFk: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
event: (prop) => selectSalesPersonId(prop.row.salesPersonFk),
},
credit: {
component: 'span',
props: () => {},
event: () => {},
},
creditInsurance: {
component: 'span',
props: () => {},
event: () => {},
},
phone: {
component: 'span',
props: () => {},
event: () => {},
},
mobile: {
component: 'span',
props: () => {},
event: () => {},
},
street: {
component: 'span',
props: () => {},
event: () => {},
},
countryFk: {
component: 'span',
props: () => {},
event: () => {},
},
provinceFk: {
component: 'span',
props: () => {},
event: () => {},
},
city: {
component: 'span',
props: () => {},
event: () => {},
},
postcode: {
component: 'span',
props: () => {},
event: () => {},
},
email: {
component: 'span',
props: () => {},
event: () => {},
},
created: {
component: 'span',
props: () => {},
event: () => {},
},
businessTypeFk: {
component: 'span',
props: () => {},
event: () => {},
},
payMethodFk: {
component: 'span',
props: () => {},
event: () => {},
},
sageTaxTypeFk: {
component: 'span',
props: () => {},
event: () => {},
},
sageTransactionTypeFk: {
component: 'span',
props: () => {},
event: () => {},
},
isActive: {
component: QIcon,
props: (prop) => ({
name: prop.row.isActive ? 'check' : 'close',
color: prop.row.isActive ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
isVies: {
component: QIcon,
props: (prop) => ({
name: prop.row.isVies ? 'check' : 'close',
color: prop.row.isVies ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
isTaxDataChecked: {
component: QIcon,
props: (prop) => ({
name: prop.row.isTaxDataChecked ? 'check' : 'close',
color: prop.row.isTaxDataChecked ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
isEqualizated: {
component: QIcon,
props: (prop) => ({
name: prop.row.isEqualizated ? 'check' : 'close',
color: prop.row.isEqualizated ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
isFreezed: {
component: QIcon,
props: (prop) => ({
name: prop.row.isFreezed ? 'check' : 'close',
color: prop.row.isFreezed ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
hasToInvoice: {
component: QIcon,
props: (prop) => ({
name: prop.row.hasToInvoice ? 'check' : 'close',
color: prop.row.hasToInvoice ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
hasToInvoiceByAddress: {
component: QIcon,
props: (prop) => ({
name: prop.row.hasToInvoiceByAddress ? 'check' : 'close',
color: prop.row.hasToInvoiceByAddress ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
isToBeMailed: {
component: QIcon,
props: (prop) => ({
name: prop.row.isToBeMailed ? 'check' : 'close',
color: prop.row.isToBeMailed ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
hasLcr: {
component: QIcon,
props: (prop) => ({
name: prop.row.hasLcr ? 'check' : 'close',
color: prop.row.hasLcr ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
hasCoreVnl: {
component: QIcon,
props: (prop) => ({
name: prop.row.hasCoreVnl ? 'check' : 'close',
color: prop.row.hasCoreVnl ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
hasSepaVnl: {
component: QIcon,
props: (prop) => ({
name: prop.row.hasSepaVnl ? 'check' : 'close',
color: prop.row.hasSepaVnl ? 'positive' : 'negative',
size: 'sm',
}),
event: () => {},
},
actions: {
component: CustomerExtendedListActions,
props: (prop) => ({
id: prop.row.id,
}),
event: () => {},
},
};
const columns = computed(() => [
{
align: 'left',
field: '',
label: '',
name: 'customerStatus',
format: () => ' ',
},
{
align: 'left',
field: 'id',
label: t('customer.extendedList.tableVisibleColumns.id'),
name: 'id',
},
{
align: 'left',
field: 'name',
label: t('customer.extendedList.tableVisibleColumns.name'),
name: 'name',
},
{
align: 'left',
field: 'fi',
label: t('customer.extendedList.tableVisibleColumns.fi'),
name: 'fi',
},
{
align: 'left',
field: 'salesPerson',
label: t('customer.extendedList.tableVisibleColumns.salesPersonFk'),
name: 'salesPersonFk',
},
{
align: 'left',
field: 'credit',
label: t('customer.extendedList.tableVisibleColumns.credit'),
name: 'credit',
},
{
align: 'left',
field: 'creditInsurance',
label: t('customer.extendedList.tableVisibleColumns.creditInsurance'),
name: 'creditInsurance',
},
{
align: 'left',
field: 'phone',
label: t('customer.extendedList.tableVisibleColumns.phone'),
name: 'phone',
},
{
align: 'left',
field: 'mobile',
label: t('customer.extendedList.tableVisibleColumns.mobile'),
name: 'mobile',
},
{
align: 'left',
field: 'street',
label: t('customer.extendedList.tableVisibleColumns.street'),
name: 'street',
},
{
align: 'left',
field: 'country',
label: t('customer.extendedList.tableVisibleColumns.countryFk'),
name: 'countryFk',
},
{
align: 'left',
field: 'province',
label: t('customer.extendedList.tableVisibleColumns.provinceFk'),
name: 'provinceFk',
},
{
align: 'left',
field: 'city',
label: t('customer.extendedList.tableVisibleColumns.city'),
name: 'city',
},
{
align: 'left',
field: 'postcode',
label: t('customer.extendedList.tableVisibleColumns.postcode'),
name: 'postcode',
},
{
align: 'left',
field: 'email',
label: t('customer.extendedList.tableVisibleColumns.email'),
name: 'email',
},
{
align: 'left',
field: 'created',
label: t('customer.extendedList.tableVisibleColumns.created'),
name: 'created',
format: (value) => toDate(value),
},
{
align: 'left',
field: 'businessType',
label: t('customer.extendedList.tableVisibleColumns.businessTypeFk'),
name: 'businessTypeFk',
},
{
align: 'left',
field: 'payMethod',
label: t('customer.extendedList.tableVisibleColumns.payMethodFk'),
name: 'payMethodFk',
},
{
align: 'left',
field: 'sageTaxType',
label: t('customer.extendedList.tableVisibleColumns.sageTaxTypeFk'),
name: 'sageTaxTypeFk',
},
{
align: 'left',
field: 'sageTransactionType',
label: t('customer.extendedList.tableVisibleColumns.sageTransactionTypeFk'),
name: 'sageTransactionTypeFk',
},
{
align: 'left',
field: 'isActive',
label: t('customer.extendedList.tableVisibleColumns.isActive'),
name: 'isActive',
format: () => ' ',
},
{
align: 'left',
field: 'isVies',
label: t('customer.extendedList.tableVisibleColumns.isVies'),
name: 'isVies',
format: () => ' ',
},
{
align: 'left',
field: 'isTaxDataChecked',
label: t('customer.extendedList.tableVisibleColumns.isTaxDataChecked'),
name: 'isTaxDataChecked',
format: () => ' ',
},
{
align: 'left',
field: 'isEqualizated',
label: t('customer.extendedList.tableVisibleColumns.isEqualizated'),
name: 'isEqualizated',
format: () => ' ',
},
{
align: 'left',
field: 'isFreezed',
label: t('customer.extendedList.tableVisibleColumns.isFreezed'),
name: 'isFreezed',
format: () => ' ',
},
{
align: 'left',
field: 'hasToInvoice',
label: t('customer.extendedList.tableVisibleColumns.hasToInvoice'),
name: 'hasToInvoice',
format: () => ' ',
},
{
align: 'left',
field: 'hasToInvoiceByAddress',
label: t('customer.extendedList.tableVisibleColumns.hasToInvoiceByAddress'),
name: 'hasToInvoiceByAddress',
format: () => ' ',
},
{
align: 'left',
field: 'isToBeMailed',
label: t('customer.extendedList.tableVisibleColumns.isToBeMailed'),
name: 'isToBeMailed',
format: () => ' ',
},
{
align: 'left',
field: 'hasLcr',
label: t('customer.extendedList.tableVisibleColumns.hasLcr'),
name: 'hasLcr',
format: () => ' ',
},
{
align: 'left',
field: 'hasCoreVnl',
label: t('customer.extendedList.tableVisibleColumns.hasCoreVnl'),
name: 'hasCoreVnl',
format: () => ' ',
},
{
align: 'left',
field: 'hasSepaVnl',
label: t('customer.extendedList.tableVisibleColumns.hasSepaVnl'),
name: 'hasSepaVnl',
format: () => ' ',
},
{
align: 'right',
field: 'actions',
label: '',
name: 'actions',
},
]);
const stopEventPropagation = (event, col) => {
if (!['id', 'salesPersonFk'].includes(col.name)) return;
event.preventDefault();
event.stopPropagation();
};
const navigateToTravelId = (id) => router.push({ path: `/customer/${id}` });
const selectCustomerId = (id) => (selectedCustomerId.value = id);
const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
</script>
<template>
<QDrawer v-model="stateStore.rightDrawer" side="right" :width="256" show-if-above>
<QScrollArea class="fit text-grey-8">
<CustomerExtendedListFilter
v-if="visibleColumns.length !== 0"
data-key="CustomerExtendedList"
:visible-columns="visibleColumns"
/>
</QScrollArea>
</QDrawer>
<VnSubToolbar>
<template #st-actions>
<TableVisibleColumns
:all-columns="allColumnNames"
table-code="clientsDetail"
labels-traductions-path="customer.extendedList.tableVisibleColumns"
@on-config-saved="
visibleColumns = ['customerStatus', ...$event, 'actions']
"
/>
</template>
</VnSubToolbar>
<QPage class="column items-center q-pa-md">
<QTable
:columns="columns"
:rows="rows"
class="full-width q-mt-md"
row-key="id"
:visible-columns="visibleColumns"
@row-click="(evt, row, id) => navigateToTravelId(row.id)"
>
<template #body-cell="{ col, value }">
<QTd @click="stopEventPropagation($event, col)">
{{ value }}
</QTd>
</template>
<template #body-cell-id="props">
<QTd @click="stopEventPropagation($event, props.col)">
<component
:is="tableColumnComponents[props.col.name].component"
class="col-content"
v-bind="tableColumnComponents[props.col.name].props(props)"
@click="tableColumnComponents[props.col.name].event(props)"
>
<CustomerDescriptorProxy :id="props.row.id" />
{{ props.row.id }}
</component>
</QTd>
</template>
<template #body-cell-salesPersonFk="props">
<QTd @click="stopEventPropagation($event, props.col)">
<component
v-if="props.row.salesPerson"
class="col-content"
:is="tableColumnComponents[props.col.name].component"
v-bind="tableColumnComponents[props.col.name].props(props)"
@click="tableColumnComponents[props.col.name].event(props)"
>
<WorkerDescriptorProxy :id="props.row.salesPersonFk" />
{{ props.row.salesPerson }}
</component>
<span class="col-content" v-else>-</span>
</QTd>
</template>
<template #body-cell-actions="props">
<QTd @click="stopEventPropagation($event, props.col)">
<component
:is="tableColumnComponents[props.col.name].component"
class="col-content"
v-bind="tableColumnComponents[props.col.name].props(props)"
@click="tableColumnComponents[props.col.name].event(props)"
/>
</QTd>
</template>
</QTable>
</QPage>
</template>
<style lang="scss" scoped>
.col-content {
border-radius: 4px;
padding: 6px;
}
</style>