diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 94d7a24..bcd6c40 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -275,7 +275,7 @@ "box.packages":"Packages", "box.tracking.id":"Tracking ID", "box.market":"Market", - "box.cargo.save.btn":"Save", + "box.cargo.save.btn":"Select", "box.type.title":"Carton types", "box.shipment.boxes":"Cartons", "box.shipment_number":"Shipment number", @@ -300,6 +300,7 @@ "box.min_caton.form.title":"Mix Carton", "box.mix_carton_btn":"Create mix carton", "box.mix_type":"Mix Box Types", + "box.selection":"Carton Selection", "Boxes End ================================================================":"", "Delivery Start ================================================================":"", diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index 29ffefc..929b177 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -275,7 +275,7 @@ "box.packages":"အထုပ်များ", "box.tracking.id":"Tracking ID", "box.market":"အွန်လိုင်စျေးဆိုင်", - "box.cargo.save.btn":"သိမ်းဆည်းမည်", + "box.cargo.save.btn":"ရွေးမည်", "box.type.title":"သေတ္တာအမျိုးအစားများ", "box.shipment.boxes":"သေတ္တာများ", "box.shipment_number":"ပို့ဆောင်နံပါတ်", @@ -300,6 +300,7 @@ "box.min_caton.form.title":"Mix Carton", "box.mix_carton_btn":"Create mix carton", "box.mix_type":"Mix Box Types", + "box.selection":"သေတ္တာ ရွေးချယ်ခြင်း", "Boxes End ================================================================":"", "Delivery Start ================================================================":"", diff --git a/lib/data/provider/carton_data_provider.dart b/lib/data/provider/carton_data_provider.dart index f2457f5..54c4117 100644 --- a/lib/data/provider/carton_data_provider.dart +++ b/lib/data/provider/carton_data_provider.dart @@ -1,5 +1,8 @@ import 'dart:async'; +import 'dart:convert'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/helpers/api_helper.dart'; import 'package:fcs/helpers/firebase_helper.dart'; @@ -11,9 +14,10 @@ class CartonDataProvider { static final CartonDataProvider instance = CartonDataProvider._(); CartonDataProvider._(); - Future createCarton(Carton carton) async { - return await requestAPI("/cartons", "POST", + Future createCarton(Carton carton) async { + var data = await requestAPI("/cartons", "POST", payload: carton.toMap(), token: await getToken()); + return Carton.fromMap(data, data['id']); } Future updateCarton(Carton carton) async { @@ -30,4 +34,32 @@ class CartonDataProvider { return await requestAPI("/cartons/deliver", "PUT", payload: carton.toMap(), token: await getToken()); } + + Future> searchCarton(String term) async { + if (term == null || term == '') return List(); + + // var bytes = utf8.encode(term); + // var base64Str = base64.encode(bytes); + // HtmlEscape htmlEscape = const HtmlEscape(); + // String escapeBuyer = htmlEscape.convert(base64Str); + + try { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("carton_number", isEqualTo: term) + .where("carton_type", + whereIn: [carton_from_packages, carton_from_cargos]) + .where("status", isEqualTo: carton_packed_status) + .where("is_deleted", isEqualTo: false) + .orderBy("user_name") + .getDocuments(); + return querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + } catch (e) { + log.warning("carton error:" + e.toString()); + return null; + } + } } diff --git a/lib/data/provider/rate_data_provider.dart b/lib/data/provider/rate_data_provider.dart index c01e863..c8c416e 100644 --- a/lib/data/provider/rate_data_provider.dart +++ b/lib/data/provider/rate_data_provider.dart @@ -36,6 +36,7 @@ class RateDataProvider { .collection(config_collection) .document(rate_doc_id) .collection(cargo_types_collection) + .where("custom_duty", isEqualTo: false) .snapshots(); await for (var snaps in snapshots) { @@ -48,18 +49,19 @@ class RateDataProvider { } } - Stream> _customDutiesStream() async* { - List customDuries = []; + Stream> _customDutiesStream() async* { + List customDuries = []; Stream snapshots = Firestore.instance .collection(config_collection) .document(rate_doc_id) - .collection(custom_duties_collection) + .collection(cargo_types_collection) + .where("custom_duty", isEqualTo: true) .snapshots(); await for (var snaps in snapshots) { customDuries = []; customDuries = snaps.documents.map((snap) { - return CustomDuty.fromMap(snap.data, snap.documentID); + return CargoType.fromMap(snap.data, snap.documentID); }).toList(); yield customDuries; } @@ -84,7 +86,7 @@ class RateDataProvider { StreamSubscription rateListener; StreamSubscription> cargoListener; - StreamSubscription> customListener; + StreamSubscription> customListener; StreamSubscription> discountListener; Stream rate() { Future _start() async { diff --git a/lib/data/services/carton_imp.dart b/lib/data/services/carton_imp.dart index 6eef25d..ba97084 100644 --- a/lib/data/services/carton_imp.dart +++ b/lib/data/services/carton_imp.dart @@ -15,7 +15,7 @@ class CartonServiceImp implements CartonService { final CartonDataProvider cartonDataProvider; @override - Future createCarton(Carton carton) { + Future createCarton(Carton carton) { return cartonDataProvider.createCarton(carton); } @@ -33,4 +33,9 @@ class CartonServiceImp implements CartonService { Future deliver(Carton carton) { return cartonDataProvider.deliver(carton); } + + @override + Future> searchCarton(String term) { + return cartonDataProvider.searchCarton(term); + } } diff --git a/lib/data/services/carton_service.dart b/lib/data/services/carton_service.dart index 45dde91..1137373 100644 --- a/lib/data/services/carton_service.dart +++ b/lib/data/services/carton_service.dart @@ -1,8 +1,9 @@ import 'package:fcs/domain/entities/carton.dart'; abstract class CartonService { - Future createCarton(Carton carton); + Future createCarton(Carton carton); Future updateCarton(Carton carton); Future deleteCarton(Carton carton); Future deliver(Carton carton); + Future> searchCarton(String term); } diff --git a/lib/domain/constants.dart b/lib/domain/constants.dart index 69ab4fc..9d1019e 100644 --- a/lib/domain/constants.dart +++ b/lib/domain/constants.dart @@ -78,6 +78,7 @@ const shipment_courier_dropoff = "Courier drop off"; //Carton types const carton_from_packages = "From packages"; +const carton_from_cargos="From cargos"; const carton_from_shipments = "From shipments"; const carton_mix_carton = "Mix carton"; const carton_small_bag = "Small bag"; diff --git a/lib/domain/entities/cargo_type.dart b/lib/domain/entities/cargo_type.dart index 76ccfe2..68ec494 100644 --- a/lib/domain/entities/cargo_type.dart +++ b/lib/domain/entities/cargo_type.dart @@ -5,23 +5,13 @@ class CargoType { double weight; bool isChecked; int qty; - bool isCutomDuty = false; + bool isCutomDuty; + double customDutyFee; double get calAmount => (calRate ?? 0) * (calWeight ?? 0); double calRate; double calWeight; - - factory CargoType.fromMap(Map map, String id) { - return CargoType( - id: id, - name: map['name'], - rate: map['rate']?.toDouble() ?? 0, - weight: map['weight']?.toDouble() ?? 0, - calWeight: map['cal_weight']?.toDouble() ?? 0, - calRate: map['cal_rate']?.toDouble() ?? 0, - ); - } CargoType( {this.id, this.name, @@ -31,7 +21,21 @@ class CargoType { this.calRate, this.isChecked = false, this.qty = 0, - this.isCutomDuty = false}); + this.isCutomDuty, + this.customDutyFee}); + + factory CargoType.fromMap(Map map, String id) { + return CargoType( + id: id, + name: map['name'], + rate: map['rate']?.toDouble() ?? 0, + weight: map['weight']?.toDouble() ?? 0, + calWeight: map['cal_weight']?.toDouble() ?? 0, + calRate: map['cal_rate']?.toDouble() ?? 0, + isCutomDuty: map['custom_duty'] ?? false, + customDutyFee: (map['custom_duty_fee'] ?? 0).toDouble(), + qty: (map['qty'] ?? 0).toInt()); + } Map toMap() { return { @@ -41,6 +45,9 @@ class CargoType { 'weight': weight, 'cal_weight': calWeight, 'cal_rate': calRate, + 'custom_duty': isCutomDuty, + 'custom_duty_fee': customDutyFee, + 'qty': qty }; } @@ -62,4 +69,10 @@ class CargoType { bool isChangedForEdit(CargoType cargoType) { return cargoType.name != this.name || cargoType.rate != this.rate; } + + bool isChangedForEditCustomDuty(CargoType cargoType) { + return cargoType.name != this.name || + cargoType.customDutyFee != this.customDutyFee || + cargoType.rate != this.rate; + } } diff --git a/lib/domain/entities/carton.dart b/lib/domain/entities/carton.dart index 7115129..7526b9b 100644 --- a/lib/domain/entities/carton.dart +++ b/lib/domain/entities/carton.dart @@ -12,8 +12,10 @@ class Carton { String id; String shipmentID; String shipmentNumber; + String senderID; String senderFCSID; String senderName; + String receiverID; String receiverFCSID; String receiverName; String receiverAddress; @@ -38,7 +40,6 @@ class Carton { String mixCartonNumber; String cartonSizeID; String cartonSizeName; - String mixBoxType; int rate; int weight; @@ -56,6 +57,11 @@ class Carton { DeliveryAddress deliveryAddress; Shipment shipment; + //for mix box + String mixBoxType; + List mixCartons; + List mixCartonIDs; + int get amount => rate != null && weight != null ? rate * weight : 0; String get packageNumber => @@ -74,7 +80,7 @@ class Carton { height <= 0 || volumetricRatio == null || volumetricRatio <= 0) return 0; - + return ((length * width * height) / volumetricRatio).round(); } @@ -126,8 +132,10 @@ class Carton { {this.id, this.shipmentID, this.shipmentNumber, + this.senderID, this.senderFCSID, this.senderName, + this.receiverID, this.receiverFCSID, this.receiverName, this.receiverNumber, @@ -164,13 +172,16 @@ class Carton { this.deliveryAddress, this.cartonSizeID, this.cartonSizeName, - this.mixBoxType}); + this.mixBoxType, + this.mixCartons, + this.mixCartonIDs}); Map toMap() { - List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); + List _cargoTypes = cargoTypes?.map((c) => c.toMap())?.toList() ?? []; List _packages = packages?.map((c) => c.toJson())?.toList(); + List _mixCartons = mixCartons?.map((c) => c.toJson())?.toList(); return { - "id": id, + 'id': id, 'fcs_shipment_id': fcsShipmentID, 'user_id': userID, 'cargo_types': _cargoTypes, @@ -181,6 +192,14 @@ class Carton { 'delivery_address': deliveryAddress?.toMap(), 'carton_type': cartonType, 'mix_carton_id': mixCartonID, + 'mix_box_type': mixBoxType, + 'mix_cartons': _mixCartons, + 'receiver_id': receiverID, + 'receiver_fcs_id': receiverFCSID, + 'receiver_name': receiverName, + 'sender_id': senderID, + 'sender_fcs_id': senderFCSID, + 'sender_name': senderName }; } @@ -192,30 +211,72 @@ class Carton { List>.from(map['cargo_types'] ?? []); var cargoTypes = cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList(); + var mixCartonsMaps = + List>.from(map['mix_cartons'] ?? []); + var _mixCartons = + mixCartonsMaps.map((e) => Carton.fromMap(e, e["id"])).toList(); + return Carton( - id: docID, - arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null, - shipmentID: map['shipment_id'], - shipmentNumber: map['shipment_number'], - receiverNumber: map['receiver_number'], - boxNumber: map['box_number'], - length: map['length'], - width: map['width'], - height: map['height'], - userName: map['user_name'], - fcsID: map['fcs_id'], - cartonType: map['carton_type'], - cartonNumber: map['carton_number'], - userID: map['user_id'], - fcsShipmentID: map['fcs_shipment_id'], - fcsShipmentNumber: map['fcs_shipment_number'], - isShipmentCarton: map['is_shipment_carton'], - mixCartonID: map['mix_carton_id'], - mixCartonNumber: map['mix_carton_number'], - status: map['status'], - packageIDs: List.from(map['package_ids'] ?? []), - deliveryAddress: _da, - cargoTypes: cargoTypes); + id: docID, + arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null, + shipmentID: map['shipment_id'], + shipmentNumber: map['shipment_number'], + receiverNumber: map['receiver_number'], + boxNumber: map['box_number'], + length: double.tryParse(map['length']?.toString()), + width: double.tryParse(map['width']?.toString()), + height: double.tryParse(map['height']?.toString()), + userName: map['user_name'], + fcsID: map['fcs_id'], + cartonType: map['carton_type'], + cartonNumber: map['carton_number'], + userID: map['user_id'], + fcsShipmentID: map['fcs_shipment_id'], + fcsShipmentNumber: map['fcs_shipment_number'], + isShipmentCarton: map['is_shipment_carton'], + mixCartonID: map['mix_carton_id'], + mixCartonNumber: map['mix_carton_number'], + status: map['status'], + packageIDs: List.from(map['package_ids'] ?? []), + deliveryAddress: _da, + cargoTypes: cargoTypes, + mixBoxType: map['mix_box_type'], + mixCartons: _mixCartons, + receiverID: map['receiver_id'], + receiverFCSID: map['receiver_fcs_id'], + receiverName: map['receiver_name'], + senderID: map['sender_id'], + senderFCSID: map['sender_fcs_id'], + senderName: map['sender_name'], + mixCartonIDs: List.from(map['mix_carton_ids'] ?? []), + ); + } + + Map toJson() { + List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); + List _packages = packages?.map((c) => c.toJson())?.toList(); + List _mixCartons = mixCartons?.map((c) => c.toJson())?.toList(); + return { + 'id': id, + 'fcs_shipment_id': fcsShipmentID, + 'user_id': userID, + 'cargo_types': _cargoTypes, + 'packages': _packages, + 'length': length, + 'width': width, + 'height': height, + 'delivery_address': deliveryAddress?.toMap(), + 'carton_type': cartonType, + 'mix_carton_id': mixCartonID, + 'mix_box_type': mixBoxType, + 'mix_cartons': _mixCartons, + 'receiver_id': receiverID, + 'receiver_fcs_id': receiverFCSID, + 'receiver_name': receiverName, + 'sender_id': senderID, + 'sender_fcs_id': senderFCSID, + 'sender_name': senderName + }; } @override diff --git a/lib/domain/entities/carton_size.dart b/lib/domain/entities/carton_size.dart index 2587bdf..7d9f494 100644 --- a/lib/domain/entities/carton_size.dart +++ b/lib/domain/entities/carton_size.dart @@ -26,6 +26,21 @@ class CartonSize { ); } + @override + bool operator ==(other) { + if (identical(this, other)) { + return true; + } + return other.id == this.id; + } + + @override + int get hashCode { + int result = 17; + result = 37 * result + id.hashCode; + return result; + } + bool isChangedForEdit(CartonSize cartonSize) { return cartonSize.name != this.name || cartonSize.length != this.length || diff --git a/lib/domain/entities/package.dart b/lib/domain/entities/package.dart index 5365350..114e787 100644 --- a/lib/domain/entities/package.dart +++ b/lib/domain/entities/package.dart @@ -138,6 +138,14 @@ class Package { package.fcsID != this.fcsID; } + bool isChangedForEditProcessing(Package package) { + return package.trackingID != this.trackingID || + package.fcsID != this.fcsID || + package.market != this.market || + package.desc != this.desc || + package.remark != this.remark; + } + @override bool operator ==(Object other) => other is Package && other.id == id; diff --git a/lib/domain/entities/rate.dart b/lib/domain/entities/rate.dart index 3dadb79..f5682e1 100644 --- a/lib/domain/entities/rate.dart +++ b/lib/domain/entities/rate.dart @@ -1,4 +1,4 @@ -import 'package:fcs/domain/entities/custom_duty.dart'; + import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'cargo_type.dart'; @@ -12,7 +12,7 @@ class Rate { double diffWeightRate; List cargoTypes; - List customDuties; + List customDuties; List discountByWeights; DiscountByWeight getDiscountByWeight(double weight) { diff --git a/lib/domain/vo/delivery_address.dart b/lib/domain/vo/delivery_address.dart index a0c507e..93e7960 100644 --- a/lib/domain/vo/delivery_address.dart +++ b/lib/domain/vo/delivery_address.dart @@ -7,6 +7,7 @@ class DeliveryAddress { String state; String phoneNumber; bool isDefault; + String userID; DeliveryAddress( {this.id, this.fullName, @@ -15,6 +16,7 @@ class DeliveryAddress { this.city, this.state, this.phoneNumber, + this.userID, this.isDefault = false}); factory DeliveryAddress.fromMap(Map map, String docID) { @@ -39,6 +41,7 @@ class DeliveryAddress { 'city': city, 'state': state, 'phone_number': phoneNumber, + 'user_id': userID, }; } diff --git a/lib/pages/carton/cargo_type_addtion.dart b/lib/pages/carton/cargo_type_addtion.dart index 043c922..1c1e5a4 100644 --- a/lib/pages/carton/cargo_type_addtion.dart +++ b/lib/pages/carton/cargo_type_addtion.dart @@ -123,7 +123,7 @@ class _CargoTypeAdditionState extends State { color: primaryColor, ), onPressed: () async { - CustomDuty customDuty = await Navigator.of(context).push( + CargoType customDuty = await Navigator.of(context).push( CupertinoPageRoute( builder: (context) => CustomList(selected: true))); @@ -143,14 +143,20 @@ class _CargoTypeAdditionState extends State { ); } - _addCustom(CustomDuty customDuty) { + _addCustom(CargoType customDuty) { if (customDuty == null) return; - if (cargos.any((c) => c.name == customDuty.productType)) return; + if (cargos.any((c) => c.name == customDuty.name)) return; + + // setState(() { + // cargos.add(CargoType( + // name: customDuty.productType, isCutomDuty: true, qty: 1, weight: 0)); + // }); setState(() { - cargos.add(CargoType( - name: customDuty.productType, isCutomDuty: true, qty: 1, weight: 0)); + customDuty.qty = 1; + customDuty.isChecked = false; + cargos.add(customDuty); }); } } diff --git a/lib/pages/carton/carton_cargo_table.dart b/lib/pages/carton/carton_cargo_table.dart index ef0f495..67df836 100644 --- a/lib/pages/carton/carton_cargo_table.dart +++ b/lib/pages/carton/carton_cargo_table.dart @@ -238,10 +238,11 @@ class _CargoTableState extends State { child: InkWell( onTap: () async { String _t = await showDialog( - context: context, - builder: (_) => DialogInput( - label: "shipment.cargo.total", - value: totalWeight.toStringAsFixed(2))); + context: context, + builder: (_) => DialogInput( + label: "shipment.cargo.total", + value: totalWeight.toStringAsFixed(2)), + ); if (_t == null) return; setState(() { diff --git a/lib/pages/carton/carton_editor.dart b/lib/pages/carton/carton_editor.dart index 7d07175..2fe89aa 100644 --- a/lib/pages/carton/carton_editor.dart +++ b/lib/pages/carton/carton_editor.dart @@ -10,13 +10,17 @@ import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/carton_package_table.dart'; import 'package:fcs/pages/carton_search/carton_search.dart'; import 'package:fcs/pages/carton_size/carton_size_list.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/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/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'; @@ -27,9 +31,9 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:provider/provider.dart'; -import 'carton_list_row.dart'; +import 'cargo_type_addtion.dart'; +import 'carton_cargo_table.dart'; import 'carton_row.dart'; -import 'mix_carton_editor.dart'; import 'model/carton_model.dart'; import '../carton_size/model/carton_size_model.dart'; import 'package_carton_editor.dart'; @@ -47,21 +51,31 @@ class _CartonEditorState extends State { TextEditingController _widthController = new TextEditingController(); TextEditingController _heightController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController(); + List _deliveryAddresses = []; + DeliveryAddress _deliveryAddress = new DeliveryAddress(); + List _cargoTypes = []; Carton _carton; bool _isLoading = false; bool _isNew; - DeliveryAddress _deliveryAddress = new DeliveryAddress(); User _user; String _selectedCartonType; - String _selectedMixType; + double volumetricRatio = 0; double shipmentWeight = 0; FcsShipment _fcsShipment; List _fcsShipments; - Carton _mixCarton; List _cartons = []; + CartonSize selectedCatonSize; + + //for mix carton List _mixCartons = []; + String _selectedMixBoxType; + + //for carton from cargos + User consignee; + User sender; + List _cartonsForCargos = []; @override void initState() { @@ -82,9 +96,29 @@ class _CartonEditorState extends State { _heightController.text = _carton.height.toString(); _lengthController.text = _carton.length.toString(); _selectedCartonType = _carton.cartonType; + _cargoTypes = List.from(_carton.cargoTypes); _isNew = false; - _user = User(fcsID: _carton.fcsID, name: _carton.userName); - _loadPackages(); + _user = User( + id: _carton.userID, fcsID: _carton.fcsID, name: _carton.userName); + consignee = User( + id: _carton.receiverID, + fcsID: _carton.receiverFCSID, + name: _carton.receiverName); + sender = User( + id: _carton.senderID, + fcsID: _carton.senderID, + name: _carton.senderName); + _selectedMixBoxType = _carton.mixBoxType ?? ""; + this._mixCartons = + _carton.mixCartons == null ? [] : List.from(_carton.mixCartons); + bool isMixBox = _carton.cartonType == carton_mix_box; + bool isFromPackages = _carton.cartonType == carton_from_packages; + if (isFromPackages) _loadPackages(); + + if (!isMixBox) { + _getDeliverAddresses(); + _getCartonSize(); + } } else { _carton = Carton( cargoTypes: [], @@ -95,14 +129,8 @@ class _CartonEditorState extends State { _heightController.text = "0"; _isNew = true; _selectedCartonType = carton_from_packages; - _selectedMixType = mix_delivery; + _selectedMixBoxType = mix_delivery; _loadFcsShipments(); - _cartons = [Carton(cartonNumber: "A100B-1#3", userName: "Seven 7")]; - - _mixCartons = [ - Carton(cartonNumber: "A100B-1#1", userName: "Seven 7"), - Carton(cartonNumber: "A100B-1#2", userName: "Seven 7"), - ]; } } @@ -152,19 +180,19 @@ class _CartonEditorState extends State { setState(() { _carton.packages = packages; }); - _populateDeliveryAddress(); + // _populateDeliveryAddress(); } - _populateDeliveryAddress() { - if (_carton.packages == null) return; - var d = _carton.packages - .firstWhere((p) => p.isChecked && p.deliveryAddress != null, - orElse: () => null) - ?.deliveryAddress; - setState(() { - _deliveryAddress = d; - }); - } + // _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); @@ -175,6 +203,31 @@ class _CartonEditorState extends State { }); } + _getDeliverAddresses() async { + var addressModel = + Provider.of(context, listen: false); + bool isFromPackages = _carton.cartonType == carton_from_packages; + this._deliveryAddresses = isFromPackages + ? await addressModel.getDeliveryAddresses(_carton.userID) + : await addressModel.getDeliveryAddresses(_carton.receiverID); + } + + _getCartonSize() { + var cartonSizeModel = Provider.of(context, listen: false); + cartonSizeModel.cartonSizes.forEach((c) { + if (c.length == _carton.length && + c.width == _carton.width && + c.height == _carton.height) { + selectedCatonSize = CartonSize( + id: c.id, + name: c.name, + length: c.length, + width: c.width, + height: c.height); + } + }); + } + @override void dispose() { super.dispose(); @@ -183,6 +236,8 @@ class _CartonEditorState extends State { @override Widget build(BuildContext context) { var boxModel = Provider.of(context); + bool isFromPackages = _selectedCartonType == carton_from_packages; + bool isFromCargos = _selectedCartonType == carton_from_cargos; bool isMixBox = _selectedCartonType == carton_mix_box; final shipmentBox = DisplayText( @@ -219,13 +274,12 @@ class _CartonEditorState extends State { _isNew ? IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => - searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this._user = u; _loadPackages(); }); - })) + }, popPage: true)) : Container(), ], )); @@ -238,7 +292,9 @@ class _CartonEditorState extends State { final createBtn = LocalButton( textKey: "box.complete.packaging", - callBack: _save, + callBack: () { + Navigator.pop(context); + }, ); final saveBtn = LocalButton( @@ -264,54 +320,7 @@ class _CartonEditorState extends State { Icons.add_circle, color: primaryColor, ), - onPressed: () async { - bool isFromPackages = _selectedCartonType == carton_from_packages; - if (_user == null && isFromPackages) { - showMsgDialog(context, "Error", "Please select customer"); - return; - } - if (_fcsShipment == null && _isNew) { - showMsgDialog(context, "Error", "Please select FCS shipment"); - 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); - - Carton carton = Carton(); - carton.id = _carton.id; - carton.cartonType = _selectedCartonType; - carton.fcsShipmentID = - _isNew ? _fcsShipment.id : _carton.fcsShipmentID; - carton.userID = _user?.id; - carton.packages = - _carton.packages.where((e) => e.isChecked).toList(); - - carton.cargoTypes = _carton.cargoTypes; - carton.length = l; - carton.width = w; - carton.height = h; - - carton.deliveryAddress = _carton.deliveryAddress; - setState(() { - _isLoading = true; - }); - try { - Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => - PackageCartonEditor(carton: carton, isNew: _isNew)), - ); - } catch (e) { - showMsgDialog(context, "Error", e.toString()); - } finally { - setState(() { - _isLoading = false; - }); - } - }), + onPressed: _addCarton), ), ); @@ -330,16 +339,16 @@ class _CartonEditorState extends State { fontWeight: FontWeight.bold, )), Row( - children: boxModel.mixTypes.map((e) { + children: boxModel.mixBoxTypes.map((e) { return Row( children: [ Radio( value: e, - groupValue: _selectedMixType, + groupValue: _selectedMixBoxType, activeColor: primaryColor, onChanged: (v) { setState(() { - _selectedMixType = v; + _selectedMixBoxType = v; }); }, ), @@ -352,6 +361,36 @@ class _CartonEditorState extends State { ), ); + final mixTypeDisplayBox = Container( + padding: EdgeInsets.only(top: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + padding: EdgeInsets.only(left: 5), + child: LocalText( + context, + "box.mix_type", + color: primaryColor, + fontSize: 15, + fontWeight: FontWeight.bold, + )), + Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Icon( + Icons.check, + color: primaryColor, + ), + ), + Text(_selectedMixBoxType ?? "") + ], + ) + ], + ), + ); + final mixcartonTitleBox = Container( child: LocalTitle( textKey: "box.mix_caton_title", @@ -360,15 +399,140 @@ class _CartonEditorState extends State { Icons.add_circle, color: primaryColor, ), - onPressed: () { - Navigator.push( - context, - CupertinoPageRoute(builder: (context) => MixCartonEditor()), - ); + onPressed: () async { + searchCarton(context, callbackCartonSelect: (c) { + _addMixCarton(c); + }); }, ), ), ); + final cargoTableTitleBox = LocalTitle( + textKey: "box.cargo.type", + trailing: IconButton( + icon: Icon( + Icons.add_circle, + color: primaryColor, + ), + onPressed: () async { + List cargos = await Navigator.push>( + context, + CupertinoPageRoute(builder: (context) => CargoTypeAddition())); + if (cargos == null) return; + setState(() { + _cargoTypes.clear(); + _cargoTypes.addAll(cargos); + }); + }), + ); + + final cargoTableBox = CargoTable( + isNew: _isNew, + cargoTypes: _cargoTypes, + onAdd: (c) => _addCargo(c), + onRemove: (c) => _removeCargo(c), + ); + + 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 createMixCarton = LocalButton( + textKey: _isNew ? "box.mix_carton_btn" : "btn.save", + callBack: _creatMixCarton, + ); + + final consigneefcsIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: consignee != null ? consignee.fcsID : "", + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + )), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, onUserSelect: (u) { + setState(() { + this.consignee = u; + }); + }, popPage: true)), + ], + ); + + final consigneeNameBox = DisplayText( + text: consignee != null ? consignee.name : "", + labelTextKey: "processing.consignee.name", + maxLines: 2, + iconData: Icons.person, + ); + + final consigneeBox = Container( + child: Column( + children: [ + consigneefcsIDBox, + consigneeNameBox, + ], + ), + ); + + final shipperIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: sender != null ? sender.fcsID : "", + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + )), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, onUserSelect: (u) { + setState(() { + this.sender = u; + }); + }, popPage: true)), + ], + ); + + final shipperNamebox = DisplayText( + text: sender != null ? sender.name : "", + labelTextKey: "processing.shipper.name", + maxLines: 2, + iconData: Icons.person, + ); + + final shipperBox = Container( + child: Column( + children: [ + shipperIDBox, + shipperNamebox, + ], + ), + ); return LocalProgress( inAsyncCall: _isLoading, @@ -391,7 +555,7 @@ class _CartonEditorState extends State { backgroundColor: Colors.white, title: LocalText( context, - "box.info.title", + _isNew ? "box.info.title" : "box.edit.title", fontSize: 20, color: primaryColor, ), @@ -408,44 +572,98 @@ class _CartonEditorState extends State { cartonTypeBox, LocalTitle(textKey: "box.shipment_info"), _isNew ? fcsShipmentsBox : shipmentBox, - isMixBox ? mixTypeBox : Container(), + isMixBox + ? _isNew + ? mixTypeBox + : mixTypeDisplayBox + : Container(), ...(isMixBox ? [ mixcartonTitleBox, Column( - children: _getMixCartons( - context, - this._mixCartons, - )), + children: _getMixCartons(context, this._mixCartons)), ] : [ - fcsIDBox, - namebox, - CartonPackageTable( - packages: _carton.packages, - onSelect: (p, checked) { - if (checked && - _deliveryAddress != null && - p.deliveryAddress?.id != _deliveryAddress.id) { - return; - } - setState(() { - p.isChecked = checked; - }); - _populateDeliveryAddress(); - }, - ), - cartonTitleBox, - Column( - children: _getCartons( - context, - this._cartons, - )), + isFromPackages ? fcsIDBox : Container(), + isFromPackages ? namebox : Container(), + isFromPackages + ? CartonPackageTable( + packages: _carton.packages, + onSelect: (p, checked) { + if (checked && + _deliveryAddress != null && + p.deliveryAddress?.id != + _deliveryAddress.id) { + return; + } + setState(() { + p.isChecked = checked; + }); + // _populateDeliveryAddress(); + }, + ) + : Container(), + isFromCargos + ? Container( + padding: const EdgeInsets.only(top: 15), + child: Row( + children: [ + Flexible(child: consigneeBox), + Flexible(child: shipperBox) + ], + ), + ) + : Container(), + _isNew ? cartonTitleBox : Container(), + _isNew + ? Column( + children: _getCartons( + context, + isFromPackages + ? this._cartons + : this._cartonsForCargos)) + : Container(), + _isNew ? Container() : cargoTableTitleBox, + _isNew ? Container() : cargoTableBox, + _isNew + ? Container() + : LocalTitle(textKey: "box.dimension"), + _isNew ? Container() : cartonSizeDropdown(), + _isNew ? Container() : dimBox, + _isNew + ? Container() + : LocalTitle(textKey: "box.delivery_address"), + _isNew + ? Container() + : DefaultDeliveryAddress( + deliveryAddress: _deliveryAddress, + labelKey: "box.delivery_address", + onTap: () async { + DeliveryAddress d = + await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => + DeliveryAddressSelection( + deliveryAddress: _deliveryAddress, + deliveryAddresses: + _deliveryAddresses)), + ); + if (d == null) return; + setState(() { + _deliveryAddress = d; + }); + }), ]), SizedBox( height: 20, ), - createBtn, + isFromPackages || isFromCargos + ? _isNew + ? createBtn + : saveBtn + : Container(), + isMixBox ? createMixCarton : Container(), SizedBox( height: 20, ), @@ -456,19 +674,33 @@ class _CartonEditorState extends State { ); } - _addCarton(Carton carton) { - if (carton == null) return; - this._cartons.add(carton); - setState(() {}); - } - List _getCartons(BuildContext context, List cartons) { - return cartons.map((c) { + return cartons.asMap().entries.map((c) { return InkWell( - onTap: () {}, + onTap: () async { + bool isFromPackages = _selectedCartonType == carton_from_packages; + bool isFromCargos = _selectedCartonType == carton_from_cargos; + if (isFromPackages) { + _loadPackages(); + c.value.packages = _carton.packages; + Carton _c = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => PackageCartonEditor( + carton: c.value, + isNew: false, + consignee: _user, + )), + ); + if (_c == null) return; + cartons.removeWhere((item) => item.id == _c.id); + cartons.insert(c.key, _c); + setState(() {}); + } + }, child: CartonRow( - key: ValueKey(c.id), - box: c, + key: ValueKey(c.value.id), + box: c.value, ), ); }).toList(); @@ -476,17 +708,16 @@ class _CartonEditorState extends State { List _getMixCartons(BuildContext context, List cartons) { return cartons.map((c) { - return InkWell( - onTap: () {}, - child: CartonRow( - key: ValueKey(c.id), - box: c, - ), + return CartonRow( + key: ValueKey(c.id), + box: c, + onRemove: (carton) { + _removeMixCarton(carton); + }, ); }).toList(); } - CartonSize selectedCatonSize; Widget cartonSizeDropdown() { List _cartonSizes = Provider.of(context).getCartonSizes; @@ -565,70 +796,204 @@ class _CartonEditorState extends State { ); } - _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; - // } + _addCargo(CargoType cargo) { + if (cargo == null) return; + setState(() { + _cargoTypes.remove(cargo); + _cargoTypes.add(cargo); + }); + } - // 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; - // }); - // } - Navigator.pop(context, true); + _removeCargo(CargoType cargo) { + setState(() { + _cargoTypes.remove(cargo); + }); + } + + _addCarton() async { + bool isFromPackages = _selectedCartonType == carton_from_packages; + bool isFromCargos = _selectedCartonType == carton_from_cargos; + + if (_fcsShipment == null && _isNew) { + showMsgDialog(context, "Error", "Please select FCS shipment"); + return; + } + + if (_user == null && isFromPackages) { + showMsgDialog(context, "Error", "Please select FCS ID"); + return; + } + + if (consignee == null && isFromCargos) { + showMsgDialog(context, "Error", "Please select consignee's FCS ID"); + return; + } + + if (sender == null && isFromCargos) { + showMsgDialog(context, "Error", "Please select sender's FCS ID"); + 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); + + Carton carton = Carton(); + carton.id = _carton.id; + carton.cartonType = _selectedCartonType; + carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; + if (isFromPackages) { + carton.userID = _user?.id; + carton.fcsID = _user?.fcsID; + carton.userName = _user?.name; + carton.packages = _carton.packages.where((e) => e.isChecked).toList(); + } + + if (isFromCargos) { + carton.receiverID = consignee?.id; + carton.receiverFCSID = consignee?.fcsID; + carton.receiverName = consignee?.name; + carton.senderID = sender?.id; + carton.senderFCSID = sender?.fcsID; + carton.senderName = sender?.name; + } + + carton.cargoTypes = _carton.cargoTypes; + carton.length = l; + carton.width = w; + carton.height = h; + carton.deliveryAddress = _carton.deliveryAddress; + + try { + Carton _c = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => PackageCartonEditor( + carton: carton, + isNew: _isNew, + consignee: _user, + )), + ); + if (_c == null) return; + var cartonModel = Provider.of(context, listen: false); + Carton _carton = await cartonModel.getCarton(_c.id); + if (isFromPackages) { + _cartons.add(_carton); + } + + if (isFromCargos) { + _cartonsForCargos.add(_carton); + } + + setState(() {}); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } + } + + _addMixCarton(Carton carton) { + if (carton == null) return; + if (this._mixCartons.any((c) => c.id == carton.id)) return; + setState(() { + this._mixCartons.add(carton); + }); + } + + _removeMixCarton(Carton carton) { + setState(() { + this._mixCartons.removeWhere((c) => c.id == carton.id); + }); + } + + _creatMixCarton() async { + if (_fcsShipment == null && _isNew) { + showMsgDialog(context, "Error", "Please select FCS shipment"); + return; + } + if ((this._mixCartons?.length ?? 0) == 0) { + showMsgDialog(context, "Error", "Expect at least one carton"); + return; + } + Carton carton = Carton(); + carton.id = _carton.id; + carton.cartonType = _selectedCartonType; + carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; + carton.mixBoxType = _selectedMixBoxType; + carton.mixCartons = this._mixCartons; + 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; + }); + } + } + + _save() async { + bool isFromPackages = _selectedCartonType == carton_from_packages; + bool isFromCargos = _selectedCartonType == carton_from_cargos; + if ((_cargoTypes?.length ?? 0) == 0 && (isFromPackages || isFromCargos)) { + 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) && (isFromPackages || isFromCargos)) { + showMsgDialog(context, "Error", "Invalid dimension"); + return; + } + if (_deliveryAddress == null && (isFromPackages || isFromCargos)) { + showMsgDialog(context, "Error", "Invalid delivery address"); + return; + } + + Carton carton = Carton(); + carton.id = _carton.id; + carton.cartonType = _selectedCartonType; + carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; + if (isFromPackages) { + carton.userID = _user?.id; + carton.packages = _carton.packages.where((e) => e.isChecked).toList(); + } + if (isFromCargos) { + carton.receiverID = consignee?.id; + carton.senderID = sender?.id; + } + + carton.cargoTypes = _cargoTypes; + carton.length = l; + carton.width = w; + carton.height = h; + carton.deliveryAddress = _deliveryAddress; + + setState(() { + _isLoading = true; + }); + try { + CartonModel cartonModel = + Provider.of(context, listen: false); + await cartonModel.updateCarton(carton); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } } isDataChanged() { diff --git a/lib/pages/carton/carton_info.dart b/lib/pages/carton/carton_info.dart index 3ee835b..0a9a7e7 100644 --- a/lib/pages/carton/carton_info.dart +++ b/lib/pages/carton/carton_info.dart @@ -1,9 +1,11 @@ import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/domain/entities/carton_size.dart'; import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/carton_size/model/carton_size_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'; @@ -49,19 +51,20 @@ class _CartonInfoState extends State { double volumetricRatio = 0; double shipmentWeight = 0; String selectMixBoxType; - List _cartons = []; bool isMixBox; bool isFromShipments; bool isFromPackages; bool isSmallBag; + bool isFromCartons; bool isEdiable; @override void initState() { super.initState(); _box = widget.box; - + // _box.cartonType = carton_from_cargos; + // _box.cartonType = carton_mix_box; //for shipment weight volumetricRatio = Provider.of(context, listen: false) .rate @@ -72,6 +75,7 @@ class _CartonInfoState extends State { _updateBoxData(); _loadPackages(); + _loadMixCartons(); } _updateBoxData() { @@ -84,20 +88,25 @@ class _CartonInfoState extends State { isFromShipments = _box.cartonType == carton_from_shipments; isFromPackages = _box.cartonType == carton_from_packages; isSmallBag = _box.cartonType == carton_small_bag; - isEdiable = !isMixBox && - (isFromPackages || isSmallBag) && + isFromCartons = _box.cartonType == carton_from_cargos; + + isEdiable = (isFromPackages || isMixBox || isFromCartons) && _box.status == carton_packed_status; - selectMixBoxType = _box.mixBoxType ?? "Mix Delivery"; - _cartons = [ - Carton( - cartonNumber: "A100B-1#1", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - Carton( - cartonNumber: "A100B-1#2", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - ]; + selectMixBoxType = _box.mixBoxType ?? ""; + getCartonSize(); + } + + getCartonSize() { + var cartonSizeModel = Provider.of(context, listen: false); + cartonSizeModel.cartonSizes.forEach((c) { + if (c.length == _box.length && + c.width == _box.width && + c.height == _box.height) { + setState(() { + _cartonSizeController.text = c.name; + }); + } + }); } _loadPackages() async { @@ -122,6 +131,20 @@ class _CartonInfoState extends State { }); } + _loadMixCartons() async { + if (_box.cartonType != carton_mix_box) return; + CartonModel cartonModel = Provider.of(context, listen: false); + List catons = []; + for (var id in _box.mixCartonIDs) { + Carton c = await cartonModel.getCarton(id); + catons.add(c); + } + + setState(() { + _box.mixCartons = catons; + }); + } + _calShipmentWeight() { double l = double.parse(_lengthController.text, (s) => 0); double w = double.parse(_widthController.text, (s) => 0); @@ -164,6 +187,55 @@ class _CartonInfoState extends State { iconData: Icons.person, ); + final consigneefcsIDBox = DisplayText( + text: _box.receiverFCSID != null ? _box.receiverFCSID : "", + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + ); + + final consigneeNameBox = DisplayText( + text: _box.receiverName != null ? _box.receiverName : "", + labelTextKey: "processing.consignee.name", + maxLines: 2, + iconData: Icons.person, + ); + + final consigneeBox = Container( + child: Column( + children: [ + consigneefcsIDBox, + consigneeNameBox, + ], + ), + ); + + final shipperIDBox = Row( + children: [ + Expanded( + child: DisplayText( + text: _box.senderFCSID != null ? _box.senderFCSID : "", + labelTextKey: "processing.fcs.id", + icon: FcsIDIcon(), + )), + ], + ); + + final shipperNamebox = DisplayText( + text: _box.senderName != null ? _box.senderName : "", + labelTextKey: "processing.shipper.name", + maxLines: 2, + iconData: Icons.person, + ); + + final shipperBox = Container( + child: Column( + children: [ + shipperIDBox, + shipperNamebox, + ], + ), + ); + final lengthBox = LengthPicker( controller: _lengthController, lableKey: "box.length", @@ -275,17 +347,29 @@ class _CartonInfoState extends State { cartonTypeBox, LocalTitle(textKey: "box.shipment_info"), shipmentBox, - isSmallBag ? mixCartonNumberBox : Container(), - isMixBox ? Container() : fcsIDBox, - isMixBox ? Container() : customerNameBox, - isMixBox ? mixTypeBox : Container(), - isMixBox ? LocalTitle(textKey: "boxes.title") : Container(), + // isSmallBag ? mixCartonNumberBox : Container(), isMixBox - ? Column( - children: _getCartons( - context, - this._cartons, - )) + ? Container() + : isFromPackages + ? fcsIDBox + : Container(), + isMixBox + ? Container() + : isFromPackages + ? customerNameBox + : Container(), + isFromCartons + ? Row( + children: [ + Flexible(child: consigneeBox), + Flexible(child: shipperBox) + ], + ) + : Container(), + isMixBox ? mixTypeBox : Container(), + isMixBox ? LocalTitle(textKey: "box.mix_caton_title") : Container(), + isMixBox + ? Column(children: _getCartons(context, _box.mixCartons)) : Container(), isFromPackages || isSmallBag ? CartonPackageTable( @@ -294,7 +378,7 @@ class _CartonInfoState extends State { : Container(), isMixBox ? Container() : LocalTitle(textKey: "box.cargo.type"), isMixBox ? Container() : cargoTableBox, - ...(isFromPackages + ...(isFromPackages || isFromCartons ? [ LocalTitle(textKey: "box.dimension"), cartonSizeBox, @@ -326,6 +410,7 @@ class _CartonInfoState extends State { } _gotoEditor() async { + widget.box.mixCartons=_box.mixCartons; bool updated = await Navigator.push( context, CupertinoPageRoute(builder: (context) => CartonEditor(box: widget.box)), @@ -335,9 +420,10 @@ class _CartonInfoState extends State { var c = await cartonModel.getCarton(widget.box.id); setState(() { _box = c; + _loadPackages(); + _loadMixCartons(); _updateBoxData(); }); - _loadPackages(); } } diff --git a/lib/pages/carton/mix_carton_editor.dart b/lib/pages/carton/mix_carton_editor.dart deleted file mode 100644 index 7092d75..0000000 --- a/lib/pages/carton/mix_carton_editor.dart +++ /dev/null @@ -1,128 +0,0 @@ -import 'package:fcs/domain/entities/carton.dart'; -import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/carton_search/carton_search.dart'; -import 'package:fcs/pages/widgets/local_button.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 'carton_row.dart'; - -class MixCartonEditor extends StatefulWidget { - final Carton box; - MixCartonEditor({this.box}); - - @override - _MixCartonEditorState createState() => _MixCartonEditorState(); -} - -class _MixCartonEditorState extends State { - Carton _box; - bool _isLoading = false; - bool _isNew; - List _cartons = []; - - @override - void initState() { - super.initState(); - - if (widget.box != null) { - _box = widget.box; - _isNew = false; - } else { - _isNew = true; - _box = Carton(cargoTypes: []); - } - } - - @override - Widget build(BuildContext context) { - final createBtn = LocalButton( - textKey: "box.mix_carton_btn", - callBack: _creatCarton, - ); - - final cargoTableTitleBox = LocalTitle( - textKey: "boxes.title", - trailing: IconButton( - icon: Icon( - Icons.add_circle, - color: primaryColor, - ), - onPressed: () => searchCarton(context, callbackCartonSelect: (c) { - _addMixCarton(c); - }), - ), - ); - - 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, - "box.min_caton.form.title", - fontSize: 20, - color: primaryColor, - ), - ), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: ListView( - children: [ - cargoTableTitleBox, - Column( - children: _getCartons( - context, - this._cartons, - )), - SizedBox( - height: 20, - ), - createBtn - ], - ), - ), - ), - ); - } - - List _getCartons(BuildContext context, List cartons) { - return cartons.map((c) { - return CartonRow( - key: ValueKey(c.id), - box: c, - onRemove: (carton) { - _removeMixCarton(carton); - }, - ); - }).toList(); - } - - _addMixCarton(Carton carton) { - if (carton == null) return; - if (this._cartons.any((c) => c.cartonNumber == carton.cartonNumber)) return; - setState(() { - this._cartons.add(carton); - }); - } - - _removeMixCarton(Carton carton) { - setState(() { - this._cartons.remove(carton); - }); - } - - _creatCarton() {} -} diff --git a/lib/pages/carton/model/carton_model.dart b/lib/pages/carton/model/carton_model.dart index 4d07acf..0348ebb 100644 --- a/lib/pages/carton/model/carton_model.dart +++ b/lib/pages/carton/model/carton_model.dart @@ -13,6 +13,7 @@ import 'package:logging/logging.dart'; class CartonModel extends BaseModel { List _boxes = []; + List cartons = []; final log = Logger('CartonModel'); List get boxes => _selectedIndex == 1 ? _boxes : List.from(_delivered.values); @@ -22,6 +23,7 @@ class CartonModel extends BaseModel { bool isLoading = false; StreamSubscription listener; + StreamSubscription cartonListener; static List statusHistory = [ ShipmentStatus(status: "Packed", date: DateTime(2020, 6, 1), done: true), ShipmentStatus(status: "Shipped", date: DateTime(2020, 6, 5), done: false), @@ -56,10 +58,15 @@ class CartonModel extends BaseModel { }); } - List cartonTypes = [carton_from_packages, carton_mix_box]; - List mixTypes = [mix_delivery, mix_pickup]; + List cartonTypes = [ + carton_from_packages, + // carton_from_cargos, + carton_mix_box + ]; + List mixBoxTypes = [mix_delivery, mix_pickup]; List cartonTypesInfo = [ carton_from_packages, + carton_from_cargos, carton_mix_box, carton_from_shipments, carton_small_bag @@ -75,6 +82,7 @@ class CartonModel extends BaseModel { initData() { _selectedIndex = 1; _loadBoxes(); + _loadCartonForMixBox(); if (_delivered != null) _delivered.close(); _delivered = _getDelivered(); @@ -108,6 +116,35 @@ class CartonModel extends BaseModel { } } + Future _loadCartonForMixBox() async { + if (user == null || !user.hasCarton()) return; + String path = "/$cartons_collection/"; + if (cartonListener != null) cartonListener.cancel(); + cartons = []; + try { + cartonListener = Firestore.instance + .collection("$path") + .where("carton_type", + whereIn: [carton_from_packages, carton_from_cargos]) + .where("status", isEqualTo: carton_packed_status) + .where("is_deleted", isEqualTo: false) + .orderBy("user_name") + .snapshots() + .listen((QuerySnapshot snapshot) { + cartons.clear(); + cartons = snapshot.documents.map((documentSnapshot) { + var s = Carton.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + + notifyListeners(); + }); + } catch (e) { + log.warning("Error!! $e"); + } + } + Paginator _getDelivered() { if (user == null || !user.hasCarton()) return null; @@ -145,8 +182,10 @@ class CartonModel extends BaseModel { @override logout() async { if (listener != null) await listener.cancel(); + if (cartonListener != null) await cartonListener.cancel(); if (_delivered != null) _delivered.close(); _boxes = []; + cartons = []; } Future> getCartons(String shipmentID) async { @@ -207,7 +246,7 @@ class CartonModel extends BaseModel { return Carton.fromMap(snap.data, snap.documentID); } - Future createCarton(Carton carton) { + Future createCarton(Carton carton) { return Services.instance.cartonService.createCarton(carton); } @@ -220,38 +259,7 @@ class CartonModel extends BaseModel { } Future> searchCarton(String term) async { - if (term == null || term == '') return List(); - - List _cartons = []; - - try { - _cartons = [ - Carton( - cartonNumber: "A100B-1#1", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - Carton( - cartonNumber: "A100B-1#2", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - Carton( - cartonNumber: "A100B-1#3", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - Carton( - cartonNumber: "A100B-1#4", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - Carton( - cartonNumber: "A100B-1#5", - cargoTypes: [CargoType(name: "General", weight: 12)], - userName: "Seven 7"), - ]; - } catch (e) { - // permission error - log.warning("user error:" + e.toString()); - return null; - } - return _cartons; + return Services.instance.cartonService.searchCarton(term); } + } diff --git a/lib/pages/carton/package_carton_editor.dart b/lib/pages/carton/package_carton_editor.dart index 3e2726a..b269fc9 100644 --- a/lib/pages/carton/package_carton_editor.dart +++ b/lib/pages/carton/package_carton_editor.dart @@ -1,7 +1,9 @@ +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/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_size/carton_size_list.dart'; @@ -29,7 +31,8 @@ import 'model/carton_model.dart'; class PackageCartonEditor extends StatefulWidget { final Carton carton; final bool isNew; - PackageCartonEditor({this.carton, this.isNew}); + final User consignee; + PackageCartonEditor({this.carton, this.isNew, this.consignee}); @override _PackageCartonEditorState createState() => _PackageCartonEditorState(); @@ -43,27 +46,65 @@ class _PackageCartonEditorState extends State { Carton _carton; bool _isLoading = false; DeliveryAddress _deliveryAddress = new DeliveryAddress(); - + List _deliveryAddresses = []; List _cargoTypes = []; + CartonSize selectedCatonSize; + bool isFromPackages; + bool isFromCargos; @override void initState() { super.initState(); + _load(); + } + + _load() { + _carton = widget.carton; + isFromPackages = _carton.cartonType == carton_from_packages; + isFromCargos = _carton.cartonType == carton_from_cargos; + _getDeliverAddresses(); if (widget.isNew) { - _carton = widget.carton; _lengthCtl.text = "0"; _widthCtl.text = "0"; _heightCtl.text = "0"; } else { - _carton = widget.carton; _cargoTypes = List.from(widget.carton.cargoTypes); _lengthCtl.text = _carton.length.toString(); _widthCtl.text = _carton.width.toString(); _heightCtl.text = _carton.height.toString(); _deliveryAddress = _carton.deliveryAddress; + _getCartonSize(); } } + _getDeliverAddresses() async { + var addressModel = + Provider.of(context, listen: false); + + var deliveryAddresses = isFromPackages + ? await addressModel.getDeliveryAddresses(_carton.userID) + : await addressModel.getDeliveryAddresses(_carton.receiverID); + setState(() { + this._deliveryAddresses = deliveryAddresses; + }); + } + + _getCartonSize() { + var cartonSizeModel = Provider.of(context, listen: false); + cartonSizeModel.cartonSizes.forEach((c) { + if (c.length == _carton.length && + c.width == _carton.width && + c.height == _carton.height) { + selectedCatonSize = CartonSize( + id: c.id, + name: c.name, + length: c.length, + width: c.width, + height: c.height); + } + }); + } + @override Widget build(BuildContext context) { final lengthBox = LengthPicker( @@ -94,7 +135,7 @@ class _PackageCartonEditorState extends State { ], ); final createBtn = LocalButton( - textKey: "box.new_carton_btn", + textKey: widget.isNew ? "box.new_carton_btn" : "box.cargo.save.btn", callBack: _creatCarton, ); @@ -164,6 +205,9 @@ class _PackageCartonEditorState extends State { CupertinoPageRoute( builder: (context) => DeliveryAddressSelection( deliveryAddress: _deliveryAddress, + deliveryAddresses: this._deliveryAddresses, + user: widget.consignee, + onAdded: () => _getDeliverAddresses(), )), ); if (d == null) return; @@ -182,7 +226,6 @@ class _PackageCartonEditorState extends State { ); } - CartonSize selectedCatonSize; Widget cartonSizeDropdown() { List _cartonSizes = Provider.of(context).getCartonSizes; @@ -293,10 +336,21 @@ class _PackageCartonEditorState extends State { carton.id = _carton.id; carton.cartonType = _carton.cartonType; carton.fcsShipmentID = _carton.fcsShipmentID; - carton.userID = _carton.userID; carton.cargoTypes = _cargoTypes; - carton.packages = _carton.packages.where((e) => e.isChecked).toList(); - // carton.cartonSizeID = selectedCatonSize?.id; + if (isFromPackages) { + carton.userID = _carton.userID; + carton.packages = _carton.packages.where((e) => e.isChecked).toList(); + } + + if (isFromCargos) { + carton.receiverID = _carton.receiverID; + carton.receiverFCSID = _carton.receiverFCSID; + carton.receiverName = _carton.receiverName; + carton.senderID = _carton.senderID; + carton.senderFCSID = _carton.senderFCSID; + carton.senderName = _carton.senderName; + } + carton.length = l; carton.width = w; carton.height = h; @@ -308,11 +362,13 @@ class _PackageCartonEditorState extends State { CartonModel cartonModel = Provider.of(context, listen: false); if (widget.isNew) { - await cartonModel.createCarton(carton); + Carton _c = await cartonModel.createCarton(carton); + Navigator.pop(context, _c); } else { await cartonModel.updateCarton(carton); + Carton _c = await cartonModel.getCarton(_carton.id); + Navigator.pop(context, _c); } - Navigator.pop(context, true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { diff --git a/lib/pages/carton_search/carton_search.dart b/lib/pages/carton_search/carton_search.dart index 741fc83..9b131d2 100644 --- a/lib/pages/carton_search/carton_search.dart +++ b/lib/pages/carton_search/carton_search.dart @@ -1,8 +1,11 @@ import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/carton/model/carton_model.dart'; +import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/widgets/barcode_scanner.dart'; import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; +import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'carton_list_row.dart'; @@ -21,7 +24,7 @@ class PartSearchDelegate extends SearchDelegate { PartSearchDelegate({this.callbackCartonSelect}); @override - String get searchFieldLabel => 'Search by Carton Number/Customer Name'; + String get searchFieldLabel => 'Search by Carton Number'; @override ThemeData appBarTheme(BuildContext context) { @@ -40,6 +43,11 @@ class PartSearchDelegate extends SearchDelegate { @override List buildActions(BuildContext context) { return [ + IconButton( + icon: Icon(MaterialCommunityIcons.barcode_scan, + size: 30, color: Colors.white), + onPressed: () => _scan(context), + ), IconButton( icon: Icon(Icons.clear), onPressed: () => query = '', @@ -106,17 +114,41 @@ class PartSearchDelegate extends SearchDelegate { @override Widget buildSuggestions(BuildContext context) { + final cartonModel = Provider.of(context); return Container( - child: Center( - child: Opacity( - opacity: 0.2, - child: Icon( - MaterialCommunityIcons.package, - color: primaryColor, - size: 200, - ), - ), + padding: EdgeInsets.only(top: 5), + child: ListView( + children: cartonModel.cartons + .map((u) => CartonListRow( + carton: u, + callbackCartonSelect: callbackCartonSelect, + )) + .toList(), ), ); } + + _scan(BuildContext context) async { + PermissionStatus permission = + await PermissionHandler().checkPermissionStatus(PermissionGroup.camera); + if (permission != PermissionStatus.granted) { + Map permissions = + await PermissionHandler() + .requestPermissions([PermissionGroup.camera]); + if (permissions[PermissionGroup.camera] != PermissionStatus.granted) { + showMsgDialog(context, "Error", "Camera permission is not granted"); + return null; + } + } + + try { + String barcode = await scanBarcode(); + if (barcode != null) { + query = barcode; + showResults(context); + } + } catch (e) { + print('error: $e'); + } + } } diff --git a/lib/pages/customer/customer_list.dart b/lib/pages/customer/customer_list.dart index 4e706df..a1fbd72 100644 --- a/lib/pages/customer/customer_list.dart +++ b/lib/pages/customer/customer_list.dart @@ -43,7 +43,7 @@ class _CustomerListState extends State { actions: [ IconButton( icon: Icon(Icons.search, color: Colors.white), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { _select(u); })), ], diff --git a/lib/pages/customer/invitation_create.dart b/lib/pages/customer/invitation_create.dart index 51fd10c..af2e2ed 100644 --- a/lib/pages/customer/invitation_create.dart +++ b/lib/pages/customer/invitation_create.dart @@ -172,7 +172,7 @@ class _InvitationCreateState extends State { } isDataChanged() { - String userName = _nameController.text; + String userName = _nameController.text; String phoneNumber = _phoneController.text; return userName != "" || phoneNumber != ""; } diff --git a/lib/pages/delivery_address/delivery_address_editor.dart b/lib/pages/delivery_address/delivery_address_editor.dart index 26bbccd..63c4715 100644 --- a/lib/pages/delivery_address/delivery_address_editor.dart +++ b/lib/pages/delivery_address/delivery_address_editor.dart @@ -1,3 +1,4 @@ +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/delivery_address/model/delivery_address_model.dart'; @@ -12,7 +13,8 @@ import 'package:provider/provider.dart'; class DeliveryAddressEditor extends StatefulWidget { final DeliveryAddress deliveryAddress; - DeliveryAddressEditor({this.deliveryAddress}); + final User user; + DeliveryAddressEditor({this.deliveryAddress, this.user}); @override _DeliveryAddressEditorState createState() => _DeliveryAddressEditorState(); @@ -195,6 +197,9 @@ class _DeliveryAddressEditorState extends State { if (!valid) { return; } + if (widget.user != null) { + deliveryAddress.userID = widget.user.id; + } setState(() { _isLoading = true; }); @@ -202,7 +207,7 @@ class _DeliveryAddressEditorState extends State { Provider.of(context, listen: false); try { await deliveryAddressModel.createDeliveryAddress(deliveryAddress); - Navigator.pop(context); + Navigator.pop(context,true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { @@ -225,7 +230,7 @@ class _DeliveryAddressEditorState extends State { Provider.of(context, listen: false); try { await deliveryAddressModel.updateDeliveryAddress(deliveryAddress); - Navigator.pop(context); + Navigator.pop(context,true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { @@ -247,7 +252,7 @@ class _DeliveryAddressEditorState extends State { DeliveryAddressModel deliveryAddressModel = Provider.of(context, listen: false); await deliveryAddressModel.deleteDeliveryAddress(_deliveryAddress); - Navigator.pop(context); + Navigator.pop(context,true); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { diff --git a/lib/pages/delivery_address/model/delivery_address_model.dart b/lib/pages/delivery_address/model/delivery_address_model.dart index 550d6af..be25889 100644 --- a/lib/pages/delivery_address/model/delivery_address_model.dart +++ b/lib/pages/delivery_address/model/delivery_address_model.dart @@ -84,4 +84,16 @@ class DeliveryAddressModel extends BaseModel { return Services.instance.deliveryAddressService .selectDefalutDeliveryAddress(deliveryAddress); } + + Future> getDeliveryAddresses(String userID) async { + String path = "$delivery_address_collection/"; + var querySnap = await Firestore.instance + .collection('users') + .document("$userID") + .collection("$path") + .getDocuments(); + return querySnap.documents + .map((e) => DeliveryAddress.fromMap(e.data, e.documentID)) + .toList(); + } } diff --git a/lib/pages/discount/discount_editor.dart b/lib/pages/discount/discount_editor.dart index d28856f..d967cb5 100644 --- a/lib/pages/discount/discount_editor.dart +++ b/lib/pages/discount/discount_editor.dart @@ -77,12 +77,12 @@ class _DiscountEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { customerId = u.id; customerName = u.name; }); - })), + },popPage: true)), ], ); diff --git a/lib/pages/package/package_info.dart b/lib/pages/package/package_info.dart index 5d18dda..5427a19 100644 --- a/lib/pages/package/package_info.dart +++ b/lib/pages/package/package_info.dart @@ -70,19 +70,20 @@ class _PackageInfoState extends State { bool canChangeDeliveryAddress = _package?.status == package_received_status || _package?.status == package_processed_status; + var deliveryAddressModel = Provider.of(context); final trackingIdBox = DisplayText( - text: _package?.trackingID??"", + text: _package?.trackingID ?? "", labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); var fcsIDBox = DisplayText( - text: _package?.fcsID??"", + text: _package?.fcsID ?? "", labelTextKey: "processing.fcs.id", icon: FcsIDIcon(), ); final customerNameBox = DisplayText( - text: _package?.userName??"", + text: _package?.userName ?? "", labelTextKey: "package.create.name", iconData: Icons.perm_identity, ); @@ -120,8 +121,8 @@ class _PackageInfoState extends State { context, CupertinoPageRoute( builder: (context) => DeliveryAddressSelection( - deliveryAddress: _package.deliveryAddress, - )), + deliveryAddress: _package.deliveryAddress, + deliveryAddresses: deliveryAddressModel.deliveryAddresses)), ); if (d == null) return; _changeDeliverayAddress(d); @@ -158,7 +159,9 @@ class _PackageInfoState extends State { widget.isSearchResult ? Container() : fcsIDBox, widget.isSearchResult ? Container() : customerNameBox, widget.isSearchResult ? Container() : marketBox, - _package==null || _package.photoUrls.length == 0 ? Container() : img, + _package == null || _package.photoUrls.length == 0 + ? Container() + : img, widget.isSearchResult ? Container() : descBox, remarkBox, _package?.status == package_received_status && diff --git a/lib/pages/package/package_list_row.dart b/lib/pages/package/package_list_row.dart index ea6052c..76c8297 100644 --- a/lib/pages/package/package_list_row.dart +++ b/lib/pages/package/package_list_row.dart @@ -23,7 +23,7 @@ class PackageListRow extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - onTap: () { + onTap: () { if (callbackPackageSelect != null) { callbackPackageSelect(package); return; diff --git a/lib/pages/package/package_new.dart b/lib/pages/package/package_new.dart index 8bda98b..54360eb 100644 --- a/lib/pages/package/package_new.dart +++ b/lib/pages/package/package_new.dart @@ -47,7 +47,7 @@ class _PackageNewState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this.user = u; }); diff --git a/lib/pages/processing/package_editor.dart b/lib/pages/processing/package_editor.dart index 4c3d49a..17a7292 100644 --- a/lib/pages/processing/package_editor.dart +++ b/lib/pages/processing/package_editor.dart @@ -1,3 +1,4 @@ +import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/entities/market.dart'; import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/user.dart'; @@ -7,7 +8,9 @@ import 'package:fcs/pages/market/model/market_model.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/package/tracking_id_page.dart'; import 'package:fcs/pages/main/util.dart'; +import 'package:fcs/pages/package_search/package_serach.dart'; import 'package:fcs/pages/widgets/barcode_scanner.dart'; +import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; @@ -32,59 +35,60 @@ class PackageEditor extends StatefulWidget { class _PackageEditorState extends State { TextEditingController _remarkCtl = new TextEditingController(); TextEditingController _descCtl = new TextEditingController(); - TextEditingController _trackingIDCtl = new TextEditingController(); bool _isLoading = false; - bool _isNew; MultiImgController multiImgController = MultiImgController(); - Package _package = Package(); + Package _package; @override void initState() { super.initState(); - if (widget.package != null) { - _isNew = false; - _package = widget.package; - _trackingIDCtl.text = _package.trackingID; + _package = Package(); + _loadPackageData(null); + } + _loadPackageData(String id) async { + if (id != null) { + PackageModel packageModel = + Provider.of(context, listen: false); + Package package = await packageModel.getPackage(id); + if (package != null) { + if (package.status != package_received_status) { + showMsgDialog(context, "Error", + "Invalid package status, expected '$package_received_status' status"); + return; + } + setState(() { + _package = package; + }); + } + } + setState(() { selectedMarket = _package.market ?? ""; _descCtl.text = _package.desc; _remarkCtl.text = _package.remark; - multiImgController.setImageFiles = _package.photoFiles; - } else { - _isNew = true; - } + multiImgController.setImageUrls = _package.photoUrls; + }); } @override Widget build(BuildContext context) { - final trackingIDBox = Container( - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, + var trackingIDBox = Row( children: [ Expanded( - child: InputText( - iconData: MaterialCommunityIcons.barcode_scan, + child: DisplayText( + text: _package.trackingID, labelTextKey: "processing.tracking.id", - controller: _trackingIDCtl, + iconData: MaterialCommunityIcons.barcode_scan, )), - InkWell( - onTap: _scan, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - Icon( - MaterialCommunityIcons.barcode_scan, - color: primaryColor, - ), - Text("Scan") - ], - ), - ), - ), + IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchPackage(context, callbackPackageSelect: (u) { + _loadPackageData(u.id); + Navigator.pop(context); + })), ], - )); + ); final descBox = InputText( labelTextKey: 'processing.desc', @@ -114,7 +118,15 @@ class _PackageEditorState extends State { centerTitle: true, leading: new IconButton( icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), - onPressed: () => Navigator.of(context).pop(), + onPressed: () { + if (isDataChanged()) { + showConfirmDialog(context, "back.button_confirm", () { + Navigator.of(context).pop(); + }); + } else { + Navigator.of(context).pop(); + } + }, ), shadowColor: Colors.transparent, backgroundColor: Colors.white, @@ -235,31 +247,6 @@ class _PackageEditorState extends State { ); } - _scan() async { - PermissionStatus permission = - await PermissionHandler().checkPermissionStatus(PermissionGroup.camera); - if (permission != PermissionStatus.granted) { - Map permissions = - await PermissionHandler() - .requestPermissions([PermissionGroup.camera]); - if (permissions[PermissionGroup.camera] != PermissionStatus.granted) { - showMsgDialog(context, "Error", "Camera permission is not granted"); - return null; - } - } - - try { - String barcode = await scanBarcode(); - if (barcode != null) { - setState(() { - _trackingIDCtl.text = barcode; - }); - } - } catch (e) { - print('error: $e'); - } - } - _selectPackage() async { setState(() { _isLoading = true; @@ -267,21 +254,17 @@ class _PackageEditorState extends State { PackageModel packageModel = Provider.of(context, listen: false); try { - Package package=await packageModel.getPackageByTrackingID(_trackingIDCtl.text); - package.trackingID = _trackingIDCtl.text; - package.market = selectedMarket; - package.desc = _descCtl.text; - package.remark = _remarkCtl.text; - package.photoFiles = _isNew - ? multiImgController.getAddedFile - : multiImgController.getUpdatedFile; - package.fcsID=widget.consignee.fcsID; - package.senderFCSID=widget.sender?.fcsID; + _package.market = selectedMarket; + _package.desc = _descCtl.text; + _package.remark = _remarkCtl.text; + _package.photoFiles = multiImgController.getUpdatedFile; + _package.fcsID = widget.consignee.fcsID; + _package.senderFCSID = widget.sender?.fcsID; - await packageModel.updateProcessing(package, + await packageModel.updateProcessing(_package, multiImgController.getAddedFile, multiImgController.getDeletedUrl); - Navigator.pop(context, package); + Navigator.pop(context, _package); } catch (e) { showMsgDialog(context, "Error", e.toString()); } finally { @@ -290,4 +273,11 @@ class _PackageEditorState extends State { }); } } + + isDataChanged() { + return selectedMarket != null || + _descCtl.text != "" || + _remarkCtl.text != "" || + multiImgController.getAddedFile.isNotEmpty; + } } diff --git a/lib/pages/processing/processing_edit_editor.dart b/lib/pages/processing/processing_edit_editor.dart index 908dbd4..40af132 100644 --- a/lib/pages/processing/processing_edit_editor.dart +++ b/lib/pages/processing/processing_edit_editor.dart @@ -68,7 +68,7 @@ class _ProcessingEditEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this._user = u; }); @@ -267,10 +267,23 @@ class _ProcessingEditEditorState extends State { } isDataChanged() { - return _user.fcsID != "" || - selectedMarket != "" || - _descCtl.text != "" || - _remarkCtl.text != "" || - multiImgController.getAddedFile.isNotEmpty; + if (isNew) { + return _user.fcsID != "" || + selectedMarket != null || + _descCtl.text != "" || + _remarkCtl.text != "" || + multiImgController.getAddedFile.isNotEmpty; + } else { + var _package = Package( + trackingID: widget.package.trackingID, + fcsID: _user.fcsID, + market: selectedMarket, + desc: _descCtl.text, + remark: _remarkCtl.text, + photoUrls: widget.package.photoUrls); + return widget.package.isChangedForEditProcessing(_package) || + multiImgController.getAddedFile.isNotEmpty || + multiImgController.getDeletedUrl.isNotEmpty; + } } } diff --git a/lib/pages/processing/processing_editor.dart b/lib/pages/processing/processing_editor.dart index dab0ad2..3618af4 100644 --- a/lib/pages/processing/processing_editor.dart +++ b/lib/pages/processing/processing_editor.dart @@ -62,11 +62,11 @@ class _ProcesingEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this.consignee = u; }); - })), + }, popPage: true)), ], ); @@ -104,11 +104,11 @@ class _ProcesingEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this.sender = u; }); - })), + }, popPage: true)), ], ); @@ -148,7 +148,8 @@ class _ProcesingEditorState extends State { ), onPressed: () async { if (this.consignee == null) { - showMsgDialog(context, "Warning", "Please select 'Consignee'"); + showMsgDialog( + context, "Warning", "Please select 'Consignee'"); return; } Package _package = await Navigator.push( @@ -181,13 +182,7 @@ class _ProcesingEditorState extends State { icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () { - if (isDataChanged()) { - showConfirmDialog(context, "back.button_confirm", () { - Navigator.of(context).pop(); - }); - } else { - Navigator.of(context).pop(); - } + Navigator.of(context).pop(); }, ), shadowColor: Colors.transparent, @@ -290,16 +285,4 @@ class _ProcesingEditorState extends State { }); } } - - isDataChanged() { - if (_isNew) { - return this.packages.isNotEmpty || consignee != null || sender != null; - } else { - Processing _processing = Processing( - userID: consignee.fcsID, - fcsID: sender.fcsID, - packages: this.packages); - return widget.processing.isChangedForEdit(_processing); - } - } } diff --git a/lib/pages/processing_old/processing_editor.dart b/lib/pages/processing_old/processing_editor.dart index e521dc3..0179675 100644 --- a/lib/pages/processing_old/processing_editor.dart +++ b/lib/pages/processing_old/processing_editor.dart @@ -69,7 +69,7 @@ class _ProcessingEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this._user = u; }); diff --git a/lib/pages/rates/custom_editor.dart b/lib/pages/rates/custom_editor.dart index 9633fb2..018804d 100644 --- a/lib/pages/rates/custom_editor.dart +++ b/lib/pages/rates/custom_editor.dart @@ -1,4 +1,4 @@ -import 'package:fcs/domain/entities/custom_duty.dart'; +import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/pages/main/util.dart'; @@ -12,7 +12,7 @@ import 'package:provider/provider.dart'; import 'model/shipment_rate_model.dart'; class CustomEditor extends StatefulWidget { - final CustomDuty custom; + final CargoType custom; CustomEditor({this.custom}); @override @@ -25,7 +25,7 @@ class _CustomEditorState extends State { TextEditingController _shipmentRateController = new TextEditingController(); bool _isLoading = false; - CustomDuty _custom = new CustomDuty(); + CargoType _custom = new CargoType(); bool _isNew = false; @override @@ -33,11 +33,10 @@ class _CustomEditorState extends State { super.initState(); if (widget.custom != null) { _custom = widget.custom; - _productController.text = _custom.productType; - _feeController.text = _custom.fee.toStringAsFixed(2); - _shipmentRateController.text = _custom.shipmentRate == null - ? "" - : _custom.shipmentRate.toStringAsFixed(2); + _productController.text = _custom.name; + _feeController.text = _custom.customDutyFee.toStringAsFixed(2); + _shipmentRateController.text = + _custom.rate == null ? "" : _custom.rate.toStringAsFixed(2); } else { _isNew = true; } @@ -123,11 +122,10 @@ class _CustomEditorState extends State { try { var shipmentRateModel = Provider.of(context, listen: false); - CustomDuty _customduty = CustomDuty( - productType: _productController.text, - fee: double.parse(_feeController.text), - shipmentRate: double.parse(_shipmentRateController.text)); - print('_customduty => $_customduty'); + CargoType _customduty = CargoType( + name: _productController.text, + customDutyFee: double.parse(_feeController.text), + rate: double.parse(_shipmentRateController.text)); if (_isNew) { await shipmentRateModel.addCustomDuty(_customduty); } else { @@ -173,12 +171,11 @@ class _CustomEditorState extends State { _feeController.text != "" || _shipmentRateController.text != ""; } else { - CustomDuty _customduty = CustomDuty( - productType: _productController.text, - fee: double.parse(_feeController.text), - // shipmentRate: double.parse(_shipmentRateController.text) - ); - return widget.custom.isChangedForEdit(_customduty); + CargoType _customduty = CargoType( + name: _productController.text, + customDutyFee: double.parse(_feeController.text), + rate: double.parse(_shipmentRateController.text)); + return widget.custom.isChangedForEditCustomDuty(_customduty); } } } diff --git a/lib/pages/rates/custom_list.dart b/lib/pages/rates/custom_list.dart index dc65fed..bbff27c 100644 --- a/lib/pages/rates/custom_list.dart +++ b/lib/pages/rates/custom_list.dart @@ -1,3 +1,4 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/custom_duty.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/theme.dart'; @@ -74,8 +75,7 @@ class _CustomListState extends State { ), itemCount: shipmentRateModel.rate.customDuties.length, itemBuilder: (context, index) { - CustomDuty custom = - shipmentRateModel.rate.customDuties[index]; + CargoType custom = shipmentRateModel.rate.customDuties[index]; return InkWell( onTap: () { _selected @@ -86,11 +86,11 @@ class _CustomListState extends State { }, child: Container( child: _row( - custom.productType, - "\$ " + custom.fee.toStringAsFixed(2), - custom.shipmentRate == null + custom.name, + "Custom Fee \$ " + custom.customDutyFee.toStringAsFixed(2), + custom.rate == null ? "" - : "\$ " + custom.shipmentRate.toStringAsFixed(2)), + : "Shipment rate \$ " + custom.rate.toStringAsFixed(2)), ), ); }), @@ -120,7 +120,7 @@ class _CustomListState extends State { : Padding( padding: const EdgeInsets.only(top: 3.0), child: Text( - "\$ " + "$shipmentRate", + "$shipmentRate", style: TextStyle(color: Colors.grey, fontSize: 14), ), ) diff --git a/lib/pages/rates/model/shipment_rate_model.dart b/lib/pages/rates/model/shipment_rate_model.dart index 1bf26d3..4304dc1 100644 --- a/lib/pages/rates/model/shipment_rate_model.dart +++ b/lib/pages/rates/model/shipment_rate_model.dart @@ -50,16 +50,18 @@ class ShipmentRateModel extends BaseModel { //CustomDuty - Future addCustomDuty(CustomDuty customDuty) { - return Services.instance.rateService.createCustomDuty(customDuty); + Future addCustomDuty(CargoType customDuty) { + customDuty.isCutomDuty=true; + return Services.instance.rateService.createCargoType(customDuty); } - Future updateCustomDuty(CustomDuty customDuty) { - return Services.instance.rateService.updateCustomDuty(customDuty); + Future updateCustomDuty(CargoType customDuty) { + customDuty.isCutomDuty=true; + return Services.instance.rateService.updateCargoType(customDuty); } Future deleteCustomDuty(String id) { - return Services.instance.rateService.deleteCustomDuty(id); + return Services.instance.rateService.deleteCargoType(id); } //Discount by weight diff --git a/lib/pages/rates/shipment_rates.dart b/lib/pages/rates/shipment_rates.dart index 0da9be3..ff4d865 100644 --- a/lib/pages/rates/shipment_rates.dart +++ b/lib/pages/rates/shipment_rates.dart @@ -145,14 +145,10 @@ class _ShipmentRatesState extends State { "Volumetric Ratio", "${rate.volumetricRatio.toStringAsFixed(2)}", "in3 per pound"), - _row( - "Weight difference discount", - "${rate.diffDiscountWeight.toStringAsFixed(2)}", - "pounds"), - _row( - "Weight difference rate", - "\$ ${rate.diffWeightRate.toStringAsFixed(2)}", - ""), + _row("Weight difference discount", + "${rate.diffDiscountWeight.toStringAsFixed(2)}", "pounds"), + _row("Weight difference rate", + "\$ ${rate.diffWeightRate.toStringAsFixed(2)}", ""), Divider( color: Colors.grey, ), @@ -195,10 +191,10 @@ class _ShipmentRatesState extends State { }).toList(); } - List getCustonWidget(List customs) { + List getCustonWidget(List customs) { return customs.map((c) { return Container( - child: _row(c.productType, "\$ " + c.fee.toStringAsFixed(2), ''), + child: _row(c.name, "\$ " + c.customDutyFee.toStringAsFixed(2), ''), ); }).toList(); } diff --git a/lib/pages/rates/shipment_rates_edit.dart b/lib/pages/rates/shipment_rates_edit.dart index 7d0cdb0..b85f5aa 100644 --- a/lib/pages/rates/shipment_rates_edit.dart +++ b/lib/pages/rates/shipment_rates_edit.dart @@ -44,7 +44,8 @@ class _ShipmentRatesEditState extends State { _minWeight.text = rate.freeDeliveryWeight?.toStringAsFixed(2) ?? ""; _deliveryFee.text = rate.deliveryFee?.toStringAsFixed(2) ?? ""; _volumetricRatio.text = rate.volumetricRatio?.toStringAsFixed(2) ?? ""; - _diffDiscountWeight.text = rate.diffDiscountWeight?.toStringAsFixed(2) ?? ""; + _diffDiscountWeight.text = + rate.diffDiscountWeight?.toStringAsFixed(2) ?? ""; _diffWeightRate.text = rate.diffWeightRate?.toStringAsFixed(2) ?? ""; } @@ -162,120 +163,4 @@ class _ShipmentRatesEditState extends State { ); return rate.isChangedForEdit(_rate); } - - List getCargoRows(List cargos) { - return cargos.map((r) { - return MyDataRow( - onSelectChanged: (selected) { - Navigator.push( - context, - CupertinoPageRoute(builder: (context) => CargoEditor(cargo: r)), - ); - }, - cells: [ - MyDataCell( - new Text( - r.name, - style: textStyle, - ), - ), - MyDataCell( - new Text( - r.rate.toString(), - style: textStyle, - ), - ), - MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), - ], - ); - }).toList(); - } - - List getCustomsRows(List customs) { - return customs.map((c) { - return MyDataRow( - onSelectChanged: (selected) { - Navigator.push( - context, - CupertinoPageRoute(builder: (context) => CustomEditor(custom: c)), - ); - }, - cells: [ - MyDataCell( - new Text( - c.productType, - style: textStyle, - ), - ), - MyDataCell( - new Text( - c.fee.toString(), - style: textStyle, - ), - ), - MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), - ], - ); - }).toList(); - } - - List getDiscounts(List discounts) { - return discounts.map((d) { - return MyDataRow( - onSelectChanged: (selected) { - // Navigator.push( - // context, - // CupertinoPageRoute(builder: (context) => CargoEditor(rate: r)), - // ); - }, - cells: [ - MyDataCell( - new Text( - "${d.weight} lb", - style: textStyle, - ), - ), - MyDataCell( - Center( - child: new Text( - d.discount.toString(), - style: textStyle, - ), - ), - ), - MyDataCell(IconButton(icon: Icon(Icons.delete), onPressed: null)), - ], - ); - }).toList(); - } - - _row(String desc, String price, String unit) { - return Container( - padding: EdgeInsets.only(left: 25, top: 5, bottom: 5), - child: Row( - children: [ - Text('$desc ', style: TextStyle(fontSize: 15)), - Spacer(), - Column( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 3.0), - child: Text( - '$price', - style: TextStyle(color: primaryColor, fontSize: 14), - ), - ), - Text( - '$unit', - style: TextStyle(color: Colors.grey, fontSize: 14), - ), - ], - ), - SizedBox( - width: 50, - ), - ], - )); - } } diff --git a/lib/pages/receiving/receiving_editor.dart b/lib/pages/receiving/receiving_editor.dart index f9c670f..ae454d8 100644 --- a/lib/pages/receiving/receiving_editor.dart +++ b/lib/pages/receiving/receiving_editor.dart @@ -77,11 +77,11 @@ class _ReceivingEditorState extends State { )), IconButton( icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { + onPressed: () => searchUser(context, onUserSelect: (u) { setState(() { this.user = u; }); - })), + },popPage: true)), ], ); diff --git a/lib/pages/shipment/shipment_box_editor.dart b/lib/pages/shipment/shipment_box_editor.dart index 5d0b46d..da45800 100644 --- a/lib/pages/shipment/shipment_box_editor.dart +++ b/lib/pages/shipment/shipment_box_editor.dart @@ -81,6 +81,7 @@ class _ShipmentBoxEditorState extends State { @override Widget build(BuildContext context) { + var deliveryAddressModel = Provider.of(context); final shipmentWeightBox = DisplayText( labelTextKey: "shipment.box.shipment.weight", text: shipmentWeight == null ? "" : shipmentWeight.toStringAsFixed(0), @@ -190,8 +191,9 @@ class _ShipmentBoxEditorState extends State { context, CupertinoPageRoute( builder: (context) => DeliveryAddressSelection( - deliveryAddress: _box.deliveryAddress, - )), + deliveryAddress: _box.deliveryAddress, + deliveryAddresses: + deliveryAddressModel.deliveryAddresses)), ); if (d == null) return; setState(() { diff --git a/lib/pages/shipment/shipment_editor.dart b/lib/pages/shipment/shipment_editor.dart index 0dbc141..ae27bba 100644 --- a/lib/pages/shipment/shipment_editor.dart +++ b/lib/pages/shipment/shipment_editor.dart @@ -91,6 +91,7 @@ class _ShipmentEditorState extends State { bool isCourierPickup = _selectedShipmentType == shipment_courier_pickup; bool isLocalDropoff = _selectedShipmentType == shipment_local_dropoff; bool isCourierDropoff = _selectedShipmentType == shipment_courier_dropoff; + var deliveryAddressModel = Provider.of(context); final fromTimeBox = InputTime( labelTextKey: 'shipment.from', iconData: Icons.timer, @@ -129,6 +130,7 @@ class _ShipmentEditorState extends State { CupertinoPageRoute( builder: (context) => DeliveryAddressSelection( deliveryAddress: _shipment.pickupAddress, + deliveryAddresses: deliveryAddressModel.deliveryAddresses, )), ); if (address == null) return; diff --git a/lib/pages/user_search/user_list_row.dart b/lib/pages/user_search/user_list_row.dart index 5f99621..da8822f 100644 --- a/lib/pages/user_search/user_list_row.dart +++ b/lib/pages/user_search/user_list_row.dart @@ -4,9 +4,9 @@ import 'package:fcs/pages/user_search/user_serach.dart'; import 'package:flutter/material.dart'; class UserListRow extends StatefulWidget { - final CallbackUserSelect callbackUserSelect; + final OnUserRowSelect onUserRowSelect; final User user; - const UserListRow({this.user, this.callbackUserSelect}); + const UserListRow({this.user, this.onUserRowSelect}); @override _UserListRowState createState() => _UserListRowState(); @@ -30,9 +30,8 @@ class _UserListRowState extends State { color: Colors.white, child: InkWell( onTap: () { - Navigator.pop(context); - if (widget.callbackUserSelect != null) - widget.callbackUserSelect(widget.user); + if (widget.onUserRowSelect != null) + widget.onUserRowSelect(widget.user); }, child: Row( children: [ diff --git a/lib/pages/user_search/user_serach.dart b/lib/pages/user_search/user_serach.dart index 4d227ef..0225b62 100644 --- a/lib/pages/user_search/user_serach.dart +++ b/lib/pages/user_search/user_serach.dart @@ -5,19 +5,22 @@ import 'package:fcs/pages/user_search/user_list_row.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; -typedef CallbackUserSelect(User suer); +typedef OnUserSelect(User suer); +typedef OnUserRowSelect(User suer); Future searchUser(BuildContext context, - {CallbackUserSelect callbackUserSelect}) async => + {OnUserSelect onUserSelect, bool popPage = false}) async => await showSearch( context: context, - delegate: UserSearchDelegate(callbackUserSelect: callbackUserSelect), + delegate: + UserSearchDelegate(onUserSelect: onUserSelect, popPage: popPage), ); class UserSearchDelegate extends SearchDelegate { - final CallbackUserSelect callbackUserSelect; + final OnUserSelect onUserSelect; + final bool popPage; - UserSearchDelegate({this.callbackUserSelect}); + UserSearchDelegate({this.onUserSelect, this.popPage}); @override String get searchFieldLabel => 'Search by FCS ID or Name'; @@ -77,7 +80,7 @@ class UserSearchDelegate extends SearchDelegate { children: snapshot.data .map((u) => UserListRow( user: u, - callbackUserSelect: callbackUserSelect, + onUserRowSelect: (u) => _onUserRowSelect(context, u), )) .toList(), ), @@ -113,4 +116,13 @@ class UserSearchDelegate extends SearchDelegate { ), ); } + + _onUserRowSelect(BuildContext context, User user) { + if (onUserSelect != null) { + onUserSelect(user); + } + if (popPage) { + Navigator.pop(context); + } + } } diff --git a/lib/pages/widgets/delivery_address_selection.dart b/lib/pages/widgets/delivery_address_selection.dart index 87e52f4..f505409 100644 --- a/lib/pages/widgets/delivery_address_selection.dart +++ b/lib/pages/widgets/delivery_address_selection.dart @@ -1,24 +1,42 @@ +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/delivery_address/delivery_address_editor.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/widgets/bottom_up_page_route.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +typedef OnAdded(); + class DeliveryAddressSelection extends StatelessWidget { final DeliveryAddress deliveryAddress; + final List deliveryAddresses; + final User user; + final OnAdded onAdded; - const DeliveryAddressSelection({Key key, this.deliveryAddress}) + const DeliveryAddressSelection( + {Key key, + this.deliveryAddress, + this.deliveryAddresses, + this.user, + this.onAdded}) : super(key: key); + Future> _getDeliverAddresses( + BuildContext context) async { + var addressModel = + Provider.of(context, listen: false); + + var _deliveryAddresses = await addressModel.getDeliveryAddresses(user.id); + return _deliveryAddresses; + } + @override Widget build(BuildContext context) { - var shipmentModel = Provider.of(context); - + if (user != null) {} return Scaffold( appBar: AppBar( centerTitle: true, @@ -32,9 +50,15 @@ class DeliveryAddressSelection extends StatelessWidget { color: primaryColor, fontSize: 20), ), floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push(CupertinoPageRoute( - builder: (context) => DeliveryAddressEditor())); + onPressed: () async { + bool updated = await Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => DeliveryAddressEditor( + user: user, + ))); + if (updated && onAdded != null) { + onAdded(); + Navigator.pop(context); + } }, icon: Icon(Icons.add), label: LocalText(context, "delivery_address.new_address", @@ -47,9 +71,9 @@ class DeliveryAddressSelection extends StatelessWidget { separatorBuilder: (c, i) => Divider( color: primaryColor, ), - itemCount: shipmentModel.deliveryAddresses.length, + itemCount: deliveryAddresses.length, itemBuilder: (context, index) { - return _row(context, shipmentModel.deliveryAddresses[index]); + return _row(context, deliveryAddresses[index]); }), )); } diff --git a/lib/pages/widgets/dialog_input.dart b/lib/pages/widgets/dialog_input.dart index 0edb5b5..6ebe4b0 100644 --- a/lib/pages/widgets/dialog_input.dart +++ b/lib/pages/widgets/dialog_input.dart @@ -7,6 +7,7 @@ import 'local_text.dart'; class DialogInput extends StatefulWidget { final String value; final String label; + const DialogInput({Key key, this.label, this.value}) : super(key: key); @override _DialogInputState createState() => _DialogInputState(); @@ -15,6 +16,7 @@ class DialogInput extends StatefulWidget { class _DialogInputState extends State { final _formKey = GlobalKey(); TextEditingController _controller = new TextEditingController(); + final _focusNode = FocusNode(); bool _isLoading = false; @@ -23,6 +25,12 @@ class _DialogInputState extends State { super.initState(); if (widget.value != null) { _controller.text = widget.value; + _focusNode.addListener(() { + if (_focusNode.hasFocus) { + _controller.selection = TextSelection( + baseOffset: 0, extentOffset: _controller.text.length); + } + }); } } @@ -41,6 +49,8 @@ class _DialogInputState extends State { key: _formKey, child: TextField( controller: _controller, + focusNode: _focusNode, + autofocus: true, keyboardType: TextInputType.number, decoration: new InputDecoration( focusedBorder: UnderlineInputBorder(