PR U-4a: Home refreshes in place instead of forceLoad
SplitBankTransactionAsync ended with NavigateTo(forceLoad: true), which tore down the SignalR circuit and re-ran every repo constructor just to refresh the pending-bookings list. Extract data loading into a LoadDataAsync helper called from OnInitializedAsync, SplitBank TransactionAsync, and OnCompletedAsync — the page refreshes in-circuit, scoped caches survive, and the NavigationManager injection can go. Also flags the plan: U-4 is split into U-4a (this) and U-4b (persist settings + drop MyHeader's forceLoad, touching ~15 pages). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
93bfcae2a0
commit
577d63c0fa
2 changed files with 18 additions and 14 deletions
|
|
@ -31,9 +31,6 @@ public partial class Home : ComponentBase
|
||||||
[Inject]
|
[Inject]
|
||||||
private ITransactionRepository transactionRepository { get; set; } = null!;
|
private ITransactionRepository transactionRepository { get; set; } = null!;
|
||||||
|
|
||||||
[Inject]
|
|
||||||
private NavigationManager Navigation { get; set; } = null!;
|
|
||||||
|
|
||||||
private List<Transaction>? matchingBankTransactions;
|
private List<Transaction>? matchingBankTransactions;
|
||||||
private IReadOnlyList<Account> accounts = [];
|
private IReadOnlyList<Account> accounts = [];
|
||||||
private IReadOnlyList<string> bookingTexts = [];
|
private IReadOnlyList<string> bookingTexts = [];
|
||||||
|
|
@ -45,11 +42,16 @@ public partial class Home : ComponentBase
|
||||||
Dictionary<int, string> Files = new();
|
Dictionary<int, string> Files = new();
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await LoadDataAsync();
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadDataAsync()
|
||||||
{
|
{
|
||||||
matchingBankTransactions = await viewService.MatchOpenBankTransactionsAsync();
|
matchingBankTransactions = await viewService.MatchOpenBankTransactionsAsync();
|
||||||
accounts = await viewService.GetAccountViewListAsync();
|
accounts = await viewService.GetAccountViewListAsync();
|
||||||
bookingTexts = (await bookingTextRepository.GetBookingTextListAsync()).Select(b => b.Text).ToArray();
|
bookingTexts = (await bookingTextRepository.GetBookingTextListAsync()).Select(b => b.Text).ToArray();
|
||||||
await base.OnInitializedAsync();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task OnProgressChangeAsync(FluentInputFileEventArgs file)
|
async Task OnProgressChangeAsync(FluentInputFileEventArgs file)
|
||||||
|
|
@ -96,7 +98,10 @@ public partial class Home : ComponentBase
|
||||||
File.Delete(file.Value);
|
File.Delete(file.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
matchingBankTransactions = await viewService.MatchOpenBankTransactionsAsync();
|
// Imports may update the bank-account balance and add new bank transactions
|
||||||
|
// — reload everything so the pending list, account balances, and booking-text
|
||||||
|
// suggestions stay consistent.
|
||||||
|
await LoadDataAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ImportXmlAndShowResultAsync(string fileName)
|
private async Task ImportXmlAndShowResultAsync(string fileName)
|
||||||
|
|
@ -174,14 +179,10 @@ public partial class Home : ComponentBase
|
||||||
var result = await dialog.Result;
|
var result = await dialog.Result;
|
||||||
if (!result.Cancelled && result.Data != null)
|
if (!result.Cancelled && result.Data != null)
|
||||||
{
|
{
|
||||||
ReloadPage();
|
// Re-run the auto-matcher in-place so the newly created split
|
||||||
await Task.CompletedTask;
|
// transactions disappear from the pending list. No forceLoad — the
|
||||||
|
// SignalR circuit stays up and the scoped RepositoryCache survives.
|
||||||
|
await LoadDataAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReloadPage()
|
|
||||||
{
|
|
||||||
var uri = Navigation.Uri;
|
|
||||||
Navigation.NavigateTo(uri, forceLoad: true); // forceLoad = true does a full reload
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,7 +157,10 @@ Sequenced by value / risk. Each is one PR unless noted.
|
||||||
|
|
||||||
### Phase 2 — The forceLoad/singleton trap (biggest single improvement)
|
### Phase 2 — The forceLoad/singleton trap (biggest single improvement)
|
||||||
|
|
||||||
- **U-4** Persist year and mandator to a cookie *and* keep them in the URL as query params. `SettingsService` becomes `Scoped`, reading initial state from query params (fallback: cookie, fallback: config default). Header switching becomes an in-place update — no `forceLoad`, no circuit teardown, no state loss.
|
Split into two PRs on delivery because the header path touches ~15 pages.
|
||||||
|
|
||||||
|
- **U-4a** Fix `Home.ReloadPage()` — the single non-settings `forceLoad` in the app. `SplitBankTransactionAsync` and `OnCompletedAsync` (statement import) now call a shared `LoadDataAsync()` that re-runs the auto-matcher, re-fetches accounts and booking texts in place, and keeps the SignalR circuit + scoped `RepositoryCache` alive. No cross-cutting scaffolding needed.
|
||||||
|
- **U-4b** Persist year and mandator (cookie + URL query params), make `SettingsService` `Scoped`, add an event or `LocationChanged` subscription so every page refreshes on year/mandator change, and drop `MyHeader`'s `forceLoad`. This is the big one — it touches every routable page.
|
||||||
|
|
||||||
### Phase 3 — Loading and error UX consistency
|
### Phase 3 — Loading and error UX consistency
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue