@page "/stock" @inject StockItemService StockItemService @inject NavigationManager Navigation @using CutList.Core.Formatting @using CutList.Web.Data.Entities Stock Items

Stock Items

Add Stock Item

Stock items represent the specific lengths of material you can cut from. Add the lengths you typically work with here, then pick from them when adding stock to a job.

@if (loading) {

Loading...

} else if (stockItems.Count == 0) {
No stock items found. Add your first stock item.
} else { @if (filteredItems.Count == 0) {
No stock items match your filters.
} else { @foreach (var item in pagedItems) { }
Shape Type Grade Size Length Actions
@item.Material.Shape.GetDisplayName() @item.Material.Type @item.Material.Grade @item.Material.Size @ArchUnits.FormatFromInches((double)item.LengthInches)
} } @code { private List stockItems = new(); private bool loading = true; private int currentPage = 1; private int pageSize = 25; private ConfirmDialog deleteDialog = null!; private StockItem? itemToDelete; private string deleteMessage = ""; private MaterialFilterState filterState = new(); private List filteredItems => stockItems.Where(s => { var m = s.Material; if (filterState.Shape.HasValue && m.Shape != filterState.Shape.Value) return false; if (filterState.Type.HasValue && m.Type != filterState.Type.Value) return false; if (!string.IsNullOrEmpty(filterState.Grade) && m.Grade != filterState.Grade) return false; if (!string.IsNullOrWhiteSpace(filterState.SearchText)) { var search = filterState.SearchText.Trim(); if (!Contains(m.Size, search) && !Contains(m.Grade, search) && !Contains(m.Description, search) && !Contains(m.Shape.GetDisplayName(), search) && !Contains(s.Name, search) && !Contains(s.Notes, search)) return false; } return true; }).ToList(); private IEnumerable availableGrades => stockItems .Select(s => s.Material.Grade) .Where(g => !string.IsNullOrEmpty(g)) .Distinct() .OrderBy(g => g)!; private IEnumerable pagedItems => filteredItems .Skip((currentPage - 1) * pageSize) .Take(pageSize); protected override async Task OnInitializedAsync() { stockItems = await StockItemService.GetAllAsync(); loading = false; } private void OnFilterChanged(MaterialFilterState state) { filterState = state; currentPage = 1; } private void ConfirmDelete(StockItem item) { itemToDelete = item; deleteMessage = $"Are you sure you want to delete \"{item.Material.DisplayName} - {ArchUnits.FormatFromInches((double)item.LengthInches)}\"?"; deleteDialog.Show(); } private async Task DeleteConfirmed() { if (itemToDelete != null) { await StockItemService.DeleteAsync(itemToDelete.Id); stockItems = await StockItemService.GetAllAsync(); var totalPages = (int)Math.Ceiling((double)filteredItems.Count / pageSize); if (currentPage > totalPages && totalPages > 0) currentPage = totalPages; } } private void OnPageChanged(int page) => currentPage = page; private static bool Contains(string? value, string search) => value != null && value.Contains(search, StringComparison.OrdinalIgnoreCase); }