refactor: add table
This commit is contained in:
parent
3608f8d0fe
commit
55f6a5f84e
2 changed files with 222 additions and 59 deletions
|
|
@ -1,32 +1,149 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { QuotationPayload } from 'src/stores/quotations/types';
|
|
||||||
import { QTableProps } from 'quasar';
|
import { QTableProps } from 'quasar';
|
||||||
|
import { QuotationPayload } from 'src/stores/quotations/types';
|
||||||
|
import BadgeComponent from 'components/BadgeComponent.vue';
|
||||||
|
import KebabAction from 'components/shared/KebabAction.vue';
|
||||||
|
import { setLocale, calculateAge, dateFormat } from 'src/utils/datetime';
|
||||||
|
import useOptionStore from 'src/stores/options';
|
||||||
|
|
||||||
|
const optionStore = useOptionStore();
|
||||||
|
|
||||||
const props = withDefaults(
|
const props = withDefaults(
|
||||||
defineProps<{
|
defineProps<{
|
||||||
rows: QTableProps['rows'];
|
rows: QTableProps['rows'];
|
||||||
columns: QTableProps['columns'];
|
columns: QTableProps['columns'];
|
||||||
grid?: boolean;
|
grid?: boolean;
|
||||||
fieldSelected?: string[];
|
visibleColumns?: string[];
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
row: () => [],
|
row: () => [],
|
||||||
column: () => [],
|
column: () => [],
|
||||||
grid: false,
|
grid: false,
|
||||||
fieldSelected: () => [],
|
visibleColumns: () => [],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
function payCondition(value: string) {
|
||||||
|
if (value === 'Full') return 'quotation.type.fullAmountCash';
|
||||||
|
if (value === 'Split') return 'quotation.type.installmentsCash';
|
||||||
|
if (value === 'SplitCustom') return 'quotation.type.installmentsCustomCash';
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function quotationStatus(value: string) {
|
||||||
|
if (value === 'Issued') return 'quotation.status.Issued';
|
||||||
|
if (value === 'Accepted') return 'quotation.status.Accepted';
|
||||||
|
if (value === 'Expired') return 'quotation.status.Expired';
|
||||||
|
if (value === 'PaymentInProcess') return 'quotation.status.PaymentInProcess';
|
||||||
|
if (value === 'PaymentSuccess') return 'quotation.status.PaymentSuccess';
|
||||||
|
if (value === 'ProcessComplete') return 'quotation.status.ProcessComplete';
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
defineEmits<{
|
||||||
|
(e: 'preview', data: any): void;
|
||||||
|
(e: 'view', data: any): void;
|
||||||
|
(e: 'edit', data: any): void;
|
||||||
|
(e: 'delete', data: any): void;
|
||||||
|
}>();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<q-table v-bind="props">
|
<q-table
|
||||||
|
v-bind="props"
|
||||||
|
flat
|
||||||
|
hide-pagination
|
||||||
|
card-container-class="q-col-gutter-sm"
|
||||||
|
>
|
||||||
<template v-slot:header="props">
|
<template v-slot:header="props">
|
||||||
<q-tr style="background-color: #f0fff1" :props="props">
|
<q-tr
|
||||||
|
style="background-color: hsla(var(--info-bg) / 0.07)"
|
||||||
|
:props="props"
|
||||||
|
>
|
||||||
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
<q-th v-for="col in props.cols" :key="col.name" :props="props">
|
||||||
{{ col.label }}
|
{{ $t(col.label) }}
|
||||||
</q-th>
|
</q-th>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:body="props">
|
||||||
|
<q-tr>
|
||||||
|
<q-td v-if="visibleColumns.includes('order')">
|
||||||
|
{{ props.rowIndex + 1 }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('workName')">
|
||||||
|
<div class="column">
|
||||||
|
<div class="col-6">{{ props.row.workName }}</div>
|
||||||
|
<div class="col-6 app-text-muted">{{ props.row.code }}</div>
|
||||||
|
</div>
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('createdAt')">
|
||||||
|
{{ dateFormat(props.row.createdAt) }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('dueDate')">
|
||||||
|
{{ dateFormat(props.row.dueDate) }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('contactName')">
|
||||||
|
{{ props.row.contactName }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('actor')">
|
||||||
|
{{ props.row.createdBy.firstName }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('summaryPrice')">
|
||||||
|
{{ props.row.finalPrice }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('payCondition')">
|
||||||
|
{{ $t(payCondition(props.row.payCondition)) }}
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('status')">
|
||||||
|
<BadgeComponent
|
||||||
|
:title-i18n="$t(quotationStatus(props.row.quotationStatus))"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td v-if="visibleColumns.includes('example')">
|
||||||
|
<span
|
||||||
|
class="text-primary cursor-pointer"
|
||||||
|
style="text-decoration: underline"
|
||||||
|
@click="$emit('preview', props.row.id)"
|
||||||
|
>
|
||||||
|
Preview
|
||||||
|
</span>
|
||||||
|
</q-td>
|
||||||
|
|
||||||
|
<q-td>
|
||||||
|
<q-btn
|
||||||
|
:id="`btn-eye-${props.row.firstName}`"
|
||||||
|
icon="mdi-eye-outline"
|
||||||
|
size="sm"
|
||||||
|
dense
|
||||||
|
round
|
||||||
|
flat
|
||||||
|
@click.stop="$emit('view', props.row)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<KebabAction
|
||||||
|
hide-toggle
|
||||||
|
@view="$emit('view', props.row)"
|
||||||
|
@edit="$emit('edit', props.row)"
|
||||||
|
@delete="$emit('delete', props.row.id)"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-slot:item="props">
|
||||||
|
<slot name="grid" :item="props" />
|
||||||
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { pageTabs, fieldSelectedOption } from './constants';
|
import { pageTabs, columnQuotation } from './constants';
|
||||||
|
|
||||||
import { onMounted, reactive, ref, watch } from 'vue';
|
import { onMounted, reactive, ref, watch, computed } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
|
|
||||||
// NOTE: Import stores
|
// NOTE: Import stores
|
||||||
|
|
@ -40,6 +40,7 @@ import {
|
||||||
|
|
||||||
import { useCustomerForm } from 'src/pages/03_customer-management/form';
|
import { useCustomerForm } from 'src/pages/03_customer-management/form';
|
||||||
import { Quotation } from 'src/stores/quotations/types';
|
import { Quotation } from 'src/stores/quotations/types';
|
||||||
|
import TableQuotation from 'src/components/05_quotation/TableQuotation.vue';
|
||||||
|
|
||||||
const quotationFormStore = useQuotationForm();
|
const quotationFormStore = useQuotationForm();
|
||||||
const customerFormStore = useCustomerForm();
|
const customerFormStore = useCustomerForm();
|
||||||
|
|
@ -55,6 +56,12 @@ const { state: customerFormState, currentFormData: customerFormData } =
|
||||||
storeToRefs(customerFormStore);
|
storeToRefs(customerFormStore);
|
||||||
const { currentMyBranch } = storeToRefs(userBranch);
|
const { currentMyBranch } = storeToRefs(userBranch);
|
||||||
|
|
||||||
|
const fieldSelectedOption = computed(() => {
|
||||||
|
return columnQuotation.map((v) => ({
|
||||||
|
label: v.label,
|
||||||
|
value: v.name,
|
||||||
|
}));
|
||||||
|
});
|
||||||
const special = ref(false);
|
const special = ref(false);
|
||||||
const branchId = ref('');
|
const branchId = ref('');
|
||||||
const agentPrice = ref<boolean>(false);
|
const agentPrice = ref<boolean>(false);
|
||||||
|
|
@ -68,7 +75,7 @@ const currentQuotationPayment = ref<Quotation>();
|
||||||
const pageState = reactive({
|
const pageState = reactive({
|
||||||
hideStat: false,
|
hideStat: false,
|
||||||
inputSearch: '',
|
inputSearch: '',
|
||||||
fieldSelected: [],
|
fieldSelected: [''],
|
||||||
gridView: true,
|
gridView: true,
|
||||||
total: 0,
|
total: 0,
|
||||||
|
|
||||||
|
|
@ -79,6 +86,8 @@ const pageState = reactive({
|
||||||
receiptModal: false,
|
receiptModal: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pageState.fieldSelected = [...columnQuotation.map((v) => v.name)];
|
||||||
|
|
||||||
const CUSTOMER_BRANCH_DEFAULT: CustomerBranchCreate & {
|
const CUSTOMER_BRANCH_DEFAULT: CustomerBranchCreate & {
|
||||||
id?: string;
|
id?: string;
|
||||||
branchCode?: string;
|
branchCode?: string;
|
||||||
|
|
@ -452,7 +461,6 @@ async function storeDataLocal(id: string) {
|
||||||
</q-input>
|
</q-input>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="false"
|
|
||||||
class="row col-12 col-md-4 justify-end"
|
class="row col-12 col-md-4 justify-end"
|
||||||
:class="{ 'q-pt-xs': $q.screen.lt.md }"
|
:class="{ 'q-pt-xs': $q.screen.lt.md }"
|
||||||
style="white-space: nowrap"
|
style="white-space: nowrap"
|
||||||
|
|
@ -582,63 +590,101 @@ async function storeDataLocal(id: string) {
|
||||||
:i18n-args="{ text: $t('quotation.title') }"
|
:i18n-args="{ text: $t('quotation.title') }"
|
||||||
/>
|
/>
|
||||||
</article>
|
</article>
|
||||||
<article v-else class="col q-pa-md surface-2 scroll">
|
<article v-else class="col q-pa-md surface-2 full-width scroll">
|
||||||
<div class="row q-col-gutter-md">
|
<div class="row">
|
||||||
<div
|
<div style="overflow-x: auto">
|
||||||
v-for="v in quotationData"
|
<TableQuotation
|
||||||
:key="v.id"
|
style="max-width: 100%"
|
||||||
class="col-md-4 col-sm-6 col-12"
|
:columns="columnQuotation"
|
||||||
>
|
:rows="quotationData"
|
||||||
<QuotationCard
|
:visible-columns="pageState.fieldSelected"
|
||||||
:urgent="v.urgent"
|
:grid="pageState.gridView"
|
||||||
:code="v.code"
|
@preview="(id: any) => storeDataLocal(id)"
|
||||||
:title="v.workName"
|
|
||||||
:created-at="
|
|
||||||
new Date(v.createdAt).toLocaleString('th-TH', {
|
|
||||||
hour12: false,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
:valid-until="
|
|
||||||
(() => {
|
|
||||||
const date = new Date(v.dueDate);
|
|
||||||
date.setHours(23, 59, 59, 0);
|
|
||||||
return date.toLocaleString('th-TH', { hour12: false });
|
|
||||||
})()
|
|
||||||
"
|
|
||||||
:status="$t(`quotation.status.${v.quotationStatus}`)"
|
|
||||||
:worker-count="v._count.worker"
|
|
||||||
:worker-max="v.workerMax || v._count.worker"
|
|
||||||
:customer-name="
|
|
||||||
v.customerBranch.registerName ||
|
|
||||||
`${v.customerBranch.firstName || '-'} ${v.customerBranch.lastName || ''}`
|
|
||||||
"
|
|
||||||
:reporter="
|
|
||||||
$i18n.locale === 'eng'
|
|
||||||
? v.createdBy.firstNameEN + ' ' + v.createdBy.lastNameEN
|
|
||||||
: v.createdBy.firstName + ' ' + v.createdBy.lastName
|
|
||||||
"
|
|
||||||
:total-price="v.finalPrice"
|
|
||||||
@preview="storeDataLocal(v.id)"
|
|
||||||
@view="
|
@view="
|
||||||
() => {
|
(item) => {
|
||||||
triggerQuotationDialog({
|
triggerQuotationDialog({
|
||||||
statusDialog: 'info',
|
statusDialog: 'info',
|
||||||
quotationId: v.id,
|
quotationId: item.id,
|
||||||
branchId: v.customerBranch.customer.registeredBranchId,
|
branchId: item.customerBranch.customer.registeredBranchId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
@edit="
|
@edit="
|
||||||
triggerQuotationDialog({
|
(item) =>
|
||||||
statusDialog: 'edit',
|
triggerQuotationDialog({
|
||||||
quotationId: v.id,
|
statusDialog: 'edit',
|
||||||
branchId: v.customerBranch.customer.registeredBranchId,
|
quotationId: item.id,
|
||||||
})
|
branchId: item.customerBranch.customer.registeredBranchId,
|
||||||
|
})
|
||||||
"
|
"
|
||||||
@link="triggerReceiptDialog(v)"
|
@delete="(id) => triggerDialogDeleteQuottaion(id)"
|
||||||
@upload="console.log('upload')"
|
>
|
||||||
@delete="triggerDialogDeleteQuottaion(v.id)"
|
<template #grid="{ item }">
|
||||||
/>
|
<div class="col-md-4 col-sm-6 col-12">
|
||||||
|
<QuotationCard
|
||||||
|
:urgent="item.row.urgent"
|
||||||
|
:code="item.row.code"
|
||||||
|
:title="item.row.workName"
|
||||||
|
:created-at="
|
||||||
|
new Date(item.row.createdAt).toLocaleString('th-TH', {
|
||||||
|
hour12: false,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
:valid-until="
|
||||||
|
(() => {
|
||||||
|
const date = new Date(item.row.dueDate);
|
||||||
|
date.setHours(23, 59, 59, 0);
|
||||||
|
return date.toLocaleString('th-TH', {
|
||||||
|
hour12: false,
|
||||||
|
});
|
||||||
|
})()
|
||||||
|
"
|
||||||
|
:status="
|
||||||
|
$t(`quotation.status.${item.row.quotationStatus}`)
|
||||||
|
"
|
||||||
|
:worker-count="item.row._count.worker"
|
||||||
|
:worker-max="item.row.workerMax || item.row._count.worker"
|
||||||
|
:customer-name="
|
||||||
|
item.row.customerBranch.registerName ||
|
||||||
|
`${item.row.customerBranch.firstName || '-'} ${item.row.customerBranch.lastName || ''}`
|
||||||
|
"
|
||||||
|
:reporter="
|
||||||
|
$i18n.locale === 'eng'
|
||||||
|
? item.row.createdBy.firstNameEN +
|
||||||
|
' ' +
|
||||||
|
item.row.createdBy.lastNameEN
|
||||||
|
: item.row.createdBy.firstName +
|
||||||
|
' ' +
|
||||||
|
item.row.createdBy.lastName
|
||||||
|
"
|
||||||
|
:total-price="item.row.finalPrice"
|
||||||
|
@preview="storeDataLocal(item.row.id)"
|
||||||
|
@view="
|
||||||
|
() => {
|
||||||
|
triggerQuotationDialog({
|
||||||
|
statusDialog: 'info',
|
||||||
|
quotationId: item.row.id,
|
||||||
|
branchId:
|
||||||
|
item.row.customerBranch.customer
|
||||||
|
.registeredBranchId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@edit="
|
||||||
|
triggerQuotationDialog({
|
||||||
|
statusDialog: 'edit',
|
||||||
|
quotationId: item.row.id,
|
||||||
|
branchId:
|
||||||
|
item.row.customerBranch.customer.registeredBranchId,
|
||||||
|
})
|
||||||
|
"
|
||||||
|
@link="triggerReceiptDialog(item.row)"
|
||||||
|
@upload="console.log('upload')"
|
||||||
|
@delete="triggerDialogDeleteQuottaion(item.row.id)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</TableQuotation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue