@page "/orders" @inject PurchaseItemService PurchaseItemService @inject SupplierService SupplierService @inject NavigationManager Navigation @using CutList.Core.Formatting @using CutList.Web.Data.Entities Orders

To Be Ordered

Add Item

Track material that needs to be ordered from suppliers. Items are added manually or automatically from job optimization results.

@if (loading) {

Loading...

} else { @if (tabItems.Count == 0) {
@if (activeTab == "pending") { No pending items. Add an item or use "Add to Order List" from a job's results page. } else if (activeTab == "ordered") { No ordered items. } else { No order items found. Add your first item. }
} else { @if (filteredItems.Count == 0) {
No items match your filters.
} else { @foreach (var item in pagedItems) { }
Material Length Qty Supplier Job Status Notes Actions
@item.StockItem.Material.DisplayName @ArchUnits.FormatFromInches((double)item.StockItem.LengthInches) @item.Quantity @if (item.Job != null) { @item.Job.DisplayName } else { - } @item.Status @(item.Notes ?? "-")
@if (item.Status == PurchaseItemStatus.Pending) { } @if (item.Status == PurchaseItemStatus.Ordered) { }
} } } @code { private List allItems = new(); private List suppliers = new(); private bool loading = true; private string activeTab = "pending"; private int currentPage = 1; private int pageSize = 25; private ConfirmDialog deleteDialog = null!; private PurchaseItem? itemToDelete; private string deleteMessage = ""; private MaterialFilterState filterState = new(); private int pendingCount => allItems.Count(i => i.Status == PurchaseItemStatus.Pending); private int orderedCount => allItems.Count(i => i.Status == PurchaseItemStatus.Ordered); private List tabItems => activeTab switch { "pending" => allItems.Where(i => i.Status == PurchaseItemStatus.Pending).ToList(), "ordered" => allItems.Where(i => i.Status == PurchaseItemStatus.Ordered).ToList(), _ => allItems }; private List filteredItems => tabItems.Where(i => { var m = i.StockItem.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.Shape.GetDisplayName(), search) && !Contains(i.Notes, search) && !Contains(i.Job?.DisplayName, search) && !Contains(i.Supplier?.Name, search)) return false; } return true; }).ToList(); private IEnumerable availableGrades => tabItems .Select(i => i.StockItem.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() { allItems = await PurchaseItemService.GetAllAsync(); suppliers = await SupplierService.GetAllAsync(); loading = false; } private void SetTab(string tab) { activeTab = tab; currentPage = 1; filterState = new(); } private void OnFilterChanged(MaterialFilterState state) { filterState = state; currentPage = 1; } private async Task OnSupplierChanged(PurchaseItem item, ChangeEventArgs e) { int? supplierId = int.TryParse(e.Value?.ToString(), out var id) && id > 0 ? id : null; await PurchaseItemService.UpdateSupplierAsync(item.Id, supplierId); item.SupplierId = supplierId; item.Supplier = supplierId.HasValue ? suppliers.FirstOrDefault(s => s.Id == supplierId.Value) : null; } private async Task MarkOrdered(PurchaseItem item) { await PurchaseItemService.UpdateStatusAsync(item.Id, PurchaseItemStatus.Ordered); item.Status = PurchaseItemStatus.Ordered; } private async Task MarkReceived(PurchaseItem item) { await PurchaseItemService.UpdateStatusAsync(item.Id, PurchaseItemStatus.Received); allItems = await PurchaseItemService.GetAllAsync(); var totalPages = (int)Math.Ceiling((double)filteredItems.Count / pageSize); if (currentPage > totalPages && totalPages > 0) currentPage = totalPages; } private void ConfirmDelete(PurchaseItem item) { itemToDelete = item; deleteMessage = $"Are you sure you want to delete this order item ({item.StockItem.Material.DisplayName} - {ArchUnits.FormatFromInches((double)item.StockItem.LengthInches)} x{item.Quantity})?"; deleteDialog.Show(); } private async Task DeleteConfirmed() { if (itemToDelete != null) { await PurchaseItemService.DeleteAsync(itemToDelete.Id); allItems = await PurchaseItemService.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 string GetStatusBadgeClass(PurchaseItemStatus status) => status switch { PurchaseItemStatus.Pending => "bg-warning text-dark", PurchaseItemStatus.Ordered => "bg-primary", PurchaseItemStatus.Received => "bg-success", _ => "bg-secondary" }; private static bool Contains(string? value, string search) => value != null && value.Contains(search, StringComparison.OrdinalIgnoreCase); }