Private
Public Access
1
0

Switch transactions to server-side pagination

Replace v-data-table with v-data-table-server so page changes
fetch from the API instead of being limited to the first 50
results. Filters reset to page 1; page/size changes trigger a
new API call with the correct page and pageSize parameters.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Catherine Renelle
2026-02-09 19:50:35 -05:00
parent 9a49adf89a
commit caf109013e
@@ -37,14 +37,17 @@
</v-card> </v-card>
<v-card> <v-card>
<v-data-table <v-data-table-server
:headers="headers" :headers="headers"
:items="transactions" :items="transactions"
:items-length="totalCount"
:loading="loading" :loading="loading"
:items-per-page="50" :items-per-page="itemsPerPage"
:page="page"
density="compact" density="compact"
show-expand show-expand
:expand-on-click="false" :expand-on-click="false"
@update:options="onTableOptions"
> >
<template #item.date="{ item }">{{ formatDate(item.date) }}</template> <template #item.date="{ item }">{{ formatDate(item.date) }}</template>
<template #item.categoryName="{ item }"> <template #item.categoryName="{ item }">
@@ -87,7 +90,7 @@
<v-btn icon size="x-small" variant="text" color="error" @click="deleteTransaction(item.id)"><v-icon size="small">mdi-delete</v-icon></v-btn> <v-btn icon size="x-small" variant="text" color="error" @click="deleteTransaction(item.id)"><v-icon size="small">mdi-delete</v-icon></v-btn>
</div> </div>
</template> </template>
</v-data-table> </v-data-table-server>
</v-card> </v-card>
<!-- Add/Edit Transaction Dialog --> <!-- Add/Edit Transaction Dialog -->
@@ -202,6 +205,9 @@ import type { Transaction, Category, SplitFormItem } from '@/types'
const props = defineProps<{ id?: string }>() const props = defineProps<{ id?: string }>()
const accountsStore = useAccountsStore() const accountsStore = useAccountsStore()
const transactions = ref<Transaction[]>([]) const transactions = ref<Transaction[]>([])
const totalCount = ref(0)
const page = ref(1)
const itemsPerPage = ref(50)
const categories = ref<Category[]>([]) const categories = ref<Category[]>([])
const loading = ref(false) const loading = ref(false)
const accountName = ref('') const accountName = ref('')
@@ -272,32 +278,37 @@ async function loadCategories() {
async function loadTransactions() { async function loadTransactions() {
loading.value = true loading.value = true
try { try {
if (props.id) { if (props.id && !search.value && !startDate.value && !endDate.value && statusFilter.value === 'All') {
const { data } = await transactionsApi.getByAccount(props.id) const { data } = await transactionsApi.getByAccount(props.id, page.value, itemsPerPage.value)
transactions.value = data.items transactions.value = data.items
totalCount.value = data.totalCount
} else { } else {
const { data } = await transactionsApi.search({}) const { data } = await transactionsApi.search({
accountId: props.id || undefined,
searchText: search.value || undefined,
startDate: startDate.value || undefined,
endDate: endDate.value || undefined,
status: statusFilter.value === 'All' ? undefined : statusFilter.value,
page: page.value,
pageSize: itemsPerPage.value,
})
transactions.value = data.items transactions.value = data.items
totalCount.value = data.totalCount
} }
} finally { } finally {
loading.value = false loading.value = false
} }
} }
async function doSearch() { function doSearch() {
loading.value = true page.value = 1
try { loadTransactions()
const { data } = await transactionsApi.search({ }
accountId: props.id || undefined,
searchText: search.value || undefined, function onTableOptions(options: { page: number; itemsPerPage: number }) {
startDate: startDate.value || undefined, page.value = options.page
endDate: endDate.value || undefined, itemsPerPage.value = options.itemsPerPage
status: statusFilter.value === 'All' ? undefined : statusFilter.value, loadTransactions()
})
transactions.value = data.items
} finally {
loading.value = false
}
} }
function openAddDialog() { function openAddDialog() {