feat: Update UI for Jobs and enhanced Materials
Navigation: - Rename Projects to Jobs in NavMenu - Add new icon for multi-material boxes Home page: - Update references from Projects to Jobs Materials pages: - Add Type and Grade columns to index - Shape-specific dimension editing with typed inputs - Error handling with detailed messages Stock pages: - Show Shape, Type, Grade, Size columns - Display QuantityOnHand with badges Shared components: - LengthInput: Add nullable binding mode for optional dimensions - LengthInput: Format on blur for better UX - CutListReport: Update for Job model references Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,14 +8,14 @@
|
||||
<h1>CUT LIST</h1>
|
||||
<div class="meta-info">
|
||||
<div class="meta-row"><span>Date:</span> @DateTime.Now.ToString("g")</div>
|
||||
<div class="meta-row"><span>Project:</span> @Project.Name</div>
|
||||
@if (!string.IsNullOrWhiteSpace(Project.Customer))
|
||||
<div class="meta-row"><span>Job:</span> @Job.Name</div>
|
||||
@if (!string.IsNullOrWhiteSpace(Job.Customer))
|
||||
{
|
||||
<div class="meta-row"><span>Customer:</span> @Project.Customer</div>
|
||||
<div class="meta-row"><span>Customer:</span> @Job.Customer</div>
|
||||
}
|
||||
@if (Project.CuttingTool != null)
|
||||
@if (Job.CuttingTool != null)
|
||||
{
|
||||
<div class="meta-row"><span>Cut Method:</span> @Project.CuttingTool.Name (kerf: @Project.CuttingTool.KerfInches")</div>
|
||||
<div class="meta-row"><span>Cut Method:</span> @Job.CuttingTool.Name (kerf: @Job.CuttingTool.KerfInches")</div>
|
||||
}
|
||||
<div class="meta-row"><span>Stock Bars:</span> @PackResult.Bins.Count</div>
|
||||
<div class="meta-row"><span>Total Pieces:</span> @TotalPieces</div>
|
||||
@@ -64,18 +64,18 @@
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@if (!string.IsNullOrEmpty(Project.Notes))
|
||||
@if (!string.IsNullOrEmpty(Job.Notes))
|
||||
{
|
||||
<div class="notes-section">
|
||||
<h3>Notes</h3>
|
||||
<p>@Project.Notes</p>
|
||||
<p>@Job.Notes</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter, EditorRequired]
|
||||
public Project Project { get; set; } = null!;
|
||||
public Job Job { get; set; } = null!;
|
||||
|
||||
[Parameter, EditorRequired]
|
||||
public PackResult PackResult { get; set; } = null!;
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
<input type="text"
|
||||
class="form-control @(HasError ? "is-invalid" : "")"
|
||||
value="@DisplayValue"
|
||||
@onchange="OnInputChange"
|
||||
@oninput="OnInputChange"
|
||||
@onblur="OnBlur"
|
||||
placeholder="@Placeholder" />
|
||||
@if (HasError)
|
||||
{
|
||||
@@ -13,24 +14,53 @@
|
||||
</div>
|
||||
|
||||
@code {
|
||||
/// <summary>
|
||||
/// Non-nullable decimal value binding.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public decimal Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<decimal> ValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Nullable decimal value binding (used for optional dimension fields).
|
||||
/// Takes precedence over Value if both ValueChanged and NullableValueChanged are set.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public decimal? NullableValue { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<decimal?> NullableValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; } = "e.g., 12' 6\" or 144";
|
||||
|
||||
private string DisplayValue { get; set; } = string.Empty;
|
||||
private bool HasError { get; set; }
|
||||
private string ErrorMessage { get; set; } = string.Empty;
|
||||
private decimal? _lastValue;
|
||||
|
||||
private bool IsNullableMode => NullableValueChanged.HasDelegate;
|
||||
|
||||
private decimal? CurrentValue => IsNullableMode ? NullableValue : Value;
|
||||
|
||||
protected override void OnParametersSet()
|
||||
{
|
||||
if (Value > 0 && string.IsNullOrEmpty(DisplayValue))
|
||||
// Reset display when Value changes externally (e.g., form reset)
|
||||
if (CurrentValue != _lastValue)
|
||||
{
|
||||
DisplayValue = ArchUnits.FormatFromInches((double)Value);
|
||||
_lastValue = CurrentValue;
|
||||
if (CurrentValue.HasValue && CurrentValue.Value > 0)
|
||||
{
|
||||
DisplayValue = ArchUnits.FormatFromInches((double)CurrentValue.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayValue = string.Empty;
|
||||
HasError = false;
|
||||
ErrorMessage = string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +73,15 @@
|
||||
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
await ValueChanged.InvokeAsync(0);
|
||||
_lastValue = null;
|
||||
if (IsNullableMode)
|
||||
{
|
||||
await NullableValueChanged.InvokeAsync(null);
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,14 +89,32 @@
|
||||
{
|
||||
// Try to parse as architectural units
|
||||
var inches = ArchUnits.ParseToInches(input);
|
||||
await ValueChanged.InvokeAsync((decimal)inches);
|
||||
_lastValue = (decimal)inches;
|
||||
|
||||
if (IsNullableMode)
|
||||
{
|
||||
await NullableValueChanged.InvokeAsync(_lastValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync(_lastValue.Value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Try to parse as plain decimal (inches)
|
||||
if (decimal.TryParse(input, out var decimalValue))
|
||||
{
|
||||
await ValueChanged.InvokeAsync(decimalValue);
|
||||
_lastValue = decimalValue;
|
||||
|
||||
if (IsNullableMode)
|
||||
{
|
||||
await NullableValueChanged.InvokeAsync(decimalValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync(decimalValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -68,6 +124,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBlur()
|
||||
{
|
||||
// Format the display value nicely on blur if we have a valid value
|
||||
if (!HasError && _lastValue.HasValue && _lastValue.Value > 0)
|
||||
{
|
||||
DisplayValue = ArchUnits.FormatFromInches((double)_lastValue.Value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatLength(decimal inches)
|
||||
{
|
||||
return ArchUnits.FormatFromInches((double)inches);
|
||||
|
||||
Reference in New Issue
Block a user