diff --git a/CutList.Web/Components/Pages/Projects/Edit.razor b/CutList.Web/Components/Pages/Projects/Edit.razor index bad23f1..aace452 100644 --- a/CutList.Web/Components/Pages/Projects/Edit.razor +++ b/CutList.Web/Components/Pages/Projects/Edit.razor @@ -2,7 +2,6 @@ @page "/projects/{Id:int}" @inject ProjectService ProjectService @inject MaterialService MaterialService -@inject SupplierService SupplierService @inject NavigationManager Navigation @using CutList.Core.Formatting @@ -20,269 +19,81 @@ {

Loading...

} +else if (IsNew) +{ + +
+
+ @RenderDetailsForm() +
+
+} else { -
- -
-
-
-
Project Details
-
-
- -
- - -
+ + -
- - - - @foreach (var material in materials) - { - - } - -
- -
- - - - @foreach (var tool in cuttingTools) - { - - } - -
- -
- - -
- - @if (!string.IsNullOrEmpty(projectErrorMessage)) - { -
@projectErrorMessage
- } - -
- - Back -
-
-
-
-
- - @if (!IsNew) +
+ @if (activeTab == Tab.Details) { - -
-
-
-
Parts
- -
-
- @if (showPartForm) - { -
-
-
- - -
-
- - -
-
- - -
-
- @if (!string.IsNullOrEmpty(partErrorMessage)) - { -
@partErrorMessage
- } -
- - -
-
- } - - @if (project.Parts.Count == 0) - { -

No parts added yet.

- } - else - { - - - - - - - - - - - @foreach (var part in project.Parts) - { - - - - - - - } - -
NameLengthQty
@part.Name@ArchUnits.FormatFromInches((double)part.LengthInches)@part.Quantity - - -
-
- Total: @project.Parts.Sum(p => p.Quantity) pieces -
- } -
-
-
- - -
-
-
-
Stock Bins
-
- - -
-
-
- @if (showImportDialog) - { -
-
Import from Supplier
- -
- - -
-
- } - - @if (showBinForm) - { -
-
-
- - -
-
- - -
-1 = unlimited
-
-
- - -
-
- @if (!string.IsNullOrEmpty(binErrorMessage)) - { -
@binErrorMessage
- } -
- - -
-
- } - - @if (project.StockBins.Count == 0) - { -

No stock bins added yet.

- } - else - { - - - - - - - - - - - @foreach (var bin in project.StockBins.OrderBy(b => b.Priority).ThenBy(b => b.LengthInches)) - { - - - - - - - } - -
LengthQtyPriority
@ArchUnits.FormatFromInches((double)bin.LengthInches)@(bin.Quantity == -1 ? "Unlimited" : bin.Quantity.ToString())@bin.Priority - - -
- } -
+
+
+ @RenderDetailsForm()
} + else if (activeTab == Tab.Parts) + { + @RenderPartsTab() + }
} @code { + private enum Tab { Details, Parts } + [Parameter] public int? Id { get; set; } private Project project = new(); private List materials = new(); private List cuttingTools = new(); - private List suppliers = new(); private bool loading = true; private bool savingProject; private string? projectErrorMessage; + private Tab activeTab = Tab.Details; + + private void SetTab(Tab tab) => activeTab = tab; // Parts form private bool showPartForm; private ProjectPart newPart = new(); private ProjectPart? editingPart; private string? partErrorMessage; + private string selectedShape = string.Empty; - // Bins form - private bool showBinForm; - private ProjectStockBin newBin = new(); - private ProjectStockBin? editingBin; - private string? binErrorMessage; - - // Import dialog - private bool showImportDialog; - private int selectedSupplierId; + private IEnumerable DistinctShapes => materials.Select(m => m.Shape).Distinct().OrderBy(s => s); + private IEnumerable FilteredMaterials => string.IsNullOrEmpty(selectedShape) + ? Enumerable.Empty() + : materials.Where(m => m.Shape == selectedShape).OrderBy(m => m.Size); private bool IsNew => !Id.HasValue; @@ -290,7 +101,6 @@ else { materials = await MaterialService.GetAllAsync(); cuttingTools = await ProjectService.GetCuttingToolsAsync(); - suppliers = await SupplierService.GetAllAsync(); if (Id.HasValue) { @@ -315,6 +125,162 @@ else loading = false; } + private RenderFragment RenderDetailsForm() => __builder => + { +
+
+
Project Details
+
+
+ +
+ + +
+ +
+ + +
+ +
+ + + + @foreach (var tool in cuttingTools) + { + + } + +
+ +
+ + +
+ + @if (!string.IsNullOrEmpty(projectErrorMessage)) + { +
@projectErrorMessage
+ } + +
+ + Back +
+
+
+
+ }; + + private RenderFragment RenderPartsTab() => __builder => + { +
+
+
Parts to Cut
+ +
+
+ @if (showPartForm) + { +
+
@(editingPart == null ? "Add Part" : "Edit Part")
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ @if (!string.IsNullOrEmpty(partErrorMessage)) + { +
@partErrorMessage
+ } +
+ + +
+
+ } + + @if (project.Parts.Count == 0) + { +
+

No parts added yet.

+

Add the parts you need to cut, selecting the material for each.

+
+ } + else + { +
+ + + + + + + + + + + + @foreach (var part in project.Parts) + { + + + + + + + + } + +
MaterialLengthQtyNameActions
@part.Material.DisplayName@ArchUnits.FormatFromInches((double)part.LengthInches)@part.Quantity@(string.IsNullOrWhiteSpace(part.Name) ? "-" : part.Name) + + +
+
+
+ Total: @project.Parts.Sum(p => p.Quantity) pieces +
+ } +
+
+ }; + private async Task SaveProjectAsync() { projectErrorMessage = null; @@ -349,10 +315,16 @@ else { editingPart = null; newPart = new ProjectPart { ProjectId = Id!.Value, Quantity = 1 }; + selectedShape = string.Empty; showPartForm = true; partErrorMessage = null; } + private void OnShapeChanged() + { + newPart.MaterialId = 0; + } + private void EditPart(ProjectPart part) { editingPart = part; @@ -360,11 +332,13 @@ else { Id = part.Id, ProjectId = part.ProjectId, + MaterialId = part.MaterialId, Name = part.Name, LengthInches = part.LengthInches, Quantity = part.Quantity, SortOrder = part.SortOrder }; + selectedShape = part.Material?.Shape ?? string.Empty; showPartForm = true; partErrorMessage = null; } @@ -379,9 +353,15 @@ else { partErrorMessage = null; - if (string.IsNullOrWhiteSpace(newPart.Name)) + if (string.IsNullOrEmpty(selectedShape)) { - partErrorMessage = "Name is required"; + partErrorMessage = "Please select a shape"; + return; + } + + if (newPart.MaterialId == 0) + { + partErrorMessage = "Please select a size"; return; } @@ -416,88 +396,4 @@ else await ProjectService.DeletePartAsync(part.Id); project = (await ProjectService.GetByIdAsync(Id!.Value))!; } - - // Bins methods - private void ShowAddBinForm() - { - editingBin = null; - newBin = new ProjectStockBin { ProjectId = Id!.Value, Quantity = -1, Priority = 25 }; - showBinForm = true; - binErrorMessage = null; - } - - private void EditBin(ProjectStockBin bin) - { - editingBin = bin; - newBin = new ProjectStockBin - { - Id = bin.Id, - ProjectId = bin.ProjectId, - LengthInches = bin.LengthInches, - Quantity = bin.Quantity, - Priority = bin.Priority, - SortOrder = bin.SortOrder - }; - showBinForm = true; - binErrorMessage = null; - } - - private void CancelBinForm() - { - showBinForm = false; - editingBin = null; - } - - private async Task SaveBinAsync() - { - binErrorMessage = null; - - if (newBin.LengthInches <= 0) - { - binErrorMessage = "Length must be greater than zero"; - return; - } - - if (newBin.Quantity < -1 || newBin.Quantity == 0) - { - binErrorMessage = "Quantity must be positive or -1 for unlimited"; - return; - } - - if (editingBin == null) - { - await ProjectService.AddStockBinAsync(newBin); - } - else - { - await ProjectService.UpdateStockBinAsync(newBin); - } - - project = (await ProjectService.GetByIdAsync(Id!.Value))!; - showBinForm = false; - editingBin = null; - } - - private async Task DeleteBin(ProjectStockBin bin) - { - await ProjectService.DeleteStockBinAsync(bin.Id); - project = (await ProjectService.GetByIdAsync(Id!.Value))!; - } - - // Import methods - private void ShowImportDialog() - { - selectedSupplierId = 0; - showImportDialog = true; - } - - private async Task ImportFromSupplier() - { - if (selectedSupplierId > 0) - { - await ProjectService.ImportStockFromSupplierAsync(Id!.Value, selectedSupplierId, project.MaterialId); - project = (await ProjectService.GetByIdAsync(Id!.Value))!; - showImportDialog = false; - } - } } diff --git a/CutList.Web/Components/Pages/Projects/Index.razor b/CutList.Web/Components/Pages/Projects/Index.razor index ebf0b1a..6c17513 100644 --- a/CutList.Web/Components/Pages/Projects/Index.razor +++ b/CutList.Web/Components/Pages/Projects/Index.razor @@ -25,7 +25,7 @@ else Name - Material + Customer Cutting Tool Last Modified Actions @@ -36,7 +36,7 @@ else { @project.Name - @(project.Material?.DisplayName ?? "-") + @(project.Customer ?? "-") @(project.CuttingTool?.Name ?? "-") @((project.UpdatedAt ?? project.CreatedAt).ToLocalTime().ToString("g"))