import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/carton_size.dart'; import 'package:fcs/domain/entities/fcs_shipment.dart'; import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/carton_cargo_table.dart'; import 'package:fcs/pages/carton/carton_package_table.dart'; import 'package:fcs/pages/carton_size/carton_size_list.dart'; import 'package:fcs/pages/delivery_address/delivery_address_list.dart'; import 'package:fcs/pages/delivery_address/delivery_address_row.dart'; import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; import 'package:fcs/pages/user_search/user_serach.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/length_picker.dart'; import 'package:fcs/pages/widgets/local_button.dart'; import 'package:fcs/pages/widgets/local_dropdown.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/progress.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:provider/provider.dart'; import 'cargo_type_addtion.dart'; import 'cargo_type_editor.dart'; import 'model/carton_model.dart'; import '../carton_size/model/carton_size_model.dart'; import 'widgets.dart'; class CartonEditor extends StatefulWidget { final Carton box; CartonEditor({this.box}); @override _CartonEditorState createState() => _CartonEditorState(); } class _CartonEditorState extends State { TextEditingController _widthController = new TextEditingController(); TextEditingController _heightController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController(); Carton _carton; bool _isLoading = false; bool _isNew; DeliveryAddress _deliveryAddress = new DeliveryAddress(); User _user; String _selectedCartonType; double volumetricRatio = 0; double shipmentWeight = 0; FcsShipment _fcsShipment; List _fcsShipments; Carton _mixCarton; List _mixCartons; @override void initState() { super.initState(); //for shipment weight volumetricRatio = Provider.of(context, listen: false) .rate .volumetricRatio; _lengthController.addListener(_calShipmentWeight); _widthController.addListener(_calShipmentWeight); _heightController.addListener(_calShipmentWeight); if (widget.box != null) { _carton = widget.box; _deliveryAddress = _carton.deliveryAddress; _widthController.text = _carton.width.toString(); _heightController.text = _carton.height.toString(); _lengthController.text = _carton.length.toString(); _selectedCartonType = _carton.cartonType; _isNew = false; _user = User(fcsID: _carton.fcsID, name: _carton.userName); _loadPackages(); } else { _carton = Carton( cargoTypes: [], packages: [], ); _lengthController.text = ""; _widthController.text = ""; _heightController.text = ""; _isNew = true; _selectedCartonType = carton_from_packages; _loadFcsShipments(); } } _loadFcsShipments() async { FcsShipmentModel fcsShipmentModel = Provider.of(context, listen: false); var fcsShipments = await fcsShipmentModel.getActiveFcsShipments(); var fcsShipment = fcsShipments .firstWhere((e) => e.id == _carton.fcsShipmentID, orElse: () => null); setState(() { _fcsShipments = fcsShipments; _fcsShipment = fcsShipment; }); } _loadPackages() async { if (_user == null) return; PackageModel packageModel = Provider.of(context, listen: false); List packages = await packageModel.getPackages( _user.id, [package_processed_status, package_packed_status]); if (_isNew) { String prevCompare; packages.forEach((p) { String compare = (p.deliveryAddress?.fullName ?? "") + (p.deliveryAddress?.phoneNumber ?? ""); if (prevCompare != null && compare == prevCompare) { p.isChecked = true; } else { p.isChecked = false; } if (prevCompare == null) { p.isChecked = true; prevCompare = compare; } }); } else { packages.forEach((p) { if (_carton.packages.contains(p)) { p.isChecked = _carton.packages.firstWhere((cp) => cp == p).isChecked; } else { p.isChecked = false; } }); } setState(() { _carton.packages = packages; }); _populateDeliveryAddress(); } _populateDeliveryAddress() { if (_carton.packages == null) return; var d = _carton.packages .firstWhere((p) => p.isChecked && p.deliveryAddress != null, orElse: () => null) ?.deliveryAddress; setState(() { _deliveryAddress = d; }); } _loadMixCartons() async { if (_fcsShipment == null || _fcsShipment.id == null) return; if (_selectedCartonType != carton_small_bag) return; CartonModel cartonModel = Provider.of(context, listen: false); List cartons = await cartonModel.getMixCartonsByFcsShipment(_fcsShipment.id); setState(() { _mixCartons = cartons; }); } _calShipmentWeight() { double l = double.parse(_lengthController.text, (s) => 0); double w = double.parse(_widthController.text, (s) => 0); double h = double.parse(_heightController.text, (s) => 0); setState(() { shipmentWeight = l * w * h / volumetricRatio; }); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { var boxModel = Provider.of(context); bool isMixBox = _selectedCartonType == carton_mix_box; bool isSmallBag = _selectedCartonType == carton_small_bag; final shipmentBox = DisplayText( text: _carton.fcsShipmentNumber, labelTextKey: "box.fcs_shipment_num", iconData: Ionicons.ios_airplane, ); final mixCartonNumberBox = DisplayText( text: _carton.mixCartonNumber, labelTextKey: "box.mix.carton", iconData: MaterialCommunityIcons.package, ); var fcsShipmentsBox = Container( padding: EdgeInsets.only(top: 10), child: LocalDropdown( callback: (v) { setState(() { _fcsShipment = v; }); _loadMixCartons(); }, labelKey: "shipment.pack.fcs.shipment", iconData: Ionicons.ios_airplane, display: (u) => u.shipmentNumber, selectedValue: _fcsShipment, values: _fcsShipments, )); var mixCartonsBox = Container( padding: EdgeInsets.only(top: 10), child: LocalDropdown( callback: (v) { setState(() { _mixCarton = v; }); }, labelKey: "box.mix.carton", iconData: MaterialCommunityIcons.package, display: (u) => u.cartonNumber, selectedValue: _mixCarton, values: _mixCartons, )); final fcsIDBox = Container( padding: EdgeInsets.only(top: 10), child: Row( children: [ Expanded( child: DisplayText( text: _user?.fcsID ?? "", labelTextKey: "box.fcs.id", icon: FcsIDIcon(), )), _isNew ? IconButton( icon: Icon(Icons.search, color: primaryColor), onPressed: () => searchUser(context, callbackUserSelect: (u) { setState(() { this._user = u; _loadPackages(); }); })) : Container(), ], )); final namebox = DisplayText( text: _user?.name ?? "", labelTextKey: "box.name", iconData: Icons.person, ); final lengthBox = LengthPicker( controller: _lengthController, lableKey: "box.length", isReadOnly: true, ); final widthBox = LengthPicker( controller: _widthController, lableKey: "box.width", isReadOnly: true, ); final heightBox = LengthPicker( controller: _heightController, lableKey: "box.height", isReadOnly: true, ); final dimBox = Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(right: 8.0), child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), ), SizedBox(child: lengthBox, width: 80), SizedBox(child: widthBox, width: 80), SizedBox(child: heightBox, width: 80), ], ); final shipmentWeightBox = DisplayText( text: shipmentWeight != null ? shipmentWeight.toStringAsFixed(2) : "", labelTextKey: "box.shipment_weight", iconData: MaterialCommunityIcons.weight, ); final createBtn = LocalButton( textKey: "box.create.btn", callBack: _save, ); final saveBtn = LocalButton( textKey: "box.cargo.save.btn", callBack: _save, ); final cartonTypeBox = LocalRadioButtons( readOnly: !_isNew, values: boxModel.cartonTypes, selectedValue: _selectedCartonType, callback: (v) { setState(() { _selectedCartonType = v; }); }); final cargoTableTitleBox = LocalTitle( textKey: "box.cargo.type", trailing: IconButton( icon: Icon( Icons.add_circle, color: primaryColor, ), onPressed: () async { // CargoType cargo = await Navigator.push(context, // CupertinoPageRoute(builder: (context) => CargoTypeEditor())); // _addCargo(cargo); List cargos = await Navigator.push>( context, CupertinoPageRoute(builder: (context) => CargoTypeAddition())); if (cargos == null) return; setState(() { _carton.cargoTypes.clear(); _carton.cargoTypes.addAll(cargos); }); }), ); final cargoTableBox = CargoTable( cargoTypes: _carton.cargoTypes, onAdd: (c) => _addCargo(c), onRemove: (c) => _removeCargo(c), ); return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( centerTitle: true, leading: new IconButton( icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () { showConfirmDialog(context, "back.button_confirm", () { Navigator.of(context).pop(); }); }, ), shadowColor: Colors.transparent, backgroundColor: Colors.white, title: _isNew ? LocalText( context, "boxes.create.title", fontSize: 20, color: primaryColor, ) : LocalText( context, "box.edit.title", fontSize: 20, color: primaryColor, ), ), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( shrinkWrap: true, children: [ _isNew ? Container() : Center(child: getCartonNumberStatus(context, _carton)), LocalTitle(textKey: "box.type.title"), cartonTypeBox, LocalTitle(textKey: "box.shipment_info"), _isNew ? fcsShipmentsBox : shipmentBox, isSmallBag ? _isNew ? mixCartonsBox : mixCartonNumberBox : Container(), ...(isMixBox ? [ // CartonMixTable( // cartons: _carton.cartons, // onSelect: (c, check) { // setState(() { // c.isChecked = check; // }); // }, // ) ] : [ fcsIDBox, namebox, CartonPackageTable( packages: _carton.packages, onSelect: (p, checked) { if (checked && _deliveryAddress != null && p.deliveryAddress?.id != _deliveryAddress.id) { return; } setState(() { p.isChecked = checked; }); _populateDeliveryAddress(); }, ), cargoTableTitleBox, cargoTableBox, isSmallBag ? Container() : LocalTitle(textKey: "box.dimension"), isSmallBag ? Container() : cartonSizeDropdown(), isSmallBag ? Container() : dimBox, isSmallBag ? Container() : shipmentWeightBox, LocalTitle(textKey: "box.delivery_address"), DefaultDeliveryAddress( deliveryAddress: _deliveryAddress, labelKey: "box.delivery_address", onTap: () async { DeliveryAddress _address = await Navigator.push( context, CupertinoPageRoute( builder: (context) => DeliveryAddressList( isAdminCreation: true, deliveryAddress: _deliveryAddress))); if (_address == null) return; setState(() { _deliveryAddress = _address; }); }, ), ]), _isNew ? createBtn : saveBtn, SizedBox( height: 20, ), ], ), ), ), ); } CartonSize selectedCatonSize; Widget cartonSizeDropdown() { List _cartonSizes = Provider.of(context).getCartonSizes; return Padding( padding: const EdgeInsets.only(top: 10), child: Row( children: [ Padding( padding: const EdgeInsets.only(left: 0, right: 10), child: Icon(AntDesign.CodeSandbox, color: primaryColor), ), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.only(right: 18.0), child: LocalText( context, "box.carton_size", color: Colors.black54, fontSize: 16, ), ), DropdownButton( isDense: true, value: selectedCatonSize, style: TextStyle(color: Colors.black, fontSize: 14), underline: Container( height: 1, color: Colors.grey, ), onChanged: (CartonSize newValue) { setState(() { if (newValue.name == MANAGE_CARTONSIZE) { selectedCatonSize = null; _manageCartonSize(); return; } selectedCatonSize = newValue; _widthController.text = selectedCatonSize.width.toString(); _heightController.text = selectedCatonSize.height.toString(); _lengthController.text = selectedCatonSize.length.toString(); }); }, isExpanded: true, items: _cartonSizes .map>((CartonSize value) { return DropdownMenuItem( value: value, child: Text(value.name ?? "", overflow: TextOverflow.ellipsis, style: TextStyle( color: value.name == MANAGE_CARTONSIZE ? secondaryColor : primaryColor)), ); }).toList(), ), ], ), ), ], ), ); } _manageCartonSize() { Navigator.push( context, CupertinoPageRoute(builder: (context) => CartonSizeList()), ); } List getAddressList( BuildContext context, List addresses) { return addresses.asMap().entries.map((s) { return InkWell( onTap: () {}, child: DeliveryAddressRow(deliveryAddress: s.value), ); }).toList(); } _addCargo(CargoType cargo) { if (cargo == null) return; setState(() { _carton.cargoTypes.remove(cargo); _carton.cargoTypes.add(cargo); }); } _removeCargo(CargoType cargo) { setState(() { _carton.cargoTypes.remove(cargo); }); } _save() async { bool isFromShipment = _selectedCartonType == carton_from_shipments; bool isSmallBag = _selectedCartonType == carton_small_bag; if (_user == null && (isFromShipment || isSmallBag)) { showMsgDialog(context, "Error", "Please select customer"); return; } if (_fcsShipment == null && _isNew) { showMsgDialog(context, "Error", "Please select FCS shipment"); return; } if ((_carton.cargoTypes?.length ?? 0) == 0 && (isFromShipment || isSmallBag)) { showMsgDialog(context, "Error", "Expect at least one cargo type"); return; } double l = double.parse(_lengthController.text, (s) => 0); double w = double.parse(_widthController.text, (s) => 0); double h = double.parse(_heightController.text, (s) => 0); if ((l <= 0 || w <= 0 || h <= 0) && isFromShipment) { showMsgDialog(context, "Error", "Invalid dimension"); return; } if (_deliveryAddress == null && (isFromShipment || isSmallBag)) { showMsgDialog(context, "Error", "Invalid delivery address"); return; } if (isSmallBag && _mixCarton == null && _isNew) { showMsgDialog(context, "Error", "Invalid mix carton"); return; } Carton carton = Carton(); carton.id = _carton.id; carton.cartonType = _selectedCartonType; carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; carton.userID = _user?.id; carton.cargoTypes = _carton.cargoTypes; carton.packages = _carton.packages.where((e) => e.isChecked).toList(); carton.mixCartonID = _mixCarton?.id; carton.length = l; carton.width = w; carton.height = h; carton.deliveryAddress = _deliveryAddress; setState(() { _isLoading = true; }); try { CartonModel cartonModel = Provider.of(context, listen: false); if (_isNew) { await cartonModel.createCarton(carton); } else { await cartonModel.updateCarton(carton); } Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { setState(() { _isLoading = false; }); } } }