fix(phasen): Tageswechsel laedt Phasen-Stand der neuen Tour (Reset), alter Tag bleibt

Beim Datumswechsel im Kopf-Kalender blieben Beladen/Ausliefern des alten
Tags 'erledigt': PhaseBloc._load brach bei bereits geladenem Auto ab und
Home stiess den Load nur einmal pro Auto an - der In-Memory-Stand wurde
beim Tour-/Token-Wechsel nie invalidiert. Die Persistenz ist bereits pro
Tour-Token (syncedAt) getrennt, nur das Nachladen fehlte.

- PhaseBloc: Guard tokenbewusst (_loadedTokenByCar); anderer Token laedt den
  persistierten Stand der neuen Tour nach (neuer Tag -> Eintrittsphase,
  Rueckkehr -> alter Stand wiederhergestellt)
- Home._ensurePhaseLoaded: Guard auf carId|tourToken statt nur carId
- Token-Ableitung zentral als TourState.phaseToken (tour_state.dart), genutzt
  von tourTokenResolver (app.dart) UND Home - eine Quelle statt Duplikat

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-09 01:14:56 +02:00
parent c5219343a0
commit 7c6f99dda1
4 changed files with 56 additions and 16 deletions

View File

@ -43,6 +43,13 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
/// Phasen an die aktuelle Tour-Version.
final TourTokenResolver? tourTokenResolver;
/// Merkt sich pro Fahrzeug, unter welchem Tour-Token der In-Memory-Stand
/// geladen wurde. Ändert sich der Token (Tageswechsel im Kopf-Kalender,
/// neuer Sync), lädt der nächste [PhaseLoadForCar] den persistierten Stand
/// der **neuen** Tour nach, statt den alten Tag weiterzuzeigen. Der alte
/// Tag bleibt persistiert und wird bei Rückkehr wiederhergestellt.
final Map<String, String> _loadedTokenByCar = {};
PhaseBloc({
PhaseService? phaseService,
this.carCountResolver,
@ -77,11 +84,18 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
Future<void> _load(PhaseLoadForCar event, Emitter<PhaseState> emit) async {
final current = _ensureReady();
// Wenn bereits geladen, nichts tun — der Stepper-Tap entscheidet aktiv.
if (current.phaseByCar.containsKey(event.carId)) return;
final token = _token();
// Bereits für GENAU diese Tour-Version geladen → nichts tun (der
// Stepper-Tap entscheidet aktiv). Ein anderer Token (Tageswechsel, neuer
// Sync) lädt den persistierten Stand der neuen Tour nach: ein neuer Tag
// startet so wieder in der Eintrittsphase (Beladen/Ausliefern zurück),
// der vorherige Tag behält seinen Stand für die Rückkehr.
if (current.phaseByCar.containsKey(event.carId) &&
_loadedTokenByCar[event.carId] == token) {
return;
}
try {
final token = _token();
final persisted = await phaseService.load(event.carId, token);
final persistedMax = await phaseService.loadMax(event.carId, token);
final phase = persisted ?? _entryPhase();
@ -102,6 +116,7 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
await phaseService.saveMax(event.carId, token, maxPhase);
}
_loadedTokenByCar[event.carId] = token;
add(PhaseLoaded(
carId: event.carId,
phase: phase,
@ -111,6 +126,7 @@ class PhaseBloc extends Bloc<PhaseEvent, PhaseState> {
debugPrint("PhaseBloc._load: $e $st");
// Fail-soft: ohne Persistenz weiter, damit der Flow nicht hängen bleibt.
final fallback = _entryPhase();
_loadedTokenByCar[event.carId] = token;
add(PhaseLoaded(
carId: event.carId,
phase: fallback,