diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index f63c83f..fa7be69 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -104,7 +104,7 @@ "reg.confirm":"Submit Registration?", "reg.date":"Registeration Date", - "profile.title": "FCS Profile", + "profile.title": "Profile", "profile.edit_title": "Edit FCS Profile", "profile.name": "Name", "profile.phone": "Phone", @@ -513,14 +513,23 @@ "rate.edit.title":"EDIT RATES", - "rate.cal.title":"CALCULATE RATES", + "rate.cal.title":"ESTIMATE SHIPPING COST", + + "boxes.name":"Boxes", + "boxes.title":"BOXES", + "boxes.new":"New Box", + "box.edit.title":"BOX", + "box.package.id":"Package ID", + "box.package.desc":"Description", + "box.package.market":"Market", + "box.add_package":"Add Package", "package.name":"Packages", "package.title":"PACKAGES", "package.new":"New Package", "package.edit.title":"PACKAGE", "package.arrival.date":"Arrival Date", - "package.number":"Package Number", + "package.number":"Box Number", "package.rate":"Rate", "package.weight":"Weight", "package.amount":"Amount", @@ -542,7 +551,7 @@ "invoices.add":"New Invoice", "invoice.form.title":"INVOICE", "invoice.payment":"Payment Receipt", - "invoice.add_package":"Add Package", + "invoice.add_box":"Add Box", "term":"TERMS", "term.btn":"Terms", @@ -552,7 +561,8 @@ "contact": "CONTACTS", - "fcs.profile": "PROFILE", + "fcs.btn": "FCS Profile", + "fcs.profile": "FCS PROFILE", "contact.usa.phone": "USA Phone", "contact.mm.phone": "Myanmar Phone" diff --git a/assets/photos/1.jpg b/assets/photos/1.jpg new file mode 100644 index 0000000..3186d79 Binary files /dev/null and b/assets/photos/1.jpg differ diff --git a/assets/photos/2.jpg b/assets/photos/2.jpg new file mode 100644 index 0000000..9f0d8de Binary files /dev/null and b/assets/photos/2.jpg differ diff --git a/assets/photos/3.jpg b/assets/photos/3.jpg new file mode 100644 index 0000000..504b6f3 Binary files /dev/null and b/assets/photos/3.jpg differ diff --git a/lib/app.dart b/lib/app.dart index 722c251..29fec3e 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -33,6 +33,7 @@ import 'model/product_model.dart'; import 'model/report_user_model.dart'; import 'model/shipment_rate_model.dart'; import 'model/user_model.dart'; +import 'model_fcs/box_model.dart'; import 'pages/home_page.dart'; import 'pages/splash.dart'; import 'pages/term.dart'; @@ -71,6 +72,7 @@ class _AppState extends State { final ShipmentRateModel shipmentRateModel = new ShipmentRateModel(); final ShipmentModel shipmentModel = new ShipmentModel(); final PackageModel packageModel=new PackageModel(); + final BoxModel boxModel=new BoxModel(); final MessageModel messageModel=new MessageModel(); final InvoiceModel invoiceModel = new InvoiceModel(); final CustomerModel customerModel = new CustomerModel(); @@ -108,6 +110,7 @@ class _AppState extends State { ..addModel(shipmentRateModel) ..addModel(shipmentModel) ..addModel(packageModel) + ..addModel(boxModel) ..addModel(messageModel) ..addModel(shipmentRateModel) ..addModel(invoiceModel) @@ -164,6 +167,7 @@ class _AppState extends State { ChangeNotifierProvider(builder: (context) => shipmentRateModel), ChangeNotifierProvider(builder: (context) => shipmentModel), ChangeNotifierProvider(builder: (context) => packageModel), + ChangeNotifierProvider(builder: (context) => boxModel), ChangeNotifierProvider(builder: (context) => messageModel), ChangeNotifierProvider(builder: (context) => invoiceModel), ChangeNotifierProvider(builder: (context) => customerModel), diff --git a/lib/model/main_model.dart b/lib/model/main_model.dart index 228c2fc..25fdeae 100644 --- a/lib/model/main_model.dart +++ b/lib/model/main_model.dart @@ -60,7 +60,9 @@ class MainModel extends ChangeNotifier { shippingAddress: '154-19 64th Ave.Flushing, \nNY 11367', deliveryAddress: '39 42th St. Kyaut Ta Thar Township Yangon'); - Setting setting = Setting(terms: '[{"insert":"* Minimum shipping weight is 1lbs.\n* Oversized goods, Light weight/Large volume items, laptops, phones, tablets may incur extra charges based on pecifications.Please contact us for pricing.\n* Goods with lithium battary needs extra packaging and declaration. Please inform us ahead of time so that we can process your package accordingly.\n* Loose Batteries, Drones, and Prescription medicines are not allowed on aircraft.\n* Payment: We accept money orders, any US bank transfers via Zelle, AYA, KBZ and CB. No COD except for pick-ups.\n*Payments made in Myanmar will incur 2% tranfer fee\n"}]'); + Setting setting = Setting( + terms: + '[{"insert":"* Minimum shipping weight is 1lbs.\n* Oversized goods, Light weight/Large volume items, laptops, phones, tablets may incur extra charges based on pecifications.Please contact us for pricing.\n* Goods with lithium battary needs extra packaging and declaration. Please inform us ahead of time so that we can process your package accordingly.\n* Loose Batteries, Drones, and Prescription medicines are not allowed on aircraft.\n* Payment: We accept money orders, any US bank transfers via Zelle, AYA, KBZ and CB. No COD except for pick-ups.\n*Payments made in Myanmar will incur 2% tranfer fee\n"}]'); PackageInfo packageInfo; bool isLoaded = true; bool isOnline = true; @@ -109,6 +111,14 @@ class MainModel extends ChangeNotifier { return this.user != null; } + bool isCustomer() { + return user != null && user.name != "Owner"; + } + + bool isOwner() { + return user != null && user.name == "Owner"; + } + bool hasEmail() { return this.user != null && this.user.isEmail(); } diff --git a/lib/model/shipment_model.dart b/lib/model/shipment_model.dart index 073328a..2bab8d5 100644 --- a/lib/model/shipment_model.dart +++ b/lib/model/shipment_model.dart @@ -8,19 +8,19 @@ class ShipmentModel extends BaseModel { Shipment( shipDate: DateTime(2020, 4, 23), shipmentNumber: 'A103B', - status: 'Pending', + status: 'In Progress', arrivalDate: DateTime(2020, 4, 30), departureDate: DateTime(2020, 4, 23)), Shipment( shipDate: DateTime(2020, 4, 2), shipmentNumber: 'A100A', - status: 'Delivered', + status: 'Ready to ship', arrivalDate: DateTime(2020, 4, 28), departureDate: DateTime(2020, 4, 15)), Shipment( shipDate: DateTime(2020, 4, 2), shipmentNumber: 'A100B', - status: 'Delivered', + status: 'Arrived', arrivalDate: DateTime(2020, 4, 28), departureDate: DateTime(2020, 4, 15)), Shipment( @@ -38,7 +38,7 @@ class ShipmentModel extends BaseModel { Shipment( shipDate: DateTime(2020, 4, 10), shipmentNumber: 'A102B', - status: 'Assigned', + status: 'Arrived', arrivalDate: DateTime(2020, 4, 30), departureDate: DateTime(2020, 4, 20), ) @@ -47,29 +47,31 @@ class ShipmentModel extends BaseModel { List get canceled { List _p = shipments.where((e) => e.status == "Canceled").toList() ..sort((e1, e2) { - return e2.shipDate.compareTo(e1.shipDate); + return e1.shipDate.compareTo(e2.shipDate); }); return _p; } List get completed { - return shipments.where((e) => e.status == "Delivered").toList() + return shipments.where((e) => e.status == "Arrived").toList() ..sort((e1, e2) { - return e2.shipDate.compareTo(e1.shipDate); + return e1.shipDate.compareTo(e2.shipDate); }); } List get upcoming { - return shipments + List _shipments = shipments .where((e) => - e.status == "Pending" || - e.status == "Assigned" || + e.status == "In Progress" || + e.status == "Ready to ship" || e.status == "Processed" || e.status == "Rescheduled") - .toList() - ..sort((e1, e2) { - return e2.shipDate.compareTo(e1.shipDate); - }); + .toList(); + + _shipments.sort((e1, e2) { + return e1.shipDate.compareTo(e2.shipDate); + }); + return _shipments; } void initUser(user) { diff --git a/lib/model_fcs/box_model.dart b/lib/model_fcs/box_model.dart new file mode 100644 index 0000000..96d3b91 --- /dev/null +++ b/lib/model_fcs/box_model.dart @@ -0,0 +1,153 @@ +import 'dart:async'; + +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:fcs/model/base_model.dart'; +import 'package:fcs/model_fcs/package_model.dart'; +import 'package:fcs/vo/box.dart'; +import 'package:fcs/vo/package.dart'; +import 'package:logging/logging.dart'; + +class BoxModel extends BaseModel { + final log = Logger('BoxModel'); + + StreamSubscription listener; + static List statusHistory = [ + Status(status: "Packed", date: DateTime(2020, 6, 1), done: true), + Status(status: "Shipped", date: DateTime(2020, 6, 5), done: false), + Status(status: "Delivered", date: DateTime(2020, 6, 15), done: false) + ]; + static List packages = [ + PackageModel.packages[0], + PackageModel.packages[1], + PackageModel.packages[2] + ]; + List boxes = [ + Box( + shipmentNumber: "A202", + receiverNumber: "3", + receiverName: "Ko Myo Min", + boxNumber: "1", + rate: 7, + packageType: "General", + weight: 25, + status: "Packed", + receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', + cargoDesc: "Clothes", + arrivedDate: DateTime(2020, 6, 1), + packages: packages, + statusHistory: statusHistory), + Box( + shipmentNumber: "A202", + receiverNumber: "3", + receiverName: "Ko Myo Min", + boxNumber: "2", + rate: 7, + packageType: "General", + weight: 20, + status: "Packed", + cargoDesc: "Clothes", + arrivedDate: DateTime(2020, 6, 1), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), + Box( + shipmentNumber: "A202", + receiverNumber: "3", + receiverName: "Ko Myo Min", + boxNumber: "3", + rate: 7, + packageType: "General", + weight: 15, + cargoDesc: "Shoes", + status: "Packed", + arrivedDate: DateTime(2020, 6, 1), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), + Box( + shipmentNumber: "A202", + receiverNumber: "2", + receiverName: "Ma Aye", + boxNumber: "1", + rate: 8, + packageType: "Medicine", + weight: 15, + status: "Packed", + cargoDesc: "Dietary supplement", + arrivedDate: DateTime(2020, 6, 1), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), + Box( + shipmentNumber: "A202", + receiverNumber: "2", + receiverName: "Ma Aye", + boxNumber: "2", + rate: 7, + packageType: "General", + cargoDesc: "Handbags", + weight: 55, + status: "Shipped", + arrivedDate: DateTime(2020, 6, 1), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), + Box( + shipmentNumber: "A201", + receiverNumber: "1", + receiverName: "Ko Wai", + boxNumber: "1", + rate: 9, + packageType: "Dangerous", + cargoDesc: "Phones and Scooters", + weight: 25, + status: "Delivered", + arrivedDate: DateTime(2020, 5, 21), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), + Box( + shipmentNumber: "A201", + receiverNumber: "1", + receiverName: "Ko Wai", + boxNumber: "2", + rate: 7, + packageType: "General", + cargoDesc: "Construction tools", + weight: 5, + status: "Delivered", + arrivedDate: DateTime(2020, 5, 21), + statusHistory: statusHistory, + packages: packages, + receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), + ]; + + List get completed { + return boxes.where((e) => e.status == "Delivered").toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); + } + + List get upcoming { + return boxes + .where((e) => + e.status == "Packed" || + e.status == "Received" || + e.status == "Shipped") + .toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); + } + + void initUser(user) { + super.initUser(user); + } + + @override + logout() async { + if (listener != null) await listener.cancel(); + boxes = []; + } +} diff --git a/lib/model_fcs/message_model.dart b/lib/model_fcs/message_model.dart index cc8c995..4e2e020 100644 --- a/lib/model_fcs/message_model.dart +++ b/lib/model_fcs/message_model.dart @@ -14,56 +14,91 @@ class MessageModel extends BaseModel { List messages = [ Message( senderName: "FCS System", - receiverName: "Online Buyer", + receiverName: "Ko Myo Min", date: DateTime(2020, 6, 1, 1, 1, 1), message: - "Hi Online Buyer, we received your goods. Please see in 'A202-3 #1'", + "Hi Ko Myo Min, we received your goods. Please see the following link", + ), + Message( + senderName: "FCS System", + receiverName: "Ko Myo Min", + date: DateTime(2020, 6, 1, 1, 1, 1), + message: + "'A202-3 #1'", ), Message( senderName: "FCS System", - receiverName: "Online Buyer", + receiverName: "Ko Myo Min", date: DateTime(2020, 6, 1, 1, 5, 1), - message: "Thank you. Will see the photos and check.", + message: "Thank you. Will check the photos.", isMe: false), Message( senderName: "FCS System", - receiverName: "Online Buyer", + receiverName: "Ko Myo Min", date: DateTime(2020, 6, 1, 2, 1, 1), message: - "Hi Online Buyer, we successfully processed your goods and ready for payment. Please see in 'INV202005010387'", + "Hi Ko Myo Min, we successfully processed your goods and ready for payment. Please see in the following link.", ), Message( senderName: "FCS System", - receiverName: "Online Buyer", + receiverName: "Ko Myo Min", + date: DateTime(2020, 6, 1, 2, 1, 1), + message: + "'INV202005010387'", + ), + Message( + senderName: "FCS System", + receiverName: "Ko Myo Min", date: DateTime(2020, 6, 1, 2, 10, 1), message: - "Hi Online Buyer, we have confirmed your payment and ready to ship your packages.", + "Hi Ko Myo Min, we have confirmed your payment and ready to ship your packages.", ), Message( senderName: "FCS System", receiverName: "Shipper", date: DateTime(2020, 6, 1, 1, 1, 1), message: - "Hi Online Buyer, we received your goods. Please see in 'A202-3 #1'", + "Hi Ko Myo Min, we received your goods. Please see in the following link.", + ), + Message( + senderName: "FCS System", + receiverName: "Shipper", + date: DateTime(2020, 6, 1, 1, 1, 1), + message: + "'A202-3 #1'", ), Message( senderName: "FCS System", receiverName: "Shipper", date: DateTime(2020, 6, 1, 2, 1, 1), message: - "Hi Online Buyer, we successfully processed your goods and ready for payment. Please see in 'INV202005010387'", + "Hi FCS Team, we successfully processed your goods and ready for payment. Please see in the following link.", + ), + Message( + senderName: "FCS System", + receiverName: "Shipper", + date: DateTime(2020, 6, 1, 2, 1, 1), + message: + "'INV202005010387'", ), Message( senderName: "FCS System", receiverName: "Shipper", date: DateTime(2020, 6, 1, 2, 10, 1), message: - "Hi Online Buyer, we have confirmed your payment and ready to ship your packages.", + "Hi FCS Team, we have confirmed your payment and ready to ship your packages.", + ), + Message( + senderName: "Ko Myo Min", + receiverName: "FCS Team", + date: DateTime(2020, 6, 1, 2, 10, 1), + message: + "Hi Ko Myo Min, we have recevied your pickup request. We will arrange the pickup soon. Thank you.", ), ]; List get lastMessage { - return [messages[2], messages[5]]; + return [messages[2], messages[6]]; } List getMessage(String receiver) { diff --git a/lib/model_fcs/package_model.dart b/lib/model_fcs/package_model.dart index dfac67e..7c17b02 100644 --- a/lib/model_fcs/package_model.dart +++ b/lib/model_fcs/package_model.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:fcs/model/base_model.dart'; +import 'package:fcs/vo/box.dart'; import 'package:fcs/vo/package.dart'; import 'package:logging/logging.dart'; @@ -9,98 +10,132 @@ class PackageModel extends BaseModel { final log = Logger('PackageModel'); StreamSubscription listener; - - List packages = [ - Package( - shipmentNumber: "A202", - receiverNumber: "3", - boxNumber: "1", - rate: 7, - packageType: "General", - weight: 25, - status: "Received", - receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', - arrivedDate: DateTime(2020, 6, 1), - ), + static List statusHistory = [ + Status(status: "Received", date: DateTime(2020, 6, 1), done: true), + Status(status: "Processed", date: DateTime(2020, 6, 1), done: true), + Status(status: "Shipped", date: DateTime(2020, 6, 5), done: false), + Status(status: "Delivered", date: DateTime(2020, 6, 15), done: false) + ]; + static List packages = [ Package( shipmentNumber: "A202", receiverNumber: "3", + receiverName: "Ko Myo Min", + boxNumber: "1", + rate: 7, + packageType: "General", + weight: 25, + status: "Received", + receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon', + cargoDesc: "Computers", + arrivedDate: DateTime(2020, 6, 1), + market: "Amazon", + id: "PKG2039", + trackingID: "23-234s-asdfl"), + Package( + shipmentNumber: "A202", + receiverNumber: "3", + receiverName: "Ko Myo Min", boxNumber: "2", rate: 7, packageType: "General", weight: 20, status: "Received", + cargoDesc: "Clothes", arrivedDate: DateTime(2020, 6, 1), + market: "Macy", + trackingID: "asd-sdf-23498", + id: "PKG2040", receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), Package( shipmentNumber: "A202", receiverNumber: "3", + receiverName: "Ko Myo Min", boxNumber: "3", rate: 7, packageType: "General", weight: 15, - status: "Received", + cargoDesc: "Shoes", + status: "Processed", + market: "Macy", + trackingID: "8923-234-sd", + id: "PKG2041", arrivedDate: DateTime(2020, 6, 1), receiverAddress: '1 Bo Yar Nyunt St.\nDagon Tsp, Yangon'), Package( shipmentNumber: "A202", receiverNumber: "2", + receiverName: "Ma Aye", boxNumber: "1", rate: 8, packageType: "Medicine", weight: 15, - status: "Processing", + status: "Processed", + market: "Macy", + trackingID: "lsdf-sd09sdf", + cargoDesc: "Dietary supplement", + id: "PKG2042", arrivedDate: DateTime(2020, 6, 1), receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), Package( shipmentNumber: "A202", receiverNumber: "2", + receiverName: "Ma Aye", boxNumber: "2", rate: 7, packageType: "General", + cargoDesc: "Handbags", weight: 55, - status: "Ready to ship", + market: "Macy", + trackingID: "234-sdflsdf-213", + status: "Processed", + id: "PKG2043", arrivedDate: DateTime(2020, 6, 1), receiverAddress: '2 Shwe Taung Kyar St, Bahan Tsp, Yangon'), Package( shipmentNumber: "A201", receiverNumber: "1", + receiverName: "Ko Wai", boxNumber: "1", rate: 9, packageType: "Dangerous", + cargoDesc: "Phones and Scooters", weight: 25, - status: "Delivered", + status: "Received", + market: "Amazon", + trackingID: "sdf-asdf-23489", + id: "PKG2044", arrivedDate: DateTime(2020, 5, 21), receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), Package( shipmentNumber: "A201", receiverNumber: "1", + receiverName: "Ko Wai", boxNumber: "2", rate: 7, packageType: "General", + cargoDesc: "Construction tools", weight: 5, - status: "Delivered", + status: "Processed", + market: "Amazon", + id: "PKG2045", + trackingID: "oiuw-sdfpo-234", arrivedDate: DateTime(2020, 5, 21), receiverAddress: '3 Kambzwza St, Bahan Tsp, Yangon'), ]; List get completed { - return packages.where((e) => e.status == "Delivered").toList() + return packages.where((e) => e.status == "Processed").toList() ..sort((e1, e2) { return e2.packageNumber.compareTo(e1.packageNumber); }); } List get upcoming { - return packages - .where((e) => - e.status == "Processing" || - e.status == "Received" || - e.status == "Ready to ship") - .toList() - ..sort((e1, e2) { - return e2.packageNumber.compareTo(e1.packageNumber); - }); + return packages.where((e) => e.status == "Received").toList() + ..sort((e1, e2) { + return e2.packageNumber.compareTo(e1.packageNumber); + }); } void initUser(user) { diff --git a/lib/pages/customer_list.dart b/lib/pages/customer_list.dart index 89ef6aa..dadd357 100644 --- a/lib/pages/customer_list.dart +++ b/lib/pages/customer_list.dart @@ -83,7 +83,7 @@ class _CustomerListState extends State { padding: new EdgeInsets.symmetric( horizontal: 32.0 - dotSize / 2), child: Icon( - Feather.users, + Feather.user, color: primaryColor, size: 40, ), diff --git a/lib/pages/home_page.dart b/lib/pages/home_page.dart index 998d49a..88636e6 100644 --- a/lib/pages/home_page.dart +++ b/lib/pages/home_page.dart @@ -1,6 +1,7 @@ import 'package:country_code_picker/country_code.dart'; import 'package:fcs/model/main_model.dart'; import 'package:fcs/pages/shipment_list.dart'; +import 'package:fcs/pages_fcs/box_list.dart'; import 'package:fcs/pages_fcs/package_list.dart'; import 'package:fcs/widget/bottom_up_page_route.dart'; import 'package:fcs/widget/localization/transalation.dart'; @@ -103,13 +104,21 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { login = Provider.of(context).isLogin(); + var owner = Provider.of(context).isOwner(); + var customer = Provider.of(context).isCustomer(); + final packagesBtn = _buildBtn2("package.name", icon: Octicons.package, btnCallback: () => Navigator.of(context).push(BottomUpPageRoute(PackageList()))); + final boxesBtn = _buildBtn2("boxes.name", + icon: MaterialCommunityIcons.package, + btnCallback: () => + Navigator.of(context).push(BottomUpPageRoute(BoxList()))); + final pickUpBtn = _buildBtn2("pickup", - icon: MaterialCommunityIcons.directions, + icon: SimpleLineIcons.direction, btnCallback: () => Navigator.of(context).push(BottomUpPageRoute(PickUpList()))); @@ -118,7 +127,7 @@ class _HomePageState extends State { btnCallback: () => Navigator.of(context).push(BottomUpPageRoute(ShipmentRates()))); - final fcsProfileBtn = _buildBtn2("profile.title", + final fcsProfileBtn = _buildBtn2("fcs.btn", // imgIcon: Image.asset("assets/logo_btn.png", height: 25,color:Colors.white), icon: MaterialCommunityIcons.home_city, btnCallback: () => @@ -171,16 +180,17 @@ class _HomePageState extends State { Navigator.of(context).push(BottomUpPageRoute(Term()))); List widgets = []; - widgets.add(buyingBtn); - widgets.add(pickUpBtn); - widgets.add(shipmentBtn); - widgets.add(notiBtn); - widgets.add(staffBtn); - widgets.add(fcsProfileBtn); + customer ? widgets.add(buyingBtn) : ""; + customer || owner ? widgets.add(pickUpBtn) : ""; + owner ? widgets.add(shipmentBtn) : ""; + customer || owner ? widgets.add(notiBtn) : ""; + owner ? widgets.add(staffBtn) : ""; + owner ? widgets.add(fcsProfileBtn) : ""; widgets.add(shipmentCostBtn); - widgets.add(packagesBtn); - widgets.add(customersBtn); - widgets.add(invoicesBtn); + customer || owner ? widgets.add(packagesBtn) : ""; + customer || owner ? widgets.add(boxesBtn) : ""; + owner ? widgets.add(customersBtn) : ""; + customer || owner ? widgets.add(invoicesBtn) : ""; widgets.add(termBtn); return OfflineRedirect( @@ -306,8 +316,8 @@ class _HomePageState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - _buildSmallButton( - "Policies", FontAwesomeIcons.fileContract), + // _buildSmallButton( + // "Policies", FontAwesomeIcons.fileContract), _buildSmallButton("Support", SimpleLineIcons.support), ], ) diff --git a/lib/pages/invoice/invoce_list.dart b/lib/pages/invoice/invoce_list.dart index 3f28280..eec9a21 100644 --- a/lib/pages/invoice/invoce_list.dart +++ b/lib/pages/invoice/invoce_list.dart @@ -65,7 +65,7 @@ class _InvoiceListState extends State { bottom: TabBar( unselectedLabelColor: Colors.grey, tabs: [ - Tab(text: "Packages"), + Tab(text: "Boxes"), Tab(text: "Pending"), Tab(text: "Paid"), ], diff --git a/lib/pages/invoice/invoice_editor.dart b/lib/pages/invoice/invoice_editor.dart index 43529e2..27b0334 100644 --- a/lib/pages/invoice/invoice_editor.dart +++ b/lib/pages/invoice/invoice_editor.dart @@ -1,3 +1,4 @@ +import 'package:fcs/model/main_model.dart'; import 'package:fcs/pages/invoice/package_addition.dart'; import 'package:fcs/theme/theme.dart'; import 'package:fcs/vo/invoice.dart'; @@ -10,6 +11,7 @@ import 'package:fcs/widget/multi_img_file.dart'; import 'package:fcs/widget/my_data_table.dart'; import 'package:fcs/widget/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'; @@ -48,7 +50,7 @@ class _InvoiceEditorState extends State { _dateController.text = dateFormatter.format(_invoice.invoiceDate); _nameController.text = _invoice.customerName; _phoneController.text = _invoice.customerPhoneNumber; - _amountController.text = _invoice.amount.toString(); + _amountController.text = _invoice.getAmount.toString(); _statusController.text = _invoice.status.toString(); _packages = _invoice.packages; } else { @@ -85,6 +87,8 @@ class _InvoiceEditorState extends State { @override Widget build(BuildContext context) { + var mainModel = Provider.of(context); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -123,8 +127,8 @@ class _InvoiceEditorState extends State { enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, icon: Icon( - Icons.pages, - color: Colors.grey, + FontAwesomeIcons.fileInvoice, + color: primaryColor, ), )), ), @@ -132,7 +136,7 @@ class _InvoiceEditorState extends State { ? Container( padding: EdgeInsets.only(top: 5), child: TextFormField( - initialValue: "U Nyi", + initialValue: "Ko Myo Min", cursorColor: primaryColor, decoration: InputDecoration( fillColor: Colors.white, @@ -144,8 +148,8 @@ class _InvoiceEditorState extends State { borderSide: BorderSide( color: Colors.grey, width: 1.0)), icon: Icon( - Icons.account_box, - color: Colors.grey, + FontAwesomeIcons.fileInvoice, + color: primaryColor, ), suffixIcon: IconButton( icon: Icon( @@ -167,34 +171,34 @@ class _InvoiceEditorState extends State { fillColor: Colors.white, labelText: 'Customer Name', labelStyle: - TextStyle(fontSize: 16, color: Colors.grey), + TextStyle(fontSize: 16, color: primaryColor), filled: true, enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, icon: Icon( - Icons.account_box, - color: Colors.grey, + Feather.user, + color: primaryColor, ), )), ), - widget.invoice == null - ? Container() - : TextFormField( - controller: _phoneController, - readOnly: true, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Customer Phone Number', - labelStyle: - TextStyle(fontSize: 16, color: Colors.grey), - filled: true, - enabledBorder: InputBorder.none, - focusedBorder: InputBorder.none, - icon: Icon( - Icons.phone, - color: Colors.grey, - ), - )), + // widget.invoice == null + // ? Container() + // : TextFormField( + // controller: _phoneController, + // readOnly: true, + // decoration: InputDecoration( + // fillColor: Colors.white, + // labelText: 'Customer Phone Number', + // labelStyle: + // TextStyle(fontSize: 16, color: Colors.grey), + // filled: true, + // enabledBorder: InputBorder.none, + // focusedBorder: InputBorder.none, + // icon: Icon( + // Icons.phone, + // color: Colors.grey, + // ), + // )), Container( padding: EdgeInsets.only(top: 0), child: fcsInput('Amount', FontAwesomeIcons.moneyBill, @@ -215,12 +219,7 @@ class _InvoiceEditorState extends State { fillColor: Colors.white, labelText: 'Status', filled: true, - icon: Image.asset( - 'assets/status.png', - width: 24, - height: 24, - color: Colors.grey[700], - ), + icon: Icon(Icons.av_timer,color: primaryColor,), )), ), SizedBox( @@ -250,7 +249,7 @@ class _InvoiceEditorState extends State { ], ), ExpansionTile( - title: Text('Package Informations'), + title: Text('Box Information'), children: [ Container( child: SingleChildScrollView( @@ -292,14 +291,14 @@ class _InvoiceEditorState extends State { ), ), ), - Container( + mainModel.isOwner()?Container( padding: EdgeInsets.only(top: 20), child: Align( alignment: Alignment.bottomRight, child: FloatingActionButton.extended( icon: Icon(Icons.add), label: Text(AppTranslations.of(context) - .text("invoice.add_package")), + .text("invoice.add_box")), backgroundColor: primaryColor, onPressed: () { Navigator.of(context) @@ -307,7 +306,7 @@ class _InvoiceEditorState extends State { }, ), ), - ), + ):Container(), SizedBox(height: 25), ], ), @@ -328,7 +327,7 @@ class _InvoiceEditorState extends State { }, ), ))) - : Container( + :mainModel.isCustomer()?Container():Container( child: Column( children: [ Align( @@ -355,7 +354,7 @@ class _InvoiceEditorState extends State { child: Container( width: 250, child: FlatButton( - child: Text('Confirm Payment'), + child: Text('Attach Payment Receipt'), color: primaryColor, textColor: Colors.white, onPressed: () { diff --git a/lib/pages/message_detail.dart b/lib/pages/message_detail.dart index 82ce76b..1af2130 100644 --- a/lib/pages/message_detail.dart +++ b/lib/pages/message_detail.dart @@ -90,7 +90,7 @@ class MessageDetail extends StatelessWidget { message: e.message, time: dateFormat.format(e.date), delivered: true, - isMe: e.isMe != null ? e.isMe : true)) + isMe: !(e.isMe != null ? e.isMe : true))) .toList(); return Scaffold( diff --git a/lib/pages/pickup_editor.dart b/lib/pages/pickup_editor.dart index 0ab7506..6a6443b 100644 --- a/lib/pages/pickup_editor.dart +++ b/lib/pages/pickup_editor.dart @@ -45,11 +45,13 @@ class _PickUpEditorState extends State { PickUp _pickUp; bool _isLoading = false; var now = new DateTime.now(); + bool isNew; @override void initState() { super.initState(); if (widget.pickUp != null) { + isNew = false; _pickUp = widget.pickUp; _addressEditingController.text = _pickUp.address; _fromTimeEditingController.text = _pickUp.fromTime; @@ -63,6 +65,8 @@ class _PickUpEditorState extends State { _recipientPhoneEditingController.text = mainModel.recipient.phoneNumber; _recipientAddressEditingController.text = mainModel.recipient.shippingAddress; + } else { + isNew = true; } } @@ -190,7 +194,7 @@ class _PickUpEditorState extends State { EdgeInsets.symmetric(vertical: 10.0, horizontal: 0.0), icon: Icon( Icons.date_range, - color: Colors.grey, + color: primaryColor, )), validator: (value) { if (value.isEmpty) { @@ -224,18 +228,20 @@ class _PickUpEditorState extends State { child: ListView(children: [ Center(child: nameWidget(mainModel.customer.name)), Center(child: nameWidget(mainModel.customer.phoneNumber)), - Center( - child: Padding( - padding: const EdgeInsets.only(left: 10.0, top: 8), - child: Text( - '#P200304', - style: TextStyle( - color: Colors.black87, - fontSize: 14, - fontWeight: FontWeight.bold), - ), - ), - ), + isNew + ? Container() + : Center( + child: Padding( + padding: const EdgeInsets.only(left: 10.0, top: 8), + child: Text( + '#P200304', + style: TextStyle( + color: Colors.black87, + fontSize: 14, + fontWeight: FontWeight.bold), + ), + ), + ), ExpansionTile( title: Text('Pickup Location / Time'), children: [ @@ -264,7 +270,7 @@ class _PickUpEditorState extends State { ], ), ExpansionTile( - title: Text('Package Informations'), + title: Text('Package Information'), children: [ Padding( padding: const EdgeInsets.only(left: 20.0), @@ -296,7 +302,7 @@ class _PickUpEditorState extends State { ], ), ExpansionTile( - title: Text('Recipient Informations'), + title: Text('Recipient Information'), children: [ Padding( padding: const EdgeInsets.only(left: 20.0), @@ -340,6 +346,7 @@ class _PickUpEditorState extends State { _recipientAddressEditingController)), ], ), + mainModel.isCustomer()?Container(): ExpansionTile( title: Text('For FCS'), children: [ diff --git a/lib/pages/pickup_list_row.dart b/lib/pages/pickup_list_row.dart index 50bb797..21528d8 100644 --- a/lib/pages/pickup_list_row.dart +++ b/lib/pages/pickup_list_row.dart @@ -58,7 +58,7 @@ class _PickupListRowState extends State { Padding( padding: EdgeInsets.all(5.0), child: Icon( - MaterialCommunityIcons.directions, + SimpleLineIcons.direction, color: primaryColor, )), new Expanded( diff --git a/lib/pages/profile_page.dart b/lib/pages/profile_page.dart index 9a29673..5042941 100644 --- a/lib/pages/profile_page.dart +++ b/lib/pages/profile_page.dart @@ -254,27 +254,6 @@ class _ProfileState extends State { ), ), )); - Future getVersionNumber() async { - PackageInfo packageInfo = await PackageInfo.fromPlatform(); - String version = packageInfo.version + "+" + packageInfo.buildNumber; - - return version; - } - - final versionbox = Container( - padding: EdgeInsets.only(top: 15), - child: Container( - child: Center( - child: FutureBuilder( - future: getVersionNumber(), - builder: (BuildContext context, AsyncSnapshot snapshot) => - Text( - snapshot.hasData ? "v${snapshot.data}" : "Loading ...", - style: TextStyle(fontSize: 16.0, fontStyle: FontStyle.normal), - ), - )), - )); - return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( diff --git a/lib/pages/shipment_editor.dart b/lib/pages/shipment_editor.dart index b356a1d..82bee4e 100644 --- a/lib/pages/shipment_editor.dart +++ b/lib/pages/shipment_editor.dart @@ -266,7 +266,7 @@ class _ShipmentEditorState extends State { child: ListView(children: [ // _showCustomerData(mainModel.customer), widget.shipment == null - ? fcsInput('Shipment Number', Icons.text_rotation_none, + ? fcsInput('Shipment Number', Ionicons.ios_airplane, controller: _shipmentNumberController) : Container( child: TextFormField( @@ -281,8 +281,8 @@ class _ShipmentEditorState extends State { enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, icon: Icon( - Icons.text_rotation_none, - color: Colors.grey, + Ionicons.ios_airplane, + color: primaryColor, ), )), ), @@ -293,26 +293,6 @@ class _ShipmentEditorState extends State { controller: _cutoffDateController), ) : Container(), - widget.shipment == null - ? Container( - padding: EdgeInsets.only(top: 5), - child: DropdownButtonFormField( - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Shipment Type', - icon: Icon(Icons.pages)), - items: shipmentModel.shipmentType - .map((e) => - DropdownMenuItem(child: Text(e), value: e)) - .toList(), - onChanged: (selected) => { - setState(() { - _currentShipment = selected; - }) - }, - ), - ) - : Container(), Container( padding: EdgeInsets.only(top: widget.shipment == null ? 5 : 0), @@ -324,6 +304,28 @@ class _ShipmentEditorState extends State { child: fcsInput('Departure Date', Icons.date_range, controller: _departureDateControler), ), + widget.shipment == null + ? Container( + padding: EdgeInsets.only(top: 5), + child: DropdownButtonFormField( + decoration: InputDecoration( + fillColor: Colors.white, + labelText: '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 ? Container( padding: EdgeInsets.only(top: 5), @@ -355,21 +357,16 @@ class _ShipmentEditorState extends State { controller: _statusController, cursorColor: primaryColor, decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Status', - filled: true, - labelStyle: - TextStyle(fontSize: 16, color: Colors.grey), - focusedBorder: UnderlineInputBorder( - borderSide: BorderSide( - color: Colors.grey, width: 1.0)), - icon: Image.asset( - 'assets/status.png', - width: 24, - height: 24, - color: Colors.grey[700], - ), - )), + fillColor: Colors.white, + labelText: 'Status', + filled: true, + labelStyle: TextStyle( + fontSize: 16, color: Colors.grey), + focusedBorder: UnderlineInputBorder( + borderSide: BorderSide( + color: Colors.grey, width: 1.0)), + icon: Icon(Icons.av_timer, + color: primaryColor))), ), widget.shipment == null ? Container() diff --git a/lib/pages/shipment_rates.dart b/lib/pages/shipment_rates.dart index b6098b4..87b8e7a 100644 --- a/lib/pages/shipment_rates.dart +++ b/lib/pages/shipment_rates.dart @@ -109,7 +109,7 @@ class _ShipmentRatesState extends State { Navigator.of(context) .push(MaterialPageRoute(builder: (_) => Term())); }), - fcsButton(context, "Calculate", callack: () { + fcsButton(context, "Estimate shipping cost", callack: () { Navigator.of(context) .push(BottomUpPageRoute(ShipmentRatesCal())); }), diff --git a/lib/pages/util.dart b/lib/pages/util.dart index 9b3d251..9249773 100644 --- a/lib/pages/util.dart +++ b/lib/pages/util.dart @@ -381,7 +381,7 @@ Widget nameWidget(String name) { child: Text( name, style: TextStyle( - color: Colors.black87, fontSize: 18, fontWeight: FontWeight.bold), + color: Colors.black87, fontSize: 18, fontWeight: FontWeight.bold), ), ), ); @@ -417,7 +417,7 @@ Widget fcsInput(String label, IconData iconData, filled: true, icon: Icon( iconData, - color: Colors.grey, + color: primaryColor, ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide(color: Colors.grey, width: 1.0)), diff --git a/lib/pages_fcs/box_editor.dart b/lib/pages_fcs/box_editor.dart new file mode 100644 index 0000000..4c3b174 --- /dev/null +++ b/lib/pages_fcs/box_editor.dart @@ -0,0 +1,407 @@ +import 'package:fcs/model/main_model.dart'; +import 'package:fcs/model_fcs/package_model.dart'; +import 'package:fcs/pages/invoice/package_addition.dart'; +import 'package:fcs/pages/util.dart'; +import 'package:fcs/vo/box.dart'; +import 'package:fcs/vo/package.dart'; +import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/widget/local_text.dart'; +import 'package:fcs/widget/localization/app_translations.dart'; +import 'package:fcs/widget/my_data_table.dart'; +import 'package:fcs/widget/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:timeline_list/timeline.dart'; +import 'package:timeline_list/timeline_model.dart'; + +import '../theme/theme.dart'; + +class BoxEditor extends StatefulWidget { + final Box box; + BoxEditor({this.box}); + + @override + _BoxEditorState createState() => _BoxEditorState(); +} + +class _BoxEditorState extends State { + TextEditingController _addressEditingController = new TextEditingController(); + TextEditingController _fromTimeEditingController = + new TextEditingController(); + TextEditingController _toTimeEditingController = new TextEditingController(); + TextEditingController _noOfPackageEditingController = + new TextEditingController(); + TextEditingController _weightEditingController = new TextEditingController(); + + Box _box; + bool _isLoading = false; + List _images = [ + "assets/photos/1.jpg", + "assets/photos/2.jpg", + "assets/photos/3.jpg" + ]; + bool isNew; + + @override + void initState() { + super.initState(); + if (widget.box != null) { + _box = widget.box; + isNew = false; + // _addressEditingController.text = _pickUp.address; + // _fromTimeEditingController.text = _pickUp.fromTime; + // _toTimeEditingController.text = _pickUp.toTime; + // _noOfPackageEditingController.text = _pickUp.numberOfPackage.toString(); + // _weightEditingController.text = _pickUp.weight.toString(); + } else { + List packages = [ + PackageModel.packages[0], + PackageModel.packages[1], + PackageModel.packages[2] + ]; + + isNew = true; + _box = Box(rate: 0, weight: 0, packages: packages); + } + } + + @override + void dispose() { + super.dispose(); + } + + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + List _models() { + // return []; + return _box.statusHistory + .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) { + var mainModel = Provider.of(context); + + var images = isNew ? [] : _images; + return LocalProgress( + inAsyncCall: _isLoading, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(Icons.close), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("box.edit.title")), + ), + body: Card( + child: Column( + children: [ + widget.box == null + ? Center( + child: Container( + padding: EdgeInsets.all(8), child: Text("New Box"))) + : Center(child: nameWidget(_box.packageNumber)), + Expanded( + child: ListView( + children: [ + ExpansionTile( + title: Text( + 'Shipment Information', + style: TextStyle( + color: primaryColor, fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: DropdownButtonFormField( + value: _box.shipmentNumber, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Shipment Number', + icon: Icon(Ionicons.ios_airplane, + color: primaryColor) + // prefixIcon: Icon(Icons.play_arrow) + ), + items: ["A102", "A103", "A201", "A202"] + .map((e) => + DropdownMenuItem(child: Text(e), value: e)) + .toList(), + onChanged: (map) => {}, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: + isNew ? "FCS-0203-390-2" : "FCS-0203-390-2", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'FCS_ID', + hintText: 'FCS_ID', + filled: true, + icon: Icon(Feather.user, color: primaryColor), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () {})), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: _box.receiverName, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Customer Name', + filled: true, + icon: Icon(Feather.user, color: Colors.white), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () {})), + ), + ), + SizedBox( + height: 30, + ) + ], + ), + ExpansionTile( + title: Text( + 'Packages', + style: TextStyle( + color: primaryColor, fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: DropdownButtonFormField( + value: _box.packageType, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Cargo Type', + icon: Icon(Entypo.box, color: primaryColor)), + items: ["General", "Medicine", "Dangerous"] + .map((e) => + DropdownMenuItem(child: Text(e), value: e)) + .toList(), + onChanged: (map) => {}, + ), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: _box.weight.toString(), + textAlign: TextAlign.end, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Total Weight', + filled: true, + icon: Icon(FontAwesomeIcons.weightHanging, + color: primaryColor), + )), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: _box.rate.toString(), + textAlign: TextAlign.end, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Rate', + filled: true, + icon: Icon(FontAwesomeIcons.tag, + color: primaryColor), + )), + ), + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: _box.amount.toString(), + textAlign: TextAlign.end, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Total Amount', + filled: true, + icon: Icon(FontAwesomeIcons.moneyBill, + color: primaryColor), + )), + ), + Container( + padding: EdgeInsets.only(top: 10), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: MyDataTable( + headingRowHeight: 40, + columnSpacing: 20, + columns: [ + MyDataColumn( + label: LocalText( + context, + "box.package.id", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "box.package.desc", + color: Colors.grey, + ), + ), + MyDataColumn( + label: LocalText( + context, + "box.package.market", + color: Colors.grey, + ), + ), + ], + rows: getPackageRow(context), + ), + ), + ), + mainModel.isOwner() + ? Container( + padding: EdgeInsets.only(top: 20), + child: Align( + alignment: Alignment.bottomRight, + child: FloatingActionButton.extended( + icon: Icon(Icons.add), + label: Text(AppTranslations.of(context) + .text("box.add_package")), + backgroundColor: primaryColor, + onPressed: () { + Navigator.of(context).push( + BottomUpPageRoute(PackageAddition())); + }, + ), + ), + ) + : Container(), + SizedBox(height: 25), + ], + ), + isNew + ? Container() + : ExpansionTile( + title: Text( + 'Status', + style: TextStyle( + color: primaryColor, + fontWeight: FontWeight.bold), + ), + children: [ + Container( + height: 500, + padding: EdgeInsets.only(left: 20), + child: isNew + ? Container() + : Timeline( + children: _models(), + position: TimelinePosition.Left), + ), + ], + ) + ], + ), + ), + widget.box == null + ? Align( + alignment: Alignment.bottomCenter, + child: Center( + child: Container( + width: 250, + child: FlatButton( + child: Text('Create New Box'), + color: primaryColor, + textColor: Colors.white, + onPressed: () { + Navigator.pop(context); + }, + ), + ))) + : Container( + child: Column( + children: [ + Align( + alignment: Alignment.bottomCenter, + child: Center( + child: Container( + width: 250, + child: FlatButton( + child: Text('Complete packing'), + color: primaryColor, + textColor: Colors.white, + onPressed: () { + Navigator.pop(context); + }, + ), + ))), + ], + )) + ], + ), + ), + ), + ); + } + + List getPackageRow(BuildContext context) { + if (_box == null || _box.packages == null) { + return []; + } + return _box.packages.map((p) { + return MyDataRow( + onSelectChanged: (bool selected) {}, + cells: [ + MyDataCell(new Text( + p.id == null ? "" : p.id, + style: textStyle, + )), + MyDataCell( + new Text(p.cargoDesc, style: textStyle), + ), + MyDataCell( + new Text("${p.market}", style: textStyle), + ), + ], + ); + }).toList(); + } +} diff --git a/lib/pages_fcs/box_list.dart b/lib/pages_fcs/box_list.dart new file mode 100644 index 0000000..9d02ab8 --- /dev/null +++ b/lib/pages_fcs/box_list.dart @@ -0,0 +1,146 @@ +import 'package:fcs/model/pickup_model.dart'; +import 'package:fcs/model_fcs/box_model.dart'; +import 'package:fcs/model_fcs/package_model.dart'; +import 'package:fcs/pages/pickup_list_row.dart'; +import 'package:fcs/pages/search_page.dart'; +import 'package:fcs/pages_fcs/box_editor.dart'; +import 'package:fcs/pages_fcs/box_list_row.dart'; +import 'package:fcs/pages_fcs/package_editor.dart'; +import 'package:fcs/pages_fcs/package_list_row.dart'; +import 'package:fcs/vo/buyer.dart'; +import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:fcs/widget/localization/app_translations.dart'; +import 'package:fcs/widget/progress.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../theme/theme.dart'; +import 'pickup_editor.dart'; + +class BoxList extends StatefulWidget { + @override + _BoxListState createState() => _BoxListState(); +} + +class _BoxListState extends State { + Buyer buyer; + bool _isLoading = false; + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return LocalProgress( + inAsyncCall: _isLoading, + child: DefaultTabController( + length: 2, + child: Scaffold( + appBar: AppBar( + centerTitle: true, + leading: new IconButton( + icon: new Icon(Icons.close), + onPressed: () => Navigator.of(context).pop(), + ), + backgroundColor: primaryColor, + title: Text(AppTranslations.of(context).text("boxes.title")), + actions: [ + IconButton( + icon: Icon( + Icons.search, + color: Colors.white, + ), + iconSize: 30, + onPressed: () => showPlacesSearch(context), + ), + ], + bottom: TabBar( + unselectedLabelColor: Colors.grey, + tabs: [ + Tab( + text: "Upcoming", + ), + Tab(text: "Delivered"), + ], + ), + ), + floatingActionButton: FloatingActionButton.extended( + onPressed: () { + _newPickup(); + }, + icon: Icon(Icons.add), + label: Text(AppTranslations.of(context).text("boxes.new")), + backgroundColor: primaryColor, + ), + body: TabBarView( + children: [ + _upComing(), + _completed(), + ], + )), + ), + ); + } + + _newPickup() { + Navigator.push( + context, + BottomUpPageRoute(BoxEditor()), + ); + } + + Widget _upComing() { + var boxModel = Provider.of(context); + return Column( + children: [ + Expanded( + child: new ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + ), + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(top: 15), + shrinkWrap: true, + itemCount: boxModel.upcoming.length, + itemBuilder: (BuildContext context, int index) { + return BoxListRow( + box: boxModel.upcoming[index], + isReadOnly: false, + ); + }), + ), + ], + ); + } + + Widget _completed() { + var boxModel = Provider.of(context); + return Column( + children: [ + Expanded( + child: new ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + ), + scrollDirection: Axis.vertical, + padding: EdgeInsets.only(top: 15), + shrinkWrap: true, + itemCount: boxModel.completed.length, + itemBuilder: (BuildContext context, int index) { + return BoxListRow( + box: boxModel.completed[index], + isReadOnly: false, + ); + }), + ), + ], + ); + } +} diff --git a/lib/pages_fcs/box_list_row.dart b/lib/pages_fcs/box_list_row.dart new file mode 100644 index 0000000..ed67f36 --- /dev/null +++ b/lib/pages_fcs/box_list_row.dart @@ -0,0 +1,119 @@ +import 'package:fcs/pages/invoice/package_info.dart'; +import 'package:fcs/pages/util.dart'; +import 'package:fcs/pages_fcs/box_editor.dart'; +import 'package:fcs/pages_fcs/package_editor.dart'; +import 'package:fcs/vo/box.dart'; +import 'package:fcs/vo/package.dart'; +import 'package:fcs/widget/bottom_up_page_route.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class BoxListRow extends StatefulWidget { + final bool isReadOnly; + final Box box; + const BoxListRow({this.box, this.isReadOnly}); + + @override + _BoxListRowState createState() => _BoxListRowState(); +} + +class _BoxListRowState extends State { + final double dotSize = 15.0; + Box _box = new Box(); + final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); + + @override + void initState() { + super.initState(); + _box = widget.box; + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only(left: 15, right: 15), + child: InkWell( + onTap: () { + if (widget.isReadOnly) { + // Navigator.push( + // context, + // BottomUpPageRoute(PackageInfo(package: _box)), + // ); + } else { + Navigator.push( + context, + BottomUpPageRoute(BoxEditor(box: _box)), + ); + } + }, + child: Row( + children: [ + Expanded( + child: new Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: new Row( + children: [ + new Expanded( + child: new Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + _box.packageNumber == null + ? '' + : _box.packageNumber, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 10.0, top: 10), + child: new Text( + dateFormat.format(_box.arrivedDate), + style: new TextStyle( + fontSize: 15.0, color: Colors.grey), + ), + ) + ], + ), + ), + ], + ), + ), + ), + Column( + children: [ + Padding( + padding: const EdgeInsets.all(0), + child: getStatus(_box.status), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), + child: Row( + children: [ + new Text( + _box.weight == null + ? '' + : _box.weight.toString() + 'lb - ', + style: + new TextStyle(fontSize: 15.0, color: Colors.grey), + ), + new Text( + _box.price == null + ? "" + : "\$ " + _box.price.toString(), + style: + new TextStyle(fontSize: 15.0, color: Colors.grey), + ), + ], + ), + ), + ], + ) + ], + ), + ), + ); + } +} diff --git a/lib/pages_fcs/package_editor.dart b/lib/pages_fcs/package_editor.dart index c061044..dd51f3c 100644 --- a/lib/pages_fcs/package_editor.dart +++ b/lib/pages_fcs/package_editor.dart @@ -1,11 +1,13 @@ -import 'package:fcs/model/main_model.dart'; -import 'package:fcs/model/pickup_model.dart'; +import 'package:fcs/pages/util.dart'; import 'package:fcs/vo/package.dart'; import 'package:fcs/widget/localization/app_translations.dart'; import 'package:fcs/widget/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:provider/provider.dart'; +import 'package:intl/intl.dart'; +import 'package:timeline_list/timeline.dart'; +import 'package:timeline_list/timeline_model.dart'; import '../theme/theme.dart'; @@ -28,17 +30,27 @@ class _PackageEditorState extends State { Package _package; bool _isLoading = false; + List _images = [ + "assets/photos/1.jpg", + "assets/photos/2.jpg", + "assets/photos/3.jpg" + ]; + bool isNew; @override void initState() { super.initState(); if (widget.package != null) { _package = widget.package; + isNew = false; // _addressEditingController.text = _pickUp.address; // _fromTimeEditingController.text = _pickUp.fromTime; // _toTimeEditingController.text = _pickUp.toTime; // _noOfPackageEditingController.text = _pickUp.numberOfPackage.toString(); // _weightEditingController.text = _pickUp.weight.toString(); + } else { + isNew = true; + _package = Package(rate: 0, weight: 0); } } @@ -47,8 +59,11 @@ class _PackageEditorState extends State { super.dispose(); } + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + @override Widget build(BuildContext context) { + var images = isNew ? [] : _images; return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -64,94 +79,197 @@ class _PackageEditorState extends State { body: Card( child: Column( children: [ + isNew ? Container() : Center(child: nameWidget(_package.market)), + isNew + ? Center( + child: Container( + padding: EdgeInsets.all(8), + child: Text("New Package"))) + : Center(child: nameWidget(_package.trackingID)), Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - DropdownButtonFormField( - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Shipment Number', - icon: Icon(Icons.pages) - // prefixIcon: Icon(Icons.play_arrow) + child: ListView( + children: [ + ExpansionTile( + title: Text( + 'Receiving', + style: TextStyle( + color: primaryColor, fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew ? "" : "PKG2039", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Package ID', + hintText: 'Package ID', + filled: true, + icon: Icon(MaterialCommunityIcons.id_card, + color: primaryColor), + ), + ), ), - items: ["A102", "A103"] - .map((e) => DropdownMenuItem(child: Text(e), value: e)) - .toList(), - onChanged: (map) => {}, - ), - TextFormField( - initialValue: "FCS383-283-1", - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'FCS_ID', - hintText: 'FCS_ID', - filled: true, - icon: Icon( - Icons.account_box, + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew ? "" : "Amazon", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Market', + hintText: 'FCS_ID', + filled: true, + icon: Icon(MaterialCommunityIcons.cart_outline, + color: primaryColor), + ), + ), ), - suffixIcon: IconButton( - icon: Icon(Icons.search), onPressed: () {})), - ), - DropdownButtonFormField( - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Cargo Type', - icon: Icon(Icons.pages) - // prefixIcon: Icon(Icons.play_arrow) + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew ? "" : "zdf-sdfl-37sdfks", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Tracking ID', + hintText: 'Tracking ID', + filled: true, + icon: Icon(Octicons.package, color: primaryColor), + ), + ), ), - items: ["General", "Medicine", "Dangerous"] - .map((e) => DropdownMenuItem(child: Text(e), value: e)) - .toList(), - onChanged: (map) => {}, - ), - TextFormField( - initialValue: "0", - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Weight', - filled: true, - icon: Icon( - FontAwesomeIcons.weightHanging, + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew ? "" : "FCS-0203-390-2", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'FCS_ID', + hintText: 'FCS_ID', + filled: true, + icon: Icon(Feather.user, color: primaryColor), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () {})), + ), ), - )), - TextFormField( - initialValue: "0", - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Rate', - filled: true, - icon: Icon( - FontAwesomeIcons.tag, + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: _package.receiverName, + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Customer Name', + filled: true, + icon: Icon(Feather.user, color: Colors.white), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () {})), + ), ), - )), - TextFormField( - initialValue: "0", - textAlign: TextAlign.end, - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Amount', - filled: true, - icon: Icon( - FontAwesomeIcons.moneyBill, + Padding( + padding: const EdgeInsets.only(left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew ? "" : "", + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Pickup ID', + filled: true, + icon: Icon(MaterialCommunityIcons.directions, + color: primaryColor), + suffixIcon: IconButton( + icon: Icon(Icons.search), + onPressed: () {})), + ), ), - )), - TextFormField( - initialValue: "P0203", - decoration: InputDecoration( - fillColor: Colors.white, - labelText: 'Pickup ID', - filled: true, - icon: Icon( - Icons.account_box, - ), - suffixIcon: IconButton( - icon: Icon(Icons.search), onPressed: () {})), - ), - ]), - )), + ], + ), + isNew + ? Container() + : ExpansionTile( + title: Text( + 'Processing', + style: TextStyle( + color: primaryColor, + fontWeight: FontWeight.bold), + ), + children: [ + Padding( + padding: const EdgeInsets.only( + left: 20.0, right: 20), + child: TextFormField( + initialValue: isNew + ? "" + : _package.cargoDesc.toString(), + decoration: InputDecoration( + fillColor: Colors.white, + labelText: 'Description', + filled: true, + icon: Icon(MaterialIcons.description, + color: primaryColor), + )), + ), + ], + ), + isNew + ? Container() + : ExpansionTile( + title: Text( + 'Photos', + style: TextStyle( + color: primaryColor, + fontWeight: FontWeight.bold), + ), + children: [ + Container( + height: 130, + width: 500, + child: ListView.separated( + separatorBuilder: (context, index) => Divider( + color: Colors.black, + ), + itemCount: images.length + 1, + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + if (index == images.length) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + width: 200, + height: 70, + decoration: BoxDecoration( + border: Border.all( + color: primaryColor, + width: 2.0, + ), + ), + child: Icon(SimpleLineIcons.plus), + ), + ); + } else { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Container( + width: 200, + height: 70, + decoration: BoxDecoration( + border: Border.all( + color: primaryColor, + width: 2.0, + ), + ), + child: Image.asset(images[index], + width: 50, height: 50), + ), + ); + } + }, + ), + ), + ], + ), + ], + ), + ), widget.package == null ? Align( alignment: Alignment.bottomCenter, @@ -159,7 +277,7 @@ class _PackageEditorState extends State { child: Container( width: 250, child: FlatButton( - child: Text('Create package'), + child: Text('Complete receiving'), color: primaryColor, textColor: Colors.white, onPressed: () { @@ -176,7 +294,7 @@ class _PackageEditorState extends State { child: Container( width: 250, child: FlatButton( - child: Text('Save package'), + child: Text('Complete processing'), color: primaryColor, textColor: Colors.white, onPressed: () { diff --git a/lib/pages_fcs/package_list.dart b/lib/pages_fcs/package_list.dart index f7d4ccc..fc744e3 100644 --- a/lib/pages_fcs/package_list.dart +++ b/lib/pages_fcs/package_list.dart @@ -62,9 +62,9 @@ class _PackageListState extends State { unselectedLabelColor: Colors.grey, tabs: [ Tab( - text: "Upcoming", + text: "Received", ), - Tab(text: "Completed"), + Tab(text: "Processed"), ], ), ), diff --git a/lib/pages_fcs/package_list_row.dart b/lib/pages_fcs/package_list_row.dart index 3a6020a..7f264ae 100644 --- a/lib/pages_fcs/package_list_row.dart +++ b/lib/pages_fcs/package_list_row.dart @@ -58,21 +58,29 @@ class _PackageListRowtate extends State { Padding( padding: const EdgeInsets.only(left: 8.0), child: new Text( - _package.packageNumber == null - ? '' - : _package.packageNumber, + _package.id == null ? '' : _package.id, style: new TextStyle( fontSize: 15.0, color: Colors.black), ), ), Padding( - padding: const EdgeInsets.only(left: 10.0, top: 10), + padding: const EdgeInsets.only(left: 8.0), child: new Text( - dateFormat.format(_package.arrivedDate), + _package.market == null ? '' : _package.market, + style: new TextStyle( + fontSize: 15.0, color: Colors.black), + ), + ), + Padding( + padding: const EdgeInsets.only(left: 8.0), + child: new Text( + _package.trackingID == null + ? '' + : _package.trackingID, style: new TextStyle( fontSize: 15.0, color: Colors.grey), ), - ) + ), ], ), ), @@ -84,7 +92,10 @@ class _PackageListRowtate extends State { children: [ Padding( padding: const EdgeInsets.all(0), - child: getStatus(_package.status), + child: new Text( + dateFormat.format(_package.arrivedDate), + style: new TextStyle(fontSize: 15.0, color: Colors.grey), + ), ), Padding( padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), diff --git a/lib/vo/box.dart b/lib/vo/box.dart new file mode 100644 index 0000000..81f7414 --- /dev/null +++ b/lib/vo/box.dart @@ -0,0 +1,61 @@ +import 'package.dart'; + +class Status { + String status; + DateTime date; + bool done; + Status({this.status, this.date, this.done}); +} + +class Box { + String id; + String shipmentNumber; + String senderFCSID; + String senderName; + String receiverFCSID; + String receiverName; + String receiverAddress; + String receiverNumber; + String boxNumber; + String status; + String cargoDesc; + + int rate; + int weight; + String packageType; + String pickUpID; + List photos; + String remark; + DateTime arrivedDate; + + List packages; + + int get amount => rate != null && weight != null ? rate * weight : 0; + + String get packageNumber => + shipmentNumber + "-" + receiverNumber + " #" + boxNumber; + double get price => rate.toDouble() * weight; + + List statusHistory; + + Box( + {this.id, + this.shipmentNumber, + this.senderFCSID, + this.senderName, + this.receiverFCSID, + this.receiverName, + this.receiverNumber, + this.receiverAddress, + this.boxNumber, + this.rate, + this.weight, + this.packageType, + this.pickUpID, + this.remark, + this.status, + this.arrivedDate, + this.cargoDesc, + this.statusHistory, + this.packages}); +} diff --git a/lib/vo/invoice.dart b/lib/vo/invoice.dart index f5257f2..57f7c6b 100644 --- a/lib/vo/invoice.dart +++ b/lib/vo/invoice.dart @@ -21,4 +21,6 @@ class Invoice { this.status, this.paymentAttachment, this.packages}); + + double get getAmount => packages.fold(0, (p, e) => (e.rate * e.weight) + p); } diff --git a/lib/vo/package.dart b/lib/vo/package.dart index 851e142..88e8ded 100644 --- a/lib/vo/package.dart +++ b/lib/vo/package.dart @@ -1,3 +1,10 @@ +// class Status { +// String status; +// DateTime date; +// bool done; +// Status({this.status, this.date, this.done}); +// } + class Package { String id; String shipmentNumber; @@ -9,20 +16,26 @@ class Package { String receiverNumber; String boxNumber; String status; + String cargoDesc; + String market; + String trackingID; int rate; int weight; - int amount; String packageType; String pickUpID; List photos; String remark; DateTime arrivedDate; + int get amount => rate != null && weight != null ? rate * weight : 0; + String get packageNumber => shipmentNumber + "-" + receiverNumber + " #" + boxNumber; double get price => rate.toDouble() * weight; + // List statusHistory; + Package( {this.id, this.shipmentNumber, @@ -35,10 +48,14 @@ class Package { this.boxNumber, this.rate, this.weight, - this.amount, this.packageType, this.pickUpID, this.remark, this.status, - this.arrivedDate}); + this.arrivedDate, + this.cargoDesc, + this.market, + this.trackingID + // this.statusHistory + }); } diff --git a/pubspec.lock b/pubspec.lock index d569aa1..bbce1c0 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -693,6 +693,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.15" + timeline_list: + dependency: "direct main" + description: + name: timeline_list + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.5" typed_data: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 470f2bb..6eb6df6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -66,6 +66,9 @@ dependencies: pin_input_text_field: flutter_icons: ^1.1.0 country_icons: ^1.1.1 + timeline_list: ^0.0.5 + + dev_dependencies: flutter_test: @@ -76,6 +79,7 @@ flutter: assets: - assets/ - assets/local/ + - assets/photos/ fonts: