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>
+19 -4
View File
@@ -32,7 +32,14 @@
</div> </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> <p><em>Loading...</em></p>
} }
@@ -331,6 +338,7 @@ else
private List<CuttingTool> cuttingTools = new(); private List<CuttingTool> cuttingTools = new();
private bool loading = true; private bool loading = true;
private string? loadError;
private bool savingJob; private bool savingJob;
private string? jobErrorMessage; private string? jobErrorMessage;
private Tab activeTab = Tab.Details; private Tab activeTab = Tab.Details;
@@ -387,6 +395,8 @@ else
} }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{
try
{ {
materials = await MaterialService.GetAllAsync(); materials = await MaterialService.GetAllAsync();
cuttingTools = await JobService.GetCuttingToolsAsync(); cuttingTools = await JobService.GetCuttingToolsAsync();
@@ -404,7 +414,7 @@ else
// Load saved optimization results if available // Load saved optimization results if available
if (job.OptimizationResultJson != null) if (job.OptimizationResultJson != null)
{ {
LoadSavedResults(); await LoadSavedResultsAsync();
} }
} }
else else
@@ -416,15 +426,20 @@ else
job.CuttingToolId = defaultTool.Id; job.CuttingToolId = defaultTool.Id;
} }
} }
}
catch (Exception ex)
{
loadError = ex.ToString();
}
loading = false; loading = false;
} }
private void LoadSavedResults() private async Task LoadSavedResultsAsync()
{ {
try try
{ {
packResult = PackingService.LoadSavedResult(job.OptimizationResultJson!); packResult = await PackingService.LoadSavedResultAsync(job.OptimizationResultJson!);
if (packResult != null) if (packResult != null)
{ {
summary = PackingService.GetSummary(packResult); summary = PackingService.GetSummary(packResult);