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/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/localization/app_translations.dart'; import 'package:fcs/pages/carton/carton_cargo_table.dart'; import 'package:fcs/pages/carton/carton_mix_table.dart'; import 'package:fcs/pages/carton/carton_package_table.dart'; import 'package:fcs/pages/delivery_address/delivery_address_row.dart'; import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; import 'package:fcs/pages/main/model/language_model.dart'; import 'package:fcs/pages/main/model/main_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/bottom_up_page_route.dart'; import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/delivery_address_selection.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/my_data_table.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_editor.dart'; import 'model/carton_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; @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); } else { _carton = Carton(cargoTypes: [], packages: [], cartons: []); _lengthController.text = "12"; _widthController.text = "12"; _heightController.text = "12"; _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); 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; } }); setState(() { _carton.packages = packages; }); _populateDeliveryAddress(); } _loadCartons() async { if (_fcsShipment == null) return; CartonModel cartonModel = Provider.of(context, listen: false); List cartons = await cartonModel.getCartonsByFcsShipment(_fcsShipment.id); cartons.forEach((c) { c.isChecked = true; }); setState(() { _carton.cartons = cartons; }); } _populateDeliveryAddress() { if (_carton.packages == null) return; var d = _carton.packages .firstWhere((p) => p.isChecked && p.deliveryAddress != null, orElse: () => null) ?.deliveryAddress; setState(() { _deliveryAddress = d; }); } _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; final shipmentBox = DisplayText( text: _carton.fcsShipmentNumber, labelTextKey: "box.fcs_shipment_num", iconData: Ionicons.ios_airplane, ); var fcsShipmentsBox = LocalDropdown( callback: (v) { setState(() { _fcsShipment = v; }); if (_selectedCartonType == carton_mix_box) { _loadCartons(); } }, labelKey: "shipment.pack.fcs.shipment", iconData: Ionicons.ios_airplane, display: (u) => u.shipmentNumber, selectedValue: _fcsShipment, values: _fcsShipments, ); final fcsIDBox = 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", ); final widthBox = LengthPicker( controller: _widthController, lableKey: "box.width", ); final heightBox = LengthPicker( controller: _heightController, lableKey: "box.height", ); 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(0) : "", 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) { print(v); setState(() { _selectedCartonType = v; }); if (_selectedCartonType == carton_mix_box) { _loadCartons(); } }); 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); }), ); 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: () => 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, ...(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, LocalTitle(textKey: "box.dimension"), dimBox, shipmentWeightBox, LocalTitle(textKey: "box.delivery_address"), DefaultDeliveryAddress( deliveryAddress: _deliveryAddress, labelKey: "box.delivery_address", ), ]), _isNew ? createBtn : saveBtn, SizedBox( height: 20, ), ], ), ), ), ); } 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 { if (_user == null) { 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) { 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) { showMsgDialog(context, "Error", "Invalid dimension"); return; } if (_deliveryAddress == null) { showMsgDialog(context, "Error", "Invalid delivery address"); 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.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; }); } } }