From 446cf73347e94283897d6f4e2c00ca67abab4b00 Mon Sep 17 00:00:00 2001 From: Dennis Nemec Date: Thu, 18 Jun 2026 16:07:22 +0200 Subject: [PATCH] feat(loading): Abschluss-Dialog 'Alles gescannt - Auslieferung starten?' im Scanner Sobald im Beladen-Scanner der letzte Pflicht-Scan erledigt ist (alle eigenen, aktiven Lieferungen im Standardlager fertig - gleiche Bedingung wie der 'Auslieferungs-Phase starten'-Gate der Uebersicht), erscheint einmalig ein Dialog: bestaetigt 'alles gescannt' und fragt, ob die Auslieferung starten soll. 'Auslieferung starten' -> PhaseSet(ausliefern) + Scanner schliessen; 'Spaeter' -> nur schliessen. BlocConsumer-Listener + Einmal-Flag (Reset wenn wieder etwas offen). Co-Authored-By: Claude Opus 4.8 (1M context) --- .../presentation/loading_customer_page.dart | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) 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(