diff --git a/lib/feature/delivery/bloc/phase_bloc.dart b/lib/feature/delivery/bloc/phase_bloc.dart index 7add197..a370871 100644 --- a/lib/feature/delivery/bloc/phase_bloc.dart +++ b/lib/feature/delivery/bloc/phase_bloc.dart @@ -66,6 +66,14 @@ class PhaseBloc extends Bloc { /// bedeutungslos. String _token() => tourTokenResolver?.call() ?? 'no-tour'; + /// `true`, wenn aktuell eine Tour geladen ist (der Resolver liefert einen + /// Token). Ohne Resolver (z. B. in Tests) gilt „Tour vorhanden", damit + /// nichts unnötig gesperrt wird. + bool _hasTour() { + final resolve = tourTokenResolver; + return resolve == null || resolve() != null; + } + PhaseReady _ensureReady() { final current = state; return current is PhaseReady @@ -106,6 +114,17 @@ class PhaseBloc extends Bloc { emit(current.withLoaded(event.carId, entry, entry)); } + // Keine Tour geladen (Tag ohne Tour): ausschließlich die Eintrittsphase, + // ohne Persistenz zu lesen oder zu schreiben. Der geteilte + // 'no-tour'-Eimer darf keinen Fortschritt tragen — sonst wären an jedem + // leeren Tag Beladen/Ausliefern anklickbar. + if (!_hasTour()) { + final entry = _entryPhase(); + _loadedTokenByCar[event.carId] = token; + add(PhaseLoaded(carId: event.carId, phase: entry, maxPhase: entry)); + return; + } + try { final persisted = await phaseService.load(event.carId, token); final persistedMax = await phaseService.loadMax(event.carId, token); @@ -156,9 +175,17 @@ class PhaseBloc extends Bloc { } Future _set(PhaseSet event, Emitter emit) async { + final hasTour = _hasTour(); + // Ohne geladene Tour gibt es nichts zu beladen/auszuliefern: nur die + // Eintrittsphase ist erlaubt, jeder Vorwärts-Wechsel wird verworfen — + // egal, welcher Button oder Stepper-Tap ihn auslöst. + if (!hasTour && event.phase.index > _entryPhase().index) return; final current = _ensureReady(); final next = current.withPhase(event.carId, event.phase); emit(next); + // Ohne Tour nichts persistieren — der 'no-tour'-Eimer darf keinen + // Fortschritt tragen (s. _load). + if (!hasTour) return; try { final token = _token(); await phaseService.save(event.carId, token, event.phase); diff --git a/lib/widget/phase_stepper/phase_stepper.dart b/lib/widget/phase_stepper/phase_stepper.dart index 6970d0b..dadeda0 100644 --- a/lib/widget/phase_stepper/phase_stepper.dart +++ b/lib/widget/phase_stepper/phase_stepper.dart @@ -125,12 +125,19 @@ class PhaseStepper extends StatelessWidget { final carCount = carsState is CarsLoaded ? carsState.cars.length : 0; final phases = visiblePhases ?? _effectivePhases(carCount); + // Ohne geladene Tour (Tag ohne Tour / noch ladend) ist ausschließlich + // der erste Schritt aktiv: es gibt nichts zu beladen oder auszuliefern, + // also dürfen die weiteren Schritte weder anklickbar noch abgehakt + // sein — unabhängig davon, was der PhaseBloc als Max kennt. + final hasTour = context.watch().state is TourLoaded; + // Höchste erreichte Phase aus dem PhaseBloc — bestimmt, welche // Vorwärts-Sprünge erlaubt sind. final phaseBlocState = context.watch().state; - final maxReached = phaseBlocState is PhaseReady + final blocMax = phaseBlocState is PhaseReady ? (phaseBlocState.maxPhaseFor(carId) ?? currentPhase) : currentPhase; + final maxReached = hasTour ? blocMax : phases.first; return Material( color: theme.primaryColor,