279 lines
8.1 KiB
Dart
279 lines
8.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
|
|
|
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_bloc.dart';
|
|
import 'package:hl_lieferservice/feature/delivery/overview/bloc/tour_state.dart';
|
|
import 'package:hl_lieferservice/feature/scan/presentation/scan_screen.dart';
|
|
import 'package:hl_lieferservice/model/tour.dart';
|
|
import 'package:hl_lieferservice/widget/home/bloc/navigation_bloc.dart';
|
|
import 'package:hl_lieferservice/widget/home/bloc/navigation_event.dart';
|
|
|
|
enum TourHomeSteps { planning, delivery, off }
|
|
|
|
class ScanPage extends StatefulWidget {
|
|
const ScanPage({super.key});
|
|
|
|
@override
|
|
State<StatefulWidget> createState() => _ScanPageState();
|
|
}
|
|
|
|
class _ScanPageState extends State<ScanPage> {
|
|
int _currentStepIndex = 0;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
_tryFinish(context
|
|
.read<TourBloc>()
|
|
.state);
|
|
}
|
|
|
|
void _onStartScan() {
|
|
Navigator.of(
|
|
context,
|
|
).push(MaterialPageRoute(builder: (context) => ArticleScanningScreen()));
|
|
}
|
|
|
|
Widget _tourSteps(Tour tour) {
|
|
var allArticlesScanned = tour.deliveries.every(
|
|
(delivery) => delivery.allArticlesScanned(),
|
|
);
|
|
|
|
return Stepper(
|
|
currentStep: _currentStepIndex,
|
|
controlsBuilder: (context, details) {
|
|
if (details.stepIndex == TourHomeSteps.planning.index) {
|
|
return Container(
|
|
alignment: Alignment.center,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(top: 15),
|
|
child: FilledButton.icon(
|
|
label: const Text("Scannen"),
|
|
onPressed: _onStartScan,
|
|
icon: const Icon(Icons.qr_code),
|
|
),
|
|
),
|
|
);
|
|
} else {
|
|
return Container(
|
|
alignment: Alignment.center,
|
|
child: Padding(
|
|
padding: const EdgeInsets.only(top: 15),
|
|
child: FilledButton.icon(
|
|
label: const Text("Auslieferung starten"),
|
|
onPressed:
|
|
allArticlesScanned
|
|
? () =>
|
|
context.read<NavigationBloc>().add(
|
|
NavigateToIndex(index: 1))
|
|
: null,
|
|
icon: const Icon(Icons.local_shipping),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
},
|
|
onStepContinue:
|
|
_currentStepIndex >= 1
|
|
? null
|
|
: () =>
|
|
setState(() {
|
|
if (_currentStepIndex < 2) {
|
|
_currentStepIndex += 1;
|
|
}
|
|
}),
|
|
onStepCancel:
|
|
_currentStepIndex == 0
|
|
? null
|
|
: () =>
|
|
setState(() {
|
|
if (_currentStepIndex > 0) {
|
|
_currentStepIndex -= 1;
|
|
}
|
|
}),
|
|
onStepTapped:
|
|
(value) =>
|
|
setState(() {
|
|
if (_currentStepIndex == 1 && allArticlesScanned) {
|
|
return;
|
|
}
|
|
|
|
_currentStepIndex = value;
|
|
}),
|
|
steps: [
|
|
Step(
|
|
title: Row(
|
|
children: [
|
|
Text(
|
|
"Fahrzeuge beladen",
|
|
style: TextStyle(
|
|
color: allArticlesScanned ? Colors.grey : null,
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 5),
|
|
child:
|
|
!allArticlesScanned
|
|
? const Icon(
|
|
Icons.access_time_filled,
|
|
color: Colors.orangeAccent,
|
|
)
|
|
: const Icon(
|
|
Icons.check_circle,
|
|
color: Colors.lightGreen,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
content: const Column(
|
|
children: [
|
|
Padding(
|
|
padding: EdgeInsets.only(bottom: 10),
|
|
child: Icon(Icons.barcode_reader, color: Colors.black),
|
|
),
|
|
Text(
|
|
"Scannen Sie die Ware, die Sie für die Auslieferungen benötigen.",
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Step(
|
|
title: const Text("Ausliefern"),
|
|
content: Container(
|
|
alignment: Alignment.centerLeft,
|
|
child:
|
|
!allArticlesScanned
|
|
? const Text(
|
|
"Scannen Sie erst die benötigte Ware, um die Auslieferungen zu beginnen.",
|
|
)
|
|
: null,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _info(Tour tour) {
|
|
int amountArticles = tour.deliveries.fold(
|
|
0,
|
|
(acc, delivery) =>
|
|
acc +
|
|
delivery.articles
|
|
.where((article) => article.scannable)
|
|
.fold(
|
|
0,
|
|
(amountArticles, article) => amountArticles + article.amount,
|
|
),
|
|
);
|
|
|
|
int amountCars = tour.driver.cars.length;
|
|
int amountDeliveries = tour.deliveries.length;
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.all(10),
|
|
child: SizedBox(
|
|
width: double.infinity,
|
|
child: Card(
|
|
color: Theme
|
|
.of(context)
|
|
.colorScheme
|
|
.onSecondary,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(20),
|
|
child: Column(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(Icons.archive),
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 5),
|
|
child: Text("Anzahl Artikel"),
|
|
),
|
|
],
|
|
),
|
|
Text(amountArticles.toString()),
|
|
],
|
|
),
|
|
),
|
|
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 15),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(Icons.local_shipping_outlined),
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 5),
|
|
child: Text("Anzahl Fahrzeuge"),
|
|
),
|
|
],
|
|
),
|
|
Text(amountCars.toString()),
|
|
],
|
|
),
|
|
),
|
|
|
|
Padding(
|
|
padding: const EdgeInsets.only(top: 15),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(Icons.person),
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 5),
|
|
child: Text("Anzahl Lieferungen"),
|
|
),
|
|
],
|
|
),
|
|
Text(amountDeliveries.toString()),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _tryFinish(TourState state) {
|
|
if (state is TourLoaded) {
|
|
if (state.tour.deliveries.every(
|
|
(delivery) => delivery.allArticlesScanned(),
|
|
)) {
|
|
setState(() {
|
|
_currentStepIndex = 1;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return BlocConsumer<TourBloc, TourState>(
|
|
listener: (context, state) {
|
|
_tryFinish(state);
|
|
},
|
|
builder: (context, state) {
|
|
if (state is TourLoaded) {
|
|
return Column(children: [_info(state.tour), _tourSteps(state.tour)]);
|
|
}
|
|
|
|
return Center(child: CircularProgressIndicator());
|
|
},
|
|
);
|
|
}
|
|
} |