From 6105b45cb8d0236f92c5c4fe09774edb789043e7 Mon Sep 17 00:00:00 2001 From: Sai Naw Wun Date: Thu, 8 Oct 2020 03:32:52 +0630 Subject: [PATCH] add fcs shipment apis --- assets/local/localization_en.json | 4 +- lib/domain/constants.dart | 40 +-- lib/domain/entities/bank_account.dart | 31 -- lib/domain/entities/fcs_shipment.dart | 56 ++- lib/domain/entities/setting.dart | 170 ++------- lib/main-local.dart | 4 +- .../buying_instruction/buying_online.dart | 6 +- lib/pages/customer/customer_editor.dart | 6 +- lib/pages/customer/invitation_editor.dart | 2 +- lib/pages/discount/discount_editor.dart | 2 +- .../fcs_shipment/fcs_shipment_editor.dart | 339 +++++++++--------- lib/pages/fcs_shipment/fcs_shipment_list.dart | 18 +- .../fcs_shipment/fcs_shipment_list_row.dart | 33 +- .../model/fcs_shipment_model.dart | 109 +++--- lib/pages/main/home_page.dart | 5 +- lib/pages/package/package_editor.dart | 6 +- lib/pages/package/package_info.dart | 12 +- lib/pages/package/package_new.dart | 6 +- .../payment_methods/payment_method_page.dart | 2 +- lib/pages/profile/profile_page.dart | 11 +- lib/pages/staff/staff_editor.dart | 4 +- lib/pages/widgets/display_text.dart | 8 +- lib/pages/widgets/input_date.dart | 99 +++++ 23 files changed, 442 insertions(+), 531 deletions(-) delete mode 100644 lib/domain/entities/bank_account.dart create mode 100644 lib/pages/widgets/input_date.dart diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 26c8c79..9742c09 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -243,9 +243,9 @@ "FCS Shipment Start ================================================================":"", "FCSshipment.title":"FCS Shipments", - "FCSshipment.list.title":"FCS SHIPMENTS", + "FCSshipment.list.title":"FCS Shipments", "FCSshipment.add":"New FCS shipment", - "FCSshipment.form.title":"FCS SHIPMENT", + "FCSshipment.form.title":"FCS Shipment", "FCSshipment.number":"FCS Shipment Number", "FCSshipment.cutoff_date":"Cutoff Date", "FCSshipment.ETA":"ETA", diff --git a/lib/domain/constants.dart b/lib/domain/constants.dart index be1bc62..9c75bbd 100644 --- a/lib/domain/constants.dart +++ b/lib/domain/constants.dart @@ -6,6 +6,7 @@ const privilege_collection = "privileges"; const markets_collection = "markets"; const packages_collection = "packages"; const messages_collection = "messages"; +const fcs_shipment_collection = "fcs_shipments"; const user_requested_status = "requested"; const user_invited_status = "invited"; @@ -20,38 +21,7 @@ const page_buying_instructions = "buying_instructions"; const message_type_package = "t_p"; const message_type_profile = "t_profile"; -////////////////////////////// - -const ok_doc_id = "ok"; - -const biz_collection = "bizs"; -const product_collection = "products"; -const user_level_collection = "user_levels"; -const storage_collection = "storages"; -const buyer_collection = "buyers"; -const buying_pos = "buying_pos"; -const selling_pos = "selling_pos"; -const inventory_takings = "inventory_takings"; -const inventory_lines = "inventory_lines"; -const pds_collection = "pds"; -const pos_collection = "pos"; -const dos_collection = "dos"; -const notification_collection = "notifications"; -const log_collection = "logs"; -const report_collection = "reports"; -const po_product_collection = "po_products"; -const device_collection = "devices"; -const do_po_lines_collection = "do_po_lines"; -const reports_collection = "reports"; -const announcement_collection = "announcements"; -const report_user_collection = "report_users"; - -const po_files_path = "/ok/po"; -const reg_files_path = "/ok/reg"; -const do_files_path = "/ok/do"; -const sign_files_path = "/ok/sign"; -const bank_images_path = "/ok/banks"; - -const po_approved_status = "approved"; -const po_closed_status = "closed"; -const do_approved_status = "approved"; +// Fcs shipment status +const fcs_shipment_confirmed_status = "confirmed"; +const fcs_shipment_shipped_status = "shipped"; +const fcs_shipment_delivered_status = "delivered"; diff --git a/lib/domain/entities/bank_account.dart b/lib/domain/entities/bank_account.dart deleted file mode 100644 index 98027f0..0000000 --- a/lib/domain/entities/bank_account.dart +++ /dev/null @@ -1,31 +0,0 @@ -class BankAccount { - int index; - String bankName; - String bankLogo; - String accountName; - String accountNumber; - BankAccount( - {this.index, - this.bankName, - this.bankLogo, - this.accountName, - this.accountNumber}); - - BankAccount.fromMap(int index, Map json) { - this.index = index; - bankName = json['bank_name']; - bankLogo = json['bank_logo']; - accountName = json['account_name']; - accountNumber = json['account_number']; - } - - Map toMap() { - return { - "index": index, - 'bank_name': bankName, - 'bank_logo': bankLogo, - 'account_name': accountName, - 'account_number': accountNumber, - }; - } -} diff --git a/lib/domain/entities/fcs_shipment.dart b/lib/domain/entities/fcs_shipment.dart index a9802db..5a6264a 100644 --- a/lib/domain/entities/fcs_shipment.dart +++ b/lib/domain/entities/fcs_shipment.dart @@ -1,6 +1,9 @@ +import 'package:cloud_firestore/cloud_firestore.dart'; + +import '../constants.dart'; + class FcsShipment { String id; - DateTime shipDate; String shipmentNumber; DateTime cutoffDate; String shipType; @@ -10,25 +13,41 @@ class FcsShipment { String port; String destination; String status; - String remark; - FcsShipment( - {this.id, - this.shipDate, - this.shipmentNumber, - this.cutoffDate, - this.shipType, - this.status, - this.arrivalDate, - this.departureDate, - this.consignee, - this.port, - this.destination, - this.remark}); + FcsShipment({ + this.id, + this.shipmentNumber, + this.cutoffDate, + this.shipType, + this.status, + this.arrivalDate, + this.departureDate, + this.consignee, + this.port, + this.destination, + }); + + factory FcsShipment.fromMap(Map map, String docID) { + var _cutoffDate = (map['cutoff_date'] as Timestamp); + var _arrivalDate = (map['arrival_date'] as Timestamp); + var _departureDate = (map['departure_date'] as Timestamp); + + return FcsShipment( + id: docID, + cutoffDate: _cutoffDate != null ? _cutoffDate.toDate() : null, + arrivalDate: _arrivalDate != null ? _arrivalDate.toDate() : null, + departureDate: _departureDate != null ? _departureDate.toDate() : null, + shipmentNumber: map['shipment_number'], + shipType: map['shipment_type'], + status: map['status'], + consignee: map['consignee'], + port: map['port'], + destination: map['destination'], + ); + } Map toMap() { return { "id": id, - 'shipment_date': shipDate?.toUtc()?.toIso8601String(), 'shipment_number': shipmentNumber, 'cutoff_date': cutoffDate?.toUtc()?.toIso8601String(), 'shipment_type': shipType, @@ -38,7 +57,10 @@ class FcsShipment { 'port': port, 'destination': destination, 'status': status, - 'remark': remark, }; } + + bool isConfirmed() { + return status == fcs_shipment_confirmed_status; + } } diff --git a/lib/domain/entities/setting.dart b/lib/domain/entities/setting.dart index 6234da0..8a203ee 100644 --- a/lib/domain/entities/setting.dart +++ b/lib/domain/entities/setting.dart @@ -1,7 +1,3 @@ -import 'package:cloud_firestore/cloud_firestore.dart'; - -import 'bank_account.dart'; - List dayLists = [ Day(id: 1, name: 'Sun'), Day(id: 2, name: 'Mon'), @@ -26,140 +22,42 @@ class Setting { String appUrl; final String termsEng; final String termsMm; + String about; - final String okEnergyId; - final String about; - int poExpireInHours; - int doExpireInHours; - int poOpenAt; - int poCloseAt; - List poCloseOn; - int latestDeliveryDay; - int firstStorageChargeIn; - int firstStorageCharge; - int secondStorageChargeIn; - int secondStorageCharge; - int deliveryStartWaitMin; - String reportURL; - String helpVersion; - String helpURL; + List shipmentTypes; - List phones; - String deliveryPhone; - String address; - String website; - DateTime priceLastUpdate; - String bankAccountInfo; - List bankAccounts; - - String get getPoOpenAt => poOpenAt > 12 - ? (poOpenAt - 12).toString() + "PM" - : poOpenAt.toString() + "AM"; - - String get getPoCloseAt => poCloseAt > 12 - ? (poCloseAt - 12).toString() + "PM" - : poCloseAt.toString() + "AM"; - - String get getPoCloseOn => poCloseOn.fold( - "", (p, e) => p + (p == "" ? "" : ", ") + dayLists[e - 1].name); - - String get getPoOpenOn => dayLists.fold( - "", - (p, e) => - p + - (p == "" ? "" : poCloseOn.contains(e.id) ? "" : ", ") + - (poCloseOn.contains(e.id) ? "" : e.name)); - - bool get isPOClose { - DateTime now = DateTime.now(); - // dart starts from monday width starting index one - // server starts from sunday with starting index one - var day = (now.weekday + 1) == 8 ? 1 : now.weekday + 1; - return poCloseOn.contains(day) || - (now.hour < poOpenAt || now.hour >= poCloseAt); - } - - Setting( - {this.supportBuildNum, - this.usaAddress, - this.mmAddress, - this.usaContactNumber, - this.mmContactNumber, - this.emailAddress, - this.facebookLink, - this.inviteRequired, - this.appUrl, - this.termsEng, - this.termsMm, - this.about, - this.okEnergyId, - this.poExpireInHours, - this.doExpireInHours, - this.poOpenAt, - this.poCloseAt, - this.poCloseOn, - this.latestDeliveryDay, - this.firstStorageCharge, - this.firstStorageChargeIn, - this.secondStorageCharge, - this.secondStorageChargeIn, - this.deliveryStartWaitMin, - this.reportURL, - this.helpVersion, - this.helpURL, - this.phones, - this.website, - this.priceLastUpdate, - this.bankAccountInfo, - this.bankAccounts, - this.deliveryPhone, - this.address}); + Setting({ + this.supportBuildNum, + this.usaAddress, + this.mmAddress, + this.usaContactNumber, + this.mmContactNumber, + this.emailAddress, + this.facebookLink, + this.inviteRequired, + this.appUrl, + this.termsEng, + this.termsMm, + this.about, + this.shipmentTypes, + }); factory Setting.fromMap(Map map) { - var ts = (map['price_last_update'] as Timestamp); - var list = (map['bank_accounts'] as List); - - List bankAccounts = []; - if (list != null) { - list.asMap().forEach((index, item) { - bankAccounts - .add(BankAccount.fromMap(index, item.cast())); - }); - } - return Setting( - supportBuildNum: map['support_build_number'], - inviteRequired: map['invite_required'], - appUrl: map['app_url'], - usaAddress: map['usa_address'], - mmAddress: map['mm_address'], - usaContactNumber: map['usa_contact_number'], - mmContactNumber: map['mm_contact_number'], - emailAddress: map['email_address'], - facebookLink: map['facebook_link'], - about: map['about'], - termsEng: map['terms_eng'], - termsMm: map['terms_mm'], - priceLastUpdate: ts?.toDate(), - okEnergyId: map['ok_energy_id'], - poExpireInHours: map['po_expire_hours'], - doExpireInHours: map['do_expire_hours'], - poOpenAt: map['po_open_at'], - poCloseAt: map['po_close_at'], - latestDeliveryDay: map['latest_delivery_days'], - firstStorageChargeIn: map['first_storage_charge_in'], - firstStorageCharge: map['first_storage_charge'], - secondStorageChargeIn: map['second_storage_charge_in'], - secondStorageCharge: map['second_storage_charge'], - deliveryStartWaitMin: map['delivery_start_wait_min'], - reportURL: map['report_url'], - helpVersion: map['help_version'], - helpURL: map['help_url'], - deliveryPhone: map['delivery_phone'], - address: map['address'], - website: map['website'], - bankAccountInfo: map['bank_account_info'], - bankAccounts: bankAccounts); + supportBuildNum: map['support_build_number'], + inviteRequired: map['invite_required'], + appUrl: map['app_url'], + usaAddress: map['usa_address'], + mmAddress: map['mm_address'], + usaContactNumber: map['usa_contact_number'], + mmContactNumber: map['mm_contact_number'], + emailAddress: map['email_address'], + facebookLink: map['facebook_link'], + about: map['about'], + termsEng: map['terms_eng'], + termsMm: map['terms_mm'], + shipmentTypes: List.from(map['shipment_types']), + ); } Map toMap() { @@ -169,13 +67,9 @@ class Setting { }; } - String helpFileName() { - return "help-v$helpVersion.zip"; - } - @override String toString() { - return 'Setting{supportBuildNum:$supportBuildNum,about:$about,okEnergyId:$okEnergyId}'; + return 'Setting{supportBuildNum:$supportBuildNum,about:$about}'; } } diff --git a/lib/main-local.dart b/lib/main-local.dart index 6f30bf4..108729e 100644 --- a/lib/main-local.dart +++ b/lib/main-local.dart @@ -9,9 +9,9 @@ void main() { Config( flavor: Flavor.DEV, color: Colors.blue, - reportURL: "http://192.168.100.11:8080", + reportURL: "http://192.168.43.88:8080", reportProjectID: "fcs-dev", - apiURL: "http://192.168.100.11:7777", + apiURL: "http://192.168.43.88:7777", level: Level.ALL); runApp(App()); } diff --git a/lib/pages/buying_instruction/buying_online.dart b/lib/pages/buying_instruction/buying_online.dart index 7fab9fa..b029846 100644 --- a/lib/pages/buying_instruction/buying_online.dart +++ b/lib/pages/buying_instruction/buying_online.dart @@ -28,7 +28,7 @@ class _BuyingOnlinePagetate extends State final phoneNumberBox = DisplayText( text: mainModel.user.phone, - labelText: getLocalString(context, "contact.phone"), + labelTextKey: getLocalString(context, "contact.phone"), iconData: Icons.location_on, ); final nameBox = Center( @@ -38,12 +38,12 @@ class _BuyingOnlinePagetate extends State )); final fcsIdBox = DisplayText( text: mainModel.user.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), + labelTextKey: getLocalString(context, "customer.fcs.id"), icon: FcsIDIcon(), ); final shippingAddressBox = DisplayText( text: mainModel.setting.usaAddress, - labelText: getLocalString(context, "profile.usa.shipping.address"), + labelTextKey: getLocalString(context, "profile.usa.shipping.address"), iconData: Icons.location_on, ); final instructionBox = Container( diff --git a/lib/pages/customer/customer_editor.dart b/lib/pages/customer/customer_editor.dart index eeb254f..ff17923 100644 --- a/lib/pages/customer/customer_editor.dart +++ b/lib/pages/customer/customer_editor.dart @@ -32,7 +32,7 @@ class _CustomerEditorState extends State { Expanded( child: DisplayText( text: widget.customer.phoneNumber, - labelText: getLocalString(context, "customer.phone"), + labelTextKey: getLocalString(context, "customer.phone"), iconData: Icons.phone, )), IconButton( @@ -72,12 +72,12 @@ class _CustomerEditorState extends State { phoneNumberBox, DisplayText( text: widget.customer.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), + labelTextKey: getLocalString(context, "customer.fcs.id"), icon: FcsIDIcon(), ), DisplayText( text: widget.customer.status, - labelText: getLocalString(context, "customer.status"), + labelTextKey: getLocalString(context, "customer.status"), iconData: Icons.add_alarm, ), SizedBox( diff --git a/lib/pages/customer/invitation_editor.dart b/lib/pages/customer/invitation_editor.dart index f7edeb9..6c333c2 100644 --- a/lib/pages/customer/invitation_editor.dart +++ b/lib/pages/customer/invitation_editor.dart @@ -31,7 +31,7 @@ class _InvitationEditorState extends State { Expanded( child: DisplayText( text: widget.customer.phoneNumber, - labelText: getLocalString(context, "customer.phone"), + labelTextKey: getLocalString(context, "customer.phone"), iconData: Icons.phone, )), IconButton( diff --git a/lib/pages/discount/discount_editor.dart b/lib/pages/discount/discount_editor.dart index d9c9b29..454e823 100644 --- a/lib/pages/discount/discount_editor.dart +++ b/lib/pages/discount/discount_editor.dart @@ -58,7 +58,7 @@ class _DiscountEditorState extends State { controller: _amountController); final statusBox = DisplayText( text: _statusController.text, - labelText: getLocalString(context, "discount.status"), + labelTextKey: getLocalString(context, "discount.status"), iconData: Icons.av_timer, ); diff --git a/lib/pages/fcs_shipment/fcs_shipment_editor.dart b/lib/pages/fcs_shipment/fcs_shipment_editor.dart index 1430dba..83083d9 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_editor.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_editor.dart @@ -5,18 +5,17 @@ import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; import 'package:fcs/pages/main/model/language_model.dart'; import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/widgets/display_text.dart'; +import 'package:fcs/pages/widgets/input_date.dart'; import 'package:fcs/pages/widgets/input_text.dart'; -import 'package:fcs/pages/widgets/label_widgets.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/popupmenu.dart'; import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_icons/flutter_icons.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -import 'package:flutter/material.dart'; - import '../main/util.dart'; class FcsShipmentEditor extends StatefulWidget { @@ -37,22 +36,28 @@ class _FcsShipmentEditorState extends State { TextEditingController _portController = new TextEditingController(); TextEditingController _destinationController = new TextEditingController(); TextEditingController _statusController = new TextEditingController(); - TextEditingController _remarkController = new TextEditingController(); FcsShipment _shipment = new FcsShipment(); bool _isLoading = false; - String _currentShipment; + String _currentShipmentType; + bool _isNew = false; @override void initState() { super.initState(); + _isNew = widget.shipment == null; if (widget.shipment != null) { _shipment = widget.shipment; _shipmentNumberController.text = _shipment.shipmentNumber; + _cutoffDateController.text = dateFormatter.format(_shipment.cutoffDate); _arrivalDateController.text = dateFormatter.format(_shipment.arrivalDate); _departureDateControler.text = dateFormatter.format(_shipment.departureDate); _statusController.text = _shipment.status; + _currentShipmentType = _shipment.shipType; + _consigneeController.text = _shipment.consignee; + _portController.text = _shipment.port; + _destinationController.text = _shipment.destination; } } @@ -61,76 +66,21 @@ class _FcsShipmentEditorState extends State { super.dispose(); } - Widget showShipmentNumber(BuildContext context) { - return Container( - padding: EdgeInsets.only(top: 10), - child: Row( - children: [ - Icon(Icons.text_rotation_none), - Padding( - padding: const EdgeInsets.only(right: 8.0), - child: labeledText( - context, _shipmentNumberController.text, "shipment.number"), - ), - ], - ), - ); - } - - Widget showShipmentTypes( - BuildContext context, FcsShipmentModel shipmentModel) { - return Row( - mainAxisSize: MainAxisSize.max, - children: [ - Icon(MaterialCommunityIcons.box_shadow), - SizedBox( - width: 10, - ), - new Flexible( - child: Container( - width: 200.0, - child: DropdownButton( - value: _currentShipment, - isExpanded: true, - hint: Text( - 'Select shipment type', - ), - onChanged: changedDropDown, - items: shipmentModel.shipmentType - .map>((String shipment) { - return new DropdownMenuItem( - value: shipment, - child: new Text(shipment, - style: - new TextStyle(color: Colors.black87, fontSize: 17)), - ); - }).toList(), - ), - ), - ), - ], - ); - } - - void changedDropDown(selected) { - setState(() { - _currentShipment = selected; - }); - } - @override Widget build(BuildContext context) { - var shipmentModel = Provider.of(context); var languageModel = Provider.of(context); + var mainModel = Provider.of(context); final createBtn = fcsButton( context, getLocalString(context, "FCSshipment.create"), + callack: _create, ); final updateBtn = fcsButton( context, getLocalString(context, "FCSshipment.update"), + callack: _update, ); return LocalProgress( @@ -150,111 +100,74 @@ class _FcsShipmentEditorState extends State { color: primaryColor, fontSize: 18, ), - actions: [menuPopWidget(context)], + actions: _isNew ? [] : [menuPopWidget(context)], ), - body: Card( - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - // _showCustomerData(mainModel.customer), - widget.shipment == null - ? InputText( - labelTextKey: "FCSshipment.number", - iconData: Ionicons.ios_airplane, - controller: _shipmentNumberController, - ) - : DisplayText( - iconData: Ionicons.ios_airplane, - labelText: "FCSshipment.number", - text: _shipmentNumberController.text), - - widget.shipment == null - ? InputText( - labelTextKey: "FCSshipment.cutoff_date", - iconData: Icons.date_range, - controller: _cutoffDateController, - ) - : Container(), - - InputText( - labelTextKey: "FCSshipment.ETA", - iconData: Icons.date_range, - controller: _arrivalDateController, - ), - - InputText( - labelTextKey: "FCSshipment.departure_date", - iconData: Icons.date_range, - controller: _departureDateControler, - ), - widget.shipment == null - ? DropdownButtonFormField( - decoration: InputDecoration( - enabledBorder: UnderlineInputBorder( - borderSide: BorderSide(color: primaryColor)), - fillColor: Colors.white, - labelStyle: languageModel.isEng - ? labelStyle - : labelStyleMM, - labelText: AppTranslations.of(context) - .text('FCSshipment.shipment_type'), - icon: Icon(Ionicons.ios_airplane, - color: primaryColor)), - items: shipmentModel.shipmentType - .map((e) => - DropdownMenuItem(child: Text(e), value: e)) - .toList(), - onChanged: (selected) => { - setState(() { - _currentShipment = selected; - }) - }, - ) - : Container(), - - widget.shipment == null - ? InputText( - labelTextKey: 'FCSshipment.consignee', - iconData: Icons.work, - controller: _consigneeController) - : Container(), - widget.shipment == null - ? InputText( - labelTextKey: 'FCSshipment.port_of_loading', - iconData: FontAwesomeIcons.ship, - controller: _portController) - : Container(), - widget.shipment == null - ? InputText( - labelTextKey: 'FCSshipment.final_destination', - iconData: MaterialCommunityIcons.location_enter, - controller: _destinationController) - : Container(), - widget.shipment == null - ? Container() - : Container( - padding: EdgeInsets.only(top: 5), - child: DisplayText( - text: _statusController.text, - iconData: Icons.av_timer, - labelText: 'FCSshipment.status', - )), - - widget.shipment == null - ? Container() - : InputText( - labelTextKey: 'FCSshipment.remark', - iconData: MaterialCommunityIcons.note, - controller: _remarkController), - ]), - )), - widget.shipment == null ? createBtn : updateBtn, - SizedBox(height: 15) - ], - ), + body: Padding( + padding: const EdgeInsets.all(10.0), + child: ListView(children: [ + InputText( + labelTextKey: "FCSshipment.number", + iconData: Ionicons.ios_airplane, + controller: _shipmentNumberController, + ), + InputDate( + labelTextKey: "FCSshipment.cutoff_date", + iconData: Icons.date_range, + controller: _cutoffDateController, + ), + InputDate( + labelTextKey: "FCSshipment.ETA", + iconData: Icons.date_range, + controller: _arrivalDateController, + ), + InputDate( + labelTextKey: "FCSshipment.departure_date", + iconData: Icons.date_range, + controller: _departureDateControler, + ), + DropdownButtonFormField( + value: _currentShipmentType == "" ? null : _currentShipmentType, + decoration: InputDecoration( + enabledBorder: UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor)), + fillColor: Colors.white, + labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, + labelText: AppTranslations.of(context) + .text('FCSshipment.shipment_type'), + icon: Icon(Ionicons.ios_airplane, color: primaryColor)), + items: mainModel.setting.shipmentTypes + .map((e) => DropdownMenuItem(child: Text(e), value: e)) + .toList(), + onChanged: (selected) => { + setState(() { + _currentShipmentType = selected; + }) + }, + ), + InputText( + labelTextKey: 'FCSshipment.consignee', + iconData: Icons.work, + controller: _consigneeController), + InputText( + labelTextKey: 'FCSshipment.port_of_loading', + iconData: FontAwesomeIcons.ship, + controller: _portController), + InputText( + labelTextKey: 'FCSshipment.final_destination', + iconData: MaterialCommunityIcons.location_enter, + controller: _destinationController), + _isNew + ? Container() + : Container( + padding: EdgeInsets.only(top: 5), + child: DisplayText( + text: _statusController.text, + iconData: Icons.av_timer, + labelTextKey: 'FCSshipment.status', + )), + _isNew ? createBtn : updateBtn, + SizedBox(height: 15) + ]), ), ), ); @@ -312,4 +225,96 @@ class _FcsShipmentEditorState extends State { }).toList(); }); } + + FcsShipment _getPayload() { + FcsShipment fcsShipment = FcsShipment(); + fcsShipment.id = _shipment.id; + fcsShipment.shipmentNumber = _shipmentNumberController.text; + fcsShipment.shipType = _currentShipmentType; + fcsShipment.consignee = _consigneeController.text; + fcsShipment.port = _portController.text; + fcsShipment.destination = _destinationController.text; + try { + var cutoffDate = _cutoffDateController.text; + var arrivalDate = _arrivalDateController.text; + var depDate = _departureDateControler.text; + fcsShipment.cutoffDate = + cutoffDate == "" ? null : dateFormatter.parse(cutoffDate); + fcsShipment.arrivalDate = + arrivalDate == "" ? null : dateFormatter.parse(arrivalDate); + fcsShipment.departureDate = + depDate == "" ? null : dateFormatter.parse(depDate); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); // shold never happen + } + return fcsShipment; + } + + Future _validate(FcsShipment fcsShipment) async { + if (fcsShipment.shipmentNumber == "") { + await showMsgDialog(context, "Error", "Invalid shipment number!"); + return false; + } + if (fcsShipment.shipType == null) { + await showMsgDialog(context, "Error", "Invalid shipment type!"); + return false; + } + if (fcsShipment.cutoffDate == null) { + await showMsgDialog(context, "Error", "Invalid cutoff date!"); + return false; + } + if (fcsShipment.arrivalDate == null) { + await showMsgDialog(context, "Error", "Invalid ETA date!"); + return false; + } + if (fcsShipment.departureDate == null) { + await showMsgDialog(context, "Error", "Invalid departure date!"); + return false; + } + return true; + } + + Future _create() async { + FcsShipment fcsShipment = _getPayload(); + bool valid = await _validate(fcsShipment); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var shipmentModel = Provider.of(context, listen: false); + try { + await shipmentModel.create(fcsShipment); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } + + Future _update() async { + FcsShipment fcsShipment = _getPayload(); + bool valid = await _validate(fcsShipment); + if (!valid) { + return; + } + setState(() { + _isLoading = true; + }); + var shipmentModel = Provider.of(context, listen: false); + try { + await shipmentModel.update(fcsShipment); + Navigator.pop(context); + } catch (e) { + showMsgDialog(context, "Error", e.toString()); + } finally { + setState(() { + _isLoading = false; + }); + } + } } diff --git a/lib/pages/fcs_shipment/fcs_shipment_list.dart b/lib/pages/fcs_shipment/fcs_shipment_list.dart index 735c7bf..28396aa 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_list.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_list.dart @@ -4,6 +4,7 @@ import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart'; import 'package:fcs/pages/widgets/bottom_up_page_route.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/progress.dart'; +import 'package:flutter/cupertino.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; @@ -39,22 +40,12 @@ class _FcsShipmentListState extends State { appBar: AppBar( centerTitle: true, leading: new IconButton( - icon: new Icon(Icons.close), + icon: new Icon(CupertinoIcons.back), onPressed: () => Navigator.of(context).pop(), ), backgroundColor: primaryColor, title: LocalText(context, 'FCSshipment.list.title', color: Colors.white, fontSize: 20), - actions: [ - IconButton( - icon: Icon( - Icons.search, - color: Colors.white, - ), - iconSize: 30, - // onPressed: () => showPlacesSearch(context), - ), - ], ), floatingActionButton: FloatingActionButton.extended( onPressed: () { @@ -74,10 +65,11 @@ class _FcsShipmentListState extends State { scrollDirection: Axis.vertical, padding: EdgeInsets.only(top: 15), shrinkWrap: true, - itemCount: shipmentModel.shipments.length, + itemCount: shipmentModel.fcsShipments.length, itemBuilder: (BuildContext context, int index) { return FcsShipmentListRow( - shipment: shipmentModel.shipments[index]); + key: ValueKey(shipmentModel.fcsShipments[index].id), + shipment: shipmentModel.fcsShipments[index]); }), ), ], diff --git a/lib/pages/fcs_shipment/fcs_shipment_list_row.dart b/lib/pages/fcs_shipment/fcs_shipment_list_row.dart index 494108a..5c5c14e 100644 --- a/lib/pages/fcs_shipment/fcs_shipment_list_row.dart +++ b/lib/pages/fcs_shipment/fcs_shipment_list_row.dart @@ -8,27 +8,10 @@ import 'package:intl/intl.dart'; import 'fcs_shipment_editor.dart'; -class FcsShipmentListRow extends StatefulWidget { +class FcsShipmentListRow extends StatelessWidget { final FcsShipment shipment; - const FcsShipmentListRow({this.shipment}); - - @override - _FcsShipmentListRowState createState() => _FcsShipmentListRowState(); -} - -class _FcsShipmentListRowState extends State { - var dateFormatter = new DateFormat('dd MMM yyyy'); - final double dotSize = 15.0; - FcsShipment _shipment = new FcsShipment(); - - @override - void initState() { - super.initState(); - - if (widget.shipment != null) { - _shipment = widget.shipment; - } - } + final dateFormatter = new DateFormat('dd MMM yyyy'); + FcsShipmentListRow({Key key, this.shipment}) : super(key: key); @override Widget build(BuildContext context) { @@ -37,7 +20,7 @@ class _FcsShipmentListRowState extends State { child: InkWell( onTap: () { Navigator.of(context) - .push(BottomUpPageRoute(FcsShipmentEditor(shipment: _shipment))); + .push(BottomUpPageRoute(FcsShipmentEditor(shipment: shipment))); }, child: Row( children: [ @@ -61,9 +44,9 @@ class _FcsShipmentListRowState extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: new Text( - _shipment.shipmentNumber == null + shipment.shipmentNumber == null ? '' - : _shipment.shipmentNumber, + : shipment.shipmentNumber, style: new TextStyle( fontSize: 15.0, color: Colors.black), ), @@ -71,7 +54,7 @@ class _FcsShipmentListRowState extends State { Padding( padding: const EdgeInsets.only(left: 10.0, top: 10), child: new Text( - dateFormatter.format(_shipment.shipDate), + dateFormatter.format(shipment.cutoffDate), style: new TextStyle( fontSize: 15.0, color: Colors.grey), ), @@ -85,7 +68,7 @@ class _FcsShipmentListRowState extends State { ), Padding( padding: const EdgeInsets.all(0), - child: getStatus(_shipment.status), + child: getStatus(shipment.status), ), ], ), diff --git a/lib/pages/fcs_shipment/model/fcs_shipment_model.dart b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart index 0115fbe..5dc8446 100644 --- a/lib/pages/fcs_shipment/model/fcs_shipment_model.dart +++ b/lib/pages/fcs_shipment/model/fcs_shipment_model.dart @@ -1,78 +1,45 @@ +import 'dart:async'; + +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/fcs_shipment.dart'; import 'package:fcs/pages/main/model/base_model.dart'; +import 'package:logging/logging.dart'; class FcsShipmentModel extends BaseModel { - List shipmentType = ['Air', 'Ship', 'Cargo Truck']; - List shipments = [ - FcsShipment( - shipDate: DateTime(2020, 4, 23), - shipmentNumber: 'A103B', - status: 'In Progress', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 23)), - FcsShipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100A', - status: 'Ready to ship', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - FcsShipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 28), - departureDate: DateTime(2020, 4, 15)), - FcsShipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 10)), - FcsShipment( - shipDate: DateTime(2020, 4, 2), - shipmentNumber: 'A100B', - status: 'Canceled', - arrivalDate: DateTime(2020, 4, 20), - departureDate: DateTime(2020, 4, 23)), - FcsShipment( - shipDate: DateTime(2020, 4, 10), - shipmentNumber: 'A102B', - status: 'Arrived', - arrivalDate: DateTime(2020, 4, 30), - departureDate: DateTime(2020, 4, 20), - ) - ]; + final log = Logger('FcsShipmentModel'); - List get canceled { - List _p = - shipments.where((e) => e.status == "Canceled").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _p; + StreamSubscription listener; + List fcsShipments = []; + + @override + void privilegeChanged() { + super.privilegeChanged(); + _loadFcsShipments(); } - List get completed { - return shipments.where((e) => e.status == "Arrived").toList() - ..sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); + Future _loadFcsShipments() async { + if (user == null) return; + String path = "/$fcs_shipment_collection/"; + if (listener != null) listener.cancel(); + fcsShipments = []; + try { + listener = Firestore.instance + .collection("$path") + .snapshots() + .listen((QuerySnapshot snapshot) { + fcsShipments.clear(); + fcsShipments = snapshot.documents.map((documentSnapshot) { + var s = FcsShipment.fromMap( + documentSnapshot.data, documentSnapshot.documentID); + return s; + }).toList(); + notifyListeners(); }); - } - - List get upcoming { - List _shipments = shipments - .where((e) => - e.status == "In Progress" || - e.status == "Ready to ship" || - e.status == "Processed" || - e.status == "Rescheduled") - .toList(); - - _shipments.sort((e1, e2) { - return e1.shipDate.compareTo(e2.shipDate); - }); - return _shipments; + } catch (e) { + log.warning("Error!! $e"); + } } void initUser(user) { @@ -81,6 +48,14 @@ class FcsShipmentModel extends BaseModel { @override logout() async { - shipments = []; + fcsShipments = []; + } + + Future create(FcsShipment fcsShipment) { + return Services.instance.fcsShipmentService.createFcsShipment(fcsShipment); + } + + Future update(FcsShipment fcsShipment) { + return Services.instance.fcsShipmentService.updateFcsShipment(fcsShipment); } } diff --git a/lib/pages/main/home_page.dart b/lib/pages/main/home_page.dart index 2d95347..fcbd185 100644 --- a/lib/pages/main/home_page.dart +++ b/lib/pages/main/home_page.dart @@ -220,8 +220,9 @@ class _HomePageState extends State { final fcsShipmentBtn = TaskButton("FCSshipment.title", icon: Ionicons.ios_airplane, - btnCallback: () => - Navigator.of(context).push(BottomUpPageRoute(FcsShipmentList()))); + btnCallback: () => Navigator.of(context).push(CupertinoPageRoute( + builder: (context) => FcsShipmentList(), + ))); final notiBtnOrg = TaskButton("message.btn", icon: Icons.message, btnCallback: () { diff --git a/lib/pages/package/package_editor.dart b/lib/pages/package/package_editor.dart index 70ce37d..b6b48db 100644 --- a/lib/pages/package/package_editor.dart +++ b/lib/pages/package/package_editor.dart @@ -52,17 +52,17 @@ class _PackageEditorPageState extends State { Widget build(BuildContext context) { final trackingIdBox = DisplayText( text: _package.trackingID, - labelText: getLocalString(context, "package.tracking.id"), + labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); final statusBox = DisplayText( text: _package.currentStatus, - labelText: getLocalString(context, "package.edit.status"), + labelTextKey: "package.edit.status", iconData: AntDesign.exclamationcircleo, ); final customerNameBox = DisplayText( text: _package.userName, - labelText: getLocalString(context, "package.create.name"), + labelTextKey: "package.create.name", iconData: Icons.perm_identity, ); final completeProcessingBtn = fcsButton( diff --git a/lib/pages/package/package_info.dart b/lib/pages/package/package_info.dart index 1d58379..1a0ec6c 100644 --- a/lib/pages/package/package_info.dart +++ b/lib/pages/package/package_info.dart @@ -58,32 +58,32 @@ class _PackageInfoState extends State { final trackingIdBox = DisplayText( text: _package.trackingID, - labelText: getLocalString(context, "package.tracking.id"), + labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); final customerNameBox = DisplayText( text: _package.userName, - labelText: getLocalString(context, "package.create.name"), + labelTextKey: "package.create.name", iconData: Icons.perm_identity, ); final statusBox = DisplayText( text: _package.currentStatus, - labelText: getLocalString(context, "package.edit.status"), + labelTextKey: "package.edit.status", iconData: AntDesign.exclamationcircleo, ); final marketBox = DisplayText( text: _package.market ?? "-", - labelText: getLocalString(context, "package.create.market"), + labelTextKey: "package.create.market", iconData: Icons.store, ); final descBox = DisplayText( text: _package.desc ?? "-", - labelText: getLocalString(context, "package.edit.desc"), + labelTextKey: "package.edit.desc", iconData: MaterialCommunityIcons.message_text_outline, ); final remarkBox = DisplayText( text: _package.remark ?? "-", - labelText: getLocalString(context, "package.edit.remark"), + labelTextKey: "package.edit.remark", iconData: Entypo.new_message, ); final img = MultiImageFile( diff --git a/lib/pages/package/package_new.dart b/lib/pages/package/package_new.dart index e1f7579..664db99 100644 --- a/lib/pages/package/package_new.dart +++ b/lib/pages/package/package_new.dart @@ -41,7 +41,7 @@ class _PackageNewState extends State { Expanded( child: DisplayText( text: user != null ? user.fcsID : "", - labelText: getLocalString(context, "package.create.fcs.id"), + labelTextKey: "package.create.fcs.id", icon: FcsIDIcon(), )), IconButton( @@ -55,12 +55,12 @@ class _PackageNewState extends State { ); final namebox = DisplayText( text: user != null ? user.name : "", - labelText: getLocalString(context, "package.create.name"), + labelTextKey: "package.create.name", iconData: Icons.person, ); final phoneNumberBox = DisplayText( text: user != null ? user.phoneNumber : "", - labelText: getLocalString(context, "package.create.phone"), + labelTextKey: "package.create.phone", iconData: Icons.phone, ); final createButton = fcsButton( diff --git a/lib/pages/payment_methods/payment_method_page.dart b/lib/pages/payment_methods/payment_method_page.dart index b861fd3..09e3807 100644 --- a/lib/pages/payment_methods/payment_method_page.dart +++ b/lib/pages/payment_methods/payment_method_page.dart @@ -132,7 +132,7 @@ class _PaymentMethodPageState extends State { Expanded( child: DisplayText( text: text, - labelText: getLocalString(context, labelKey), + labelTextKey: getLocalString(context, labelKey), iconData: iconData, ), ), diff --git a/lib/pages/profile/profile_page.dart b/lib/pages/profile/profile_page.dart index 8fab3bf..f954822 100644 --- a/lib/pages/profile/profile_page.dart +++ b/lib/pages/profile/profile_page.dart @@ -60,13 +60,13 @@ class _ProfileState extends State { } final namebox = DisplayText( text: mainModel.user.name, - labelText: getLocalString(context, "profile.name"), + labelTextKey: getLocalString(context, "profile.name"), iconData: Icons.person, ); final phonenumberbox = DisplayText( text: mainModel.user.phone, - labelText: getLocalString(context, "profile.phone"), + labelTextKey: getLocalString(context, "profile.phone"), iconData: Icons.phone, ); final fcsIDBox = Row( @@ -74,7 +74,7 @@ class _ProfileState extends State { Expanded( child: DisplayText( text: mainModel.user.fcsID, - labelText: getLocalString(context, "customer.fcs.id"), + labelTextKey: getLocalString(context, "customer.fcs.id"), icon: FcsIDIcon(), ), ), @@ -90,7 +90,8 @@ class _ProfileState extends State { Expanded( child: DisplayText( text: mainModel.setting.usaAddress, - labelText: getLocalString(context, "profile.usa.shipping.address"), + labelTextKey: + getLocalString(context, "profile.usa.shipping.address"), iconData: Icons.location_on, ), ), @@ -158,7 +159,7 @@ class _ProfileState extends State { usaShippingAddressBox, DisplayText( text: mainModel.user.status, - labelText: getLocalString(context, "customer.status"), + labelTextKey: getLocalString(context, "customer.status"), iconData: Icons.add_alarm, ), // getShippingAddressList(context), diff --git a/lib/pages/staff/staff_editor.dart b/lib/pages/staff/staff_editor.dart index 5295011..cb48073 100644 --- a/lib/pages/staff/staff_editor.dart +++ b/lib/pages/staff/staff_editor.dart @@ -128,7 +128,7 @@ class _StaffEditorState extends State { Widget build(BuildContext context) { final namebox = DisplayText( text: user.name, - labelText: getLocalString(context, "customer.name"), + labelTextKey: getLocalString(context, "customer.name"), iconData: Icons.person, ); var phoneNumberBox = Row( @@ -136,7 +136,7 @@ class _StaffEditorState extends State { Expanded( child: DisplayText( text: user.phoneNumber, - labelText: getLocalString(context, "customer.phone"), + labelTextKey: getLocalString(context, "customer.phone"), iconData: Icons.phone, )), isNew diff --git a/lib/pages/widgets/display_text.dart b/lib/pages/widgets/display_text.dart index 456213c..8b3bf37 100644 --- a/lib/pages/widgets/display_text.dart +++ b/lib/pages/widgets/display_text.dart @@ -7,7 +7,7 @@ import 'package:provider/provider.dart'; class DisplayText extends StatelessWidget { final String text; - final String labelText; + final String labelTextKey; final IconData iconData; final int maxLines; final bool withBorder; @@ -17,7 +17,7 @@ class DisplayText extends StatelessWidget { const DisplayText({ Key key, this.text, - this.labelText, + this.labelTextKey, this.iconData, this.maxLines = 1, this.withBorder = false, @@ -57,10 +57,10 @@ class DisplayText extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - labelText == null + labelTextKey == null ? Container() : Text( - AppTranslations.of(context).text(labelText), + AppTranslations.of(context).text(labelTextKey), style: labelStyle, ), Text( diff --git a/lib/pages/widgets/input_date.dart b/lib/pages/widgets/input_date.dart new file mode 100644 index 0000000..f9ac184 --- /dev/null +++ b/lib/pages/widgets/input_date.dart @@ -0,0 +1,99 @@ +import 'package:fcs/helpers/theme.dart'; +import 'package:fcs/localization/app_translations.dart'; +import 'package:fcs/pages/main/model/language_model.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:provider/provider.dart'; + +class InputDate extends StatelessWidget { + final String labelTextKey; + final IconData iconData; + final TextEditingController controller; + final FormFieldValidator validator; + final int maxLines; + final bool withBorder; + final Color borderColor; + final TextInputType textInputType; + final bool autoFocus; + final String dateFormatString; + + const InputDate( + {Key key, + this.labelTextKey, + this.iconData, + this.controller, + this.validator, + this.maxLines = 1, + this.withBorder = false, + this.borderColor, + this.autoFocus = false, + this.dateFormatString = "dd MMM yyyy", + this.textInputType}) + : super(key: key); + + @override + Widget build(BuildContext context) { + var languageModel = Provider.of(context); + + return Padding( + padding: const EdgeInsets.only(top: 15.0, bottom: 5), + child: TextFormField( + readOnly: true, + onTap: () async { + var dateFormatter = new DateFormat(dateFormatString); + FocusScope.of(context).unfocus(); + var initialDate = DateTime.now(); + if (controller != null) { + try { + initialDate = dateFormatter.parse(controller.text); + } catch (e) {} // ignore error + } + var d = await showDatePicker( + context: context, + firstDate: DateTime(0), + lastDate: DateTime(2025), + initialDate: initialDate, + ); + if (d != null && controller != null) { + controller.text = dateFormatter.format(d); + } + }, + controller: controller, + autofocus: autoFocus, + cursorColor: primaryColor, + style: textStyle, + maxLines: maxLines, + keyboardType: textInputType, + decoration: new InputDecoration( + // hintText: '', + hintStyle: TextStyle( + height: 1.5, + ), + labelText: labelTextKey == null + ? null + : AppTranslations.of(context).text(labelTextKey), + labelStyle: languageModel.isEng ? labelStyle : labelStyleMM, + icon: iconData == null + ? null + : Icon( + iconData, + color: primaryColor, + ), + enabledBorder: withBorder + ? OutlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0), + ) + : UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + focusedBorder: withBorder + ? OutlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0), + ) + : UnderlineInputBorder( + borderSide: BorderSide(color: primaryColor, width: 1.0)), + ), + validator: validator), + ); + } +}