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<TourBloc>-Listener + Einmal-Flag (Reset wenn wieder etwas offen). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -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/car_selection/bloc/state.dart';
|
||||||
import 'package:hl_lieferservice/feature/cars/bloc/cars_bloc.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/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_bloc.dart';
|
||||||
import 'package:hl_lieferservice/feature/delivery/bloc/tour_event.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/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_catalog.dart';
|
||||||
import 'package:hl_lieferservice/feature/loading/widget/reason_picker_sheet.dart';
|
import 'package:hl_lieferservice/feature/loading/widget/reason_picker_sheet.dart';
|
||||||
import 'package:hl_lieferservice/widget/scanner/article_scanner_stripe.dart';
|
import 'package:hl_lieferservice/widget/scanner/article_scanner_stripe.dart';
|
||||||
@ -57,6 +60,10 @@ class _LoadingCustomerPageState extends State<LoadingCustomerPage> {
|
|||||||
/// vom (lebenslang einen) Scanner für die Barcode-Auflösung benutzt.
|
/// vom (lebenslang einen) Scanner für die Barcode-Auflösung benutzt.
|
||||||
int _currentIndex = 0;
|
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
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -331,13 +338,78 @@ class _LoadingCustomerPageState extends State<LoadingCustomerPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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<void> _showLoadingCompleteDialog(String carId) async {
|
||||||
|
final start = await showDialog<bool>(
|
||||||
|
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<PhaseBloc>()
|
||||||
|
.add(PhaseSet(carId: carId, phase: DeliveryPhase.ausliefern));
|
||||||
|
// Scanner schließen → zurück zum Phasen-Router, der nun 'ausliefern' zeigt.
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<CarSelectBloc, CarSelectState>(
|
return BlocBuilder<CarSelectBloc, CarSelectState>(
|
||||||
builder: (context, carState) {
|
builder: (context, carState) {
|
||||||
final carId =
|
final carId =
|
||||||
carState is CarSelectComplete ? carState.selectedCar.id : '';
|
carState is CarSelectComplete ? carState.selectedCar.id : '';
|
||||||
return BlocBuilder<TourBloc, TourState>(
|
return BlocConsumer<TourBloc, TourState>(
|
||||||
|
listener: (context, tourState) =>
|
||||||
|
_maybePromptLoadingComplete(context, tourState, carId),
|
||||||
builder: (context, tourState) {
|
builder: (context, tourState) {
|
||||||
if (tourState is! TourLoaded) {
|
if (tourState is! TourLoaded) {
|
||||||
return const Scaffold(
|
return const Scaffold(
|
||||||
|
|||||||
Reference in New Issue
Block a user