From 34341b213105a71d181879ed78ad316a255a0913 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 4 Sep 2025 11:40:10 +0530 Subject: [PATCH 1/4] fix: pagination. --- .../billing/paymentHistory.svelte | 199 ++++++++++-------- 1 file changed, 106 insertions(+), 93 deletions(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index 078990471..c3ace4695 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -27,7 +27,9 @@ IconExternalLink, IconRefresh } from '@appwrite.io/pink-icons-svelte'; + import { onMount } from 'svelte'; + let limit = $state(5); let offset = $state(0); let isLoadingInvoices = $state(false); let invoiceList: InvoiceList = $state({ @@ -35,16 +37,29 @@ total: 0 }); - const limit = 5; const endpoint = getApiEndpoint(); const hasPaymentError = $derived(invoiceList?.invoices.some((invoice) => invoice?.lastError)); - async function request() { + /** + * Special case handling for the first page! + * + * As per Damodar - `there is some logic to **hide current cycle invoice** in the endpoint`. + * + * Due to this, the first page always loads `limit - 1` invoices which is inconsistent! + * Therefore, we load `limit + 1` to counter that so the returned invoices are consistent. + */ + onMount(() => request(true)); + + async function request(patchQuery: boolean = false) { isLoadingInvoices = true; invoiceList = await sdk.forConsole.billing.listInvoices(page.params.organization, [ - Query.limit(limit), - Query.offset(offset), - Query.orderDesc('$createdAt') + Query.orderDesc('$createdAt'), + + // first page extra must have an extra limit! + Query.limit(patchQuery ? limit + 1 : limit), + + // so an invoice isn't repeated on 2nd page! + Query.offset(patchQuery ? offset : offset + 1) ]); isLoadingInvoices = false; @@ -62,12 +77,6 @@ } }); - $effect(() => { - if (offset !== null) { - request(); - } - }); - const columns = $derived([ { id: 'dueDate', width: { min: 120 } }, { id: 'status', width: { min: hasPaymentError ? 200 : 100 } }, @@ -90,7 +99,7 @@ {#if isLoadingInvoices} - {#each Array.from({ length: 2 }).keys() as index (index)} + {#each Array.from({ length: 5 }).keys() as index (index)} {#each columns as column} @@ -99,91 +108,95 @@ {/each} {/each} - {/if} - - {#each invoiceList?.invoices as invoice} - {@const status = invoice.status} - - - {toLocaleDate(invoice.dueAt)} - - - {@const isDanger = - status === 'overdue' || - status === 'failed' || - status === 'requires_authentication'} - {@const isSuccess = status === 'paid' || status === 'succeeded'} - {@const isWarning = status === 'pending'} - - - {#if invoice?.lastError} - - Details - - The scheduled payment has failed. - retryPayment(invoice)} - >Try again - - - - {/if} - - - - {formatCurrency(invoice.grossAmount)} - - - - - - - - View invoice - - - Download PDF - - {#if status === 'overdue' || status === 'failed' || status === 'abandoned'} - { - retryPayment(invoice); - trackEvent(`click_retry_payment`, { - from: 'button', - source: 'billing_invoice_menu' - }); - }}> - Retry payment - + {:else} + {#each invoiceList?.invoices as invoice (invoice.$id)} + {@const status = invoice.status} + + {toLocaleDate(invoice.dueAt)} + + {@const isDanger = + status === 'overdue' || + status === 'failed' || + status === 'requires_authentication'} + {@const isSuccess = status === 'paid' || status === 'succeeded'} + {@const isWarning = status === 'pending'} + + + {#if invoice?.lastError} + + Details + + The scheduled payment has failed. + retryPayment(invoice)} + >Try again + + + {/if} - - - - - {/each} + + + + {formatCurrency(invoice.grossAmount)} + + + + + + + + View invoice + + + Download PDF + + {#if status === 'overdue' || status === 'failed' || status === 'abandoned'} + { + retryPayment(invoice); + trackEvent(`click_retry_payment`, { + from: 'button', + source: 'billing_invoice_menu' + }); + }}> + Retry payment + + {/if} + + + + + {/each} + {/if} - {#if invoiceList.total > limit} + {#if invoiceList.total >= limit}

Total results: {invoiceList.total}

- + request()} />
{/if} {:else} From 4c9631e8d67fb5fee6848c53b40e68e2a00edca6 Mon Sep 17 00:00:00 2001 From: Darshan Date: Thu, 4 Sep 2025 11:42:49 +0530 Subject: [PATCH 2/4] move: import. --- .../organization-[organization]/billing/paymentHistory.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte index c3ace4695..dfc55935f 100644 --- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte +++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte @@ -1,5 +1,6 @@