Feature: Add pagination to Receipts page
- Add PageNumber and PageSize query parameters (default 25 per page) - Implement server-side pagination with Skip/Take - Display "Showing X-Y of Z" count in header - Add Bootstrap pagination controls with sliding page window 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -142,7 +142,14 @@
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
<strong>All Receipts</strong>
|
||||
<span class="text-muted">- @Model.Receipts.Count total</span>
|
||||
@if (Model.TotalCount > 0)
|
||||
{
|
||||
<span class="text-muted">- Showing @((Model.PageNumber - 1) * Model.PageSize + 1)-@(Math.Min(Model.PageNumber * Model.PageSize, Model.TotalCount)) of @Model.TotalCount</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="text-muted">- 0 total</span>
|
||||
}
|
||||
</div>
|
||||
@if (Model.Receipts.Any(r => !r.TransactionId.HasValue && (!string.IsNullOrWhiteSpace(r.Merchant) || r.ReceiptDate.HasValue || r.Total.HasValue)))
|
||||
{
|
||||
@@ -273,6 +280,47 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (Model.TotalPages > 1)
|
||||
{
|
||||
<div class="card-footer">
|
||||
<nav aria-label="Receipts pagination">
|
||||
<ul class="pagination mb-0 justify-content-center">
|
||||
<li class="page-item @(Model.PageNumber <= 1 ? "disabled" : "")">
|
||||
<a class="page-link" asp-page="/Receipts" asp-route-pageNumber="1" asp-route-pageSize="@Model.PageSize">First</a>
|
||||
</li>
|
||||
<li class="page-item @(Model.PageNumber <= 1 ? "disabled" : "")">
|
||||
<a class="page-link" asp-page="/Receipts" asp-route-pageNumber="@(Model.PageNumber - 1)" asp-route-pageSize="@Model.PageSize">Previous</a>
|
||||
</li>
|
||||
@{
|
||||
var startPage = Math.Max(1, Model.PageNumber - 2);
|
||||
var endPage = Math.Min(Model.TotalPages, Model.PageNumber + 2);
|
||||
if (endPage - startPage < 4)
|
||||
{
|
||||
if (startPage == 1)
|
||||
endPage = Math.Min(Model.TotalPages, startPage + 4);
|
||||
else
|
||||
startPage = Math.Max(1, endPage - 4);
|
||||
}
|
||||
}
|
||||
@for (var i = startPage; i <= endPage; i++)
|
||||
{
|
||||
<li class="page-item @(i == Model.PageNumber ? "active" : "")">
|
||||
<a class="page-link" asp-page="/Receipts" asp-route-pageNumber="@i" asp-route-pageSize="@Model.PageSize">@i</a>
|
||||
</li>
|
||||
}
|
||||
<li class="page-item @(Model.PageNumber >= Model.TotalPages ? "disabled" : "")">
|
||||
<a class="page-link" asp-page="/Receipts" asp-route-pageNumber="@(Model.PageNumber + 1)" asp-route-pageSize="@Model.PageSize">Next</a>
|
||||
</li>
|
||||
<li class="page-item @(Model.PageNumber >= Model.TotalPages ? "disabled" : "")">
|
||||
<a class="page-link" asp-page="/Receipts" asp-route-pageNumber="@Model.TotalPages" asp-route-pageSize="@Model.PageSize">Last</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="text-center mt-2">
|
||||
<small class="text-muted">Page @Model.PageNumber of @Model.TotalPages</small>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Map to Transaction Modals -->
|
||||
|
||||
@@ -24,6 +24,15 @@ namespace MoneyMap.Pages
|
||||
public List<ReceiptRow> Receipts { get; set; } = new();
|
||||
public Dictionary<long, List<TransactionOption>> ReceiptTransactionMatches { get; set; } = new();
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public int PageNumber { get; set; } = 1;
|
||||
|
||||
[BindProperty(SupportsGet = true)]
|
||||
public int PageSize { get; set; } = 25;
|
||||
|
||||
public int TotalCount { get; set; }
|
||||
public int TotalPages => (int)Math.Ceiling((double)TotalCount / PageSize);
|
||||
|
||||
[BindProperty]
|
||||
public IFormFile? UploadFile { get; set; }
|
||||
|
||||
@@ -238,9 +247,19 @@ namespace MoneyMap.Pages
|
||||
|
||||
private async Task LoadReceiptsAsync()
|
||||
{
|
||||
var receipts = await _db.Receipts
|
||||
if (PageNumber < 1) PageNumber = 1;
|
||||
if (PageSize < 1) PageSize = 25;
|
||||
if (PageSize > 100) PageSize = 100;
|
||||
|
||||
var query = _db.Receipts
|
||||
.Include(r => r.Transaction)
|
||||
.OrderByDescending(r => r.UploadedAtUtc)
|
||||
.OrderByDescending(r => r.UploadedAtUtc);
|
||||
|
||||
TotalCount = await query.CountAsync();
|
||||
|
||||
var receipts = await query
|
||||
.Skip((PageNumber - 1) * PageSize)
|
||||
.Take(PageSize)
|
||||
.ToListAsync();
|
||||
|
||||
Receipts = receipts.Select(r => new ReceiptRow
|
||||
|
||||
Reference in New Issue
Block a user