UI-Restructuring: - TabBar in scan_page durch dedizierte Phasen ersetzt: Sortieren / Beladen / Ausliefern - PhaseBloc + PhaseService leiten Phase aus Tour-/Item-States ab - DeliverySelectionPage (ab 2 Autos) und DeliverySortPage als eigene Flows - LoadingOverviewPage / LoadingCustomerPage für die Beladephase - PhaseStepper-Widget im Home für Phasen-Anzeige - Lager-Differenzierung (Standardlager 0 vs. Außenlager) via WarehouseBadge Process-Stubs: - ProcessRepository für Hold/Cancel/Sort/Assign-Flows (stub, bereit für Backend-Anbindung) Doku: - docs/BACKEND_MIGRATION.md: Phasenplan für Umstellung auf das neue Rust-Backend (OpenAPI-Generator, Keycloak OIDC, Clean-Arch-Layering)
59 lines
2.2 KiB
Dart
59 lines
2.2 KiB
Dart
import 'package:hl_lieferservice/feature/delivery/model/delivery_phase.dart';
|
|
|
|
abstract class PhaseState {}
|
|
|
|
class PhaseInitial extends PhaseState {}
|
|
|
|
/// Die aktive Phase pro Fahrzeug. Die Map ist pro Auto-ID separiert,
|
|
/// weil zwei Lieferketten am selben Tag (selten, aber möglich) parallel
|
|
/// laufen könnten und sich gegenseitig nicht überschreiben dürfen.
|
|
///
|
|
/// Zusätzlich wird die **höchste je heute erreichte Phase** pro Fahrzeug
|
|
/// gehalten ([maxPhaseByCar]). Damit kann der Stepper Vorwärts-Sprünge
|
|
/// auf bereits besuchte Phasen erlauben, auch wenn der Fahrer vorher
|
|
/// zurückgesprungen ist.
|
|
class PhaseReady extends PhaseState {
|
|
final Map<String, DeliveryPhase> phaseByCar;
|
|
final Map<String, DeliveryPhase> maxPhaseByCar;
|
|
|
|
PhaseReady({
|
|
required this.phaseByCar,
|
|
this.maxPhaseByCar = const {},
|
|
});
|
|
|
|
DeliveryPhase? phaseFor(String carId) => phaseByCar[carId];
|
|
|
|
/// Höchste am Tag erreichte Phase für [carId]. Fallback: aktuelle Phase
|
|
/// — wenn nichts gemerkt ist, gilt die aktuelle Phase als "höchste".
|
|
DeliveryPhase? maxPhaseFor(String carId) =>
|
|
maxPhaseByCar[carId] ?? phaseByCar[carId];
|
|
|
|
/// Setzt eine neue Phase und bumpt das Max-Tracking, falls die neue Phase
|
|
/// in der Enum-Reihenfolge höher ist als das bisherige Max.
|
|
PhaseReady withPhase(String carId, DeliveryPhase phase) {
|
|
final next = Map<String, DeliveryPhase>.from(phaseByCar);
|
|
next[carId] = phase;
|
|
|
|
final nextMax = Map<String, DeliveryPhase>.from(maxPhaseByCar);
|
|
final currentMax = nextMax[carId];
|
|
if (currentMax == null || phase.index > currentMax.index) {
|
|
nextMax[carId] = phase;
|
|
}
|
|
return PhaseReady(phaseByCar: next, maxPhaseByCar: nextMax);
|
|
}
|
|
|
|
/// Wird nach dem Laden aus dem [PhaseService] verwendet, damit die echte
|
|
/// historische Max-Phase übernommen wird (nicht automatisch geboostet).
|
|
PhaseReady withLoaded(
|
|
String carId,
|
|
DeliveryPhase phase,
|
|
DeliveryPhase maxPhase,
|
|
) {
|
|
final next = Map<String, DeliveryPhase>.from(phaseByCar);
|
|
next[carId] = phase;
|
|
final nextMax = Map<String, DeliveryPhase>.from(maxPhaseByCar);
|
|
nextMax[carId] = maxPhase;
|
|
return PhaseReady(phaseByCar: next, maxPhaseByCar: nextMax);
|
|
}
|
|
}
|