Add comprehensive CV verification checks and dashboard auto-refresh

- Add dashboard auto-refresh polling to update when processing completes
- Skip verification for freelance employers (but not contractors)
- Add incorporation date check (flags employment before company existed)
- Add dissolution date check (flags employment at dissolved companies)
- Add dormant company check (flags non-director roles at dormant companies)
- Add company size vs role check (flags senior roles at micro-entities)
- Add SIC code mismatch check (flags tech roles at non-tech companies)
- Add director verification against Companies House officers
- Add rapid career progression detection (3+ seniority jumps in <2 years)
- Add early career senior role detection (<2 years after education)
- Extend CompanyVerificationResult with flags and company data
- Add officers endpoint to Companies House client
- Fix null reference warning in Report.razor

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-20 20:00:24 +01:00
parent acf4d96fae
commit 652aa2e612
9 changed files with 937 additions and 36 deletions

View File

@@ -1,6 +1,7 @@
@page "/dashboard"
@attribute [Authorize]
@rendermode InteractiveServer
@implements IDisposable
@inject ICVCheckService CVCheckService
@inject NavigationManager NavigationManager
@@ -250,10 +251,54 @@
private bool _isExporting;
private string? _errorMessage;
private Guid _userId;
private System.Threading.Timer? _pollingTimer;
private bool _isPolling;
protected override async Task OnInitializedAsync()
{
await LoadChecks();
StartPollingIfNeeded();
}
private void StartPollingIfNeeded()
{
if (HasProcessingChecks() && !_isPolling)
{
_isPolling = true;
_pollingTimer = new System.Threading.Timer(async _ =>
{
await InvokeAsync(async () =>
{
await LoadChecks();
if (!HasProcessingChecks())
{
StopPolling();
}
StateHasChanged();
});
}, null, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3));
}
}
private bool HasProcessingChecks()
{
foreach (var c in _checks)
{
if (c.Status == "Processing" || c.Status == "Pending") return true;
}
return false;
}
private void StopPolling()
{
_isPolling = false;
_pollingTimer?.Dispose();
_pollingTimer = null;
}
public void Dispose()
{
StopPolling();
}
private async Task LoadChecks()

View File

@@ -115,7 +115,7 @@
<div class="card-body p-4">
<div class="row align-items-center">
<div class="col-md-4 text-center border-end">
<div class="score-circle @GetScoreColorClass(_report.OverallScore) mx-auto mb-2">
<div class="score-circle @GetScoreColorClass(_report!.OverallScore) mx-auto mb-2">
<span class="score-value">@_report.OverallScore</span>
</div>
<h5 class="mb-0">@_report.ScoreLabel</h5>