refactor: 04 => screen.xs fetch scroll

This commit is contained in:
puriphatt 2025-01-29 17:07:43 +07:00
parent a894bacb13
commit f559987e0c
2 changed files with 733 additions and 671 deletions

View file

@ -276,7 +276,10 @@ async function fetchWorkflowList() {
: 'INACTIVE', : 'INACTIVE',
}); });
if (res) { if (res) {
workflowData.value = res.result; $q.screen.xs
? workflowData.value.push(...res.result)
: (workflowData.value = res.result);
workflowPageMax.value = Math.ceil(res.total / workflowPageSize.value); workflowPageMax.value = Math.ceil(res.total / workflowPageSize.value);
if (pageState.inputSearch || statusFilter.value !== 'all') return; if (pageState.inputSearch || statusFilter.value !== 'all') return;
pageState.total = res.total; pageState.total = res.total;
@ -351,7 +354,7 @@ watch([() => pageState.inputSearch, workflowPageSize], fetchWorkflowList);
<!-- SEC: header content --> <!-- SEC: header content -->
<section class="col surface-1 rounded bordered overflow-hidden"> <section class="col surface-1 rounded bordered overflow-hidden">
<div class="column full-height"> <div class="column full-height no-wrap">
<header <header
class="row surface-3 justify-between full-width items-center bordered-b" class="row surface-3 justify-between full-width items-center bordered-b"
style="z-index: 1" style="z-index: 1"
@ -500,6 +503,18 @@ watch([() => pageState.inputSearch, workflowPageSize], fetchWorkflowList);
</article> </article>
<article v-else class="col q-pa-md surface-2 scroll full-width"> <article v-else class="col q-pa-md surface-2 scroll full-width">
<q-infinite-scroll
:offset="100"
@load="
(_, done) => {
if ($q.screen.gt.xs || workflowPage === workflowPageMax) return;
workflowPage = workflowPage + 1;
fetchWorkflowList().then(() =>
done(workflowPage >= workflowPageMax),
);
}
"
>
<q-table <q-table
flat flat
bordered bordered
@ -588,7 +603,10 @@ watch([() => pageState.inputSearch, workflowPageSize], fetchWorkflowList);
{{ props.row.name }} {{ props.row.name }}
</section> </section>
</q-td> </q-td>
<q-td v-if="fieldSelected.includes('step')" class="text-right"> <q-td
v-if="fieldSelected.includes('step')"
class="text-right"
>
{{ props.row.step.length }} {{ props.row.step.length }}
</q-td> </q-td>
<q-td style="width: 20%" class="text-right"> <q-td style="width: 20%" class="text-right">
@ -659,9 +677,15 @@ watch([() => pageState.inputSearch, workflowPageSize], fetchWorkflowList);
{{ props.row.name }} {{ props.row.name }}
</q-tooltip> </q-tooltip>
</div> </div>
<div v-if="fieldSelected.includes('step')" class="self-end"> <div
v-if="fieldSelected.includes('step')"
class="self-end"
>
<div class="bordered rounded q-px-sm"> <div class="bordered rounded q-px-sm">
<q-icon name="mdi-note-edit-outline" class="q-pr-sm" /> <q-icon
name="mdi-note-edit-outline"
class="q-pr-sm"
/>
{{ props.row.step.length }} {{ props.row.step.length }}
</div> </div>
</div> </div>
@ -703,12 +727,22 @@ watch([() => pageState.inputSearch, workflowPageSize], fetchWorkflowList);
</section> </section>
</template> </template>
</q-table> </q-table>
<template v-slot:loading>
<div
v-if="$q.screen.lt.sm && workflowPage !== workflowPageMax"
class="row justify-center"
>
<q-spinner-dots color="primary" size="40px" />
</div>
</template>
</q-infinite-scroll>
</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="workflowPageMax > 0" v-if="workflowPageMax > 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">

View file

@ -35,6 +35,7 @@ import {
ToggleButton, ToggleButton,
} from 'components/button'; } from 'components/button';
import TableProduct from 'src/components/04_product-service/TableProduct.vue'; import TableProduct from 'src/components/04_product-service/TableProduct.vue';
import PaginationPageSize from 'src/components/PaginationPageSize.vue';
import useFlowStore from 'stores/flow'; import useFlowStore from 'stores/flow';
@ -612,7 +613,10 @@ async function fetchListGroups() {
currentPageGroup.value = res.page; currentPageGroup.value = res.page;
totalGroup.value = res.total; totalGroup.value = res.total;
maxPageGroup.value = Math.ceil(res.total / pageSizeGroup.value); maxPageGroup.value = Math.ceil(res.total / pageSizeGroup.value);
productGroup.value = res.result; if (!productGroup.value) productGroup.value = [];
$q.screen.lt.md
? productGroup.value.push(...res.result)
: (productGroup.value = res.result);
} }
} }
@ -668,13 +672,22 @@ async function fetchListOfProduct() {
maxPageServiceAndProduct.value = Math.ceil( maxPageServiceAndProduct.value = Math.ceil(
res.total / pageSizeServiceAndProduct.value, res.total / pageSizeServiceAndProduct.value,
); );
if (!product.value) product.value = [];
product.value = res.result.map((v) => { $q.screen.xs
? product.value.push(
...res.result.map((v) => {
return {
...v,
type: 'product' as const,
};
}),
)
: (product.value = res.result.map((v) => {
return { return {
...v, ...v,
type: 'product', type: 'product',
}; };
}); }));
} }
} }
@ -701,12 +714,22 @@ async function fetchListOfService() {
maxPageServiceAndProduct.value = Math.ceil( maxPageServiceAndProduct.value = Math.ceil(
res.total / pageSizeServiceAndProduct.value, res.total / pageSizeServiceAndProduct.value,
); );
service.value = res.result.map((v) => { if (!service.value) service.value = [];
$q.screen.xs
? service.value.push(
...res.result.map((v) => {
return {
...v,
type: 'service' as const,
};
}),
)
: (service.value = res.result.map((v) => {
return { return {
...v, ...v,
type: 'service', type: 'service',
}; };
}); }));
} }
} }
@ -1541,8 +1564,11 @@ async function enterNext(type: 'service' | 'product') {
filterStat.value.push('group'); filterStat.value.push('group');
filterStat.value.push('service'); filterStat.value.push('service');
} }
if (productMode.value === 'service') await fetchListOfService();
if (productMode.value === 'product') await fetchListOfProduct(); if (productMode.value === 'service' && $q.screen.gt.xs)
await fetchListOfService();
if (productMode.value === 'product' && $q.screen.gt.xs)
await fetchListOfProduct();
flowStore.rotate(); flowStore.rotate();
} }
@ -1566,6 +1592,8 @@ async function fetchImageList(
} }
onMounted(async () => { onMounted(async () => {
$q.screen.gt.sm && (await fetchListGroups());
navigatorStore.current.title = 'productService.title'; navigatorStore.current.title = 'productService.title';
navigatorStore.current.path = [ navigatorStore.current.path = [
{ {
@ -1581,7 +1609,6 @@ onMounted(async () => {
modeView.value = $q.screen.lt.md ? true : false; modeView.value = $q.screen.lt.md ? true : false;
calculateStats(); calculateStats();
await fetchListGroups();
flowStore.rotate(); flowStore.rotate();
}); });
@ -1876,8 +1903,20 @@ watch(
</q-input> </q-input>
</div> </div>
<div class="col full-width scroll"> <div class="col full-width scroll q-pa-md">
<div class="q-pa-md"> <q-infinite-scroll
:offset="100"
@load="
async (_, done) => {
if ($q.screen.gt.sm) return;
fetchListGroups().then(() => {
currentPageGroup = currentPageGroup + 1;
done(currentPageGroup > maxPageGroup);
});
}
"
>
<TreeComponent <TreeComponent
v-model:nodes="treeProductTypeAndGroup" v-model:nodes="treeProductTypeAndGroup"
v-model:expanded-tree="expandedTree" v-model:expanded-tree="expandedTree"
@ -1980,7 +2019,15 @@ watch(
" "
@handle-hold="handleHold" @handle-hold="handleHold"
/> />
<template v-slot:loading>
<div
v-if="$q.screen.lt.sm && currentPageGroup !== maxPageGroup"
class="row justify-center"
>
<q-spinner-dots color="primary" size="40px" />
</div> </div>
</template>
</q-infinite-scroll>
</div> </div>
</div> </div>
</template> </template>
@ -2438,7 +2485,8 @@ watch(
</q-table> </q-table>
</div> </div>
<div <!-- footer group -->
<footer
v-if="productMode === 'group'" v-if="productMode === 'group'"
class="row items-center justify-between q-px-md q-py-sm full-width" class="row items-center justify-between q-px-md q-py-sm full-width"
> >
@ -2451,31 +2499,7 @@ watch(
{{ $t('general.recordPerPage') }} {{ $t('general.recordPerPage') }}
</div> </div>
<div> <div>
<q-btn-dropdown <PaginationPageSize v-model="pageSizeGroup" />
dense
unelevated
:label="pageSizeGroup"
class="bordered q-pl-md"
>
<q-list>
<q-item
v-for="v in [10, 30, 50, 100, 500, 1000]"
:key="v"
clickable
v-close-popup
@click="
async () => {
pageSizeGroup = v;
await fetchListGroups();
}
"
>
<q-item-section>
<q-item-label>{{ v }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</div> </div>
</div> </div>
</div> </div>
@ -2506,7 +2530,7 @@ watch(
" "
/> />
</div> </div>
</div> </footer>
</template> </template>
</div> </div>
@ -2672,6 +2696,22 @@ watch(
<template v-else> <template v-else>
<div <div
class="flex scroll full-width q-pa-md surface-2 column col" class="flex scroll full-width q-pa-md surface-2 column col"
>
<q-infinite-scroll
:offset="100"
@load="
(_, done) => {
if ($q.screen.gt.xs) return;
alternativeFetch().then(() => {
currentPageServiceAndProduct =
currentPageServiceAndProduct + 1;
done(
currentPageServiceAndProduct >
maxPageServiceAndProduct,
);
});
}
"
> >
<q-table <q-table
class="full-width" class="full-width"
@ -3094,7 +3134,11 @@ watch(
:price-display="priceDisplay" :price-display="priceDisplay"
@toggle-status=" @toggle-status="
() => { () => {
triggerChangeStatus(row.id, row.status, row.type); triggerChangeStatus(
row.id,
row.status,
row.type,
);
} }
" "
@menu-view-detail=" @menu-view-detail="
@ -3142,10 +3186,24 @@ watch(
</div> </div>
</template> </template>
</q-table> </q-table>
<template v-slot:loading>
<div
v-if="
$q.screen.lt.sm &&
currentPageServiceAndProduct !==
maxPageServiceAndProduct
"
class="row justify-center"
>
<q-spinner-dots color="primary" size="40px" />
</div> </div>
</template> </template>
<!-- footer --> </q-infinite-scroll>
<div </div>
</template>
<!-- footer product service -->
<footer
v-if="$q.screen.gt.xs"
class="row items-center justify-between q-py-sm q-px-md surface-2" class="row items-center justify-between q-py-sm q-px-md surface-2"
> >
<div class="col-4"> <div class="col-4">
@ -3154,37 +3212,7 @@ watch(
{{ $t('general.recordPerPage') }} {{ $t('general.recordPerPage') }}
</div> </div>
<div> <div>
<q-btn-dropdown <PaginationPageSize v-model="pageSizeServiceAndProduct" />
dense
unelevated
:label="pageSizeServiceAndProduct"
class="bordered q-pl-md"
>
<q-list>
<q-item
v-for="v in [10, 30, 50, 100, 500, 1000]"
:key="v"
clickable
v-close-popup
@click="
async () => {
pageSizeServiceAndProduct = v;
if (productAndServiceTab === 'product') {
await fetchListOfProduct();
}
if (productAndServiceTab === 'service') {
await fetchListOfService();
}
}
"
>
<q-item-section>
<q-item-label>{{ v }}</q-item-label>
</q-item-section>
</q-item>
</q-list>
</q-btn-dropdown>
</div> </div>
</div> </div>
</div> </div>
@ -3220,7 +3248,7 @@ watch(
" "
/> />
</div> </div>
</div> </footer>
</div> </div>
</div> </div>
</template> </template>