From 5c3cee2d92cca23b02f8fe750552438dd0dfa9ff Mon Sep 17 00:00:00 2001 From: Sven Carstensen Date: Tue, 14 Nov 2023 14:57:57 +0100 Subject: [PATCH] Erweiterungen --- lib/content_views/assigned_jobs_page.dart | 128 +++++++++++++----- lib/content_views/task_list_page.dart | 46 ++++++- lib/popups/map_popup.dart | 2 +- lib/popups/tasks_popups/arrived_popup.dart | 62 +++++++++ .../tasks_popups/commision_number_popup.dart | 67 +++++++++ .../tasks_popups/scan_barcodes_popup.dart | 123 +++++++++++++++++ lib/tools/constants.dart | 7 +- lib/tools/util.dart | 76 ++++++++--- pubspec.lock | 8 ++ pubspec.yaml | 1 + 10 files changed, 466 insertions(+), 54 deletions(-) create mode 100644 lib/popups/tasks_popups/arrived_popup.dart create mode 100644 lib/popups/tasks_popups/commision_number_popup.dart create mode 100644 lib/popups/tasks_popups/scan_barcodes_popup.dart diff --git a/lib/content_views/assigned_jobs_page.dart b/lib/content_views/assigned_jobs_page.dart index 1415562..4b602b7 100644 --- a/lib/content_views/assigned_jobs_page.dart +++ b/lib/content_views/assigned_jobs_page.dart @@ -1,6 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:flutter_broadcast_receiver/flutter_broadcast_receiver.dart'; +import 'package:isar/isar.dart'; +import 'package:stadtbote/content_views/tour_list_page.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; +import 'package:intl/intl.dart'; + +import '../main.dart'; +import '../model/job.dart'; +import '../tools/constants.dart'; +import '../tools/util.dart'; class AssignedJobsPage extends ContentViewWidget { const AssignedJobsPage({super.key}); @@ -12,7 +21,7 @@ class AssignedJobsPage extends ContentViewWidget { Future getHeaderInfo(BuildContext context) async { return HeaderInfo( titleWidget: const Text( - 'Startseite', + 'Zugewiesene Aufträge', style: TextStyle( color: Colors.white, fontSize: 24.0, @@ -28,42 +37,99 @@ class AssignedJobsPage extends ContentViewWidget { } class _AssignedJobsPageState extends State { - void sendMessage(Widget message) { - //Messaging.instance.sendMessage(message); - } + late List _jobs; - void _clicked() { - //sendMessage(const InfoDetailsWidget()); + late bool _initCompleted = false; + + @override + void initState() { + Future.delayed(const Duration(seconds: 0), () async { + _jobs = await MyApp.isarInstance.jobs.filter().stateEqualTo(0).findAll(); + + _initCompleted = true; + + setState(() {}); + }); + + super.initState(); } @override Widget build(BuildContext context) { + if (!_initCompleted) { + return Util.getWaitWidget(context); + } + + late List jobWidgets = _createjobWidgets(); + return ListView( - children: [ - ListTile( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: const [ - Text( - 'Dies ist ein linksbündigerText', - textAlign: TextAlign.left, - ), - Text( - 'Dies ist ein linksbündiger Text', - textAlign: TextAlign.left, - style: TextStyle( - color: Colors.blue, - fontSize: 24.0, - ), - ), - ], - ), - onTap: () { - _clicked(); - }, - ), - ], + children: jobWidgets ); } + + List _createjobWidgets() { + List jobWidgets = []; + + for (var job in _jobs) { + jobWidgets.add( + ListTile( + onTap: () { + _clicked(job); + }, + title: Container( + decoration: BoxDecoration( + color: Colors.white, + border: Border.all(color: Colors.grey, width: 0.5), + borderRadius: const BorderRadius.all(Radius.circular(13)) + ), + padding: const EdgeInsets.all(15.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + DateFormat('dd.MM.yyyy HH:mm').format(DateTime.parse(job.ordertime)).toString(), + textAlign: TextAlign.left, + ), + Text( + job.crFilter != null ? job.crFilter.toString() : "Kein CR-Filter vorhanden", + textAlign: TextAlign.left, + ), + Row( + children: [ + const Icon(Icons.arrow_back, size: 30.0, color: Colors.black), + const SizedBox(width: 10), + Text( + job.vhtId.toString() + ), + ], + ), + Text( + job.id.toString(), + textAlign: TextAlign.left, + ), + Text( + job.tours[0].comp, + textAlign: TextAlign.left, + ), + Text( + job.tours[0].street, + textAlign: TextAlign.left, + ), + Text( + job.tours[0].city, + textAlign: TextAlign.left, + ), + ], + ), + ) + ), + ); + } + + return jobWidgets; + } + + void _clicked(Job job) { + } } diff --git a/lib/content_views/task_list_page.dart b/lib/content_views/task_list_page.dart index 0afc29e..068f14a 100644 --- a/lib/content_views/task_list_page.dart +++ b/lib/content_views/task_list_page.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; import 'package:isar/isar.dart'; +import 'package:kumi_popup_window/kumi_popup_window.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:stadtbote/content_views/utils/header_info.dart'; import 'package:stadtbote/model/job_tour.dart'; +import 'package:stadtbote/popups/tasks_popups/arrived_popup.dart'; +import 'package:stadtbote/popups/tasks_popups/commision_number_popup.dart'; +import 'package:stadtbote/popups/tasks_popups/scan_barcodes_popup.dart'; import '../main.dart'; import '../model/task_info.dart'; @@ -40,6 +44,8 @@ class _TaskListPageState extends State { late List _taskList; + late KumiPopupWindow _popup; + @override void initState() { Future.delayed(const Duration(seconds: 0), () async { @@ -118,6 +124,7 @@ class _TaskListPageState extends State { const SizedBox(width: 20), Column( crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, children: [ Text( taskInfo.task.topic, @@ -127,8 +134,9 @@ class _TaskListPageState extends State { fontSize: 15.0, ), ), + const SizedBox(height: 5), Text( - taskInfo.additionalText ?? '', + taskInfo.additionalText ?? 'Additonal text', textAlign: TextAlign.left, style: const TextStyle( color: Colors.blue, @@ -141,7 +149,7 @@ class _TaskListPageState extends State { ), ), onTap: () { - print('1'); + _processTask(taskInfo); }, ), ); @@ -166,4 +174,38 @@ class _TaskListPageState extends State { return taskList; } + + void _processTask(TaskInfo taskInfo) { + switch(taskInfo.task.type) { + case 3: + _processTaskArrived(taskInfo); + break; + + case 5: + _processScanBarcodes(taskInfo); + break; + + case 9: + _processCommissionNumber(taskInfo); + break; + } + } + + void _processTaskArrived(TaskInfo taskInfo) { + _popup = showTaskArrivedPopup(context, taskInfo, () => { + _popup.dismiss(context), + }); + } + + void _processCommissionNumber(TaskInfo taskInfo) { + _popup = showCommisionNumberPopup(context, taskInfo, () => { + _popup.dismiss(context), + }); + } + + void _processScanBarcodes(TaskInfo taskInfo) { + _popup = showScanBarcodesPopup(context, taskInfo, () => { + _popup.dismiss(context) + }); + } } diff --git a/lib/popups/map_popup.dart b/lib/popups/map_popup.dart index f28b742..19c02a6 100644 --- a/lib/popups/map_popup.dart +++ b/lib/popups/map_popup.dart @@ -72,7 +72,7 @@ void showMapPopup(BuildContext context, JobTour currentTour, List tourL height: 12.0, width: 70, child: Text( - "Tour ${tour.sort}", + "Station ${tour.sort}", softWrap: true, textAlign: TextAlign.center, style: const TextStyle( diff --git a/lib/popups/tasks_popups/arrived_popup.dart b/lib/popups/tasks_popups/arrived_popup.dart new file mode 100644 index 0000000..368f07a --- /dev/null +++ b/lib/popups/tasks_popups/arrived_popup.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:kumi_popup_window/kumi_popup_window.dart'; +import 'package:stadtbote/model/task_info.dart'; +import 'package:stadtbote/tools/util.dart'; + +KumiPopupWindow showTaskArrivedPopup(BuildContext context, TaskInfo taskInfo, Function() onFinished) { + return showPopupWindow( + context, + //childSize:Size(240, MediaQuery.of(context).size.width * 0.8), + gravity: KumiPopupGravity.center, + //curve: Curves.elasticOut, + bgColor: Colors.grey.withOpacity(0.5), + clickOutDismiss: true, + clickBackDismiss: true, + customAnimation: false, + customPop: false, + customPage: false, + // targetRenderBox: (btnKey.currentContext.findRenderObject() as RenderBox), + //needSafeDisplay: true, + underStatusBar: false, + underAppBar: false, + //offsetX: -180, + //offsetY: 50, + duration: const Duration(milliseconds: 200), + onShowStart: (pop) {}, + onShowFinish: (pop) {}, + onDismissStart: (pop) {}, + onDismissFinish: (pop) {}, + onClickOut: (pop) {}, + onClickBack: (pop) {}, + childFun: (pop) { + return SizedBox( + key: GlobalKey(), + height: MediaQuery.of(context).size.height * 0.2, + width: MediaQuery.of(context).size.width * 0.8, + child: Container( + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(35.0), + child: Column( + children: [ + const Text('Bitte bestätigen Sie Ihre Ankunft'), + const SizedBox(height: 20), + getDefaultButton('Ankunft bestätigen', () => { + onFinished() + }), + ], + ), + ), + )); + }, + ); +} + diff --git a/lib/popups/tasks_popups/commision_number_popup.dart b/lib/popups/tasks_popups/commision_number_popup.dart new file mode 100644 index 0000000..acea400 --- /dev/null +++ b/lib/popups/tasks_popups/commision_number_popup.dart @@ -0,0 +1,67 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:kumi_popup_window/kumi_popup_window.dart'; +import 'package:stadtbote/model/task_info.dart'; +import 'package:stadtbote/tools/util.dart'; + +KumiPopupWindow showCommisionNumberPopup(BuildContext context, TaskInfo taskInfo, Function() onFinished) { + return showPopupWindow( + context, + //childSize:Size(240, MediaQuery.of(context).size.width * 0.8), + gravity: KumiPopupGravity.center, + //curve: Curves.elasticOut, + bgColor: Colors.grey.withOpacity(0.5), + clickOutDismiss: true, + clickBackDismiss: true, + customAnimation: false, + customPop: false, + customPage: false, + // targetRenderBox: (btnKey.currentContext.findRenderObject() as RenderBox), + //needSafeDisplay: true, + underStatusBar: false, + underAppBar: false, + //offsetX: -180, + //offsetY: 50, + duration: const Duration(milliseconds: 200), + onShowStart: (pop) {}, + onShowFinish: (pop) {}, + onDismissStart: (pop) {}, + onDismissFinish: (pop) {}, + onClickOut: (pop) {}, + onClickBack: (pop) {}, + childFun: (pop) { + TextEditingController textEditingController = TextEditingController(); + + return SizedBox( + key: GlobalKey(), + height: 260, + width: MediaQuery.of(context).size.width * 0.8, + child: Container( + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(35.0), + child: Column( + children: [ + const Text('Bitte geben Sie die Kommisionsnummer ein'), + const SizedBox(height: 20), + Util.getDefaultTextField('Kommisionsnummer', + type: TextInputType.text, formatter: [FilteringTextInputFormatter.singleLineFormatter], controller: textEditingController, autofocus: true), + const SizedBox(height: 20), + getDefaultButton('Ankunft bestätigen', () => { + onFinished() + }) ], + ), + ), + )); + }, + ); +} + diff --git a/lib/popups/tasks_popups/scan_barcodes_popup.dart b/lib/popups/tasks_popups/scan_barcodes_popup.dart new file mode 100644 index 0000000..57fc267 --- /dev/null +++ b/lib/popups/tasks_popups/scan_barcodes_popup.dart @@ -0,0 +1,123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; +import 'package:kumi_popup_window/kumi_popup_window.dart'; +import 'package:stadtbote/model/task_info.dart'; +import 'package:stadtbote/tools/util.dart'; + +KumiPopupWindow showScanBarcodesPopup(BuildContext context, TaskInfo taskInfo, Function() onFinished) { + return showPopupWindow( + context, + //childSize:Size(240, MediaQuery.of(context).size.width * 0.8), + gravity: KumiPopupGravity.center, + //curve: Curves.elasticOut, + bgColor: Colors.grey.withOpacity(0.5), + clickOutDismiss: true, + clickBackDismiss: true, + customAnimation: false, + customPop: false, + customPage: false, + // targetRenderBox: (btnKey.currentContext.findRenderObject() as RenderBox), + //needSafeDisplay: true, + underStatusBar: false, + underAppBar: false, + //offsetX: -180, + //offsetY: 50, + duration: const Duration(milliseconds: 200), + onShowStart: (pop) {}, + onShowFinish: (pop) {}, + onDismissStart: (pop) {}, + onDismissFinish: (pop) {}, + onClickOut: (pop) {}, + onClickBack: (pop) {}, + childFun: (pop) { + List scannedBarcodes = []; + + final ValueNotifier> scannedBarcodeWidgetsNotifier = ValueNotifier>([]); + + List createBarcodeWidgets() { + List barcodeWidgets = []; + + for(var barcode in scannedBarcodes) { + barcodeWidgets.add(Container( + height: 20, + child: Center(child: Text(barcode)), + )); + } + + return barcodeWidgets; + } + + void scanBarcode() async { + String barcodeScanResult; + try { + barcodeScanResult = await FlutterBarcodeScanner.scanBarcode('#ff6666', 'Abbrechen', true, ScanMode.QR); + + scannedBarcodes.add(barcodeScanResult); + + var barcodeWidgets = createBarcodeWidgets(); + + scannedBarcodeWidgetsNotifier.value = barcodeWidgets; + } on PlatformException { + barcodeScanResult = 'Failed to get platform version.'; + } + } + + return SizedBox( + key: GlobalKey(), + height: 340, + width: MediaQuery.of(context).size.width * 0.8, + child: Container( + height: 100, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 0.5, + ), + ), + child: Padding( + padding: const EdgeInsets.all(35.0), + child: Column( + children: [ + const Text('Gescannte Barcodes'), + const SizedBox(height: 20), + Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + color: Colors.white, + border: Border.all( + color: Colors.grey, + width: 0.5, + ), + ), + height: 100, + child: ValueListenableBuilder>( + valueListenable: scannedBarcodeWidgetsNotifier, + builder: (context, value, child) { + return ListView( + padding: const EdgeInsets.all(8), + children: value + ); + }, + ), + ), + const SizedBox(height: 20), + getDefaultButton('Hinzufügen', buttonHeight: 50, () => { + scanBarcode() + }), + getDefaultButton('Übernehmen', buttonHeight: 50, () => { + onFinished() + }) + ], + ), + ), + )); + }, + ); +} + +/* + + */ \ No newline at end of file diff --git a/lib/tools/constants.dart b/lib/tools/constants.dart index 5fa6b76..4d9650d 100644 --- a/lib/tools/constants.dart +++ b/lib/tools/constants.dart @@ -1,11 +1,12 @@ +import 'dart:ui'; + class Constants { + static const Color colorPrimary = Color(0xff0095DB); + static const String messageTopicConnectionStatusChanged = "connection_status_changed"; static const String messageTopicPushContentView = "push_content_view"; static const String messageTopicPopContentView = "pop_content_view"; static const String messageTopicReplaceContentView = "replace_content_view"; static const String messageTopicHideRightButton = "hide_right_button"; static const String messageShowPopup = "show_popup"; - - //static const String topicToServer = "/app/100/2/208738/to_server"; - //static const String topicFromServer = "/app/100/2/208738/from_server"; } \ No newline at end of file diff --git a/lib/tools/util.dart b/lib/tools/util.dart index 9032fc5..2e84311 100644 --- a/lib/tools/util.dart +++ b/lib/tools/util.dart @@ -1,6 +1,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:stadtbote/tools/constants.dart'; import 'package:uuid/uuid.dart'; import '../Tools/colored_safe_area.dart'; @@ -16,8 +18,7 @@ class Util { await prefs.setString(key, value); } - static Future preferencesGetString( - String key, String? defaultValue) async { + static Future preferencesGetString(String key, String? defaultValue) async { if (await preferencesContainsKey(key)) { var prefs = await SharedPreferences.getInstance(); return prefs.getString(key); @@ -109,11 +110,61 @@ class Util { return icon; }); } + + static TextField getDefaultTextField(String hint, + {TextEditingController? controller, + FocusNode? focusNode, + IconButton? iconButton, + int? maxLines = 1, + TextInputType? type, + List? formatter, + Function()? onTap, + bool? autofocus}) { + iconButton ??= IconButton( + icon: const Icon(Icons.clear), + onPressed: () { + if (controller != null) { + controller.text = ""; + } + }, + ); + + return TextField( + controller: controller, + focusNode: focusNode, + maxLines: maxLines, + onTap: onTap, + keyboardType: type, + inputFormatters: formatter, + autofocus: (autofocus != null) ? autofocus : false, + decoration: InputDecoration( + hintText: hint, + contentPadding: const EdgeInsets.all(10), + border: Util.getDefaultBorder(), + errorBorder: Util.getDefaultBorder(), + disabledBorder: Util.getDefaultBorder(), + focusedBorder: Util.getDefaultFocusedBorder(), + focusedErrorBorder: Util.getDefaultBorder(), + suffixIcon: iconButton, + labelText: hint), + ); + } + + static OutlineInputBorder getDefaultBorder() { + return const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(20.0))); + } + + static OutlineInputBorder getDefaultFocusedBorder() { + return const OutlineInputBorder( + borderSide: BorderSide(color: Constants.colorPrimary), + borderRadius: BorderRadius.all(Radius.circular(20.0)), + ); + } } -Widget getDefaultButton(String text, Function() onPressed, {Image? image}) { +Widget getDefaultButton(String text, Function() onPressed, {Image? image, double? buttonHeight}) { return SizedBox( - height: 60, + height: buttonHeight ?? 60, child: Stack( children: [ Row( @@ -137,30 +188,21 @@ Widget getDefaultButton(String text, Function() onPressed, {Image? image}) { onPressed: () { onPressed(); }, - child: Text(text) - ), + child: Text(text)), ), ), ), ], ), - Positioned( - left: 20, - top: 15, - child: Center( - child: image - ) - ) + Positioned(left: 20, top: 15, child: Center(child: image)) ], ), ); } -String mapTourMode(String mode) -{ +String mapTourMode(String mode) { var text = ""; - switch (mode) - { + switch (mode) { case "pu": text += "/ Abholung"; break; diff --git a/pubspec.lock b/pubspec.lock index d0f0505..fea5d38 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -318,6 +318,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_barcode_scanner: + dependency: "direct main" + description: + name: flutter_barcode_scanner + sha256: a4ba37daf9933f451a5e812c753ddd045d6354e4a3280342d895b07fecaab3fa + url: "https://pub.dev" + source: hosted + version: "2.0.0" flutter_broadcast_receiver: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index a745f79..7103ad3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -60,6 +60,7 @@ dependencies: animated_toggle_switch: ^0.6.2 flutter_map: ^4.0.0 latlong2: ^0.8.2 + flutter_barcode_scanner: ^2.0.0 dev_dependencies: flutter_test: