"Add pagination to OrderBookingsTable.vue with next/previous controls, dynamic page limit, and loading state management; refine empty state handling and table structure for improved user experience"

This commit is contained in:
Jeppe Bundgaard
2025-11-10 12:06:50 +01:00
parent 61484f01bd
commit f040534f2e
@@ -8,12 +8,44 @@ import ActionSettingsWheelItemLabel from "@/components/displays/buttons/ActionSe
import ActionSettingsWheelItem from "@/components/displays/buttons/ActionSettingsWheelItem.vue";
const bookings = ref([]);
const page = ref(1);
const limit = ref(10);
const loading = ref(false);
const isLastPage = ref(false);
const fetch = async () => {
SessionUser.objects.order_bookings.get.all().then((res) => {
bookings.value = res;
loading.value = true;
return SessionUser.objects.order_bookings.get.all({ page: page.value, limit: limit.value }).then((res) => {
bookings.value = res || [];
// Infer if this is the last page based on result size
isLastPage.value = bookings.value.length < limit.value;
}).catch((e) => {
console.error(e);
bookings.value = [];
isLastPage.value = true;
}).finally(() => {
loading.value = false;
});
}
const nextPage = async () => {
if (isLastPage.value || loading.value) return;
page.value += 1;
await fetch();
}
const prevPage = async () => {
if (page.value === 1 || loading.value) return;
page.value -= 1;
await fetch();
}
const onLimitChange = async () => {
// Reset to first page when page size changes
page.value = 1;
await fetch();
}
onMounted(() => {
fetch();
})
@@ -109,95 +141,118 @@ const formatSummaryString = (items) => {
<th><!-- Items -->Ydelser</th>
<th><!-- Actions --></th>
</tr>
<template v-if="bookings.length === 0">
<template v-if="bookings.length === 0 && !loading">
<tr>
<td colspan="1">Ingen bookinger fundet</td>
<td colspan="8">Ingen bookinger fundet</td>
</tr>
</template>
<tr v-for="booking in bookings" :key="booking.id">
<!-- Date -->
<EditableTableColumn
<template v-else>
<tr v-for="booking in bookings" :key="booking.id">
<!-- Date -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="datetime"
:parse-function="(value) => value ? `${value}` : 'Ingen dato valgt'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Vehicles -->
<td>
<p>
<EditableTableColumn
:componentWrapper="'div'"
:object="booking"
:loadList="fetch"
column="reg_1"
:parse-function="(value) => value || 'Ingen registreret'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
</p>
<p>
<EditableTableColumn
:componentWrapper="'div'"
:object="booking"
:loadList="fetch"
column="reg_2"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
</p>
</td>
<!-- Department -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="department"
:parse-function="(value) => getDepartmentName(parseInt(booking.department))"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- PO -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="po"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Reference -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="reference"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Pickup -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="pickup"
:permissionCheckFunction="(bookingobj) => true"
:parse-function="(value) => value ? 'Ja' : 'Nej'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Items -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="datetime"
:parse-function="(value) => value ? `${value}` : 'Ingen dato valgt'"
column="items"
:permissionCheckFunction = "(bookingobj) => booking.items.length > 0"
:parse-function="(bookingobj) => formatSummaryString(booking.items)"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Vehicles -->
<td>
<p>
<EditableTableColumn
:componentWrapper="'div'"
:object="booking"
:loadList="fetch"
column="reg_1"
:parse-function="(value) => value || 'Ingen registreret'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
</p>
<p>
<EditableTableColumn
:componentWrapper="'div'"
:object="booking"
:loadList="fetch"
column="reg_2"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
</p>
</td>
<!-- Department -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="department"
:parse-function="(value) => getDepartmentName(parseInt(booking.department))"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- PO -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="po"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Reference -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="reference"
:parse-function="(value) => value || '-'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Pickup -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="pickup"
:permissionCheckFunction="(bookingobj) => true"
:parse-function="(value) => value ? 'Ja' : 'Nej'"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Items -->
<EditableTableColumn
:object="booking"
:loadList="fetch"
column="items"
:permissionCheckFunction = "(bookingobj) => booking.items.length > 0"
:parse-function="(bookingobj) => formatSummaryString(booking.items)"
:edit-function="SessionUser.objects.order_bookings.showEditObjectFieldForm"
/>
<!-- Actions -->
<td>
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="fetch">
<template #actions>
</template>
</ActionSettingsWheelButton>
</td>
<!-- TODO: Complete implementation! -->
</tr>
/>
<!-- Actions -->
<td>
<ActionSettingsWheelButton :order_booking_id="booking.id" :order_id="booking.order_id" :customer_number="booking.customer_number" :department_id="booking.department" :refresh-function="fetch">
<template #actions>
</template>
</ActionSettingsWheelButton>
</td>
<!-- TODO: Complete implementation! -->
</tr>
</template>
</table>
<!-- Pagination Controls -->
<div class="level">
<div class="level-left">
<nav class="pagination is-centered" role="navigation" aria-label="pagination">
<a class="pagination-previous" :class="{ 'is-disabled': page === 1 || loading }" @click="prevPage">Forrige</a>
<a class="pagination-next" :class="{ 'is-disabled': isLastPage || loading }" @click="nextPage">Næste</a>
</nav>
</div>
<div class="level-right">
<div class="select">
<select v-model.number="limit" @change="onLimitChange" :disabled="loading">
<option :value="5">5</option>
<option :value="10">10</option>
<option :value="20">20</option>
<option :value="50">50</option>
</select>
</div>
<span class="ml-3">Side {{ page }}</span>
</div>
</div>
</div>
</template>