refactor: add table

This commit is contained in:
Thanaphon Frappet 2024-11-07 17:53:40 +07:00
parent 3608f8d0fe
commit 55f6a5f84e
2 changed files with 222 additions and 59 deletions

View file

@ -1,32 +1,149 @@
<script lang="ts" setup>
import { QuotationPayload } from 'src/stores/quotations/types';
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(
defineProps<{
rows: QTableProps['rows'];
columns: QTableProps['columns'];
grid?: boolean;
fieldSelected?: string[];
visibleColumns?: string[];
}>(),
{
row: () => [],
column: () => [],
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>
<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">
<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">
{{ col.label }}
{{ $t(col.label) }}
</q-th>
</q-tr>
</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>
</template>

View file

@ -1,7 +1,7 @@
<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';
// NOTE: Import stores
@ -40,6 +40,7 @@ import {
import { useCustomerForm } from 'src/pages/03_customer-management/form';
import { Quotation } from 'src/stores/quotations/types';
import TableQuotation from 'src/components/05_quotation/TableQuotation.vue';
const quotationFormStore = useQuotationForm();
const customerFormStore = useCustomerForm();
@ -55,6 +56,12 @@ const { state: customerFormState, currentFormData: customerFormData } =
storeToRefs(customerFormStore);
const { currentMyBranch } = storeToRefs(userBranch);
const fieldSelectedOption = computed(() => {
return columnQuotation.map((v) => ({
label: v.label,
value: v.name,
}));
});
const special = ref(false);
const branchId = ref('');
const agentPrice = ref<boolean>(false);
@ -68,7 +75,7 @@ const currentQuotationPayment = ref<Quotation>();
const pageState = reactive({
hideStat: false,
inputSearch: '',
fieldSelected: [],
fieldSelected: [''],
gridView: true,
total: 0,
@ -79,6 +86,8 @@ const pageState = reactive({
receiptModal: false,
});
pageState.fieldSelected = [...columnQuotation.map((v) => v.name)];
const CUSTOMER_BRANCH_DEFAULT: CustomerBranchCreate & {
id?: string;
branchCode?: string;
@ -452,7 +461,6 @@ async function storeDataLocal(id: string) {
</q-input>
<div
v-if="false"
class="row col-12 col-md-4 justify-end"
:class="{ 'q-pt-xs': $q.screen.lt.md }"
style="white-space: nowrap"
@ -582,63 +590,101 @@ async function storeDataLocal(id: string) {
:i18n-args="{ text: $t('quotation.title') }"
/>
</article>
<article v-else class="col q-pa-md surface-2 scroll">
<div class="row q-col-gutter-md">
<div
v-for="v in quotationData"
:key="v.id"
class="col-md-4 col-sm-6 col-12"
>
<QuotationCard
:urgent="v.urgent"
:code="v.code"
: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)"
<article v-else class="col q-pa-md surface-2 full-width scroll">
<div class="row">
<div style="overflow-x: auto">
<TableQuotation
style="max-width: 100%"
:columns="columnQuotation"
:rows="quotationData"
:visible-columns="pageState.fieldSelected"
:grid="pageState.gridView"
@preview="(id: any) => storeDataLocal(id)"
@view="
() => {
(item) => {
triggerQuotationDialog({
statusDialog: 'info',
quotationId: v.id,
branchId: v.customerBranch.customer.registeredBranchId,
quotationId: item.id,
branchId: item.customerBranch.customer.registeredBranchId,
});
}
"
@edit="
triggerQuotationDialog({
statusDialog: 'edit',
quotationId: v.id,
branchId: v.customerBranch.customer.registeredBranchId,
})
(item) =>
triggerQuotationDialog({
statusDialog: 'edit',
quotationId: item.id,
branchId: item.customerBranch.customer.registeredBranchId,
})
"
@link="triggerReceiptDialog(v)"
@upload="console.log('upload')"
@delete="triggerDialogDeleteQuottaion(v.id)"
/>
@delete="(id) => triggerDialogDeleteQuottaion(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>
</article>