From 4d0e5b68339084a9a064c8f404131986f44dafc3 Mon Sep 17 00:00:00 2001 From: Sai Naw Wun Date: Tue, 20 Oct 2020 06:19:10 +0630 Subject: [PATCH] add carton api --- assets/local/localization_en.json | 1 + assets/local/localization_mu.json | 1 + lib/domain/constants.dart | 5 + lib/domain/entities/carton.dart | 13 +- lib/pages/carton/cargo_type_editor.dart | 1 - lib/pages/carton/carton_cargo_table.dart | 118 ++++ lib/pages/carton/carton_editor.dart | 520 ++++++------------ lib/pages/carton/carton_info.dart | 430 ++++----------- lib/pages/carton/carton_mix_table.dart | 87 +++ lib/pages/carton/carton_package_table.dart | 120 ++++ lib/pages/carton/model/carton_model.dart | 308 ++--------- lib/pages/carton/widgets.dart | 24 + lib/pages/fcs_shipment/fcs_shipment_info.dart | 2 +- lib/pages/package/model/package_model.dart | 3 +- lib/pages/shipment/widgets.dart | 2 - 15 files changed, 685 insertions(+), 950 deletions(-) create mode 100644 lib/pages/carton/carton_cargo_table.dart create mode 100644 lib/pages/carton/carton_mix_table.dart create mode 100644 lib/pages/carton/carton_package_table.dart create mode 100644 lib/pages/carton/widgets.dart diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index ac4eb8b..bfd6f44 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -285,6 +285,7 @@ "box.popupmenu.active":"Active Cartons", "box.popupmenu.delivered":"Delivered Cartons", "box.cargo.total":"Total Weight", + "box.delete.confirm":"Delete carton?", "Boxes End ================================================================":"", "Delivery Start ================================================================":"", diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index 877a894..27cbaa5 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -285,6 +285,7 @@ "box.popupmenu.active":"လာမည့် သေတ္တာများ", "box.popupmenu.delivered":"ပို့ပြီးသော သေတ္တာများ", "box.cargo.total":"စုစုပေါင်း အလေးချိန်", + "box.delete.confirm":"Delete carton?", "Boxes End ================================================================":"", "Delivery Start ================================================================":"", diff --git a/lib/domain/constants.dart b/lib/domain/constants.dart index bffb153..c5ac918 100644 --- a/lib/domain/constants.dart +++ b/lib/domain/constants.dart @@ -75,6 +75,11 @@ const carton_from_packages = "From packages"; const carton_from_shipments = "From shipments"; const carton_mix_box = "Mix carton"; +//Carton status +const carton_packed_status = "packed"; +const carton_shipped_status = "shipped"; +const carton_delivered_status = "delivered"; + // shipment status const shipment_pending_status = "pending"; const shipment_assigned_status = "assigned"; diff --git a/lib/domain/entities/carton.dart b/lib/domain/entities/carton.dart index 954c65c..5c68ace 100644 --- a/lib/domain/entities/carton.dart +++ b/lib/domain/entities/carton.dart @@ -25,6 +25,7 @@ class Carton { double length; int shipmentWeight; bool isChecked; + bool isShipmentCarton; String cartonType; String fcsID; String userName; @@ -40,10 +41,12 @@ class Carton { String remark; DateTime arrivedDate; String cartonNumber; + List packageIDs; List packages; List cargoTypes; + List cartons; DeliveryAddress deliveryAddress; @@ -129,6 +132,9 @@ class Carton { this.cartonNumber, this.fcsShipmentID, this.fcsShipmentNumber, + this.cartons, + this.packageIDs, + this.isShipmentCarton = false, this.deliveryAddress}); Map toMap() { @@ -136,6 +142,8 @@ class Carton { List _packages = packages?.map((c) => c.toJson())?.toList(); return { "id": id, + 'fcs_shipment_id': fcsShipmentID, + 'user_id': userID, 'cargo_types': _cargoTypes, 'packages': _packages, 'length': length, @@ -166,9 +174,12 @@ class Carton { fcsID: map['fcs_id'], cartonType: map['carton_type'], cartonNumber: map['carton_number'], - status: map['status'], + userID: map['user_id'], fcsShipmentID: map['fcs_shipment_id'], fcsShipmentNumber: map['fcs_shipment_number'], + isShipmentCarton: map['is_shipment_carton'], + status: map['status'], + packageIDs: List.from(map['package_ids'] ?? []), deliveryAddress: _da, cargoTypes: cargoTypes); } diff --git a/lib/pages/carton/cargo_type_editor.dart b/lib/pages/carton/cargo_type_editor.dart index 8ef809d..876250b 100644 --- a/lib/pages/carton/cargo_type_editor.dart +++ b/lib/pages/carton/cargo_type_editor.dart @@ -105,7 +105,6 @@ class _CargoTypeEditorState extends State { cargoTypeBox, rateBox, SizedBox(height: 40), - Spacer(), saveBtn, SizedBox(height: 20), ], diff --git a/lib/pages/carton/carton_cargo_table.dart b/lib/pages/carton/carton_cargo_table.dart new file mode 100644 index 0000000..3b49332 --- /dev/null +++ b/lib/pages/carton/carton_cargo_table.dart @@ -0,0 +1,118 @@ +import 'package:fcs/domain/entities/cargo_type.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/my_data_table.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +import 'cargo_type_editor.dart'; + +typedef OnAdd(CargoType cargoType); +typedef OnRemove(CargoType cargoType); + +class CargoTable extends StatelessWidget { + final List cargoTypes; + final OnAdd onAdd; + final OnRemove onRemove; + + const CargoTable({Key key, this.cargoTypes, this.onAdd, this.onRemove}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return MyDataTable( + headingRowHeight: 40, + columns: [ + MyDataColumn( + label: LocalText( + context, + "cargo.type", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "cargo.weight", + color: Colors.grey, + ), + ), + ], + rows: getCargoRows(context), + ); + } + + List getCargoRows(BuildContext context) { + if (cargoTypes == null) { + return []; + } + double total = 0; + var rows = cargoTypes.map((c) { + total += c.weight; + return MyDataRow( + onSelectChanged: (bool selected) async { + CargoType cargo = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => CargoTypeEditor( + cargo: c, + ))); + if (onAdd != null) onAdd(cargo); + }, + cells: [ + MyDataCell(new Text( + c.name == null ? "" : c.name, + style: textStyle, + )), + MyDataCell( + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text(c.weight == null ? "0" : c.weight.toString(), + style: textStyle), + onRemove == null + ? SizedBox( + width: 50, + ) + : IconButton( + icon: Icon( + Icons.remove_circle, + color: primaryColor, + ), + onPressed: () { + if (onRemove != null) onRemove(c); + }) + ], + ), + ), + ], + ); + }).toList(); + + var totalRow = MyDataRow( + onSelectChanged: (bool selected) {}, + cells: [ + MyDataCell(Align( + alignment: Alignment.centerRight, + child: LocalText( + context, + "shipment.cargo.total", + color: Colors.black87, + fontWeight: FontWeight.bold, + ), + )), + MyDataCell( + Padding( + padding: const EdgeInsets.only(right: 48.0), + child: Align( + alignment: Alignment.centerRight, + child: Text(total.toString(), + style: TextStyle(fontWeight: FontWeight.bold))), + ), + ), + ], + ); + rows.add(totalRow); + return rows; + } +} diff --git a/lib/pages/carton/carton_editor.dart b/lib/pages/carton/carton_editor.dart index c42b826..6e02991 100644 --- a/lib/pages/carton/carton_editor.dart +++ b/lib/pages/carton/carton_editor.dart @@ -7,6 +7,9 @@ import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/carton/carton_cargo_table.dart'; +import 'package:fcs/pages/carton/carton_mix_table.dart'; +import 'package:fcs/pages/carton/carton_package_table.dart'; import 'package:fcs/pages/delivery_address/delivery_address_row.dart'; import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart'; import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; @@ -35,6 +38,7 @@ import 'package:flutter_icons/flutter_icons.dart'; import 'package:provider/provider.dart'; import 'cargo_type_editor.dart'; import 'model/carton_model.dart'; +import 'widgets.dart'; class CartonEditor extends StatefulWidget { final Carton box; @@ -49,14 +53,12 @@ class _CartonEditorState extends State { TextEditingController _heightController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController(); - Carton _box; + Carton _carton; bool _isLoading = false; bool _isNew; DeliveryAddress _deliveryAddress = new DeliveryAddress(); User _user; String _selectedCartonType; - List _packages = []; - List _mixBoxes = []; double volumetricRatio = 0; double shipmentWeight = 0; FcsShipment _fcsShipment; @@ -66,19 +68,6 @@ class _CartonEditorState extends State { void initState() { super.initState(); - //for shipment boxes - var boxModel = Provider.of(context, listen: false); - - //for mix boxes - _mixBoxes = [ - boxModel.boxeList[0], - boxModel.boxeList[1], - boxModel.boxeList[2] - ]; - _mixBoxes.forEach((b) { - b.isChecked = false; - }); - //for shipment weight volumetricRatio = Provider.of(context, listen: false) .rate @@ -88,16 +77,16 @@ class _CartonEditorState extends State { _heightController.addListener(_calShipmentWeight); if (widget.box != null) { - _box = widget.box; - _deliveryAddress = _box.deliveryAddress; - _widthController.text = _box.width.toString(); - _heightController.text = _box.height.toString(); - _lengthController.text = _box.length.toString(); - _selectedCartonType = _box.cartonType; + _carton = widget.box; + _deliveryAddress = _carton.deliveryAddress; + _widthController.text = _carton.width.toString(); + _heightController.text = _carton.height.toString(); + _lengthController.text = _carton.length.toString(); + _selectedCartonType = _carton.cartonType; _isNew = false; - _user = User(fcsID: _box.fcsID, name: _box.userName); + _user = User(fcsID: _carton.fcsID, name: _carton.userName); } else { - _box = Carton(cargoTypes: []); + _carton = Carton(cargoTypes: [], packages: [], cartons: []); _lengthController.text = "12"; _widthController.text = "12"; _heightController.text = "12"; @@ -111,8 +100,8 @@ class _CartonEditorState extends State { FcsShipmentModel fcsShipmentModel = Provider.of(context, listen: false); var fcsShipments = await fcsShipmentModel.getActiveFcsShipments(); - var fcsShipment = fcsShipments.firstWhere((e) => e.id == _box.fcsShipmentID, - orElse: () => null); + var fcsShipment = fcsShipments + .firstWhere((e) => e.id == _carton.fcsShipmentID, orElse: () => null); setState(() { _fcsShipments = fcsShipments; _fcsShipment = fcsShipment; @@ -140,14 +129,27 @@ class _CartonEditorState extends State { }); setState(() { - _packages = packages; + _carton.packages = packages; }); _populateDeliveryAddress(); } + _loadCartons() async { + if (_fcsShipment == null) return; + CartonModel cartonModel = Provider.of(context, listen: false); + List cartons = + await cartonModel.getCartonsByFcsShipment(_fcsShipment.id); + cartons.forEach((c) { + c.isChecked = true; + }); + setState(() { + _carton.cartons = cartons; + }); + } + _populateDeliveryAddress() { - if (_packages == null) return; - var d = _packages + if (_carton.packages == null) return; + var d = _carton.packages .firstWhere((p) => p.isChecked && p.deliveryAddress != null, orElse: () => null) ?.deliveryAddress; @@ -173,15 +175,24 @@ class _CartonEditorState extends State { @override Widget build(BuildContext context) { var boxModel = Provider.of(context); + bool isMixBox = _selectedCartonType == carton_mix_box; + final shipmentBox = DisplayText( + text: _carton.fcsShipmentNumber, + labelTextKey: "box.fcs_shipment_num", + iconData: Ionicons.ios_airplane, + ); var fcsShipmentsBox = LocalDropdown( callback: (v) { setState(() { _fcsShipment = v; }); + if (_selectedCartonType == carton_mix_box) { + _loadCartons(); + } }, labelKey: "shipment.pack.fcs.shipment", - iconData: MaterialCommunityIcons.worker, + iconData: Ionicons.ios_airplane, display: (u) => u.shipmentNumber, selectedValue: _fcsShipment, values: _fcsShipments, @@ -195,14 +206,16 @@ class _CartonEditorState extends State { labelTextKey: "box.fcs.id", icon: FcsIDIcon(), )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, callbackUserSelect: (u) { - setState(() { - this._user = u; - _loadPackages(); - }); - })), + _isNew + ? IconButton( + icon: Icon(Icons.search, color: primaryColor), + onPressed: () => searchUser(context, callbackUserSelect: (u) { + setState(() { + this._user = u; + _loadPackages(); + }); + })) + : Container(), ], ); @@ -212,151 +225,6 @@ class _CartonEditorState extends State { iconData: Icons.person, ); - final packageTitle = Container( - padding: EdgeInsets.only(right: 10.0, top: 20), - child: Row( - children: [ - Container( - width: 30, - ), - Expanded( - child: LocalText(context, 'box.tracking.id', color: Colors.grey), - ), - LocalText(context, 'box.package.desc', color: Colors.grey), - ], - ), - ); - - List getPackageRowList() { - return _packages.asMap().entries.map((p) { - return Container( - color: p.value.isChecked - ? Colors.grey.withOpacity(0.2) - : Colors.grey[50].withOpacity(0.2), - child: Container( - padding: - EdgeInsets.only(left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: p.key == _packages.length - 1 - ? Colors.white - : Colors.grey[350], - width: 1), - ), - ), - child: Row( - children: [ - Checkbox( - value: p.value.isChecked, - activeColor: primaryColor, - onChanged: (bool check) { - if (check && - _deliveryAddress != null && - p.value.deliveryAddress?.id != _deliveryAddress.id) { - return; - } - setState(() { - p.value.isChecked = check; - }); - _populateDeliveryAddress(); - }), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - p.value.trackingID, - style: textStyle, - ), - Text( - p.value.deliveryAddress?.fullName ?? "", - style: textStyle, - ), - Text( - p.value.deliveryAddress?.phoneNumber ?? "", - style: textStyle, - ), - ], - )), - new Column( - children: [ - new Text( - p.value?.desc ?? "", - style: textStyle, - ), - new Text( - "(${p.value?.market ?? ""})", - style: textStyle, - ) - ], - ) - ], - ), - ), - ); - }).toList(); - } - - final mixBoxTitle = Container( - padding: EdgeInsets.only(right: 10.0, top: 20), - child: Row( - children: [ - Container( - width: 30, - ), - Expanded( - child: LocalText(context, 'box.mix.number', color: Colors.grey), - ), - LocalText(context, 'box.mix.desc', color: Colors.grey), - ], - ), - ); - - List getMixBoxRowList() { - return _mixBoxes.asMap().entries.map((b) { - return Container( - color: b.value.isChecked - ? Colors.grey.withOpacity(0.2) - : Colors.grey[50].withOpacity(0.2), - child: Container( - padding: - EdgeInsets.only(left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: b.key == _mixBoxes.length - 1 - ? Colors.white - : Colors.grey[350], - width: 1), - ), - ), - child: Row( - children: [ - Checkbox( - value: b.value.isChecked, - activeColor: primaryColor, - onChanged: (bool check) { - setState(() { - b.value.isChecked = check; - }); - }), - Expanded( - child: new Text( - b.value.packageNumber, - style: textStyle, - )), - new Text( - b.value.desc == null ? "" : b.value.desc, - style: textStyle, - ), - ], - ), - ), - ); - }).toList(); - } - final lengthBox = LengthPicker( controller: _lengthController, lableKey: "box.length", @@ -394,14 +262,13 @@ class _CartonEditorState extends State { callBack: _save, ); - final completeBtn = LocalButton( - textKey: "box.complete.btn", + final saveBtn = LocalButton( + textKey: "box.cargo.save.btn", + callBack: _save, ); - final deliveryBtn = LocalButton( - textKey: "box.deliver.btn", - ); final cartonTypeBox = LocalRadioButtons( + readOnly: !_isNew, values: boxModel.cartonTypes, selectedValue: _selectedCartonType, callback: (v) { @@ -409,8 +276,31 @@ class _CartonEditorState extends State { setState(() { _selectedCartonType = v; }); + if (_selectedCartonType == carton_mix_box) { + _loadCartons(); + } }); + final cargoTableTitleBox = LocalTitle( + textKey: "box.cargo.type", + trailing: IconButton( + icon: Icon( + Icons.add_circle, + color: primaryColor, + ), + onPressed: () async { + CargoType cargo = await Navigator.push(context, + CupertinoPageRoute(builder: (context) => CargoTypeEditor())); + _addCargo(cargo); + }), + ); + + final cargoTableBox = CargoTable( + cargoTypes: _carton.cargoTypes, + onAdd: (c) => _addCargo(c), + onRemove: (c) => _removeCargo(c), + ); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -422,7 +312,7 @@ class _CartonEditorState extends State { ), shadowColor: Colors.transparent, backgroundColor: Colors.white, - title: widget.box == null + title: _isNew ? LocalText( context, "boxes.create.title", @@ -441,96 +331,53 @@ class _CartonEditorState extends State { child: ListView( shrinkWrap: true, children: [ + _isNew + ? Container() + : Center(child: getCartonNumberStatus(context, _carton)), LocalTitle(textKey: "box.type.title"), cartonTypeBox, LocalTitle(textKey: "box.shipment_info"), - fcsShipmentsBox, - SizedBox( - height: 10, - ), - fcsIDBox, - namebox, - _selectedCartonType == carton_from_packages - ? Column( - children: [ - LocalTitle(textKey: "box.packages"), - packageTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: getPackageRowList(), - ), - ], - ) - : _selectedCartonType == carton_mix_box - ? Column( - children: [ - LocalTitle(textKey: "box.shipment.boxes"), - mixBoxTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: getMixBoxRowList(), - ) - ], - ) - : Container(), - LocalTitle( - textKey: "box.cargo.type", - trailing: IconButton( - icon: Icon( - Icons.add_circle, - color: primaryColor, - ), - onPressed: () async { - CargoType cargo = await Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => CargoTypeEditor())); - _addCargo(cargo); - }), - ), - MyDataTable( - headingRowHeight: 40, - columns: [ - MyDataColumn( - label: LocalText( - context, - "cargo.type", - color: Colors.grey, - ), - ), - MyDataColumn( - label: LocalText( - context, - "cargo.weight", - color: Colors.grey, - ), - ), - ], - rows: getCargoRows(context), - ), - LocalTitle(textKey: "box.dimension"), - dimBox, - shipmentWeightBox, - LocalTitle(textKey: "box.delivery_address"), - DefaultDeliveryAddress( - deliveryAddress: _deliveryAddress, - labelKey: "box.delivery_address", - ), - widget.box == null - ? createBtn - : Container( - child: Column( - children: [ - completeBtn, - widget.box.status == 'Arrived' - ? deliveryBtn - : Container(), - ], - )), + _isNew ? fcsShipmentsBox : shipmentBox, + ...(isMixBox + ? [ + CartonMixTable( + cartons: _carton.cartons, + onSelect: (c, check) { + setState(() { + c.isChecked = check; + }); + }, + ) + ] + : [ + fcsIDBox, + namebox, + CartonPackageTable( + packages: _carton.packages, + onSelect: (p, checked) { + if (checked && + _deliveryAddress != null && + p.deliveryAddress?.id != _deliveryAddress.id) { + return; + } + setState(() { + p.isChecked = checked; + }); + _populateDeliveryAddress(); + }, + ), + cargoTableTitleBox, + cargoTableBox, + LocalTitle(textKey: "box.dimension"), + dimBox, + shipmentWeightBox, + LocalTitle(textKey: "box.delivery_address"), + DefaultDeliveryAddress( + deliveryAddress: _deliveryAddress, + labelKey: "box.delivery_address", + ), + ]), + _isNew ? createBtn : saveBtn, SizedBox( height: 20, ), @@ -541,75 +388,6 @@ class _CartonEditorState extends State { ); } - List getCargoRows(BuildContext context) { - if (_box?.cargoTypes == null) { - return []; - } - double total = 0; - var rows = _box.cargoTypes.map((c) { - total += c.weight; - return MyDataRow( - onSelectChanged: (bool selected) async { - CargoType cargo = await Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => CargoTypeEditor( - cargo: c, - ))); - _addCargo(cargo); - }, - cells: [ - MyDataCell(new Text( - c.name == null ? "" : c.name, - style: textStyle, - )), - MyDataCell( - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text(c.weight == null ? "0" : c.weight.toString(), - style: textStyle), - IconButton( - icon: Icon( - Icons.remove_circle, - color: primaryColor, - ), - onPressed: () => {_removeCargo(c)}, - ) - ], - ), - ), - ], - ); - }).toList(); - - var totalRow = MyDataRow( - onSelectChanged: (bool selected) {}, - cells: [ - MyDataCell(Align( - alignment: Alignment.centerRight, - child: LocalText( - context, - "shipment.cargo.total", - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - )), - MyDataCell( - Padding( - padding: const EdgeInsets.only(right: 48.0), - child: Align( - alignment: Alignment.centerRight, - child: Text(total.toString(), - style: TextStyle(fontWeight: FontWeight.bold))), - ), - ), - ], - ); - rows.add(totalRow); - return rows; - } - List getAddressList( BuildContext context, List addresses) { return addresses.asMap().entries.map((s) { @@ -623,30 +401,54 @@ class _CartonEditorState extends State { _addCargo(CargoType cargo) { if (cargo == null) return; setState(() { - _box.cargoTypes.remove(cargo); - _box.cargoTypes.add(cargo); + _carton.cargoTypes.remove(cargo); + _carton.cargoTypes.add(cargo); }); } _removeCargo(CargoType cargo) { setState(() { - _box.cargoTypes.remove(cargo); + _carton.cargoTypes.remove(cargo); }); } _save() async { - _box.cartonType = _selectedCartonType; - _box.fcsShipmentID = _fcsShipment.id; - _box.userID = _user.id; - _box.packages = _packages.map((e) => e.isChecked ? e : null).toList(); - + if (_user == null) { + showMsgDialog(context, "Error", "Please select customer"); + return; + } + if (_fcsShipment == null && _isNew) { + showMsgDialog(context, "Error", "Please select FCS shipment"); + return; + } + if ((_carton.cargoTypes?.length ?? 0) == 0) { + showMsgDialog(context, "Error", "Expect at least one cargo type"); + return; + } double l = double.parse(_lengthController.text, (s) => 0); double w = double.parse(_widthController.text, (s) => 0); double h = double.parse(_heightController.text, (s) => 0); - _box.length = l; - _box.width = w; - _box.height = h; - _box.deliveryAddress = _deliveryAddress; + if (l <= 0 || w <= 0 || h <= 0) { + showMsgDialog(context, "Error", "Invalid dimension"); + return; + } + if (_deliveryAddress == null) { + showMsgDialog(context, "Error", "Invalid delivery address"); + return; + } + + Carton carton = Carton(); + carton.id = _carton.id; + carton.cartonType = _selectedCartonType; + carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; + carton.userID = _user.id; + carton.cargoTypes = _carton.cargoTypes; + carton.packages = _carton.packages.where((e) => e.isChecked).toList(); + + carton.length = l; + carton.width = w; + carton.height = h; + carton.deliveryAddress = _deliveryAddress; setState(() { _isLoading = true; @@ -655,9 +457,9 @@ class _CartonEditorState extends State { CartonModel cartonModel = Provider.of(context, listen: false); if (_isNew) { - await cartonModel.createCarton(_box); + await cartonModel.createCarton(carton); } else { - await cartonModel.updateCarton(_box); + await cartonModel.updateCarton(carton); } Navigator.pop(context, true); } catch (e) { diff --git a/lib/pages/carton/carton_info.dart b/lib/pages/carton/carton_info.dart index 96425e7..d83e93e 100644 --- a/lib/pages/carton/carton_info.dart +++ b/lib/pages/carton/carton_info.dart @@ -1,5 +1,6 @@ -import 'package:fcs/domain/entities/carton.dart'; +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/package.dart'; import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/theme.dart'; @@ -10,6 +11,7 @@ import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/length_picker.dart'; +import 'package:fcs/pages/widgets/local_radio_buttons.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_title.dart'; import 'package:fcs/pages/widgets/progress.dart'; @@ -18,11 +20,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:timeline_list/timeline.dart'; -import 'package:timeline_list/timeline_model.dart'; +import 'carton_cargo_table.dart'; import 'carton_editor.dart'; +import 'carton_mix_table.dart'; +import 'carton_package_table.dart'; import 'model/carton_model.dart'; +import 'widgets.dart'; final DateFormat dateFormat = DateFormat("d MMM yyyy"); @@ -38,7 +42,6 @@ class _CartonInfoState extends State { bool _isLoading = false; Carton _box; String _selectedCartonType; - String _shipmentNumber; List _packages = []; List _mixBoxes = []; Carton _selectedShipmentBox = new Carton(); @@ -50,35 +53,16 @@ class _CartonInfoState extends State { double volumetricRatio = 0; double shipmentWeight = 0; + bool isMixBox; + bool isFromShipments; + bool isFromPackage; + bool isEdiable; + @override void initState() { super.initState(); _box = widget.box; - _shipmentNumber = _box.shipmentNumber; _selectedCartonType = _box.cartonType; - // for packages - var packageModel = Provider.of(context, listen: false); - _packages = [ - // packageModel.packages[0], - // packageModel.packages[1], - ]; - _packages.forEach((p) { - p.isChecked = false; - }); - - //for shipment boxes - var boxModel = Provider.of(context, listen: false); - _selectedShipmentBox = boxModel.boxeList[0]; - - //for mix boxes - _mixBoxes = [ - boxModel.boxeList[0], - boxModel.boxeList[1], - boxModel.boxeList[2] - ]; - _mixBoxes.forEach((b) { - b.isChecked = false; - }); //for shipment weight volumetricRatio = Provider.of(context, listen: false) @@ -94,6 +78,34 @@ class _CartonInfoState extends State { _cargoTypes = _box.cargoTypes; _deliveryAddress = _box.deliveryAddress; + + isMixBox = _box.cartonType == carton_mix_box; + isFromShipments = _box.cartonType == carton_from_shipments; + isFromPackage = _box.cartonType == carton_from_packages; + isEdiable = + (isMixBox || isFromPackage) && _box.status == carton_packed_status; + + if (isFromPackage) { + _loadPackages(); + } + } + + _loadPackages() async { + if (_box.cartonType == carton_from_packages && _box.userID == null) return; + PackageModel packageModel = + Provider.of(context, listen: false); + List packages = await packageModel.getPackages(_box.userID); + packages.forEach((p) { + if (_box.packageIDs.contains(p.id)) { + p.isChecked = true; + } else { + p.isChecked = false; + } + }); + + setState(() { + _box.packages = packages; + }); } _calShipmentWeight() { @@ -111,64 +123,18 @@ class _CartonInfoState extends State { } final DateFormat dateFormat = DateFormat("d MMM yyyy"); - List _models() { - if (_box.shipmentHistory == null) return []; - // return []; - return _box.shipmentHistory - .map((e) => TimelineModel( - Padding( - padding: const EdgeInsets.all(18.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(e.status, - style: TextStyle( - color: e.done ? primaryColor : Colors.grey, - fontSize: 16, - fontWeight: FontWeight.bold)), - e.status == "Processed" - ? Text("(Waiting for payment)", - style: TextStyle( - color: e.done ? primaryColor : Colors.grey, - fontSize: 14, - fontWeight: FontWeight.bold)) - : Container(), - Text(dateFormat.format(e.date)), - ], - ), - ), - iconBackground: e.done ? primaryColor : Colors.grey, - icon: Icon( - e.status == "Shipped" - ? Ionicons.ios_airplane - : e.status == "Delivered" - ? MaterialCommunityIcons.truck_fast - : e.status == "Processed" - ? MaterialIcons.check - : Octicons.package, - color: Colors.white, - ))) - .toList(); - } @override Widget build(BuildContext context) { - final cargoType = Container( - height: 30, - padding: EdgeInsets.only(left: 15), - child: Row( - children: [ - Icon(Icons.check_circle, color: primaryColor), - SizedBox( - width: 10, - ), - Text(_selectedCartonType ?? ""), - ], - ), - ); + var cartonModel = Provider.of(context); + final cartonTypeBox = LocalRadioButtons( + readOnly: true, + values: cartonModel.cartonTypesInfo, + selectedValue: + _box.isShipmentCarton ? carton_from_shipments : _box.cartonType); final shipmentBox = DisplayText( - text: _shipmentNumber == null ? "" : _shipmentNumber, + text: _box.fcsShipmentNumber, labelTextKey: "box.fcs_shipment_num", iconData: Ionicons.ios_airplane, ); @@ -184,60 +150,6 @@ class _CartonInfoState extends State { iconData: Icons.person, ); - final packageTitle = Container( - padding: EdgeInsets.only(left: 15, right: 10.0, top: 20), - child: Row( - children: [ - Expanded( - child: LocalText(context, 'box.tracking.id', color: Colors.grey), - ), - LocalText(context, 'box.package.desc', color: Colors.grey), - ], - ), - ); - - List getPackageRowList() { - return _packages.asMap().entries.map((p) { - return Container( - color: Colors.grey[50].withOpacity(0.2), - child: Container( - padding: - EdgeInsets.only(left: 15.0, right: 10.0, top: 5.0, bottom: 5.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: p.key == _packages.length - 1 - ? Colors.white - : Colors.grey[350], - width: 1), - ), - ), - child: Row( - children: [ - Expanded( - child: new Text( - p.value.trackingID, - style: textStyle, - )), - new Column( - children: [ - new Text( - p.value.desc == null ? "" : p.value.desc, - style: textStyle, - ), - new Text( - "(${p.value.market == null ? "" : p.value.market})", - style: textStyle, - ) - ], - ) - ], - ), - ), - ); - }).toList(); - } - final shipmentBoxTitle = Container( padding: EdgeInsets.only(left: 15, right: 10.0, top: 20), child: Row( @@ -270,139 +182,6 @@ class _CartonInfoState extends State { ), ); - final mixBoxTitle = Container( - padding: EdgeInsets.only(left: 15, right: 10.0, top: 20), - child: Row( - children: [ - Expanded( - child: LocalText(context, 'box.mix.number', color: Colors.grey), - ), - LocalText(context, 'box.mix.desc', color: Colors.grey), - ], - ), - ); - - List getMixBoxRowList() { - return _mixBoxes.asMap().entries.map((b) { - return Container( - color: Colors.grey[50].withOpacity(0.2), - child: Container( - padding: EdgeInsets.only( - left: 15.0, right: 10.0, top: 13.0, bottom: 13.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide( - color: b.key == _mixBoxes.length - 1 - ? Colors.white - : Colors.grey[350], - width: 1), - ), - ), - child: Row( - children: [ - Expanded( - child: new Text( - b.value.packageNumber, - style: textStyle, - )), - new Text( - b.value.desc == null ? "" : b.value.desc, - style: textStyle, - ), - ], - ), - ), - ); - }).toList(); - } - - final cargoTitle = Container( - padding: EdgeInsets.only(left: 15, right: 0.0, top: 20), - child: Row( - children: [ - Expanded( - child: LocalText(context, 'cargo.type', color: Colors.grey), - ), - Container( - padding: EdgeInsets.only(right: 10), - child: LocalText(context, 'cargo.weight', color: Colors.grey)), - ], - ), - ); - - List getCargoRowList() { - if (_cargoTypes == null) { - return []; - } - double total = 0; - - var rows = _cargoTypes.asMap().entries.map((c) { - total += c.value.weight; - return InkWell( - onTap: () {}, - child: Container( - color: Colors.grey[50].withOpacity(0.2), - child: Container( - padding: EdgeInsets.only( - left: 15.0, right: 10.0, top: 13.0, bottom: 13.0), - decoration: BoxDecoration( - border: Border( - bottom: BorderSide(color: Colors.grey[350], width: 1), - ), - ), - child: Row( - children: [ - Expanded( - child: new Text( - c.value.name, - style: textStyle, - )), - Container( - padding: EdgeInsets.only(right: 10), - child: new Text( - c.value.weight == null ? "0" : c.value.weight.toString(), - style: textStyle, - ), - ) - ], - ), - ), - ), - ); - }).toList(); - - var totalRow = InkWell( - child: Container( - color: Colors.grey[50].withOpacity(0.2), - child: Container( - padding: - EdgeInsets.only(left: 15.0, right: 10.0, top: 15.0, bottom: 15.0), - child: Row( - children: [ - Expanded( - child: new Text( - "Total Weight", - style: TextStyle(fontWeight: FontWeight.bold), - )), - Padding( - padding: const EdgeInsets.only(right: 10.0), - child: Align( - alignment: Alignment.centerRight, - child: new Text( - total.toString(), - style: TextStyle(fontWeight: FontWeight.bold), - ), - ), - ) - ], - ), - ), - )); - - rows.add(totalRow); - return rows; - } - final lengthBox = LengthPicker( controller: _lengthController, lableKey: "box.length", @@ -437,6 +216,9 @@ class _CartonInfoState extends State { labelTextKey: "box.shipment_weight", iconData: MaterialCommunityIcons.weight, ); + final cargoTableBox = CargoTable( + cargoTypes: _box.cargoTypes, + ); return LocalProgress( inAsyncCall: _isLoading, @@ -455,12 +237,18 @@ class _CartonInfoState extends State { fontSize: 20, color: primaryColor, ), - actions: [ - IconButton( - icon: Icon(Icons.edit, color: primaryColor), - onPressed: _gotoEditor, - ), - ], + actions: isEdiable + ? [ + IconButton( + icon: Icon(Icons.edit, color: primaryColor), + onPressed: _gotoEditor, + ), + IconButton( + icon: Icon(Icons.delete, color: primaryColor), + onPressed: _delete, + ), + ] + : [], ), body: Card( child: Column( @@ -469,30 +257,21 @@ class _CartonInfoState extends State { child: Padding( padding: const EdgeInsets.all(10.0), child: ListView(children: [ - // Center(child: nameWidget(_box.packageNumber)), - SizedBox( - height: 10, - ), + Center(child: getCartonNumberStatus(context, _box)), LocalTitle(textKey: "box.type.title"), - cargoType, + cartonTypeBox, LocalTitle(textKey: "box.shipment_info"), shipmentBox, fcsIDBox, customerNameBox, - _selectedCartonType == "From packages" - ? Column( - children: [ - LocalTitle(textKey: "box.packages"), - packageTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: getPackageRowList(), - ), - ], + isFromPackage + ? CartonPackageTable( + packages: _box.packages, ) - : _selectedCartonType == "From shipments" + : Container(), + isFromPackage + ? Container() + : isFromShipments ? Column( children: [ LocalTitle(textKey: "box.shipment.boxes"), @@ -504,27 +283,17 @@ class _CartonInfoState extends State { ], ) : _selectedCartonType == "Mix carton" - ? Column( - children: [ - LocalTitle(textKey: "box.shipment.boxes"), - mixBoxTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: getMixBoxRowList(), - ) - ], + ? CartonMixTable( + cartons: _box.cartons, + onSelect: (c, check) { + setState(() { + c.isChecked = check; + }); + }, ) : Container(), - LocalTitle(textKey: "box.cargo_type"), - cargoTitle, - Divider( - color: Colors.grey[400], - ), - Column( - children: getCargoRowList(), - ), + LocalTitle(textKey: "box.cargo.type"), + cargoTableBox, LocalTitle(textKey: "box.dimension"), dimBox, shipmentWeightBox, @@ -533,12 +302,6 @@ class _CartonInfoState extends State { deliveryAddress: _deliveryAddress, labelKey: "box.delivery_address", ), - LocalTitle(textKey: "box.status"), - Container( - height: 230, - child: Timeline( - children: _models(), position: TimelinePosition.Left), - ), SizedBox( height: 20, ) @@ -552,9 +315,40 @@ class _CartonInfoState extends State { } _gotoEditor() async { - Navigator.push( + bool updated = await Navigator.push( context, CupertinoPageRoute(builder: (context) => CartonEditor(box: widget.box)), ); + if (updated ?? false) { + var cartonModel = Provider.of(context, listen: false); + var c = await cartonModel.getCarton(widget.box.id); + setState(() { + _box = c; + }); + _loadPackages(); + } + } + + _delete() { + showConfirmDialog(context, "box.delete.confirm", () { + _deleteCarton(); + }); + } + + _deleteCarton() async { + setState(() { + _isLoading = true; + }); + try { + var cartonModel = Provider.of(context, listen: false); + await cartonModel.deleteCarton(widget.box); + Navigator.pop(context, true); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } } } diff --git a/lib/pages/carton/carton_mix_table.dart b/lib/pages/carton/carton_mix_table.dart new file mode 100644 index 0000000..33187c2 --- /dev/null +++ b/lib/pages/carton/carton_mix_table.dart @@ -0,0 +1,87 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnSelect = Function(Carton carton, bool checked); + +class CartonMixTable extends StatelessWidget { + final List cartons; + final OnSelect onSelect; + + const CartonMixTable({Key key, this.cartons, this.onSelect}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final tableTitle = Container( + padding: EdgeInsets.only(right: 10.0, top: 20), + child: Row( + children: [ + Container( + width: 30, + ), + Expanded( + child: LocalText(context, 'box.mix.number', color: Colors.grey), + ), + LocalText(context, 'box.cargo.total', color: Colors.grey), + ], + ), + ); + + final rows = cartons.asMap().entries.map((p) { + return Container( + color: p.value.isChecked + ? Colors.grey.withOpacity(0.2) + : Colors.grey[50].withOpacity(0.2), + child: Container( + padding: + EdgeInsets.only(left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: p.key == cartons.length - 1 + ? Colors.white + : Colors.grey[350], + width: 1), + ), + ), + child: Row( + children: [ + Checkbox( + value: p.value.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + if (onSelect != null) onSelect(p.value, check); + }), + Expanded( + child: new Text( + p.value.cartonNumber ?? "", + style: textStyle, + )), + new Text( + p.value?.actualWeight?.toString() ?? "", + style: textStyle, + ), + ], + ), + ), + ); + }).toList(); + + return Column( + children: [ + LocalTitle(textKey: "box.shipment.boxes"), + tableTitle, + Divider( + color: Colors.grey[400], + ), + Column( + children: rows, + ), + ], + ); + } +} diff --git a/lib/pages/carton/carton_package_table.dart b/lib/pages/carton/carton_package_table.dart new file mode 100644 index 0000000..07eb9f3 --- /dev/null +++ b/lib/pages/carton/carton_package_table.dart @@ -0,0 +1,120 @@ +import 'package:fcs/domain/entities/package.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:fcs/pages/widgets/local_title.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +typedef OnSelect = Function(Package package, bool checked); + +class CartonPackageTable extends StatelessWidget { + final List packages; + final OnSelect onSelect; + + const CartonPackageTable({Key key, this.packages, this.onSelect}) + : super(key: key); + + @override + Widget build(BuildContext context) { + final tableTitle = Container( + padding: EdgeInsets.only(right: 10.0, top: 20), + child: Row( + children: [ + SizedBox( + width: 50, + ), + SizedBox( + width: 150, + child: LocalText(context, 'box.tracking.id', color: Colors.grey), + ), + LocalText(context, 'box.package.desc', color: Colors.grey), + ], + ), + ); + + final rows = packages == null + ? [Container()] + : packages.asMap().entries.map((p) { + return Container( + color: p.value.isChecked + ? Colors.grey.withOpacity(0.2) + : Colors.grey[50].withOpacity(0.2), + child: Container( + padding: EdgeInsets.only( + left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: p.key == packages.length - 1 + ? Colors.white + : Colors.grey[350], + width: 1), + ), + ), + child: Row( + children: [ + onSelect == null + ? p.value.isChecked + ? SizedBox( + child: Icon(Icons.check, color: primaryColor), + width: 30) + : SizedBox(width: 30) + : Checkbox( + value: p.value.isChecked, + activeColor: primaryColor, + onChanged: (bool check) { + if (onSelect != null) onSelect(p.value, check); + }), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + p.value.trackingID, + style: textStyle, + ), + Text( + p.value.deliveryAddress?.fullName ?? "", + style: textStyle, + ), + Text( + p.value.deliveryAddress?.phoneNumber ?? "", + style: textStyle, + ), + ], + )), + Flexible( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + new Text( + p.value?.desc ?? "", + style: textStyle, + ), + new Text( + "(${p.value?.market ?? ""})", + style: textStyle, + ) + ], + ), + ) + ], + ), + ), + ); + }).toList(); + + return Column( + children: [ + LocalTitle(textKey: "box.packages"), + tableTitle, + Divider( + color: Colors.grey[400], + ), + Column( + children: rows, + ), + ], + ); + } +} diff --git a/lib/pages/carton/model/carton_model.dart b/lib/pages/carton/model/carton_model.dart index 981bd01..98e17ed 100644 --- a/lib/pages/carton/model/carton_model.dart +++ b/lib/pages/carton/model/carton_model.dart @@ -4,11 +4,8 @@ import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/data/services/services.dart'; 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/package.dart'; import 'package:fcs/domain/vo/message.dart'; import 'package:fcs/domain/vo/shipment_status.dart'; -import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/helpers/paginator.dart'; import 'package:fcs/pages/main/model/base_model.dart'; import 'package:logging/logging.dart'; @@ -30,261 +27,6 @@ class CartonModel extends BaseModel { ShipmentStatus( status: "Delivered", date: DateTime(2020, 6, 15), done: false) ]; - static List packages = [ - // PackageModel.packages[0], - // PackageModel.packages[1], - // PackageModel.packages[2] - ]; - - List boxeList = [ - Carton( - shipmentNumber: "A202", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cargoDesc: "Clothes", - desc: "Desc 1", - cartonType: carton_from_packages, - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - packages: packages, - shipmentHistory: statusHistory, - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A203", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "2", - rate: 7, - packageType: "General", - weight: 75, - status: "Packed", - cargoDesc: "Clothes", - desc: "Desc 2", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 20, - length: 30, - shipmentWeight: 36, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - cartonType: carton_from_shipments, - deliveryAddress: DeliveryAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A204", - receiverNumber: "3", - receiverName: "Ko Myo Min", - boxNumber: "3", - rate: 7, - packageType: "General", - weight: 75, - cargoDesc: "Shoes", - status: "Packed", - desc: "Desc 3", - cartonType: carton_mix_box, - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'Mg Myo', - addressLine1: '153-154 5th Thitsar.', - addressLine2: 'South Okkalapa Township', - city: 'Yangon', - state: 'Myanmar', - phoneNumber: '+09 95724 8750'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "1", - rate: 8, - packageType: "Medicine", - weight: 75, - status: "Packed", - cargoDesc: "Dietary supplement", - desc: "Desc 4", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "3", - rate: 7, - packageType: "General", - cargoDesc: "Handbags", - weight: 75, - status: "Arrived", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A202", - receiverNumber: "2", - receiverName: "Ma Aye", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Handbags", - weight: 75, - status: "Shipped", - arrivedDate: DateTime(2020, 6, 1), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "1", - rate: 9, - packageType: "Dangerous", - cargoDesc: "Phones and Scooters", - weight: 75, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - Carton( - shipmentNumber: "A201", - receiverNumber: "1", - receiverName: "Ko Wai", - boxNumber: "2", - rate: 7, - packageType: "General", - cargoDesc: "Construction tools", - weight: 75, - status: "Delivered", - arrivedDate: DateTime(2020, 5, 21), - width: 10, - height: 10, - length: 10, - shipmentWeight: 6, - shipmentHistory: statusHistory, - packages: packages, - receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon', - deliveryAddress: DeliveryAddress( - fullName: 'U Nyi Nyi', - addressLine1: '154-19 64th Ave.', - addressLine2: 'Flushing', - city: 'NY', - state: 'NY', - phoneNumber: '+1 (292)215-2247'), - cargoTypes: [ - CargoType(name: 'General', weight: 25), - CargoType(name: 'Medicine', weight: 20), - CargoType(name: 'Dangerous', weight: 30) - ]), - ]; List get completed { return boxes.where((e) => e.status == "Delivered").toList() @@ -314,6 +56,11 @@ class CartonModel extends BaseModel { } List cartonTypes = [carton_from_packages, carton_mix_box]; + List cartonTypesInfo = [ + carton_from_packages, + carton_mix_box, + carton_from_shipments + ]; set selectedIndex(int index) { _selectedIndex = index; @@ -362,16 +109,20 @@ class CartonModel extends BaseModel { try { listener = Firestore.instance .collection("$path") + .where("status", + whereIn: [carton_packed_status, carton_shipped_status]) + .where("is_deleted", isEqualTo: false) + .orderBy("created_at", descending: true) .snapshots() .listen((QuerySnapshot snapshot) { - _boxes.clear(); - _boxes = snapshot.documents.map((documentSnapshot) { - var s = Carton.fromMap( - documentSnapshot.data, documentSnapshot.documentID); - return s; - }).toList(); - notifyListeners(); - }); + _boxes.clear(); + _boxes = snapshot.documents.map((documentSnapshot) { + var s = Carton.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); + }); } catch (e) { log.warning("Error!! $e"); } @@ -391,7 +142,7 @@ class CartonModel extends BaseModel { } Future loadMore() async { - if (_delivered.ended) return; + if (_delivered.ended || selectedIndex == 1) return; isLoading = true; notifyListeners(); await _delivered.load(onFinished: () { @@ -401,6 +152,7 @@ class CartonModel extends BaseModel { } Future refresh() async { + if (selectedIndex == 1) return; await _delivered.refresh(onFinished: () { notifyListeners(); }); @@ -428,6 +180,24 @@ class CartonModel extends BaseModel { .toList(); } + Future> getCartonsByFcsShipment(String fcsShipmentID) async { + String path = "/$cartons_collection"; + var querySnap = await Firestore.instance + .collection(path) + .where("fcs_shipment_id", isEqualTo: fcsShipmentID) + .where("is_deleted", isEqualTo: false) + .getDocuments(); + return querySnap.documents + .map((e) => Carton.fromMap(e.data, e.documentID)) + .toList(); + } + + Future getCarton(String id) async { + String path = "/$cartons_collection"; + var snap = await Firestore.instance.collection(path).document(id).get(); + return Carton.fromMap(snap.data, snap.documentID); + } + Future createCarton(Carton carton) { return Services.instance.cartonService.createCarton(carton); } @@ -435,4 +205,8 @@ class CartonModel extends BaseModel { Future updateCarton(Carton carton) { return Services.instance.cartonService.updateCarton(carton); } + + Future deleteCarton(Carton carton) { + return Services.instance.cartonService.deleteCarton(carton); + } } diff --git a/lib/pages/carton/widgets.dart b/lib/pages/carton/widgets.dart new file mode 100644 index 0000000..3e9a50c --- /dev/null +++ b/lib/pages/carton/widgets.dart @@ -0,0 +1,24 @@ +import 'package:fcs/domain/entities/carton.dart'; +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; +import 'package:flutter/material.dart'; + +Widget getCartonNumberStatus(BuildContext context, Carton carton) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + LocalText( + context, + '', + text: carton.cartonNumber ?? "", + color: primaryColor, + fontSize: 18, + fontWeight: FontWeight.bold, + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: Chip(label: Text(carton.status ?? "")), + ), + ], + ); +} diff --git a/lib/pages/fcs_shipment/fcs_shipment_info.dart b/lib/pages/fcs_shipment/fcs_shipment_info.dart index e41f7c5..2fd29b8 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_info.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_info.dart @@ -186,7 +186,7 @@ class _FcsShipmentInfoState extends State { CupertinoPageRoute( builder: (context) => FcsShipmentEditor(shipment: _fcsShipment)), ); - if (updated) { + if (updated ?? false) { var shipmentModel = Provider.of(context, listen: false); var f = await shipmentModel.getFcsShipment(_fcsShipment.id); setState(() { diff --git a/lib/pages/package/model/package_model.dart b/lib/pages/package/model/package_model.dart index 1a8a037..6289bc4 100644 --- a/lib/pages/package/model/package_model.dart +++ b/lib/pages/package/model/package_model.dart @@ -204,7 +204,8 @@ class PackageModel extends BaseModel { try { var snaps = await Firestore.instance .collection("/$packages_collection") - .where("status", isEqualTo: package_processed_status) + .where("status", + whereIn: [package_processed_status, package_packed_status]) .where("user_id", isEqualTo: userID) .where("is_deleted", isEqualTo: false) .where("is_delivered", isEqualTo: false) diff --git a/lib/pages/shipment/widgets.dart b/lib/pages/shipment/widgets.dart index ab3ed24..af2b342 100644 --- a/lib/pages/shipment/widgets.dart +++ b/lib/pages/shipment/widgets.dart @@ -1,7 +1,5 @@ import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/widgets/local_popup_menu_button.dart'; -import 'package:fcs/pages/widgets/local_popupmenu.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:flutter/material.dart';