From ca152cd5448575b4a00281e354af5a27576daf9a Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Wed, 15 Apr 2026 22:18:59 +0200 Subject: [PATCH] fix(loyalty): use shared pagination macro on card detail transactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace custom pagination with the shared pagination_simple macro to match the cards list page pattern. Always shows "Showing X-Y of Z" with Previous/Next — no longer hidden when only 1 page. Uses standard Alpine.js pagination interface (pagination.page, totalPages, startIndex, endIndex, pageNumbers, previousPage, nextPage, goToPage). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../static/store/js/loyalty-card-detail.js | 43 +++++++++++++------ .../templates/loyalty/store/card-detail.html | 18 +------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/app/modules/loyalty/static/store/js/loyalty-card-detail.js b/app/modules/loyalty/static/store/js/loyalty-card-detail.js index a808b99a..ea63cf54 100644 --- a/app/modules/loyalty/static/store/js/loyalty-card-detail.js +++ b/app/modules/loyalty/static/store/js/loyalty-card-detail.js @@ -11,7 +11,7 @@ function storeLoyaltyCardDetail() { cardId: null, card: null, transactions: [], - txPagination: { page: 1, perPage: 20, total: 0, pages: 0 }, + pagination: { page: 1, per_page: 20, total: 0 }, loading: false, error: null, @@ -42,7 +42,7 @@ function storeLoyaltyCardDetail() { // Use platform pagination setting if available if (window.PlatformSettings) { try { - this.txPagination.perPage = await window.PlatformSettings.getRowsPerPage(); + this.pagination.per_page = await window.PlatformSettings.getRowsPerPage(); } catch (e) { /* use default */ } } @@ -77,29 +77,46 @@ function storeLoyaltyCardDetail() { async loadTransactions(page = 1) { try { - const skip = (page - 1) * this.txPagination.perPage; + const skip = (page - 1) * this.pagination.per_page; const response = await apiClient.get( - `/store/loyalty/cards/${this.cardId}/transactions?skip=${skip}&limit=${this.txPagination.perPage}` + `/store/loyalty/cards/${this.cardId}/transactions?skip=${skip}&limit=${this.pagination.per_page}` ); if (response && response.transactions) { this.transactions = response.transactions; - this.txPagination.total = response.total || 0; - this.txPagination.page = page; - this.txPagination.pages = Math.ceil(this.txPagination.total / this.txPagination.perPage); - loyaltyCardDetailLog.info(`Loaded ${this.transactions.length} of ${this.txPagination.total} transactions (page ${page})`); + this.pagination.total = response.total || 0; + this.pagination.page = page; + loyaltyCardDetailLog.info(`Loaded ${this.transactions.length} of ${this.pagination.total} transactions (page ${page})`); } } catch (error) { loyaltyCardDetailLog.warn('Failed to load transactions:', error.message); } }, - txPreviousPage() { - if (this.txPagination.page > 1) this.loadTransactions(this.txPagination.page - 1); + // Standard pagination interface (matches shared pagination macro) + get totalPages() { + return Math.max(1, Math.ceil(this.pagination.total / this.pagination.per_page)); }, - - txNextPage() { - if (this.txPagination.page < this.txPagination.pages) this.loadTransactions(this.txPagination.page + 1); + get startIndex() { + if (this.pagination.total === 0) return 0; + return (this.pagination.page - 1) * this.pagination.per_page + 1; }, + get endIndex() { + return Math.min(this.pagination.page * this.pagination.per_page, this.pagination.total); + }, + get pageNumbers() { + const pages = []; + for (let i = 1; i <= this.totalPages; i++) { + if (i === 1 || i === this.totalPages || Math.abs(i - this.pagination.page) <= 1) { + pages.push(i); + } else if (pages[pages.length - 1] !== '...') { + pages.push('...'); + } + } + return pages; + }, + previousPage() { if (this.pagination.page > 1) this.loadTransactions(this.pagination.page - 1); }, + nextPage() { if (this.pagination.page < this.totalPages) this.loadTransactions(this.pagination.page + 1); }, + goToPage(p) { if (p >= 1 && p <= this.totalPages) this.loadTransactions(p); }, formatNumber(num) { return num == null ? '0' : new Intl.NumberFormat('en-US').format(num); diff --git a/app/modules/loyalty/templates/loyalty/store/card-detail.html b/app/modules/loyalty/templates/loyalty/store/card-detail.html index 8a18f693..49a83980 100644 --- a/app/modules/loyalty/templates/loyalty/store/card-detail.html +++ b/app/modules/loyalty/templates/loyalty/store/card-detail.html @@ -3,6 +3,7 @@ {% from 'shared/macros/headers.html' import detail_page_header %} {% from 'shared/macros/alerts.html' import loading_state, error_state %} {% from 'shared/macros/tables.html' import table_wrapper, table_header %} +{% from 'shared/macros/pagination.html' import pagination_simple %} {% block title %}{{ _('loyalty.store.card_detail.title') }}{% endblock %} @@ -152,22 +153,7 @@ {% endcall %} - -
- - - - -
+ {{ pagination_simple() }} {% endblock %}