forked from verdnatura/salix-front
feat: refs #6825 create vnTableColumn, cardActions
This commit is contained in:
parent
e0379dd1bc
commit
ed3c9db919
|
@ -1,15 +1,11 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, markRaw, computed } from 'vue';
|
import { ref, onMounted, computed } from 'vue';
|
||||||
import { QCheckbox, useQuasar } from 'quasar';
|
import { useQuasar } from 'quasar';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import VnPaginate from 'components/ui/VnPaginate.vue';
|
import VnPaginate from 'components/ui/VnPaginate.vue';
|
||||||
import VnBreadcrumbs from 'components/common/VnBreadcrumbs.vue';
|
import VnBreadcrumbs from 'components/common/VnBreadcrumbs.vue';
|
||||||
|
import VnTableColumn from 'src/components/common/VnTableColumn.vue';
|
||||||
/* basic input */
|
import VnLv from 'src/components/ui/VnLv.vue';
|
||||||
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 VnLv from 'src/components/ui/VnLv.vue';
|
|
||||||
|
|
||||||
const $props = defineProps({
|
const $props = defineProps({
|
||||||
columns: {
|
columns: {
|
||||||
|
@ -64,13 +60,6 @@ const tableModes = computed(() => {
|
||||||
|
|
||||||
return modes;
|
return modes;
|
||||||
});
|
});
|
||||||
const basicInputs = {
|
|
||||||
input: markRaw(VnInput),
|
|
||||||
number: markRaw(VnInput),
|
|
||||||
date: markRaw(VnInputDate),
|
|
||||||
checkbox: markRaw(QCheckbox),
|
|
||||||
select: markRaw(VnSelect),
|
|
||||||
};
|
|
||||||
// {
|
// {
|
||||||
// isId: Boolean
|
// isId: Boolean
|
||||||
// align: 'left',
|
// align: 'left',
|
||||||
|
@ -146,19 +135,12 @@ onMounted(() => {
|
||||||
/>
|
/>
|
||||||
</QTh>
|
</QTh>
|
||||||
</template>
|
</template>
|
||||||
<template #body-cell="{ props, row, col }">
|
<template #body-cell="{ row, col }">
|
||||||
<QTd auto-width :class="`text-${col.align ?? 'left'}`">
|
<QTd auto-width :class="`text-${col.align ?? 'left'}`">
|
||||||
<!-- {{ row[col.field] }} -->
|
<VnTableColumn :column="col" :row />
|
||||||
<component
|
|
||||||
v-if="col.component"
|
|
||||||
: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>
|
</QTd>
|
||||||
</template>
|
</template>
|
||||||
<template #item="{ row, cols }">
|
<template #item="{ row, cols, colsMap }">
|
||||||
<QCard bordered flat>
|
<QCard bordered flat>
|
||||||
<QCardSection horizontal>
|
<QCardSection horizontal>
|
||||||
<span
|
<span
|
||||||
|
@ -166,57 +148,47 @@ onMounted(() => {
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
>
|
||||||
<QChip
|
<QChip
|
||||||
color="primary"
|
color="primary-light"
|
||||||
v-if="cols[index]?.isId"
|
|
||||||
square
|
square
|
||||||
|
v-if="cols[index]?.isId"
|
||||||
:title="t(cols[index].label)"
|
:title="t(cols[index].label)"
|
||||||
|
class="no-margin"
|
||||||
>
|
>
|
||||||
{{ prop[1] }}
|
{{ prop[1] }}
|
||||||
</QChip>
|
</QChip>
|
||||||
</span>
|
</span>
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
<QCardSection>
|
<QCardSection class="row justify-between q-pa-sm">
|
||||||
|
<div>
|
||||||
|
<div v-for="col of colsMap" :key="col.field">
|
||||||
<div
|
<div
|
||||||
v-for="(prop, index) of Object.entries(row)"
|
v-if="
|
||||||
|
col.cardVisible &&
|
||||||
|
!col.isId &&
|
||||||
|
col.field != 'tableActions'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<VnLv :label="`${col.label}:`">
|
||||||
|
<template #value>
|
||||||
|
<VnTableColumn :column="col" :row />
|
||||||
|
</template>
|
||||||
|
</VnLv>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="colsMap.tableActions" class="column">
|
||||||
|
<QBtn
|
||||||
|
v-for="(btn, index) of colsMap.tableActions.actions"
|
||||||
:key="index"
|
:key="index"
|
||||||
>
|
:title="btn.title"
|
||||||
<div
|
:icon="btn.icon"
|
||||||
v-if="cols[index]?.cardVisible && !cols[index]?.isId"
|
:outline="!btn.isPrimary"
|
||||||
>
|
size="sm"
|
||||||
{{ t(cols[index].label) }} :
|
class="q-pa-sm q-mb-sm"
|
||||||
<component
|
:class="{ 'bg-primary-light': btn.isPrimary }"
|
||||||
v-if="cols[index]?.component"
|
@click.stop="btn.action(row)"
|
||||||
: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[1] }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</QCardSection>
|
|
||||||
<QCardSection>
|
|
||||||
<span
|
|
||||||
v-for="(prop, index) of Object.entries(row)"
|
|
||||||
:key="index"
|
|
||||||
>
|
|
||||||
<QChip
|
|
||||||
color="primary"
|
|
||||||
v-if="cols[index]?.isId"
|
|
||||||
square
|
|
||||||
:title="t(cols[index].label)"
|
|
||||||
>
|
|
||||||
{{ prop[1] }}
|
|
||||||
</QChip>
|
|
||||||
</span>
|
|
||||||
</QCardSection>
|
</QCardSection>
|
||||||
</QCard>
|
</QCard>
|
||||||
</template>
|
</template>
|
||||||
|
@ -225,12 +197,22 @@ onMounted(() => {
|
||||||
</VnPaginate>
|
</VnPaginate>
|
||||||
</template>
|
</template>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
* {
|
||||||
|
--primary-light: #f5b351;
|
||||||
|
}
|
||||||
|
.bg-primary-light {
|
||||||
|
background-color: var(--primary-light);
|
||||||
|
color: var(--vn-section-color);
|
||||||
|
}
|
||||||
|
.text-primary-light {
|
||||||
|
color: var(--primary-light);
|
||||||
|
}
|
||||||
.q-checkbox {
|
.q-checkbox {
|
||||||
& .q-checkbox__label {
|
& .q-checkbox__label {
|
||||||
color: #f5b351; /* use global*/
|
color: var(--primary-light); /* use global*/
|
||||||
}
|
}
|
||||||
& .q-checkbox__inner {
|
& .q-checkbox__inner {
|
||||||
color: #f5b351; /* use global*/
|
color: var(--primary-light); /* use global*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.q-table--dark .q-table__bottom,
|
.q-table--dark .q-table__bottom,
|
||||||
|
@ -248,7 +230,7 @@ onMounted(() => {
|
||||||
/* Works on Firefox */
|
/* Works on Firefox */
|
||||||
* {
|
* {
|
||||||
scrollbar-width: thin;
|
scrollbar-width: thin;
|
||||||
scrollbar-color: #f5b351 transparent;
|
scrollbar-color: var(--primary-light) transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Works on Chrome, Edge, and Safari */
|
/* Works on Chrome, Edge, and Safari */
|
||||||
|
@ -263,7 +245,7 @@ onMounted(() => {
|
||||||
*::-webkit-scrollbar-thumb {
|
*::-webkit-scrollbar-thumb {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
border: 3px solid #f5b351;
|
border: 3px solid var(--primary-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-one {
|
.grid-one {
|
||||||
|
@ -297,4 +279,9 @@ onMounted(() => {
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vn-label-value {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<template>
|
||||||
|
<component
|
||||||
|
v-if="column.component"
|
||||||
|
:is="components[column.component] ?? column.component"
|
||||||
|
v-bind="column.props && column.props(row)"
|
||||||
|
@click="column.event && column.event(row)"
|
||||||
|
/>
|
||||||
|
<span v-else>{{ dashIfEmpty(row[column.field]) }}</span>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { markRaw } from 'vue';
|
||||||
|
import { QIcon, QCheckbox } from 'quasar';
|
||||||
|
import { dashIfEmpty } from 'src/filters';
|
||||||
|
|
||||||
|
/* 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';
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
input: markRaw(VnInput),
|
||||||
|
number: markRaw(VnInput),
|
||||||
|
date: markRaw(VnInputDate),
|
||||||
|
checkbox: markRaw(QCheckbox),
|
||||||
|
select: markRaw(VnSelect),
|
||||||
|
icon: markRaw(QIcon),
|
||||||
|
};
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
column: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
row: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,19 +1,15 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, computed, onBeforeMount, onMounted } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import VnInput from 'src/components/common/VnInput.vue';
|
|
||||||
import VnTable from 'components/common/VnTable.vue';
|
import VnTable from 'components/common/VnTable.vue';
|
||||||
|
import CustomerSummary from '../Card/CustomerSummary.vue';
|
||||||
|
import { useSummaryDialog } from 'src/composables/useSummaryDialog';
|
||||||
|
|
||||||
import { QBtn, QIcon } from 'quasar';
|
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 CustomerExtendedListActions from './CustomerExtendedListActions.vue';
|
||||||
import CustomerExtendedListFilter from './CustomerExtendedListFilter.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 { useStateStore } from 'stores/useStateStore';
|
||||||
import { toDate } from 'src/filters';
|
import { toDate } from 'src/filters';
|
||||||
|
|
||||||
|
@ -21,17 +17,6 @@ const { t } = useI18n();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const stateStore = useStateStore();
|
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(() => {
|
onMounted(() => {
|
||||||
const filteredColumns = columns.value.filter(
|
const filteredColumns = columns.value.filter(
|
||||||
(col) => col.name !== 'actions' && col.name !== 'customerStatus'
|
(col) => col.name !== 'actions' && col.name !== 'customerStatus'
|
||||||
|
@ -39,8 +24,6 @@ onMounted(() => {
|
||||||
allColumnNames.value = filteredColumns.map((col) => col.name);
|
allColumnNames.value = filteredColumns.map((col) => col.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
const rows = computed(() => arrayData.value.store.data);
|
|
||||||
|
|
||||||
const selectedCustomerId = ref(0);
|
const selectedCustomerId = ref(0);
|
||||||
const selectedSalesPersonId = ref(0);
|
const selectedSalesPersonId = ref(0);
|
||||||
const allColumnNames = ref([]);
|
const allColumnNames = ref([]);
|
||||||
|
@ -264,6 +247,17 @@ const tableColumnComponents = {
|
||||||
event: () => {},
|
event: () => {},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
const { viewSummary } = useSummaryDialog();
|
||||||
|
const redirectToCreateView = (row) => {
|
||||||
|
router.push({
|
||||||
|
name: 'TicketList',
|
||||||
|
query: {
|
||||||
|
params: JSON.stringify({
|
||||||
|
clientFk: row.id,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const columns = computed(() => [
|
const columns = computed(() => [
|
||||||
{
|
{
|
||||||
|
@ -284,14 +278,12 @@ const columns = computed(() => [
|
||||||
field: 'name',
|
field: 'name',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.name'),
|
label: t('customer.extendedList.tableVisibleColumns.name'),
|
||||||
name: 'name',
|
name: 'name',
|
||||||
cardVisible: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'fi',
|
field: 'fi',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.fi'),
|
label: t('customer.extendedList.tableVisibleColumns.fi'),
|
||||||
name: 'fi',
|
name: 'fi',
|
||||||
cardVisible: true,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -316,12 +308,14 @@ const columns = computed(() => [
|
||||||
field: 'phone',
|
field: 'phone',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.phone'),
|
label: t('customer.extendedList.tableVisibleColumns.phone'),
|
||||||
name: 'phone',
|
name: 'phone',
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
field: 'mobile',
|
field: 'mobile',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.mobile'),
|
label: t('customer.extendedList.tableVisibleColumns.mobile'),
|
||||||
name: 'mobile',
|
name: 'mobile',
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -358,6 +352,7 @@ const columns = computed(() => [
|
||||||
field: 'email',
|
field: 'email',
|
||||||
label: t('customer.extendedList.tableVisibleColumns.email'),
|
label: t('customer.extendedList.tableVisibleColumns.email'),
|
||||||
name: 'email',
|
name: 'email',
|
||||||
|
cardVisible: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left',
|
||||||
|
@ -469,9 +464,22 @@ const columns = computed(() => [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'right',
|
align: 'right',
|
||||||
field: 'actions',
|
field: 'tableActions',
|
||||||
label: '',
|
label: '',
|
||||||
name: 'actions',
|
name: 'tableActions',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
title: t('Client ticket list'),
|
||||||
|
icon: 'vn:ticket',
|
||||||
|
action: redirectToCreateView,
|
||||||
|
isPrimary: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t('Client ticket list'),
|
||||||
|
icon: 'preview',
|
||||||
|
action: (row) => viewSummary(row.id, CustomerSummary),
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -513,12 +521,10 @@ const selectSalesPersonId = (id) => (selectedSalesPersonId.value = id);
|
||||||
|
|
||||||
<VnTable
|
<VnTable
|
||||||
data-key="CustomerExtendedList"
|
data-key="CustomerExtendedList"
|
||||||
|
url="Clients/extendedListFilter"
|
||||||
|
order="id DESC"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:rows="rows"
|
auto-load
|
||||||
class="full-width q-mt-md"
|
|
||||||
row-key="id"
|
|
||||||
:visible-columns="visibleColumns"
|
|
||||||
@row-click="(evt, row, id) => navigateToTravelId(row.id)"
|
|
||||||
>
|
>
|
||||||
<!--
|
<!--
|
||||||
default-mode="table"
|
default-mode="table"
|
||||||
|
|
Loading…
Reference in New Issue