Refactor tables to Razor components
This commit is contained in:
@ -2,65 +2,55 @@
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
|
||||
@layout Layout
|
||||
|
||||
@inject AppDbContext DbContext
|
||||
@inject NavigationManager Navigation
|
||||
@inject IHttpContextAccessor HttpContextAccessor
|
||||
|
||||
<PageTitle>Groceries – Items</PageTitle>
|
||||
|
||||
<div class="row">
|
||||
<header class="row">
|
||||
<h1 class="row__fill">Items</h1>
|
||||
<SearchForm data-turbo-frame="table" data-turbo-action="advance">
|
||||
<input type="hidden" name="page" value="1" />
|
||||
</SearchForm>
|
||||
</div>
|
||||
<search title="Items">
|
||||
<SearchForm data-turbo-frame="table" data-turbo-action="advance">
|
||||
<input type="hidden" name="page" value="1" />
|
||||
</SearchForm>
|
||||
</search>
|
||||
</header>
|
||||
|
||||
<turbo-frame id="table" target="top">
|
||||
<section class="table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="table__header table__header--shaded">Brand</th>
|
||||
<th scope="col" class="table__header table__header--shaded" style="width: 100%">Name</th>
|
||||
<th scope="col" class="table__header table__header--shaded">Last Purchased</th>
|
||||
<th scope="col" class="table__header table__header--shaded">Barcode</th>
|
||||
@*<th scope="col" class="table__header table__header--shaded"></th>*@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in items)
|
||||
{
|
||||
<tr>
|
||||
<td class="table__cell">@item.Brand</td>
|
||||
<td class="table__cell">@item.Name</td>
|
||||
<td class="table__cell">
|
||||
<time datetime="@item.LastPurchasedAt?.ToString("o")">@item.LastPurchasedAt?.ToLongDateString()</time>
|
||||
</td>
|
||||
<td class="table__cell table__cell--icon" style="width: fit-content">@(item.HasBarcode ? "✓" : "")</td>
|
||||
@*<td class="table__cell">
|
||||
<a class="link" href="/items/edit/@item.Id">Edit</a>
|
||||
</td>*@
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
<TablePaginator Model="items" />
|
||||
<Table Items="items" Pagination="pagination" HeaderClass="table__header--shaded">
|
||||
<PropertyTableColumn Property="i => i.Brand" Sortable="true" />
|
||||
<PropertyTableColumn Property="i => i.Name" Fill="true" Sortable="true" />
|
||||
<PropertyTableColumn Property="i => i.LastPurchasedAt" Title="Last Purchased" Sortable="true">
|
||||
<time datetime="@context?.ToString("o")">@context?.ToLongDateString()</time>
|
||||
</PropertyTableColumn>
|
||||
<PropertyTableColumn Property="i => i.HasBarcode" Title="Barcode" Align="Align.Center" Sortable="true">
|
||||
<span class="icon icon--sm">@(context ? "✓" : "")</span>
|
||||
</PropertyTableColumn>
|
||||
@* <TemplateTableColumn>
|
||||
<a class="link" href="/items/edit/@context.Id">Edit</a>
|
||||
</TemplateTableColumn> *@
|
||||
</Table>
|
||||
<TablePaginator State="pagination" />
|
||||
</section>
|
||||
</turbo-frame>
|
||||
|
||||
@code {
|
||||
[SupplyParameterFromQuery]
|
||||
public int? Page { get; set; }
|
||||
private record ItemModel
|
||||
{
|
||||
public Guid Id { get; init; }
|
||||
public required string Brand { get; init; }
|
||||
public required string Name { get; init; }
|
||||
public bool HasBarcode { get; init; }
|
||||
public DateTime? LastPurchasedAt { get; init; }
|
||||
}
|
||||
|
||||
private IQueryable<ItemModel> items = null!;
|
||||
private PaginationState pagination = new();
|
||||
|
||||
[SupplyParameterFromQuery]
|
||||
public string? Search { get; set; }
|
||||
|
||||
private record ItemModel(Guid Id, string Brand, string Name, bool HasBarcode, DateTime? LastPurchasedAt);
|
||||
|
||||
private ListPageModel<ItemModel> items = ListPageModel.Empty<ItemModel>();
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
var itemsQuery = DbContext.Items.AsQueryable();
|
||||
if (!string.IsNullOrEmpty(Search))
|
||||
@ -69,27 +59,23 @@
|
||||
itemsQuery = itemsQuery.Where(item => EF.Functions.ILike(item.Brand + ' ' + item.Name, searchPattern));
|
||||
}
|
||||
|
||||
items = await itemsQuery
|
||||
.OrderBy(item => item.Brand)
|
||||
.ThenBy(item => item.Name)
|
||||
items = itemsQuery
|
||||
.GroupJoin(
|
||||
DbContext.ItemPurchases.Where(purchase => purchase.IsLastPurchase),
|
||||
item => item.Id,
|
||||
lastPurchase => lastPurchase.ItemId,
|
||||
(item, lastPurchase) => new { item, lastPurchase })
|
||||
purchase => purchase.ItemId,
|
||||
(item, purchases) => new { item, purchases })
|
||||
.SelectMany(
|
||||
group => group.lastPurchase.DefaultIfEmpty(),
|
||||
(group, lastPurchase) => new ItemModel(
|
||||
group.item.Id,
|
||||
group.item.Brand,
|
||||
group.item.Name,
|
||||
group.item.Barcodes.Count != 0,
|
||||
lastPurchase != null ? lastPurchase.CreatedAt : null))
|
||||
.ToListPageModelAsync(Page.GetValueOrDefault(), cancellationToken: HttpContextAccessor.HttpContext!.RequestAborted);
|
||||
|
||||
if (items.Page != Page)
|
||||
{
|
||||
Navigation.NavigateTo(Navigation.GetUriWithQueryParameter("page", items.Page));
|
||||
}
|
||||
group => group.purchases.DefaultIfEmpty(),
|
||||
(group, lastPurchase) => new ItemModel
|
||||
{
|
||||
Id = group.item.Id,
|
||||
Brand = group.item.Brand,
|
||||
Name = group.item.Name,
|
||||
HasBarcode = group.item.Barcodes.Count != 0,
|
||||
LastPurchasedAt = lastPurchase != null ? lastPurchase.CreatedAt : null,
|
||||
})
|
||||
.OrderBy(item => item.Brand)
|
||||
.ThenBy(item => item.Name);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user