refactor: 07 => screen.xs fetch scroll

This commit is contained in:
puriphatt 2025-01-29 17:37:42 +07:00
parent f559987e0c
commit 508e6d3f5b

View file

@ -241,7 +241,7 @@ async function fetchData() {
}); });
if (ret) { if (ret) {
data.value = ret.result; $q.screen.xs ? data.value.push(...ret.result) : (data.value = ret.result);
pageMax.value = Math.ceil(ret.total / pageSize.value); pageMax.value = Math.ceil(ret.total / pageSize.value);
pageState.total = ret.total; pageState.total = ret.total;
} }
@ -316,7 +316,7 @@ watch(
<!-- 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"
@ -448,107 +448,104 @@ watch(
</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-table <q-infinite-scroll
flat :offset="100"
bordered @load="
:grid="pageState.gridView" (_, done) => {
:rows="data" if ($q.screen.gt.xs || page === pageMax) return;
:columns="columns" page = page + 1;
class="full-width" fetchData().then(() => done(page >= pageMax));
card-container-class="q-col-gutter-md" }
row-key="name" "
:rows-per-page-options="[0]"
hide-pagination
:visible-columns="fieldSelected"
> >
<template v-slot:header="props"> <q-table
<q-tr flat
style="background-color: hsla(var(--info-bg) / 0.07)" bordered
:props="props" :grid="pageState.gridView"
> :rows="data"
<q-th v-for="col in props.cols" :key="col.name" :props="props"> :columns="columns"
{{ $t(col.label) }} class="full-width"
</q-th> card-container-class="q-col-gutter-md"
<q-th auto-width /> row-key="name"
</q-tr> :rows-per-page-options="[0]"
</template> hide-pagination
:visible-columns="fieldSelected"
<template v-slot:body="props"> >
<q-tr <template v-slot:header="props">
:class="{ <q-tr
'app-text-muted': props.row.status === 'INACTIVE', style="background-color: hsla(var(--info-bg) / 0.07)"
'status-active': props.row.status !== 'INACTIVE', :props="props"
'status-inactive': props.row.status === 'INACTIVE',
}"
:props="props"
:style="
props.rowIndex % 2 !== 0
? $q.dark.isActive
? 'background: hsl(var(--gray-11-hsl)/0.2)'
: `background: #f9fafc`
: ''
"
>
<q-td
class="text-center"
v-if="fieldSelected.includes('orderNumber')"
> >
{{ props.rowIndex + 1 }} <q-th
<!-- {{ (currentPage - 1) * pageSize + props.rowIndex + 1 }} --> v-for="col in props.cols"
</q-td> :key="col.name"
<q-td v-if="fieldSelected.includes('name')"> :props="props"
<section class="row items-center no-wrap"> >
<q-avatar size="md"> {{ $t(col.label) }}
<q-img </q-th>
class="text-center" <q-th auto-width />
:ratio="1" </q-tr>
:src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`" </template>
>
<template #error> <template v-slot:body="props">
<div <q-tr
class="no-padding full-width full-height flex items-center justify-center" :class="{
style=" 'app-text-muted': props.row.status === 'INACTIVE',
background: hsla(var(--green-8-hsl) / 0.1); 'status-active': props.row.status !== 'INACTIVE',
color: hsla(var(--green-8-hsl) / 1); 'status-inactive': props.row.status === 'INACTIVE',
" }"
> :props="props"
<Icon icon="ph-building-office" /> :style="
</div> props.rowIndex % 2 !== 0
</template> ? $q.dark.isActive
</q-img> ? 'background: hsl(var(--gray-11-hsl)/0.2)'
</q-avatar> : `background: #f9fafc`
<span class="col q-pl-md"> : ''
<div> "
{{ >
$i18n.locale === 'eng' <q-td
? props.row.nameEN class="text-center"
: props.row.name v-if="fieldSelected.includes('orderNumber')"
}} >
</div> {{ props.rowIndex + 1 }}
<div class="app-text-muted"> <!-- {{ (currentPage - 1) * pageSize + props.rowIndex + 1 }} -->
{{ props.row.code }} </q-td>
</div> <q-td v-if="fieldSelected.includes('name')">
</span> <section class="row items-center no-wrap">
</section> <q-avatar size="md">
</q-td> <q-img
<q-td v-if="fieldSelected.includes('address')"> class="text-center"
{{ :ratio="1"
formatAddress({ :src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`"
address: props.row.address, >
addressEN: props.row.addressEN, <template #error>
moo: props.row.moo, <div
mooEN: props.row.mooEN, class="no-padding full-width full-height flex items-center justify-center"
soi: props.row.soi, style="
soiEN: props.row.soiEN, background: hsla(var(--green-8-hsl) / 0.1);
street: props.row.street, color: hsla(var(--green-8-hsl) / 1);
streetEN: props.row.streetEN, "
province: props.row.province, >
district: props.row.district, <Icon icon="ph-building-office" />
subDistrict: props.row.subDistrict, </div>
en: $i18n.locale === 'eng', </template>
}) </q-img>
}} </q-avatar>
<q-tooltip> <span class="col q-pl-md">
<div>
{{
$i18n.locale === 'eng'
? props.row.nameEN
: props.row.name
}}
</div>
<div class="app-text-muted">
{{ props.row.code }}
</div>
</span>
</section>
</q-td>
<q-td v-if="fieldSelected.includes('address')">
{{ {{
formatAddress({ formatAddress({
address: props.row.address, address: props.row.address,
@ -565,119 +562,7 @@ watch(
en: $i18n.locale === 'eng', en: $i18n.locale === 'eng',
}) })
}} }}
</q-tooltip> <q-tooltip>
</q-td>
<q-td>
<q-btn
icon="mdi-eye-outline"
size="sm"
dense
round
flat
@click.stop="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
/>
<KebabAction
hide-toggle
:id-name="props.row.id"
:status="props.row.status"
@view="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
@edit="
() => {
assignFormData(props.row);
triggerDialog('edit');
}
"
@delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/>
</q-td>
</q-tr>
</template>
<template v-slot:item="props">
<section class="column col-12 col-md-6">
<div class="bordered col surface-1 rounded q-pa-md">
<header class="row items-center">
<q-avatar size="xl">
<q-img
class="text-center"
:ratio="1"
:src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`"
>
<template #error>
<div
class="no-padding full-width full-height flex items-center justify-center"
style="
background: hsla(var(--green-8-hsl) / 0.1);
color: hsla(var(--green-8-hsl) / 1);
"
>
<Icon icon="ph-building-office" />
</div>
</template>
</q-img>
</q-avatar>
<span class="text-weight-bold column q-pl-md">
{{
$i18n.locale === 'eng'
? props.row.nameEN
: props.row.name
}}
<span class="text-caption app-text-muted-2">
{{ props.row.code }}
</span>
</span>
<nav class="row q-ml-auto items-center justify-end no-wrap">
<q-btn
icon="mdi-eye-outline"
size="sm"
dense
round
flat
@click.stop="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
/>
<KebabAction
hide-toggle
:id-name="props.row.id"
:status="props.row.status"
@view="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
@edit="
() => {
assignFormData(props.row);
triggerDialog('edit');
}
"
@delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/>
</nav>
</header>
<q-separator spaced="lg" />
<div class="row full-width">
<span class="col-2 app-text-muted">
{{ $t('general.address') }}
</span>
<span class="col">
{{ {{
formatAddress({ formatAddress({
address: props.row.address, address: props.row.address,
@ -694,7 +579,121 @@ watch(
en: $i18n.locale === 'eng', en: $i18n.locale === 'eng',
}) })
}} }}
<q-tooltip> </q-tooltip>
</q-td>
<q-td>
<q-btn
icon="mdi-eye-outline"
size="sm"
dense
round
flat
@click.stop="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
/>
<KebabAction
hide-toggle
:id-name="props.row.id"
:status="props.row.status"
@view="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
@edit="
() => {
assignFormData(props.row);
triggerDialog('edit');
}
"
@delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/>
</q-td>
</q-tr>
</template>
<template v-slot:item="props">
<section class="column col-12 col-md-6">
<div class="bordered col surface-1 rounded q-pa-md">
<header class="row items-center">
<q-avatar size="xl">
<q-img
class="text-center"
:ratio="1"
:src="`${baseUrl}/institution/${props.row.id}/image/${props.row.selectedImage}?ts=${Date.now()}`"
>
<template #error>
<div
class="no-padding full-width full-height flex items-center justify-center"
style="
background: hsla(var(--green-8-hsl) / 0.1);
color: hsla(var(--green-8-hsl) / 1);
"
>
<Icon icon="ph-building-office" />
</div>
</template>
</q-img>
</q-avatar>
<span class="text-weight-bold column q-pl-md">
{{
$i18n.locale === 'eng'
? props.row.nameEN
: props.row.name
}}
<span class="text-caption app-text-muted-2">
{{ props.row.code }}
</span>
</span>
<nav
class="row q-ml-auto items-center justify-end no-wrap"
>
<q-btn
icon="mdi-eye-outline"
size="sm"
dense
round
flat
@click.stop="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
/>
<KebabAction
hide-toggle
:id-name="props.row.id"
:status="props.row.status"
@view="
() => {
assignFormData(props.row);
triggerDialog('view');
}
"
@edit="
() => {
assignFormData(props.row);
triggerDialog('edit');
}
"
@delete="() => triggerDelete(props.row.id)"
@change-status="() => triggerChangeStatus(props.row)"
/>
</nav>
</header>
<q-separator spaced="lg" />
<div class="row full-width">
<span class="col-2 app-text-muted">
{{ $t('general.address') }}
</span>
<span class="col">
{{ {{
formatAddress({ formatAddress({
address: props.row.address, address: props.row.address,
@ -711,19 +710,45 @@ watch(
en: $i18n.locale === 'eng', en: $i18n.locale === 'eng',
}) })
}} }}
</q-tooltip> <q-tooltip>
</span> {{
formatAddress({
address: props.row.address,
addressEN: props.row.addressEN,
moo: props.row.moo,
mooEN: props.row.mooEN,
soi: props.row.soi,
soiEN: props.row.soiEN,
street: props.row.street,
streetEN: props.row.streetEN,
province: props.row.province,
district: props.row.district,
subDistrict: props.row.subDistrict,
en: $i18n.locale === 'eng',
})
}}
</q-tooltip>
</span>
</div>
</div> </div>
</div> </section>
</section> </template>
</q-table>
<template v-slot:loading>
<div
v-if="$q.screen.lt.sm && page !== pageMax"
class="row justify-center"
>
<q-spinner-dots color="primary" size="40px" />
</div>
</template> </template>
</q-table> </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="pageMax > 0" v-if="pageMax > 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">