// ignore_for_file: use_build_context_synchronously import 'package:fcs/constants.dart'; import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/carton_image_upload_editor.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/multi_img_file.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import '../../domain/entities/carton_size.dart'; import '../../domain/entities/fcs_shipment.dart'; import '../carton_size/model/carton_size_model.dart'; import '../fcs_shipment/model/fcs_shipment_model.dart'; import '../widgets/local_button.dart'; import 'carton_package_editor.dart'; import 'mix_carton/mix_carton_editor.dart'; import 'mix_carton_detail_list.dart'; import 'model/carton_model.dart'; import 'package_detail_list.dart'; import 'print_qr_code_page.dart'; class CartonInfo extends StatefulWidget { final Carton carton; const CartonInfo({super.key, required this.carton}); @override _CartonInfoState createState() => _CartonInfoState(); } class _CartonInfoState extends State { var dateFormatter = DateFormat('dd MMM yyyy'); final NumberFormat numberFormatter = NumberFormat("#,###"); MultiImgController multiImgController = MultiImgController(); bool _isLoading = false; late Carton _carton; List _cargoTypes = []; List _surchareItems = []; List _mixCartons = []; List _packages = []; double totalWeight = 0.0; double totalSurchargeCount = 0.0; CartonSize? standardSize; FcsShipment? _shipment; @override void initState() { _carton = widget.carton; _init(); super.initState(); } _init() async { try { _isLoading = true; multiImgController.setImageUrls = _carton.photoUrls; _cargoTypes = _carton.cargoTypes; _surchareItems = _carton.surchareItems; // check carton size type List cartonSizes = context.read().cartonSizes; var sameLength = cartonSizes.any((size) => size.length == _carton.length); var sameWidth = cartonSizes.any((size) => size.width == _carton.width); var sameHeight = cartonSizes.any((size) => size.height == _carton.height); bool isStandartSize = sameLength && sameWidth && sameHeight; if (isStandartSize) { _carton.cartonSizeType = standardCarton; standardSize = cartonSizes.firstWhere((size) => size.length == _carton.length && size.width == _carton.width && size.height == _carton.height); } else if (_carton.length == 0 && _carton.width == 0 && _carton.height == 0) { _carton.cartonSizeType = packageCarton; } else { _carton.cartonSizeType = customCarton; } if (widget.carton.fcsShipmentID != null && widget.carton.fcsShipmentID != '') { var s = await context .read() .getFcsShipment(widget.carton.fcsShipmentID!); _shipment = s; } if (_carton.cartonType == carton_from_packages) { _packages = await context .read() .getPackagesByIds(_carton.packageIDs); } if (_carton.cartonType == mix_carton) { _mixCartons = await context .read() .getCartonsByIds(_carton.cartonIDs); _cargoTypes.sort((a, b) => a.name!.compareTo(b.name!)); _surchareItems.sort((a, b) => a.name!.compareTo(b.name!)); } totalWeight = _carton.cargoTypes.fold(0, (sum, value) => sum + value.weight); totalSurchargeCount = _surchareItems.fold(0, (sum, value) => sum + value.qty); } finally { _isLoading = false; } if (mounted) { setState(() {}); } } @override Widget build(BuildContext context) { var fromPackage = _carton.cartonType == carton_from_packages; String? boxDimension = _carton.cartonSizeType == standardCarton ? "${standardSize?.name} - ${standardSize?.length.toInt()}”x${standardSize?.width.toInt()}”x${standardSize?.height.toInt()}”" : _carton.cartonSizeType == customCarton ? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”" : null; final cartonQrBox = IconButton( onPressed: () { Navigator.push( context, CupertinoPageRoute( builder: (context) => PrintQrCodePage(carton: _carton)), ); }, icon: Icon(AntDesign.qrcode, color: primaryColor)); final cartonTypeBox = DisplayText( text: _carton.cartonType == carton_from_packages ? "For packages" : _carton.cartonType == mix_carton ? carton_mix_carton : '', labelTextKey: "box.carton.type", ); final billInfoBox = DisplayText( text: _carton.billTo == billToSender ? "Sender" : _carton.billTo == billToConsignee ? "Consignee" : null, labelTextKey: "box.bill_to", ); final lastMileBox = DisplayText( text: _carton.lastMile == delivery_caton ? 'Delivery' : _carton.lastMile == pickup_carton ? 'Pick-up' : '', labelTextKey: "box.delivery_type", ); final cartonSizeBox = DisplayText( subText: Text(boxDimension ?? 'No defined size'), labelTextKey: "box.select_carton_size", ); final packageLengthBox = DisplayText( showLabelLink: true, subText: Text(numberFormatter.format(_packages.length)), labelTextKey: "box.package", onTapLabel: () { Navigator.push( context, CupertinoPageRoute( builder: (context) => PackageDetailList( cartonNumber: _carton.cartonNumber ?? '', packages: _packages))); }, ); final mixCartonLengthBox = DisplayText( showLabelLink: true, subText: Text(numberFormatter.format(_mixCartons.length)), labelTextKey: "box.shipment.boxes", onTapLabel: () { Navigator.push( context, CupertinoPageRoute( builder: (context) => MixCartonDetailList( cartonNumber: _carton.cartonNumber ?? '', cartons: _mixCartons))); }, ); final senderBox = userDisplayBox(context, lableKey: "box.sender.title", name: _carton.senderName, fcsID: _carton.senderFCSID); final consigneeNameBox = userDisplayBox(context, lableKey: "box.consignee.title", name: _carton.consigneeName, fcsID: _carton.consigneeFCSID); // final billWidget = Expanded( // child: Padding( // padding: EdgeInsets.only(left: 0, top: 15), // child: Row( // mainAxisAlignment: MainAxisAlignment.start, // children: [ // Icon(Ionicons.document_text_outline, // color: primaryColor, size: 20), // Text("Bill to", // style: TextStyle(color: primaryColor, fontSize: 15)) // ], // ))); final userRowBox = Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ consigneeNameBox, ], ), ), // _carton.billTo == billToConsignee ? billWidget : const SizedBox() ], )), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ senderBox, ], ), ), // _carton.billTo == billToSender ? billWidget : const SizedBox() ], ), ), ], ); final cargosBox = Padding( padding: const EdgeInsets.only(top: 20), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LocalText(context, 'box.cargo.type', color: Colors.black54, fontSize: 16, fontWeight: FontWeight.normal), _cargoTypes.isNotEmpty ? Padding( padding: EdgeInsets.only(right: 0), child: Text("${removeTrailingZeros(totalWeight)} lb", textAlign: TextAlign.end, style: TextStyle(color: Colors.black54, fontSize: 15))) : const SizedBox() ], ), Padding( padding: const EdgeInsets.only(right: 0), child: Column( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: _cargoTypes.asMap().entries.map((e) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Container( color: e.key.isEven ? Colors.grey.shade200 : oddColor, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( e.value.name ?? "", style: TextStyle( color: Colors.black, fontSize: 15), ), Text( "${removeTrailingZeros(e.value.weight)} lb", textAlign: TextAlign.end, style: TextStyle( color: Colors.black, fontSize: 15)) ], ), e.value.isMixCargo ? Padding( padding: const EdgeInsets.only(left: 20), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: e.value.mixCargoes.map((c) { return Padding( padding: const EdgeInsets.symmetric( vertical: 2), child: Text( "- ${c.name}", style: TextStyle( fontSize: 14, color: labelColor), ), ); }).toList()), ) : const SizedBox() ], ), ), ); }).toList()), ], ), ), ]), ); final surchargeItemBox = Padding( padding: const EdgeInsets.only(top: 16), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ LocalText(context, 'box.input_surcharge_item', color: Colors.black54, fontSize: 16, fontWeight: FontWeight.normal), Padding( padding: const EdgeInsets.only(right: 0), child: Column( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: _surchareItems.asMap().entries.map((e) { return Padding( padding: const EdgeInsets.symmetric(vertical: 2), child: Container( color: e.key.isEven ? Colors.grey.shade200 : oddColor, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( e.value.name ?? "", style: TextStyle(color: Colors.black, fontSize: 15), ), Text( "${removeTrailingZeros((e.value.qty).toDouble())} pc", textAlign: TextAlign.end, style: TextStyle( color: Colors.black, fontSize: 15)) ], ), ), ); }).toList()), ], ), ), ]), ); final img = MultiImageFile( enabled: false, controller: multiImgController, title: "Receipt File", ); final uploadImageBtn = Padding( padding: EdgeInsets.only(left: 200.0, right: 8.0), child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Color(0xff272262), elevation: 3, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(5.0)), minimumSize: Size(10, 35), ), onPressed: () async { bool? updated = await Navigator.push( context, CupertinoPageRoute( builder: (context) => CartonImageUploadEditor(carton: _carton)), ); if (updated ?? false) { Carton? c = await context .read() .getCarton(widget.carton.id ?? ""); if (c == null) return; _carton = c; _init(); } }, child: LocalText(context, "box.imageupload.title", color: Colors.white, fontSize: 14)), ); final deleteBtn = Padding( padding: const EdgeInsets.symmetric(horizontal: 30), child: LocalButton( color: dangerColor, textKey: "box.delete.btn", callBack: () { _delete(); }, ), ); final shipmentBox = Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ LocalText(context, "package.shipment.title", fontSize: 15, color: Colors.black54), const SizedBox(height: 5), Container( decoration: BoxDecoration( border: Border.all(color: dividerColor), borderRadius: BorderRadius.circular(5), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: Column( children: [ DisplayText( text: _shipment?.shipmentNumber, labelTextKey: "FCSshipment.number", ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible( child: DisplayText( text: _shipment != null ? _shipment!.cutoffDate != null ? dateFormatter.format(_shipment!.cutoffDate!) : "" : "", labelTextKey: "FCSshipment.cutoff_date", )), Flexible( child: DisplayText( text: _shipment != null ? _shipment!.etaDate != null ? dateFormatter.format(_shipment!.etaDate!) : "" : "", labelTextKey: "FCSshipment.ETA", )), ], ) ], ), ), ) ], ), ); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: LocalAppBar( titleWidget: Column( children: [ LocalText(context, "box.info.title", fontSize: 20, color: primaryColor), Text(_carton.cartonNumber ?? '', style: TextStyle(fontSize: 15, color: Colors.black)) ], ), backgroundColor: Colors.white, labelColor: primaryColor, arrowColor: primaryColor, actions: [ cartonQrBox, _carton.status == carton_packed_status ? IconButton( icon: Icon(Icons.edit, color: primaryColor), onPressed: _gotoEditor) : const SizedBox(), ]), body: Container( padding: const EdgeInsets.only(left: 20, right: 20), child: ListView(children: [ Row( children: [ Flexible(child: cartonTypeBox), ], ), fromPackage ? userRowBox : const SizedBox(), fromPackage ? Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible(child: billInfoBox), Flexible(child: lastMileBox), ], ) : const SizedBox(), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Flexible(child: cartonSizeBox), _packages.isEmpty ? const SizedBox() : Flexible(child: packageLengthBox), ], ), fromPackage ? const SizedBox() : _mixCartons.isEmpty ? const SizedBox() : mixCartonLengthBox, shipmentBox, // _packages.isEmpty // ? const SizedBox() // : Padding( // padding: const EdgeInsets.only(top: 15), // child: Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // LocalText(context, "box.package", // color: Colors.black54, fontSize: 15), // const SizedBox(height: 5), // Column( // children: getPackageList(_packages), // ), // ], // ), // ), // _mixCartons.isEmpty // ? const SizedBox() // : Padding( // padding: const EdgeInsets.only(top: 15), // child: Column( // crossAxisAlignment: CrossAxisAlignment.start, // children: [ // LocalText(context, "box.shipment.boxes", // color: Colors.black54, fontSize: 15), // const SizedBox(height: 5), // Column(children: getCartonList(_mixCartons)), // ], // ), // ), cargosBox, _surchareItems.isNotEmpty ? surchargeItemBox : const SizedBox(), const SizedBox(height: 10), uploadImageBtn, _carton.photoUrls.isNotEmpty ? const SizedBox(height: 10) : const SizedBox(), img, _carton.photoUrls.isNotEmpty ? const SizedBox(height: 40) : const SizedBox(), _carton.status == carton_packed_status ? deleteBtn : const SizedBox(), const SizedBox(height: 20) ])))); } List getPackageList(List list) { return list.map((p) { return Container( padding: EdgeInsets.only(top: 0), child: Row(children: [Text(p.trackingID ?? "")])); }).toList(); } List getCartonList(List list) { return list.map((c) { return Container( padding: EdgeInsets.only(top: 0), child: Row(children: [Text(c.cartonNumber ?? '')])); }).toList(); } _gotoEditor() async { bool? updated = false; if (_carton.cartonType == mix_carton) { updated = await Navigator.push( context, CupertinoPageRoute( builder: (context) => MixCartonEditor(carton: _carton)), ); } if (_carton.cartonType == carton_from_packages) { updated = await Navigator.push( context, CupertinoPageRoute( builder: (context) => CartonPackageEditor(carton: _carton)), ); } if (updated ?? false) { Carton? c = await context.read().getCarton(widget.carton.id ?? ""); if (c == null) return; _carton = c; _init(); } } _delete() { showConfirmDialog(context, "box.delete.confirm", () { _deleteCarton(); }); } _deleteCarton() async { setState(() { _isLoading = true; }); try { await context.read().deleteCarton(widget.carton); Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } }