import 'dart:convert' show utf8; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:intl/intl.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.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/pickup_delivery_status_popup.dart'; import 'package:stadtbote/popups/tasks_popups/receipt_giver_popup.dart'; import 'package:stadtbote/popups/tasks_popups/scan_barcodes_popup.dart'; import 'package:stadtbote/popups/tasks_popups/signature_popup.dart'; import 'package:stadtbote/popups/tasks_popups/station_notice_popup.dart'; import 'package:stadtbote/popups/tasks_popups/take_photos_popup.dart'; import 'package:stadtbote/protocoll_messages/accept_job_message.dart'; import 'package:stadtbote/protocoll_messages/fin_task_message.dart'; import 'package:stadtbote/protocoll_messages/fin_tour_message.dart'; import 'package:stadtbote/protocoll_messages/track_station_message.dart'; import 'package:stadtbote/tools/constants.dart'; import 'package:stadtbote/tools/mqtt_core.dart'; import '../main.dart'; import '../model/task_info.dart'; import '../tools/util.dart'; class TaskListPage extends ContentViewWidget { const TaskListPage({super.key, required this.job, required this.tour, this.readOnly = false}); final Job job; final JobTour tour; final bool readOnly; @override State createState() => _TaskListPageState(); @override Future getHeaderInfo(BuildContext context) async { return HeaderInfo( titleWidget: const Text( 'Liste der Aufgaben', style: TextStyle( color: Colors.white, fontSize: 20.0, ), ), rightButtonEnabled: true, rightButtonVisible: true, rightButtonImage: Util.fetchFutureIcon(const Icon(Icons.help_outline, size: 20.0, color: Colors.white)), rightButtonOnPressed: () async { await Util.startBrowser('https://app.assecutor.de/help/sb/app/context/002/index.html'); }); } } class _TaskListPageState extends State { late bool _initCompleted = false; late List _taskList; late KumiPopupWindow _popup; @override void initState() { Future.delayed(const Duration(seconds: 0), () async { _taskList = await _fetchTaskList(); _initCompleted = true; setState(() {}); }); super.initState(); } @override Widget build(BuildContext context) { if (!_initCompleted) { return Util.getWaitWidget(context); } var steps = _initSteps(); return Padding( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView( scrollDirection: Axis.vertical, padding: const EdgeInsets.all(0), child: AbsorbPointer( absorbing: widget.readOnly, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: steps, ), ), ), ); } List _initSteps() { List steps = []; for (int i=0; i<_taskList.length; i++) { var taskInfo = _taskList[i]; var textColor = isTaskActive(i) ? Colors.black : const Color(0x33000000); steps.add( ListTile( minVerticalPadding: 0, title: Container( padding: const EdgeInsets.all(0), height: 60, child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Stack( children: [ Positioned( left: 16.5, top: i == 0 ? 40 : 40, child: Container( height: i == widget.tour.tasks.length - 1 ? 0 : 20, width: 6, color: isTaskActive(i) ? Constants.colorPrimary : Constants.colorPrimaryOpaque, ), ), Column( children: [ Container( width: 40, height: 40, decoration: BoxDecoration( shape: BoxShape.circle, color: isTaskActive(i) ? Constants.colorPrimary : Constants.colorPrimaryOpaque, ), child: const Icon(Icons.check, size: 30.0, color: Colors.white), ), ], ), ], ), const SizedBox(width: 20), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start, children: [ Text( taskInfo.task.topic, textAlign: TextAlign.left, style: TextStyle( color: textColor, fontSize: 15.0, ), ), const SizedBox(height: 5), Text( taskInfo.additionalText ?? '', textAlign: TextAlign.left, style: TextStyle( color: textColor, fontSize: 12.0, ), ), ], ), ], ), ), onTap: () { if (isTaskActive(i)) { _processTask(taskInfo); } }, ), ); } return steps; } Future> _fetchTaskList() async { List taskList = []; for(var task in widget.tour.tasks) { var taskInfo = await MyApp.isarInstance.taskInfos.filter().sIdEqualTo(task.sId).findFirst(); if (taskInfo == null) { taskInfo = TaskInfo(); taskInfo.answer = null; taskInfo.additionalText = null; taskInfo.completed = task.opt != null ? task.opt! : false; } taskInfo.task = task; taskList.add(taskInfo); } return taskList; } void _processTask(TaskInfo taskInfo) { switch(taskInfo.task.type) { case 2: _processSignature(taskInfo); break; case 3: _processTaskArrivedOrFinished(taskInfo); break; case 4: _processTakePhotos(taskInfo); break; case 5: _processScanBarcodes(taskInfo); break; case 7: _processReceiptGiver(taskInfo); break; case 8: _processStationNotice(taskInfo); break; case 9: _processCommissionNumber(taskInfo); break; case 11: _processPickupDeliveryStatusTask(taskInfo); break; } } _processTaskArrivedOrFinished(TaskInfo taskInfo) { _popup = showTaskArrivedPopup(context, taskInfo, () => { _finishProcessTaskArrivedOrFinished(taskInfo) }); } _finishProcessTaskArrivedOrFinished(TaskInfo taskInfo) { _popup.dismiss(context); DateFormat dateFormat = DateFormat("dd.MM.yyyy HH:mm"); taskInfo.additionalText = dateFormat.format(DateTime.now()); taskInfo.completed = true; _sendArrivedMessage(taskInfo); setState(() {}); } _processCommissionNumber(TaskInfo taskInfo) { _popup = showComissionNumberPopup(context, taskInfo, (text) => { _finishProcessCommissionNumber(taskInfo, text) }); } _finishProcessCommissionNumber(TaskInfo taskInfo, String comissionNumber) { _popup.dismiss(context); taskInfo.additionalText = comissionNumber; taskInfo.completed = true; setState(() {}); } _processScanBarcodes(TaskInfo taskInfo) { _popup = showScanBarcodesPopup(context, taskInfo, (List barcodes) => { _finishProcessScanBarcodes(taskInfo, barcodes) }); } _finishProcessScanBarcodes(TaskInfo taskInfo, List barcodess) { _popup.dismiss(context); taskInfo.additionalText = "Barcodes gescannt"; taskInfo.completed = true; setState(() {}); } _processTakePhotos(TaskInfo taskInfo) { _popup = showTakePhotosPopup(context, taskInfo, () => { _finishProcessTakePhotos(taskInfo) }); } _finishProcessTakePhotos(TaskInfo taskInfo) { _popup.dismiss(context); taskInfo.additionalText = "Fotos aufgenommen"; taskInfo.completed = true; setState(() {}); } void _processStationNotice(TaskInfo taskInfo) { _popup = showStationNoticePopup(context, taskInfo, (notice) => { _finishProcessStationNotice(taskInfo, notice) }); } _finishProcessStationNotice(TaskInfo taskInfo, String notice) { _popup.dismiss(context); taskInfo.additionalText = notice; taskInfo.completed = true; setState(() {}); } void _processReceiptGiver(TaskInfo taskInfo) { _popup = showReceiptGiverPopup(context, taskInfo, (receiptGiver) => { _finishReceiptGiver(taskInfo, receiptGiver) }); } _finishReceiptGiver(TaskInfo taskInfo, String receiptGiver) { _popup.dismiss(context); taskInfo.additionalText = receiptGiver; taskInfo.completed = true; setState(() {}); } void _processPickupDeliveryStatusTask(TaskInfo taskInfo) { Future.delayed(const Duration(seconds: 1), () async { _popup = showPickupDeliveryStatusPopup(context, taskInfo, (tourEntry) => { _popup.dismiss(context), taskInfo.completed = true, }); }); } void _processSignature(TaskInfo taskInfo) { SystemChrome.setPreferredOrientations([DeviceOrientation.landscapeLeft]); Future.delayed(const Duration(seconds: 1), () async { _popup = showSignaturePopup(context, taskInfo, () { _popup.dismiss(context); taskInfo.completed = true; SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); _sendFinTourMessage(); }); }); } bool isTaskActive(int index) { for (int i = 0; i < index; i++) { var taskInfo = _taskList[i]; if (!taskInfo.completed) return false; } return true; } _sendArrivedMessage(TaskInfo taskInfo) { var finTaskMessage = FinTaskMessage(); finTaskMessage.finTask = FinTask(); finTaskMessage.finTask.trId = widget.tour.id; finTaskMessage.finTask.task = Task(); finTaskMessage.finTask.task.sId = taskInfo.task.sId; finTaskMessage.finTask.task.time = DateTime.now().toIso8601String(); var position = MyApp.currentPosition; if (position != null) { finTaskMessage.finTask.task.pos = FinTaskPos(); finTaskMessage.finTask.task.pos!.lat = position.latitude; finTaskMessage.finTask.task.pos!.long = position.longitude; } MqttCore.instance.publishPayloadMessage("job", finTaskMessage.toJson()); } _sendTrackStationMessage(TaskInfo taskInfo) { var trackStationMessage = TrackStationMessage(); trackStationMessage.sid = taskInfo.task.sId; trackStationMessage.time = DateTime.now().toIso8601String(); var position = MyApp.currentPosition; if (position != null) { trackStationMessage.pos = FinTaskPos(); trackStationMessage.pos!.lat = position.latitude; trackStationMessage.pos!.long = position.latitude; } MqttCore.instance.publishPayloadMessage("", trackStationMessage.toJson()); } /* "fin_tour": { "tr_id": 211, "com": "changed com#", "track": { "time": "2021-02-18T12:35:51Z", "pos": { "lat": 53.595121, "long": 9.907433, "acc": 35 } }, "tasks": [ { "s_id": 1, "time": "2021-02-18T12:32:10Z", "pos": { "lat": 53.595124, "long": 9.907435 } }, } } } */ _sendFinTourMessage() async { var finTourMessage = FinTourMessage(); finTourMessage.finTour = FinTour(); finTourMessage.finTour.trId = widget.tour.id; finTourMessage.finTour.com = "Mir doch egal!"; var position = MyApp.currentPosition; if (position != null) { finTourMessage.finTour.track = Track(); finTourMessage.finTour.track.time = DateTime.now().toIso8601String(); finTourMessage.finTour.track.pos = FinTaskPos(); finTourMessage.finTour.track.pos.lat = position.latitude; finTourMessage.finTour.track.pos.long = position.longitude; } finTourMessage.finTour.tasks = []; for(var taskInfo in _taskList) { var finTourTask = FinTourTask(); finTourTask.sId = taskInfo.task.sId; finTourTask.time = DateTime.now().toIso8601String(); finTourTask.pos = FinTaskPos(); finTourTask.pos.lat = 0; finTourTask.pos.long = 0; finTourMessage.finTour.tasks.add(finTourTask); } MqttCore.instance.publishPayloadMessage("fin_tour", finTourMessage.toJson()); widget.tour.state = 9; await MyApp.isarInstance.writeTxn(() async { await MyApp.isarInstance.jobs.put(widget.job); }); Navigator.of(context).popUntil((route) => route.isFirst); } }