refactor: 05 => xs scroll & adjust TableQuotation row index calculation

This commit is contained in:
puriphatt 2025-02-03 11:22:33 +07:00
parent 8a937dfa31
commit 1fc6b39e37
2 changed files with 137 additions and 102 deletions

View file

@ -16,12 +16,16 @@ const props = withDefaults(
grid?: boolean; grid?: boolean;
visibleColumns?: string[]; visibleColumns?: string[];
hideEdit?: boolean; hideEdit?: boolean;
page?: number;
pageSize?: number;
}>(), }>(),
{ {
row: () => [], row: () => [],
column: () => [], column: () => [],
grid: false, grid: false,
visibleColumns: () => [], visibleColumns: () => [],
page: 1,
pageSize: 30,
}, },
); );
@ -64,7 +68,11 @@ defineEmits<{
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :class="{ urgent: props.row.urgent }"> <q-tr :class="{ urgent: props.row.urgent }">
<q-td v-if="visibleColumns.includes('order')"> <q-td v-if="visibleColumns.includes('order')">
{{ props.rowIndex + 1 }} {{
$q.screen.xs
? props.rowIndex + 1
: (page - 1) * pageSize + props.rowIndex + 1
}}
</q-td> </q-td>
<q-td v-if="visibleColumns.includes('workName')"> <q-td v-if="visibleColumns.includes('workName')">

View file

@ -278,10 +278,10 @@ onMounted(async () => {
flowStore.rotate(); flowStore.rotate();
}); });
async function fetchQuotationList() { async function fetchQuotationList(mobileFetch?: boolean) {
{ {
const ret = await quotationStore.getQuotationList({ const ret = await quotationStore.getQuotationList({
page: quotationPage.value, page: mobileFetch ? 1 : quotationPage.value,
pageSize: quotationPageSize.value, pageSize: quotationPageSize.value,
status: status:
pageState.currentTab !== 'Issued' pageState.currentTab !== 'Issued'
@ -301,7 +301,10 @@ async function fetchQuotationList() {
}); });
if (ret) { if (ret) {
quotationData.value = ret.result; quotationData.value =
$q.screen.xs && !mobileFetch
? [...quotationData.value, ...ret.result]
: ret.result;
quotationPageMax.value = Math.ceil(ret.total / quotationPageSize.value); quotationPageMax.value = Math.ceil(ret.total / quotationPageSize.value);
pageState.total = ret.total; pageState.total = ret.total;
} }
@ -319,7 +322,11 @@ async function fetchQuotationList() {
watch( watch(
[() => pageState.currentTab, () => pageState.inputSearch, quotationPageSize], [() => pageState.currentTab, () => pageState.inputSearch, quotationPageSize],
fetchQuotationList, () => {
quotationPage.value = 1;
quotationData.value = [];
fetchQuotationList();
},
); );
async function storeDataLocal(id: string) { async function storeDataLocal(id: string) {
@ -383,19 +390,11 @@ async function storeDataLocal(id: string) {
" "
> >
{{ {{
pageState.currentTab === 'Issued' quotationStats[
? quotationStats.issued pageState.currentTab === 'Invoice'
: pageState.currentTab === 'Accepted' ? 'paymentInProcess'
? quotationStats.accepted : (pageState.currentTab.toLowerCase() as keyof typeof quotationStats)
: pageState.currentTab === 'Expired' ]
? quotationStats.expired
: pageState.currentTab === 'Invoice'
? quotationStats.paymentInProcess
: pageState.currentTab === 'PaymentSuccess'
? quotationStats.paymentSuccess
: pageState.currentTab === 'ProcessComplete'
? quotationStats.processComplete
: 0
}} }}
</q-badge> </q-badge>
<q-btn <q-btn
@ -625,106 +624,134 @@ async function storeDataLocal(id: string) {
</article> </article>
<article v-else class="col surface-2 full-width scroll"> <article v-else class="col surface-2 full-width scroll">
<div class="q-pa-md"> <div class="q-pa-md">
<TableQuotation <q-infinite-scroll
:columns="columnQuotation" :key="pageState.currentTab"
:rows="quotationData" :offset="100"
:visible-columns="pageState.fieldSelected" @load="
:grid="pageState.gridView" (_, done) => {
:hide-edit="pageState.currentTab !== 'Issued'" if ($q.screen.gt.xs) return;
@preview="(id: any) => storeDataLocal(id)" quotationPage = quotationPage + 1;
@view="
(item) => { fetchQuotationList().then(() => {
triggerQuotationDialog({ done(quotationPage >= quotationPageMax);
statusDialog: 'info',
quotationId: item.id,
branchId: item.customerBranch.customer.registeredBranchId,
}); });
} }
" "
@edit="
(item) =>
triggerQuotationDialog({
statusDialog: 'edit',
quotationId: item.id,
branchId: item.customerBranch.customer.registeredBranchId,
})
"
@delete="(id) => triggerDialogDeleteQuottaion(id)"
> >
<template #grid="{ item }"> <TableQuotation
<div class="col-md-4 col-sm-6 col-12 column"> :page="quotationPage"
<QuotationCard :page-size="quotationPageSize"
class="col" :columns="columnQuotation"
hide-kebab-delete :rows="quotationData"
:hide-kebab-edit="!(pageState.currentTab === 'Issued')" :visible-columns="pageState.fieldSelected"
:urgent="item.row.urgent" :grid="pageState.gridView"
:code="item.row.code" :hide-edit="pageState.currentTab !== 'Issued'"
:title="item.row.workName" @preview="(id: any) => storeDataLocal(id)"
:created-at=" @view="
new Date(item.row.createdAt).toLocaleString('th-TH', { (item) => {
hour12: false, triggerQuotationDialog({
}) statusDialog: 'info',
" quotationId: item.id,
:valid-until=" branchId: item.customerBranch.customer.registeredBranchId,
(() => { });
const date = new Date(item.row.dueDate); }
date.setHours(23, 59, 59, 0); "
return date.toLocaleString('th-TH', { @edit="
(item) =>
triggerQuotationDialog({
statusDialog: 'edit',
quotationId: item.id,
branchId: item.customerBranch.customer.registeredBranchId,
})
"
@delete="(id) => triggerDialogDeleteQuottaion(id)"
>
<template #grid="{ item }">
<div class="col-md-4 col-sm-6 col-12 column">
<QuotationCard
class="col"
hide-kebab-delete
:hide-kebab-edit="!(pageState.currentTab === 'Issued')"
:urgent="item.row.urgent"
:code="item.row.code"
:title="item.row.workName"
:created-at="
new Date(item.row.createdAt).toLocaleString('th-TH', {
hour12: false, hour12: false,
}); })
})() "
" :valid-until="
:status="$t(`quotation.status.${item.row.quotationStatus}`)" (() => {
:worker-count="item.row._count.worker" const date = new Date(item.row.dueDate);
:worker-max="item.row.workerMax || item.row._count.worker" date.setHours(23, 59, 59, 0);
:customer-name=" return date.toLocaleString('th-TH', {
item.row.customerBranch.registerName || hour12: false,
`${item.row.customerBranch.firstName || '-'} ${item.row.customerBranch.lastName || ''}` });
" })()
:reporter=" "
$i18n.locale === 'eng' :status="
? item.row.createdBy.firstNameEN + $t(`quotation.status.${item.row.quotationStatus}`)
' ' + "
item.row.createdBy.lastNameEN :worker-count="item.row._count.worker"
: item.row.createdBy.firstName + :worker-max="item.row.workerMax || item.row._count.worker"
' ' + :customer-name="
item.row.createdBy.lastName item.row.customerBranch.registerName ||
" `${item.row.customerBranch.firstName || '-'} ${item.row.customerBranch.lastName || ''}`
:total-price="item.row.finalPrice" "
:badge-color="hslaColors[item.row.quotationStatus] || ''" :reporter="
@preview="storeDataLocal(item.row.id)" $i18n.locale === 'eng'
@view=" ? item.row.createdBy.firstNameEN +
() => { ' ' +
item.row.createdBy.lastNameEN
: item.row.createdBy.firstName +
' ' +
item.row.createdBy.lastName
"
:total-price="item.row.finalPrice"
:badge-color="hslaColors[item.row.quotationStatus] || ''"
@preview="storeDataLocal(item.row.id)"
@view="
() => {
triggerQuotationDialog({
statusDialog: 'info',
quotationId: item.row.id,
branchId:
item.row.customerBranch.customer
.registeredBranchId,
});
}
"
@edit="
triggerQuotationDialog({ triggerQuotationDialog({
statusDialog: 'info', statusDialog: 'edit',
quotationId: item.row.id, quotationId: item.row.id,
branchId: branchId:
item.row.customerBranch.customer.registeredBranchId, item.row.customerBranch.customer.registeredBranchId,
}); })
} "
" @link="triggerReceiptDialog(item.row)"
@edit=" @upload="console.log('upload')"
triggerQuotationDialog({ @delete="triggerDialogDeleteQuottaion(item.row.id)"
statusDialog: 'edit', />
quotationId: item.row.id, </div>
branchId: </template>
item.row.customerBranch.customer.registeredBranchId, </TableQuotation>
}) <template v-slot:loading>
" <div
@link="triggerReceiptDialog(item.row)" v-if="$q.screen.lt.sm && quotationPage !== quotationPageMax"
@upload="console.log('upload')" class="row justify-center"
@delete="triggerDialogDeleteQuottaion(item.row.id)" >
/> <q-spinner-dots color="primary" size="40px" />
</div> </div>
</template> </template>
</TableQuotation> </q-infinite-scroll>
</div> </div>
</article> </article>
<!-- SEC: footer content --> <!-- SEC: footer content -->
<footer <footer
class="row justify-between items-center q-px-md q-py-sm surface-2" class="row justify-between items-center q-px-md q-py-sm surface-2"
v-if="quotationPageMax > 0" v-if="quotationPageMax > 0 && $q.screen.gt.xs"
> >
<div class="col-4"> <div class="col-4">
<div class="row items-center no-wrap"> <div class="row items-center no-wrap">
@ -755,7 +782,7 @@ async function storeDataLocal(id: string) {
<PaginationComponent <PaginationComponent
v-model:current-page="quotationPage" v-model:current-page="quotationPage"
v-model:max-page="quotationPageMax" v-model:max-page="quotationPageMax"
:fetch-data="fetchQuotationList" :fetch-data="() => fetchQuotationList()"
/> />
</nav> </nav>
</footer> </footer>