@page "/materials/new" @page "/materials/{Id:int}" @inject MaterialService MaterialService @inject NavigationManager Navigation @using CutList.Core.Formatting @(IsNew ? "Add Material" : "Edit Material")

@(IsNew ? "Add Material" : material.DisplayName)

@if (loading) {

Loading...

} else {
Material Details
@foreach (var shape in MaterialService.CommonShapes) { }
Examples: "1" OD x 0.065 wall", "2x2", "1.5 x 1.5 x 0.125"
@if (!string.IsNullOrEmpty(errorMessage)) {
@errorMessage
}
@(IsNew ? "Cancel" : "Back to List")
@if (!IsNew) {
Available Stock Lengths
@if (showStockForm) {
@(editingStock == null ? "Add Stock Length" : "Edit Stock Length")
@if (!string.IsNullOrEmpty(stockErrorMessage)) {
@stockErrorMessage
}
} @if (stockLengths.Count == 0) {

No stock lengths configured yet.

Add common stock lengths for this material (e.g., 20', 24') to quickly populate project stock bins.

} else { @foreach (var stock in stockLengths) { }
Length Qty Notes Actions
@ArchUnits.FormatFromInches((double)stock.LengthInches) @stock.Quantity @(stock.Notes ?? "-")
}
}
} @code { [Parameter] public int? Id { get; set; } private Material material = new(); private List stockLengths = new(); private bool loading = true; private bool saving; private string? errorMessage; // Stock form private bool showStockForm; private bool savingStock; private MaterialStockLength newStock = new(); private MaterialStockLength? editingStock; private string? stockErrorMessage; // Delete dialog private ConfirmDialog deleteStockDialog = null!; private MaterialStockLength? stockToDelete; private string deleteStockMessage = ""; private bool IsNew => !Id.HasValue; protected override async Task OnInitializedAsync() { if (Id.HasValue) { var existing = await MaterialService.GetByIdAsync(Id.Value); if (existing == null) { Navigation.NavigateTo("materials"); return; } material = existing; stockLengths = await MaterialService.GetStockLengthsAsync(Id.Value); } loading = false; } private async Task SaveAsync() { errorMessage = null; saving = true; try { if (string.IsNullOrWhiteSpace(material.Shape)) { errorMessage = "Shape is required"; return; } if (string.IsNullOrWhiteSpace(material.Size)) { errorMessage = "Size is required"; return; } // Check for duplicates if (await MaterialService.ExistsAsync(material.Shape, material.Size, Id)) { errorMessage = "A material with this shape and size already exists"; return; } if (IsNew) { var created = await MaterialService.CreateAsync(material); Navigation.NavigateTo($"materials/{created.Id}"); } else { await MaterialService.UpdateAsync(material); } } finally { saving = false; } } // Stock length methods private void ShowAddStockForm() { editingStock = null; newStock = new MaterialStockLength { MaterialId = Id!.Value }; showStockForm = true; stockErrorMessage = null; } private void EditStock(MaterialStockLength stock) { editingStock = stock; newStock = new MaterialStockLength { Id = stock.Id, MaterialId = stock.MaterialId, LengthInches = stock.LengthInches, Quantity = stock.Quantity, Notes = stock.Notes }; showStockForm = true; stockErrorMessage = null; } private void CancelStockForm() { showStockForm = false; editingStock = null; stockErrorMessage = null; } private async Task SaveStockAsync() { stockErrorMessage = null; savingStock = true; try { if (newStock.LengthInches <= 0) { stockErrorMessage = "Length must be greater than zero"; return; } var exists = await MaterialService.StockLengthExistsAsync( newStock.MaterialId, newStock.LengthInches, editingStock?.Id); if (exists) { stockErrorMessage = "This stock length already exists for this material"; return; } if (editingStock == null) { await MaterialService.AddStockLengthAsync(newStock); } else { await MaterialService.UpdateStockLengthAsync(newStock); } stockLengths = await MaterialService.GetStockLengthsAsync(Id!.Value); showStockForm = false; editingStock = null; } finally { savingStock = false; } } private void ConfirmDeleteStock(MaterialStockLength stock) { stockToDelete = stock; deleteStockMessage = $"Are you sure you want to delete the {ArchUnits.FormatFromInches((double)stock.LengthInches)} stock length?"; deleteStockDialog.Show(); } private async Task DeleteStockConfirmed() { if (stockToDelete != null) { await MaterialService.DeleteStockLengthAsync(stockToDelete.Id); stockLengths = await MaterialService.GetStockLengthsAsync(Id!.Value); } } }