diff --git a/lib/feature/loading/presentation/loading_customer_page.dart b/lib/feature/loading/presentation/loading_customer_page.dart index 8377b15..9a4c693 100644 --- a/lib/feature/loading/presentation/loading_customer_page.dart +++ b/lib/feature/loading/presentation/loading_customer_page.dart @@ -11,9 +11,12 @@ import 'package:hl_lieferservice/feature/car_selection/bloc/bloc.dart'; import 'package:hl_lieferservice/feature/car_selection/bloc/state.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_bloc.dart'; import 'package:hl_lieferservice/feature/cars/bloc/cars_state.dart'; +import 'package:hl_lieferservice/feature/delivery/bloc/phase_bloc.dart'; +import 'package:hl_lieferservice/feature/delivery/bloc/phase_event.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/tour_bloc.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.dart'; import 'package:hl_lieferservice/feature/delivery/bloc/tour_state.dart'; +import 'package:hl_lieferservice/feature/delivery/model/delivery_phase.dart'; import 'package:hl_lieferservice/feature/loading/widget/reason_catalog.dart'; import 'package:hl_lieferservice/feature/loading/widget/reason_picker_sheet.dart'; import 'package:hl_lieferservice/widget/scanner/article_scanner_stripe.dart'; @@ -57,6 +60,10 @@ class _LoadingCustomerPageState extends State { /// vom (lebenslang einen) Scanner für die Barcode-Auflösung benutzt. int _currentIndex = 0; + /// Verhindert, dass der „Alles gescannt"-Abschluss-Dialog mehrfach erscheint. + /// Wird zurückgesetzt, sobald wieder etwas zu beladen offen ist. + bool _completionPromptShown = false; + @override void initState() { super.initState(); @@ -331,13 +338,78 @@ class _LoadingCustomerPageState extends State { } } + /// Reagiert auf jedes TourBloc-Update: Sind ALLE eigenen, **aktiven** + /// Lieferungen im Standardlager fertig beladen (dieselbe Bedingung wie der + /// „Auslieferungs-Phase starten"-Gate der Beladen-Übersicht)? Genau beim + /// Übergang „noch offen → alles fertig" (also nach dem letzten Pflicht-Scan) + /// erscheint einmalig der Abschluss-Dialog. + void _maybePromptLoadingComplete( + BuildContext context, + TourState state, + String carId, + ) { + if (state is! TourLoaded) return; + final deliveries = _ownInLoadingOrder(context, state.details, carId); + final active = + deliveries.where((d) => d.state == DeliveryState.active).toList(); + final allDone = active.isNotEmpty && + active.every(state.details.standardWarehouseLoadingDone); + + if (!allDone) { + // Wieder etwas offen (Item entfernt/zurückgesetzt) → Dialog darf erneut. + _completionPromptShown = false; + return; + } + if (_completionPromptShown) return; + _completionPromptShown = true; + _showLoadingCompleteDialog(carId); + } + + /// Abschluss-Dialog der Beladung: weist darauf hin, dass alles gescannt ist, + /// und fragt, ob die Auslieferung gestartet werden soll. Bei „Ja" wird die + /// Phase auf `ausliefern` gesetzt (PhaseBloc, app-weit) und der Scanner + /// geschlossen — der Phasen-Router (`home`) zeigt dann die Auslieferungs- + /// Übersicht. „Später" schließt nur den Dialog (Start wie bisher über die + /// Übersicht möglich). + Future _showLoadingCompleteDialog(String carId) async { + final start = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + icon: const Icon(Icons.check_circle, color: Colors.green, size: 40), + title: const Text('Alles gescannt'), + content: const Text( + 'Alle zu beladenden Artikel sind gescannt. ' + 'Möchten Sie die Auslieferung starten?', + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(ctx).pop(false), + child: const Text('Später'), + ), + FilledButton( + onPressed: () => Navigator.of(ctx).pop(true), + child: const Text('Auslieferung starten'), + ), + ], + ), + ); + if (start != true || !mounted) return; + context + .read() + .add(PhaseSet(carId: carId, phase: DeliveryPhase.ausliefern)); + // Scanner schließen → zurück zum Phasen-Router, der nun 'ausliefern' zeigt. + Navigator.of(context).pop(); + } + @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, carState) { final carId = carState is CarSelectComplete ? carState.selectedCar.id : ''; - return BlocBuilder( + return BlocConsumer( + listener: (context, tourState) => + _maybePromptLoadingComplete(context, tourState, carId), builder: (context, tourState) { if (tourState is! TourLoaded) { return const Scaffold(