import 'package:dart_mq/dart_mq.dart'; import 'package:expandable/expandable.dart'; import 'package:flutter/material.dart'; import 'package:isar/isar.dart'; import 'package:stadtbote/content_views/utils/content_view_widget.dart'; import 'package:intl/intl.dart'; import 'package:badges/badges.dart' as badges; import 'package:stadtbote/messages/pop_content_view_message.dart'; import 'package:stadtbote/network_messages/accept_job_message.dart'; import 'package:stadtbote/network_messages/fin_task_message.dart'; import 'package:stadtbote/tools/messages/job_received_message.dart'; import 'package:stadtbote/tools/messages/publish_payload_message.dart'; import 'package:stadtbote/tools/messages/refresh_badges_message.dart'; import 'package:stadtbote/tools/messages/remove_job_message.dart'; import 'package:stadtbote/tools/messages/remove_state_0_job_from_map.dart'; import '../main.dart'; import '../model/job.dart'; import '../tools/constants.dart'; import '../tools/util.dart'; class AssignedJobsPage extends ContentViewWidget { const AssignedJobsPage({super.key}); @override State createState() => _AssignedJobsPageState(); @override Future getHeaderWidget(BuildContext context) async { await Future.delayed(const Duration(microseconds: 0)); return _HeaderWidget(); } } class _AssignedJobsPageState extends State with ProducerMixin, ConsumerMixin { late bool _initCompleted = false; List _jobs = []; @override void initState() { Future.delayed(const Duration(seconds: 0), () async { _jobs = await _fetchState0Jobs(); _initMessages(); _initCompleted = true; setState(() {}); }); super.initState(); } @override Widget build(BuildContext context) { if (!_initCompleted) { return Util.getWaitWidget(context); } var jobWidgets = _createWidgets(); return Padding( padding: const EdgeInsets.all(8.0), child: Scrollbar( thumbVisibility: true, child: ListView( children: jobWidgets ), ), ); } Future> _fetchState0Jobs() async { return await MyApp.isarInstance.jobs.filter().stateEqualTo(Constants.stateAssigned).findAll(); } List _createWidgets() { List widgets = []; for (var job in _jobs) { var expandableController = ExpandableController(); expandableController.expanded = true; widgets.add(ExpandableNotifier( child: ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 8, vertical: 8), title: Container( decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all( color: Constants.colorPrimary, width: 1, ), ), child: badges.Badge( position: badges.BadgePosition.topEnd(top: -13, end: -5), showBadge: true, badgeContent: const Text( 'Neu', style: TextStyle( color: Colors.white, fontSize: 18.0, ), ), badgeStyle: badges.BadgeStyle( shape: badges.BadgeShape.square, badgeColor: Constants.colorPrimary, padding: const EdgeInsets.all(5), borderRadius: BorderRadius.circular(5), borderSide: const BorderSide(color: Constants.colorPrimary, width: 0), ), child: Padding( padding: const EdgeInsets.all(12.0), child: Column( children: [ Text( DateFormat('dd.MM.yyyy HH:mm').format(DateTime.parse(job.ordertime).toLocal()).toString(), textAlign: TextAlign.left, style: TextStyle(backgroundColor: isJobTooFarInFuture(job) ? Colors.red : Colors.white), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset("assets/${mapVehicleTypeToImageName(job.vhtId)}", width: 60, height: 60), const SizedBox(width: 10), Text( mapVehicleTypeToText(job.vhtId) ), ], ), Text('Auftragsnummer: ${job.id}'), Text(job.tours[0].comp), Text(job.tours[0].street), Text(job.tours[0].city), const SizedBox(height: 20), ScrollOnExpand( scrollOnExpand: true, scrollOnCollapse: false, child: ExpandablePanel( controller: expandableController, theme: const ExpandableThemeData( headerAlignment: ExpandablePanelHeaderAlignment.center, tapBodyToCollapse: true, ), header: const Padding( padding: EdgeInsets.all(0), child: Text( "Weitere Infos....", style: TextStyle(fontSize: 15, color: Colors.black, fontWeight: FontWeight.bold), )), collapsed: const SizedBox(), expanded: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Container( height: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), color: const Color(0xfffff4e4), border: Border.all( color: Colors.grey, width: 0.5, ), ), child: Text(job.rem), ), ], ), ), ), const SizedBox(height: 20), Row(children: [ Expanded( child: getDefaultButton(!job.global ? 'Ablehnen' : 'Ignorieren', () { job.sendMessage( routingKey: Constants.messageTopicRemoveJob, payload: RemoveJobMessage(id: job.id), ); _sendAnswer(job, !job.global ? 2 : 3); _jobs.removeWhere((databaseJob) => databaseJob.id == job.id); setState(() {}); }), ), const SizedBox(width: 20), Expanded( child: getDefaultButton('Annehmen', () { job.sendMessage( routingKey: Constants.messageTopicRemoveJob, payload: RemoveJobMessage(id: job.id), ); _sendAnswer(job, 1); _jobs.removeWhere((databaseJob) => databaseJob.id == job.id); setState(() {}); }), ) ]) ], ), ), ), ), ), )); } return widgets; } _sendAnswer(Job job, int item) async { var currentPosition = MyApp.currentPosition; var message = Reaction(); message.id = job.id; message.ver = job.ver.toString(); message.item = item; message.track = Track(); message.track.time = DateTime.now().toUtc().toIso8601String(); message.track.pos = FinTaskPos(); message.track.pos!.lat = currentPosition != null ? currentPosition.latitude : 0.0; message.track.pos!.long = currentPosition != null ? currentPosition.longitude : 0.0; message.track.pos!.acc = currentPosition != null ? currentPosition.accuracy.toInt() : 0; sendMessage( routingKey: Constants.messageTopicRemoveState0JobFromMap, payload: RemoveState0JobFromMapMessage(jobId: job.id), ); sendMessage( routingKey: Constants.messageTopicPublishPayload, payload: PublishPayloadMessage(topic: "reaction", message: message.toJson(), acknowledgeRequired: true), ); sendMessage( routingKey: Constants.messageTopicUpdateBadges, payload: RefreshBadgesMessage(), ); } void _initMessages() { subscribe( queueId: Constants.messageTopicJobReceived, callback: (message) { var job = (message.payload as JobReceivedMessage).job; if (job.state == Constants.stateAssigned) { _jobs.add(job); setState(() {}); } }, ); } } class _HeaderWidget extends StatefulWidget { @override State<_HeaderWidget> createState() => _HeaderWidgetState(); } class _HeaderWidgetState extends State<_HeaderWidget> with ProducerMixin { @override void initState() { super.initState(); } @override Widget build(BuildContext context) { var cellWidth = (MediaQuery.of(context).size.width - 60 - 60 - 25) / 2; return Padding( padding: const EdgeInsets.all(8), child: Stack( alignment: Alignment.center, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Visibility( visible: true, child: Container( width: 60, height: 60, decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.white, ), child: FittedBox( child: GestureDetector( onTap: () async { sendMessage( routingKey: Constants.messageTopicPopContentView, payload: PopContentViewMessage(count: 1), ); }, child: const CircleAvatar( radius: 10, backgroundColor: Constants.colorPrimary, child: Padding(padding: EdgeInsets.all(1.0), child: Icon(Icons.arrow_back, size: 20.0, color: Colors.white)), ), ), ), ), ), Visibility( visible: false, child: Container( width: 60, height: 60, decoration: const BoxDecoration( shape: BoxShape.circle, color: Colors.red, ), child: FittedBox( child: GestureDetector( onTap: () async { sendMessage( routingKey: Constants.messageTopicPopContentView, payload: PopContentViewMessage(count: 1), ); }, child: const CircleAvatar( backgroundColor: Constants.colorPrimary, radius: 10, child: Padding(padding: EdgeInsets.all(1.0), child: Icon(Icons.info_outline, size: 20.0, color: Colors.white))), ), ), ), ), ], ), SizedBox( height: 100, width: cellWidth * 2, child: const Center( child: Text( textAlign: TextAlign.center, "Zugewiesene Aufträge", style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18, color: Colors.white), ), ), ), ], ), ); } }