feat: Convert part form to modal dialog and improve material ordering
- Replace inline part form with Bootstrap modal dialog for better UX - Add SortOrder to material dropdown ordering in Parts and Stock tabs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,67 @@ else
|
||||
</div>
|
||||
}
|
||||
|
||||
@* Part Modal Dialog *@
|
||||
@if (showPartForm)
|
||||
{
|
||||
<div class="modal fade show d-block" tabindex="-1" style="background-color: rgba(0,0,0,0.5);">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">@(editingPart == null ? "Add Part" : "Edit Part")</h5>
|
||||
<button type="button" class="btn-close" @onclick="CancelPartForm"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Shape</label>
|
||||
<select class="form-select" @bind="selectedShape" @bind:after="OnShapeChanged">
|
||||
<option value="">-- Select --</option>
|
||||
@foreach (var shape in DistinctShapes)
|
||||
{
|
||||
<option value="@shape">@shape.GetDisplayName()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Size</label>
|
||||
<select class="form-select" @bind="newPart.MaterialId" disabled="@(!selectedShape.HasValue)">
|
||||
<option value="0">-- Select --</option>
|
||||
@foreach (var material in FilteredMaterials)
|
||||
{
|
||||
<option value="@material.Id">@material.Size</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Length</label>
|
||||
<LengthInput @bind-Value="newPart.LengthInches" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Quantity</label>
|
||||
<input type="number" class="form-control" @bind="newPart.Quantity" min="1" />
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label">Name <span class="text-muted fw-normal">(optional)</span></label>
|
||||
<input type="text" class="form-control" @bind="newPart.Name" placeholder="Part name" />
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(partErrorMessage))
|
||||
{
|
||||
<div class="alert alert-danger mt-3 mb-0">@partErrorMessage</div>
|
||||
}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" @onclick="CancelPartForm">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" @onclick="SavePartAsync">
|
||||
@(editingPart == null ? "Add Part" : "Save Changes")
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
private enum Tab { Details, Parts, Stock }
|
||||
|
||||
@@ -119,7 +180,7 @@ else
|
||||
private IEnumerable<MaterialShape> DistinctShapes => materials.Select(m => m.Shape).Distinct().OrderBy(s => s);
|
||||
private IEnumerable<Material> FilteredMaterials => !selectedShape.HasValue
|
||||
? Enumerable.Empty<Material>()
|
||||
: materials.Where(m => m.Shape == selectedShape.Value).OrderBy(m => m.Size);
|
||||
: materials.Where(m => m.Shape == selectedShape.Value).OrderBy(m => m.SortOrder).ThenBy(m => m.Size);
|
||||
|
||||
private bool IsNew => !Id.HasValue;
|
||||
|
||||
@@ -221,55 +282,6 @@ else
|
||||
<button class="btn btn-primary" @onclick="ShowAddPartForm">Add Part</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@if (showPartForm)
|
||||
{
|
||||
<div class="border rounded p-3 mb-3 bg-light">
|
||||
<h6>@(editingPart == null ? "Add Part" : "Edit Part")</h6>
|
||||
<div class="row g-3">
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Shape</label>
|
||||
<select class="form-select" @bind="selectedShape" @bind:after="OnShapeChanged">
|
||||
<option value="">-- Select --</option>
|
||||
@foreach (var shape in DistinctShapes)
|
||||
{
|
||||
<option value="@shape">@shape.GetDisplayName()</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Size</label>
|
||||
<select class="form-select" @bind="newPart.MaterialId" disabled="@(!selectedShape.HasValue)">
|
||||
<option value="0">-- Select --</option>
|
||||
@foreach (var material in FilteredMaterials)
|
||||
{
|
||||
<option value="@material.Id">@material.Size</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Length</label>
|
||||
<LengthInput @bind-Value="newPart.LengthInches" />
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Qty</label>
|
||||
<input type="number" class="form-control" @bind="newPart.Quantity" min="1" />
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Name <span class="text-muted fw-normal">(optional)</span></label>
|
||||
<input type="text" class="form-control" @bind="newPart.Name" placeholder="Part name" />
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(partErrorMessage))
|
||||
{
|
||||
<div class="alert alert-danger mt-3 mb-0">@partErrorMessage</div>
|
||||
}
|
||||
<div class="mt-3 d-flex gap-2">
|
||||
<button class="btn btn-primary" @onclick="SavePartAsync">@(editingPart == null ? "Add Part" : "Save Changes")</button>
|
||||
<button class="btn btn-outline-secondary" @onclick="CancelPartForm">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (job.Parts.Count == 0)
|
||||
{
|
||||
<div class="text-center py-4 text-muted">
|
||||
@@ -482,7 +494,7 @@ else
|
||||
<select class="form-select" @bind="stockSelectedMaterialId" @bind:after="OnStockMaterialChanged"
|
||||
disabled="@(!stockSelectedShape.HasValue)">
|
||||
<option value="0">-- Select --</option>
|
||||
@foreach (var material in materials.Where(m => stockSelectedShape.HasValue && m.Shape == stockSelectedShape.Value).OrderBy(m => m.Size))
|
||||
@foreach (var material in materials.Where(m => stockSelectedShape.HasValue && m.Shape == stockSelectedShape.Value).OrderBy(m => m.SortOrder).ThenBy(m => m.Size))
|
||||
{
|
||||
<option value="@material.Id">@material.Size</option>
|
||||
}
|
||||
@@ -542,7 +554,7 @@ else
|
||||
<label class="form-label">Size</label>
|
||||
<select class="form-select" @bind="newStock.MaterialId" disabled="@(!stockSelectedShape.HasValue)">
|
||||
<option value="0">-- Select --</option>
|
||||
@foreach (var material in materials.Where(m => stockSelectedShape.HasValue && m.Shape == stockSelectedShape.Value).OrderBy(m => m.Size))
|
||||
@foreach (var material in materials.Where(m => stockSelectedShape.HasValue && m.Shape == stockSelectedShape.Value).OrderBy(m => m.SortOrder).ThenBy(m => m.Size))
|
||||
{
|
||||
<option value="@material.Id">@material.Size</option>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user