feat: add error handling to job editor and Error page

Wrap job editor initialization in try/catch to display errors instead of
crashing the circuit. Make LoadSavedResults async. Add a simple Error
page for the production exception handler.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
aj
2026-03-12 13:48:36 -04:00
co-authored by Claude Opus 4.6
parent b5bef23c1d
commit 545678c30f
2 changed files with 56 additions and 24 deletions
+17
View File
@@ -0,0 +1,17 @@
@page "/Error"
<PageTitle>Error</PageTitle>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card border-danger">
<div class="card-body text-center">
<h1 class="text-danger mb-3">Something went wrong</h1>
<p class="lead">An unexpected error occurred. Please try again later.</p>
<a href="/" class="btn btn-primary mt-3">Return to home page</a>
</div>
</div>
</div>
</div>
</div>
+39 -24
View File
@@ -32,7 +32,14 @@
</div>
}
@if (loading)
@if (!string.IsNullOrEmpty(loadError))
{
<div class="alert alert-danger">
<h5>Error loading job</h5>
<pre class="mb-0">@loadError</pre>
</div>
}
else if (loading)
{
<p><em>Loading...</em></p>
}
@@ -331,6 +338,7 @@ else
private List<CuttingTool> cuttingTools = new();
private bool loading = true;
private string? loadError;
private bool savingJob;
private string? jobErrorMessage;
private Tab activeTab = Tab.Details;
@@ -388,43 +396,50 @@ else
protected override async Task OnInitializedAsync()
{
materials = await MaterialService.GetAllAsync();
cuttingTools = await JobService.GetCuttingToolsAsync();
if (Id.HasValue)
try
{
var existing = await JobService.GetByIdAsync(Id.Value);
if (existing == null)
{
Navigation.NavigateTo("jobs");
return;
}
job = existing;
materials = await MaterialService.GetAllAsync();
cuttingTools = await JobService.GetCuttingToolsAsync();
// Load saved optimization results if available
if (job.OptimizationResultJson != null)
if (Id.HasValue)
{
LoadSavedResults();
var existing = await JobService.GetByIdAsync(Id.Value);
if (existing == null)
{
Navigation.NavigateTo("jobs");
return;
}
job = existing;
// Load saved optimization results if available
if (job.OptimizationResultJson != null)
{
await LoadSavedResultsAsync();
}
}
else
{
// Set default cutting tool for new jobs
var defaultTool = await JobService.GetDefaultCuttingToolAsync();
if (defaultTool != null)
{
job.CuttingToolId = defaultTool.Id;
}
}
}
else
catch (Exception ex)
{
// Set default cutting tool for new jobs
var defaultTool = await JobService.GetDefaultCuttingToolAsync();
if (defaultTool != null)
{
job.CuttingToolId = defaultTool.Id;
}
loadError = ex.ToString();
}
loading = false;
}
private void LoadSavedResults()
private async Task LoadSavedResultsAsync()
{
try
{
packResult = PackingService.LoadSavedResult(job.OptimizationResultJson!);
packResult = await PackingService.LoadSavedResultAsync(job.OptimizationResultJson!);
if (packResult != null)
{
summary = PackingService.GetSummary(packResult);