import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/model/carton_model.dart'; import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/shipment/model/shipment_model.dart'; import 'package:fcs/pages/shipment/shipment_pack.dart'; import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_button.dart'; import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; import 'package:fcs/pages/widgets/local_popupmenu.dart'; import 'package:fcs/pages/widgets/local_radio_buttons.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_title.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'box_row.dart'; import 'shipment_assign.dart'; import 'shipment_confirm.dart'; import 'shipment_editor.dart'; import 'widgets.dart'; class ShipmentInfo extends StatefulWidget { final bool? isCustomer; final Shipment? shipment; ShipmentInfo({this.shipment, this.isCustomer}); @override _ShipmentInfoState createState() => _ShipmentInfoState(); } class _ShipmentInfoState extends State { var dateFormatter = new DateFormat('dd MMM yyyy'); final numberFormatter = new NumberFormat("#,###"); MultiImgController multiImgController = MultiImgController(); var timeFormatter = new DateFormat('jm'); TextEditingController _addressEditingController = new TextEditingController(); TextEditingController _fromTimeEditingController = new TextEditingController(); TextEditingController _toTimeEditingController = new TextEditingController(); TextEditingController _noOfPackageEditingController = new TextEditingController(); TextEditingController _weightEditingController = new TextEditingController(); TextEditingController _recipientNameEditingController = new TextEditingController(); TextEditingController _recipientPhoneEditingController = new TextEditingController(); TextEditingController _recipientAddressEditingController = new TextEditingController(); TextEditingController _pickupDate = new TextEditingController(); TextEditingController _handlingFeeController = new TextEditingController(); Shipment? _shipment; bool _isLoading = false; late bool _isCustomer; var now = new DateTime.now(); @override void initState() { super.initState(); _shipment = widget.shipment; _isCustomer = widget.isCustomer!; _loadCartons(_shipment!.id!); _addressEditingController.text = _shipment!.address ?? ""; _fromTimeEditingController.text = _shipment!.pickupTimeStart ?? ""; _toTimeEditingController.text = _shipment!.pickupTimeEnd ?? ""; _noOfPackageEditingController.text = _shipment!.numberOfPackage != null ? _shipment!.numberOfPackage.toString() : ""; _weightEditingController.text = _shipment!.weight != null ? _shipment!.weight.toString() : ""; _pickupDate.text = dateFormatter.format(_shipment!.pickupDate ?? now); } _loadCartons(String shipmentID) async { CartonModel cartonModel = Provider.of(context, listen: false); var cartons = await cartonModel.getCartons(shipmentID); setState(() { _shipment!.boxes = cartons; }); } _loadShipment(String id) async { ShipmentModel shipmentModel = Provider.of(context, listen: false); Shipment? s = await shipmentModel.getShipment(id); s!.boxes = _shipment!.boxes; setState(() { _shipment = s; }); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { MainModel mainModel = Provider.of(context); ShipmentModel pickupModel = Provider.of(context); bool isLocalPickup = _shipment!.shipmentType == shipment_local_pickup; bool isCourierPickup = _shipment!.shipmentType == shipment_courier_pickup; bool isLocalDropoff = _shipment!.shipmentType == shipment_local_dropoff; bool isCourierDropoff = _shipment!.shipmentType == shipment_courier_dropoff; bool isEditable = widget.isCustomer! ? (_shipment!.isPending || _shipment!.isAssigned) : (_shipment!.isPending || _shipment!.isAssigned || _shipment!.isPickuped); bool canCancel = _shipment!.isPending || _shipment!.isConfirmed || _shipment!.isAssigned; final popupMenu = LocalPopupMenuButton( popmenus: [ LocalPopupMenu( enabled: _shipment!.isPending && isLocalPickup, id: 1, textKey: "shipment.assign.for.pickup", ), LocalPopupMenu( enabled: (_shipment!.isPickuped && isLocalPickup) || _shipment!.isReceived, id: 3, textKey: "shipment.pack.menuitem", ), LocalPopupMenu( enabled: _shipment!.isPending && (isCourierPickup || isCourierDropoff), id: 4, textKey: "shipment.confirm.menuitem", ), LocalPopupMenu( enabled: canCancel, id: 2, textKey: "btn.cancel", ), ], selectable: false, buttonIcon: Icons.more_vert, popupMenuCallback: (p) => p.id == 1 ? _gotoAssign() : p.id == 2 ? _cancel() : p.id == 3 ? _gotoPack() : p.id == 4 ? _gotoConfirm() : null, ); final popupMenuCustomer = LocalPopupMenuButton( popmenus: [ LocalPopupMenu( enabled: canCancel, id: 2, textKey: "btn.cancel", ), ], selectable: false, buttonIcon: Icons.more_vert, popupMenuCallback: (p) => p.id == 2 ? _cancel() : null, ); final shipmentNumberBox = getShipmentNumberStatus(context, _shipment!); final fromTimeBox = DisplayText( labelTextKey: 'shipment.from', iconData: Icons.timer, text: _shipment!.pickupTimeStart ?? "", ); final toTimeBox = DisplayText( labelTextKey: 'shipment.to', iconData: Icons.timer_off, text: _shipment!.pickupTimeEnd ?? "", ); final pickupDateBox = DisplayText( labelTextKey: "shipment.date", iconData: Icons.date_range, text: _shipment!.pickupDate != null ? dateFormatter.format(_shipment!.pickupDate!) : '', ); var localDropoffAddressBox = Row(children: [ FcsIDIcon(), Expanded( child: DisplayText( text: mainModel.setting!.usaAddress ?? "", ), ) ]); final curierDropoffAddress = Padding( padding: EdgeInsets.all(8), child: FloatingActionButton.extended( onPressed: _openCourierWebsite, icon: Icon(Icons.open_in_new, color: primaryColor), label: Text( 'Visit courier website \nfor nearest drop-off', style: TextStyle(fontSize: 16, color: primaryColor), ), backgroundColor: Colors.white, )); final pickupAddressBox = DefaultDeliveryAddress( deliveryAddress: _shipment!.pickupAddress, iconData: Icons.location_on, labelKey: "shipment.location", ); var usersBox = DisplayText( labelTextKey: "shipment.staff", text: _shipment!.pickupUserName ?? "", iconData: MaterialCommunityIcons.worker); var handlingFeeBox = DisplayText( labelTextKey: "shipment.handling.fee", text: (_shipment!.handlingFee ?? 0).toString(), iconData: FontAwesome.truck); final assignCompleteBtn = LocalButton( textKey: "shipment.assign.complete.btn", callBack: _completeAssign, ); final completePickupBtn = LocalButton( textKey: "shipment.pickup.complete.btn", callBack: _pickup, ); final completePackBtn = LocalButton( textKey: "shipment.pack.complete.btn", callBack: _pack, ); final confirmCompleteBtn = LocalButton( textKey: "shipment.confirm.complete.btn", callBack: _confirm, ); final fcsShipmentNumberBox = DisplayText( text: _shipment!.fcsShipmentNumber ?? "", labelTextKey: "FCSshipment.number", iconData: Ionicons.ios_airplane, ); final completeReceiveBtn = LocalButton( textKey: "shipment.receive.complete.btn", callBack: _receive, ); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( centerTitle: true, leading: new IconButton( icon: new Icon( CupertinoIcons.back, color: primaryColor, ), onPressed: () => Navigator.of(context).pop(), ), shadowColor: Colors.transparent, backgroundColor: Colors.white, title: LocalText( context, "shipment.info", fontSize: 20, color: primaryColor, ), actions: [ IconButton( icon: Icon(Icons.edit, color: isEditable ? primaryColor : Colors.grey), onPressed: isEditable ? _edit : null, ), widget.isCustomer! ? popupMenuCustomer : popupMenu, ]), body: Padding( padding: const EdgeInsets.all(10.0), child: ListView( children: [ shipmentNumberBox, LocalTitle(textKey: "shipment.type"), LocalRadioButtons( readOnly: true, values: pickupModel.shipmentTypes, selectedValue: _shipment!.shipmentType, ), ...(isLocalDropoff ? [ LocalTitle(textKey: "shipment.location.dropoff"), localDropoffAddressBox ] : []), ...(isCourierDropoff ? [ LocalTitle(textKey: "shipment.courier.dropoff"), curierDropoffAddress ] : []), ...(isCourierPickup || isLocalPickup ? [ LocalTitle(textKey: "shipment.location"), pickupAddressBox, LocalTitle(textKey: "shipment.date.time"), pickupDateBox, fromTimeBox, toTimeBox, ] : []), LocalTitle( textKey: "boxes.name", trailing: Text( "${_shipment!.totalCount} Cartons - ${_shipment!.totalWeight} lb"), ), Column( children: getBoxList(context, _shipment!.boxes), ), !_isCustomer ? fcsShipmentNumberBox : Container(), ...(!_shipment!.isPending ? [ handlingFeeBox, ] : []), ...(isLocalPickup ? [ LocalTitle(textKey: "shipment.assign.for.pickup"), usersBox, ] : []), ...(isLocalPickup && !_isCustomer ? [ _shipment!.isPending ? assignCompleteBtn : Container(), _shipment!.isAssigned ? completePickupBtn : Container(), _shipment!.isPickuped ? completePackBtn : Container(), ] : []), ...((isCourierPickup || isCourierDropoff) && !_isCustomer ? [ _shipment!.isPending ? confirmCompleteBtn : Container(), _shipment!.isConfirmed ? completeReceiveBtn : Container(), _shipment!.isReceived ? completePackBtn : Container(), ] : []), ...((isLocalDropoff) && !_isCustomer ? [ _shipment!.isPending ? completeReceiveBtn : Container(), _shipment!.isReceived ? completePackBtn : Container(), ] : []), ], ), ), ), ); } List getBoxList(BuildContext context, List boxes) { if (boxes == null) return []; return boxes.asMap().entries.map((_box) { return Row( children: [ Expanded(child: BoxRow(box: _box.value)), ], ); }).toList(); } _edit() async { bool? updated = await Navigator.push( context, CupertinoPageRoute( builder: (context) => ShipmentEditor( shipment: _shipment, )), ); if (updated ?? false) { await _loadShipment(_shipment!.id!); await _loadCartons(_shipment!.id!); } } _cancel() { showConfirmDialog(context, "shipment.cancel.confirm", () { _cancelShipment(); }); } _cancelShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.cancelShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _openCourierWebsite() { MainModel mainModel = Provider.of(context, listen: false); launch("${mainModel.setting!.courierWebsite}"); } _gotoAssign() async { bool? assigned = await Navigator.push( context, CupertinoPageRoute( builder: (context) => ShipmentAssign( shipment: _shipment, )), ); if (assigned ?? false) { await _loadShipment(_shipment!.id!); } } _completeAssign() { showConfirmDialog(context, "shipment.assign.complete.confirm", () { _completeAssignShipment(); }); } _completeAssignShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.completeAssignShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _pickup() { showConfirmDialog(context, "shipment.pickup.complete.confirm", () { _pickupShipment(); }); } _pickupShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.completePickupShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _gotoPack() async { bool? assigned = await Navigator.push( context, CupertinoPageRoute( builder: (context) => ShipmentPack( shipment: _shipment!, )), ); if (assigned ?? false) { await _loadShipment(_shipment!.id!); await _loadCartons(_shipment!.id!); } } _pack() { showConfirmDialog(context, "shipment.pack.complete.confirm", () { _packShipment(); }); } _packShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.completePackShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _gotoConfirm() async { bool? assigned = await Navigator.push( context, CupertinoPageRoute( builder: (context) => ShipmentConfirm( shipment: _shipment, )), ); if (assigned ?? false) { await _loadShipment(_shipment!.id!); } } _confirm() { showConfirmDialog(context, "shipment.confirm.complete.confirm", () { _confirmShipment(); }); } _confirmShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.completeConfirmShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } _receive() { showConfirmDialog(context, "shipment.receive.complete.confirm", () { _receiveShipment(); }); } _receiveShipment() async { setState(() { _isLoading = true; }); try { ShipmentModel shipmentModel = Provider.of(context, listen: false); await shipmentModel.completeReceiveShipment(_shipment!); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } }