From e75eacd1f99a9fe5551a91ec414af2f969f055db Mon Sep 17 00:00:00 2001 From: tzw Date: Thu, 6 Mar 2025 17:59:15 +0630 Subject: [PATCH] add shipment in processing, update package, processing and receiving --- assets/local/localization_en.json | 6 +- assets/local/localization_mu.json | 4 +- lib/domain/entities/fcs_shipment.dart | 11 +- lib/domain/entities/package.dart | 56 ++-- lib/domain/vo/delivery_address.dart | 24 +- lib/helpers/api_helper.dart | 14 +- lib/helpers/theme.dart | 1 + lib/pages/chat/bubble.dart | 2 +- lib/pages/main/util.dart | 108 +++++++- lib/pages/package/model/package_model.dart | 27 +- lib/pages/package/package_info.dart | 175 +++++++++---- lib/pages/package/package_list_row.dart | 6 +- lib/pages/processing/package_editor.dart | 72 +++--- .../processing/processing_edit_editor.dart | 193 ++++++-------- lib/pages/processing/processing_editor.dart | 241 +++++++----------- lib/pages/processing/processing_info.dart | 192 ++++++++------ lib/pages/profile/profile_page.dart | 88 +++---- lib/pages/receiving/receiving_editor.dart | 76 ++---- lib/pages/receiving/receiving_info.dart | 41 +-- lib/pages/widgets/status_tree.dart | 12 +- 20 files changed, 746 insertions(+), 603 deletions(-) diff --git a/assets/local/localization_en.json b/assets/local/localization_en.json index 623a9f0..17e438a 100644 --- a/assets/local/localization_en.json +++ b/assets/local/localization_en.json @@ -231,6 +231,8 @@ "package.delivery.address":"Delivery address", "package.popupmenu.active":"Active Packages", "package.popupmenu.delivered":"Delivered Packages", + "package.shipment.title":"Shipment", + "package.processing.date":"Processing date", "Package End ================================================================":"", "Market Start ================================================================":"", @@ -665,10 +667,10 @@ "processing.delete.confirm":"Delete this package?", "processing.edit.sub_title":"Processing", "processing.edit.complete.btn":"Complete processing", - "processing.new":"New Processing", + "processing.new":"New processing", "processing.create":"New Processing", "processing.update":"Update Processing", - "processing.consignee.name":"Consignee", + "processing.consignee.name":"Consignee name", "processing.shipper.name":"Sender name", "processing.package.select.btn":"Select", "processing.package.create":"New Package", diff --git a/assets/local/localization_mu.json b/assets/local/localization_mu.json index 78afcdd..849ea11 100644 --- a/assets/local/localization_mu.json +++ b/assets/local/localization_mu.json @@ -232,6 +232,8 @@ "package.delivery.address":"ပို့ဆောင်ရမည့်လိပ်စာ", "package.popupmenu.active":"လာမည့် အထုပ်များ", "package.popupmenu.delivered":"ပို့ပြီးသော အထုပ်များ", + "package.shipment.title":"တင်ပို့ခြင်း", + "package.processing.date":"လုပ်ဆောင်သည့်ရက်", "Package End ================================================================":"", "Market Start ================================================================":"", @@ -672,7 +674,7 @@ "processing.new":"လုပ်ဆောင်ခြင်း အသစ်", "processing.create":"လုပ်ဆောင်ခြင်း အသစ်", "processing.update":"လုပ်ဆောင်ခြင်း ပြင်ဆင်ခြင်း", - "processing.consignee.name":"လက်ခံသူ", + "processing.consignee.name":"လက်ခံသူ အမည်", "processing.shipper.name":"တင်ပို့သူ အမည်", "processing.package.select.btn":"ရွေးချယ်မည်", "processing.package.create":"အထုပ် အသစ်", diff --git a/lib/domain/entities/fcs_shipment.dart b/lib/domain/entities/fcs_shipment.dart index f894a79..21e2e69 100644 --- a/lib/domain/entities/fcs_shipment.dart +++ b/lib/domain/entities/fcs_shipment.dart @@ -18,6 +18,7 @@ class FcsShipment { String? reportName; int packageCount; int cartonCount; + DateTime? processingDate; FcsShipment( {this.id, @@ -36,7 +37,8 @@ class FcsShipment { this.destinationPortName, this.reportName, this.packageCount = 0, - this.cartonCount = 0}); + this.cartonCount = 0, + this.processingDate}); factory FcsShipment.fromMap(Map map, String docID) { var cutoffDate = @@ -44,6 +46,10 @@ class FcsShipment { var arrivalDate = map['eta_date'] == null ? null : (map['eta_date'] as Timestamp); + var processingDate = map['processing_date'] == null + ? null + : (map['processing_date'] as Timestamp); + return FcsShipment( id: docID, cutoffDate: cutoffDate?.toDate(), @@ -59,7 +65,8 @@ class FcsShipment { destinationPortId: map['destination_port_id'], destinationPortName: map['destination_port_name'], packageCount: map['package_count'] ?? 0, - cartonCount: map['carton_count'] ?? 0); + cartonCount: map['carton_count'] ?? 0, + processingDate: processingDate?.toDate()); } Map toMap() { diff --git a/lib/domain/entities/package.dart b/lib/domain/entities/package.dart index c57e8ec..12bb1ff 100644 --- a/lib/domain/entities/package.dart +++ b/lib/domain/entities/package.dart @@ -7,21 +7,25 @@ import 'package:fcs/domain/vo/shipment_status.dart'; class Package { String? id; String? trackingID; - String? userID; - String? fcsID; - String? userName; - String? phoneNumber; DateTime? currentStatusDate; List photoUrls; List shipmentHistory; List cartonIds; String? desc; - String? status; + + String? shipmentId; String? shipmentNumber; + + String? userID; + String? fcsID; + String? userName; + String? phoneNumber; + String? senderFCSID; String? senderName; String? senderPhoneNumber; + String? boxNumber; String? cargoDesc; String? market; @@ -50,6 +54,7 @@ class Package { this.userName, this.fcsID, this.phoneNumber, + this.shipmentId, this.shipmentNumber, this.senderFCSID, this.senderName, @@ -77,9 +82,11 @@ class Package { var currentStatusDate = map['status_date'] != null ? (map['status_date'] as Timestamp) : null; - List shipmentStatus = List.from(map['all_status']) - .map((e) => ShipmentStatus.fromMap(Map.from(e))) - .toList(); + List shipmentStatus = map['all_status'] == null + ? [] + : List.from(map['all_status']) + .map((e) => ShipmentStatus.fromMap(Map.from(e))) + .toList(); List photoUrls = map['photo_urls'] == null ? [] : List.from(map['photo_urls']); var deliveryAddress = map['delivery_address']; @@ -96,14 +103,16 @@ class Package { fcsID: map['fcs_id'], trackingID: map['tracking_id'], market: map['market'], - userName: map['user_name'], - phoneNumber: map['phone_number'], + userName: map['user_name'] ?? "", + phoneNumber: map['phone_number'] ?? "", remark: map['remark'], - desc: map['desc'] ?? "", + desc: map['desc'], status: map['status'], senderFCSID: map['sender_fcs_id'], - senderName: map['sender_name'], - senderPhoneNumber: map['sender_phone_number'], + senderName: map['sender_name'] ?? "", + senderPhoneNumber: map['sender_phone_number'] ?? "", + shipmentId: map['shipment_id'], + shipmentNumber: map['shipment_number'], deliveryAddress: da, currentStatusDate: currentStatusDate?.toDate().toLocal(), photoUrls: photoUrls, @@ -136,19 +145,20 @@ class Package { currentStatusDate: DateTime.parse(json['status_date'])); } - bool isChangedForEdit(Package package) { - return package.trackingID != this.trackingID || - package.remark != this.remark || - package.fcsID != this.fcsID; + bool isChangedForEditReceiving(Package package) { + return package.trackingID != trackingID || + package.remark != remark || + package.fcsID != fcsID; } bool isChangedForEditProcessing(Package package) { - return package.fcsID != this.fcsID || - package.senderFCSID != this.senderFCSID || - package.market != this.market || - package.desc != this.desc || - package.remark != this.remark || - package.photoUrls != this.photoUrls; + return package.fcsID != fcsID || + package.senderFCSID != senderFCSID || + package.market != market || + package.desc != desc || + package.remark != remark || + package.photoUrls != photoUrls || + package.shipmentId != shipmentId; } @override diff --git a/lib/domain/vo/delivery_address.dart b/lib/domain/vo/delivery_address.dart index e62ee5e..07c9ffb 100644 --- a/lib/domain/vo/delivery_address.dart +++ b/lib/domain/vo/delivery_address.dart @@ -23,12 +23,12 @@ class DeliveryAddress { factory DeliveryAddress.fromMap(Map map, String docID) { return DeliveryAddress( id: docID, - fullName: map['full_name'], - addressLine1: map['address_line1'], - addressLine2: map['address_line2'], - city: map['city'], - state: map['state'], - phoneNumber: map['phone_number'], + fullName: map['full_name'] ?? "", + addressLine1: map['address_line1'] ?? "", + addressLine2: map['address_line2'] ?? "", + city: map['city'] ?? "", + state: map['state'] ?? "", + phoneNumber: map['phone_number'] ?? "", isDefault: map['is_default'] ?? false, ); } @@ -51,11 +51,11 @@ class DeliveryAddress { } bool isChangedForEdit(DeliveryAddress deliveryAddress) { - return deliveryAddress.fullName != this.fullName || - deliveryAddress.phoneNumber != this.phoneNumber || - deliveryAddress.addressLine1 != this.addressLine1 || - deliveryAddress.addressLine2 != this.addressLine2 || - deliveryAddress.state != this.state || - deliveryAddress.city != this.city; + return deliveryAddress.fullName != fullName || + deliveryAddress.phoneNumber != phoneNumber || + deliveryAddress.addressLine1 != addressLine1 || + deliveryAddress.addressLine2 != addressLine2 || + deliveryAddress.state != state || + deliveryAddress.city != city; } } diff --git a/lib/helpers/api_helper.dart b/lib/helpers/api_helper.dart index 64330fe..cc54218 100644 --- a/lib/helpers/api_helper.dart +++ b/lib/helpers/api_helper.dart @@ -67,11 +67,15 @@ Future requestAPI(String path, method, path, data: payload, ); - var data = Status.fromJson(response.data); - if (data.status == 'Ok') { - return response.data["data"]; - } else { - throw Exception(data.message); + if (response.statusCode == HttpStatus.ok) { + var data = Status.fromJson(response.data); + if (data.status == 'Ok') { + return response.data["data"]; + } else { + throw Exception(data.message); + } + }else{ + throw Exception( "${response.statusCode} - ${response.statusMessage}"); } } catch (e) { logger.warning("path:$path, api:$e"); diff --git a/lib/helpers/theme.dart b/lib/helpers/theme.dart index d5c8907..3a59a8a 100644 --- a/lib/helpers/theme.dart +++ b/lib/helpers/theme.dart @@ -10,6 +10,7 @@ const labelColor = const Color(0xFF757575); var dividerColor = Colors.grey.shade400; const dangerColor = const Color(0xffff0606); const hintTextColor = Color.fromARGB(255, 187, 187, 187); +const linkColor= Color(0xff0000EE); const TextStyle labelStyle = TextStyle(fontSize: 20, color: labelColor, fontWeight: FontWeight.w500); diff --git a/lib/pages/chat/bubble.dart b/lib/pages/chat/bubble.dart index 10a8b4e..b2077a7 100644 --- a/lib/pages/chat/bubble.dart +++ b/lib/pages/chat/bubble.dart @@ -1,5 +1,4 @@ import 'package:fcs/helpers/theme.dart'; -import 'package:fcs/pages/package/package_info.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:flutter/material.dart'; @@ -7,6 +6,7 @@ import 'package:intl/intl.dart'; DateFormat dayFormat = DateFormat("MMM dd yyyy"); DateFormat timeFormat = DateFormat("HH:mm"); +final DateFormat dateFormat = DateFormat("d MMM yyyy"); typedef CallbackOnViewDetail(); diff --git a/lib/pages/main/util.dart b/lib/pages/main/util.dart index 5d14196..de8b2fe 100644 --- a/lib/pages/main/util.dart +++ b/lib/pages/main/util.dart @@ -1,3 +1,6 @@ +// ignore_for_file: deprecated_member_use + +import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/localization/app_translations.dart'; import 'package:fcs/pages/main/model/language_model.dart'; @@ -16,11 +19,11 @@ Future showMsgDialog(BuildContext context, String title, String msg) { context: context, builder: (_) { return AlertDialog( - title: new Text(title), - content: new Text(msg), + title: Text(title), + content: Text(msg), actions: [ - new TextButton( - child: new Text( + TextButton( + child: Text( "Close", style: TextStyle(color: primaryColor), ), @@ -208,7 +211,7 @@ Widget getStatus(String status) { call(BuildContext context, String phone) { showConfirmDialog(context, "contact.phone.confim", () => launch("tel:$phone"), - translationVariables: ["$phone"]); + translationVariables: [phone]); } Widget nameWidget(String name) { @@ -297,7 +300,7 @@ Widget fcsDropDown(String label, IconData iconData, child: Icon(iconData), ), Expanded( - child: Container( + child: SizedBox( height: 50.0, child: Row(children: [ Expanded(child: _dropDown()), @@ -393,7 +396,7 @@ bool hasUnicode(String text) { final int maxBits = 128; List unicodeSymbols = text.codeUnits.where((ch) => ch > maxBits).toList(); - return unicodeSymbols.length > 0; + return unicodeSymbols.isNotEmpty; } String removeTrailingZeros(double number) { @@ -416,3 +419,94 @@ String capitalizeFirstLetter(String text) { if (text.isEmpty) return text; return text[0].toUpperCase() + text.substring(1); } + +Widget userSearchBox(BuildContext context, + {required String lableKey, + IconData? icon, + User? user, + Function()? onSearch, + MainAxisAlignment rowMainAxisAlignment = MainAxisAlignment.start}) { + return Column( + children: [ + Row( + mainAxisAlignment: rowMainAxisAlignment, + children: [ + Flexible( + child: Padding( + padding: const EdgeInsets.only(left: 2), + child: + LocalText(context, lableKey, color: labelColor, fontSize: 15), + )), + IconButton( + icon: Icon(Icons.search, color: Colors.black), + onPressed: onSearch), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only( + right: 15, + ), + child: user != null && user.fcsID != "" + ? Icon(icon, color: primaryColor) + : const SizedBox(), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(user?.name ?? ''), + Text(user?.fcsID ?? '', + style: TextStyle(fontSize: 13, color: labelColor)), + Text(user?.phoneNumber ?? '', + style: TextStyle(fontSize: 13, color: labelColor)) + ], + )) + ], + ) + ], + ); +} + +Widget userDisplayBox(BuildContext context, + {required String lableKey, IconData? icon, String? name, String? fcsID}) { + return fcsID != null && fcsID != "" + ? Padding( + padding: const EdgeInsets.only(top: 8.0, bottom: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(right: 15), + child: Icon(icon, color: primaryColor)), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocalText(context, lableKey, + color: Colors.black54, fontSize: 15), + InkWell( + onTap: null, + child: Text( + name ?? '', + style: TextStyle( + shadows: [ + Shadow(color: linkColor, offset: Offset(0, -2)) + ], + color: Colors.transparent, + decoration: TextDecoration.underline, + decorationColor: linkColor), + ), + ), + Text(fcsID, + style: TextStyle(fontSize: 13, color: labelColor)) + ], + ), + ), + ], + ), + ) + : const SizedBox(); +} diff --git a/lib/pages/package/model/package_model.dart b/lib/pages/package/model/package_model.dart index 10e6a4d..fed9bfc 100644 --- a/lib/pages/package/model/package_model.dart +++ b/lib/pages/package/model/package_model.dart @@ -163,33 +163,28 @@ class PackageModel extends BaseModel { try { var qsnap = await FirebaseFirestore.instance - .collection("$path") + .collection(path) .where("tracking_id", isEqualTo: trackingID) .where("has_user_id", isEqualTo: false) .where("is_deleted", isEqualTo: false) .get(const GetOptions(source: Source.server)); - if (qsnap.docs.length > 0) { - var snap = qsnap.docs[0]; - if (snap.exists) { - var package = - Package.fromMap(snap.data as Map, snap.id); - return package; - } + + if (qsnap.docs.isNotEmpty) { + var snap = qsnap.docs.first; + var package = Package.fromMap(snap.data(), snap.id); + return package; } qsnap = await FirebaseFirestore.instance - .collection("$path") + .collection(path) .where("tracking_id", isEqualTo: trackingID) .where("user_id", isEqualTo: user!.id) .where("is_deleted", isEqualTo: false) .get(const GetOptions(source: Source.server)); - if (qsnap.docs.length > 0) { - var snap = qsnap.docs[0]; - if (snap.exists) { - var package = - Package.fromMap(snap.data as Map, snap.id); - return package; - } + if (qsnap.docs.isNotEmpty) { + var snap = qsnap.docs.first; + var package = Package.fromMap(snap.data(), snap.id); + return package; } } catch (e) { log.warning("Error!! $e"); diff --git a/lib/pages/package/package_info.dart b/lib/pages/package/package_info.dart index 421526c..111e2f9 100644 --- a/lib/pages/package/package_info.dart +++ b/lib/pages/package/package_info.dart @@ -9,7 +9,6 @@ import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/delivery_address_selection.dart'; import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_button.dart'; import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; @@ -22,15 +21,19 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; -final DateFormat dateFormat = DateFormat("d MMM yyyy"); +import '../../domain/entities/fcs_shipment.dart'; +import '../fcs_shipment/model/fcs_shipment_model.dart'; class PackageInfo extends StatefulWidget { - final isCustomer; - final isSearchResult; - final Package? package; + final bool isCustomer; + final bool isSearchResult; + final Package package; - PackageInfo( - {this.package, this.isSearchResult = false, this.isCustomer = false}); + const PackageInfo( + {super.key, + required this.package, + this.isSearchResult = false, + this.isCustomer = false}); @override _PackageInfoState createState() => _PackageInfoState(); @@ -41,14 +44,16 @@ class _PackageInfoState extends State { Package? _package = Package(); bool _isLoading = false; MultiImgController multiImgController = MultiImgController(); + FcsShipment? _shipment; @override void initState() { super.initState(); - initPackage(widget.package!); + _initPackage(widget.package); + _loadShipment(); } - initPackage(Package? pkg) async { + _initPackage(Package? pkg) async { setState(() { _isLoading = true; }); @@ -64,6 +69,17 @@ class _PackageInfoState extends State { }); } + _loadShipment() async { + if (widget.package.shipmentId == null) return; + var s = await context + .read() + .getFcsShipment(widget.package.shipmentId!); + _shipment = s; + if (mounted) { + setState(() {}); + } + } + @override void dispose() { super.dispose(); @@ -83,41 +99,51 @@ class _PackageInfoState extends State { labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); - var fcsIDBox = DisplayText( - text: _package?.fcsID ?? "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - ); - final customerNameBox = DisplayText( - text: _package?.userName ?? "", - labelTextKey: "package.create.name", - iconData: Icons.perm_identity, - ); + + final consigneeBox = userDisplayBox(context, + lableKey: "box.consignee.title", + icon: MaterialCommunityIcons.account_arrow_left, + name: _package?.userName ?? "", + fcsID: _package?.fcsID ?? ""); + + final senderBox = userDisplayBox(context, + lableKey: "box.sender.title", + icon: MaterialCommunityIcons.account_arrow_right, + name: _package?.senderName ?? "", + fcsID: _package?.senderFCSID ?? ""); + final marketBox = DisplayText( text: _package?.market ?? "-", labelTextKey: "package.create.market", iconData: Icons.store, ); + final descBox = DisplayText( text: _package?.desc ?? "-", labelTextKey: "package.edit.desc", iconData: MaterialCommunityIcons.message_text_outline, ); + final remarkBox = DisplayText( text: _package?.remark ?? "-", labelTextKey: "package.edit.remark", iconData: Entypo.new_message, ); + final img = MultiImageFile( enabled: false, controller: multiImgController, title: "Receipt File", ); - final returnButton = LocalButton( - textKey: "receiving.return.btn", - callBack: _return, + final returnButton = Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: LocalButton( + textKey: "receiving.return.btn", + callBack: _return, + ), ); + final deliveryAddressBox = DefaultDeliveryAddress( deliveryAddress: _package!.deliveryAddress, labelKey: "package.delivery.address", @@ -136,13 +162,72 @@ class _PackageInfoState extends State { : null, ); + final shipmentBox = Padding( + padding: const EdgeInsets.only(top: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + LocalText(context, "package.shipment.title", + color: primaryColor, fontSize: 17, fontWeight: FontWeight.normal), + Row( + children: [ + Flexible( + child: DisplayText( + text: _shipment?.shipmentNumber ?? '', + labelTextKey: "FCSshipment.number", + iconData: Ionicons.ios_airplane, + ), + ), + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.processingDate != null + ? dateFormatter.format(_shipment!.processingDate!) + : "" + : "", + labelTextKey: "package.processing.date", + iconData: Icons.date_range, + ), + ), + ], + ), + Row( + children: [ + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.cutoffDate != null + ? dateFormatter.format(_shipment!.cutoffDate!) + : "" + : "", + labelTextKey: "FCSshipment.cutoff_date", + iconData: Icons.date_range, + ), + ), + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.etaDate != null + ? dateFormatter.format(_shipment!.etaDate!) + : "" + : "", + labelTextKey: "FCSshipment.ETA", + iconData: Icons.date_range, + ), + ), + ], + ), + ], + ), + ); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), + leading: IconButton( + icon: Icon(CupertinoIcons.back, color: primaryColor, size: 30), onPressed: () => Navigator.of(context).pop(), ), shadowColor: Colors.transparent, @@ -163,30 +248,34 @@ class _PackageInfoState extends State { padding: const EdgeInsets.all(10.0), child: ListView(children: [ trackingIdBox, - widget.isSearchResult ? Container() : fcsIDBox, - widget.isSearchResult ? Container() : customerNameBox, - widget.isSearchResult ? Container() : marketBox, - _package == null || _package!.photoUrls.length == 0 - ? Container() - : img, + Row( + children: [ + Flexible(child: consigneeBox), + Flexible(child: senderBox) + ], + ), + marketBox, widget.isSearchResult ? Container() : descBox, remarkBox, - _package?.status == package_received_status && - widget.isCustomer - ? returnButton - : Container(), widget.isSearchResult ? Container() : deliveryAddressBox, - widget.isSearchResult + _package == null || _package!.photoUrls.isEmpty ? Container() : Padding( - padding: const EdgeInsets.only(top: 15), - child: StatusTree( - shipmentHistory: _package!.shipmentHistory, - currentStatus: _package!.status), - ), - SizedBox( - height: 20, - ) + padding: const EdgeInsets.only(top: 12), child: img), + shipmentBox, + Padding( + padding: const EdgeInsets.only(top: 15), + child: StatusTree( + shipmentHistory: _package!.shipmentHistory, + currentStatus: _package!.status), + ), + _package?.status == package_received_status && + widget.isCustomer + ? Padding( + padding: EdgeInsets.only(top: 15), + child: returnButton) + : Container(), + SizedBox(height: 20) ]), )), ], diff --git a/lib/pages/package/package_list_row.dart b/lib/pages/package/package_list_row.dart index aa05379..eee3313 100644 --- a/lib/pages/package/package_list_row.dart +++ b/lib/pages/package/package_list_row.dart @@ -33,10 +33,8 @@ class PackageListRow extends StatelessWidget { Navigator.push( context, CupertinoPageRoute( - builder: (context) => PackageInfo( - package: package, - isCustomer: isCustomer, - )), + builder: (context) => + PackageInfo(package: package, isCustomer: isCustomer)), ); }, child: Container( diff --git a/lib/pages/processing/package_editor.dart b/lib/pages/processing/package_editor.dart index e27c0c6..c3bbe08 100644 --- a/lib/pages/processing/package_editor.dart +++ b/lib/pages/processing/package_editor.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:fcs/constants.dart'; import 'package:fcs/domain/entities/market.dart'; import 'package:fcs/domain/entities/package.dart'; @@ -20,19 +22,25 @@ import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/fcs_shipment.dart'; + class PackageEditor extends StatefulWidget { - final Package? package; - final User? consignee; - final User? sender; - PackageEditor({this.package, this.consignee, this.sender}); + final User consignee; + final User sender; + final FcsShipment shipment; + const PackageEditor( + {super.key, + required this.consignee, + required this.sender, + required this.shipment}); @override _PackageEditorState createState() => _PackageEditorState(); } class _PackageEditorState extends State { - TextEditingController _remarkCtl = new TextEditingController(); - TextEditingController _descCtl = new TextEditingController(); + final _remarkCtl = TextEditingController(); + final _descCtl = TextEditingController(); bool _isLoading = false; MultiImgController multiImgController = MultiImgController(); @@ -42,7 +50,6 @@ class _PackageEditorState extends State { void initState() { super.initState(); _package = Package(); - _loadPackageData(widget.package?.id!); } _loadPackageData(String? id) async { @@ -75,7 +82,7 @@ class _PackageEditorState extends State { children: [ Expanded( child: DisplayText( - text: _package!.trackingID != null ? _package!.trackingID : "", + text: _package!.trackingID ?? "", labelTextKey: "processing.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, )), @@ -113,35 +120,23 @@ class _PackageEditorState extends State { inAsyncCall: _isLoading, child: Scaffold( appBar: AppBar( - centerTitle: true, - leading: new IconButton( - icon: new Icon(CupertinoIcons.back, color: primaryColor, size: 30), - onPressed: () { - if (isDataChanged()) { - showConfirmDialog(context, "back.button_confirm", () { + centerTitle: true, + leading: IconButton( + icon: Icon(CupertinoIcons.back, color: primaryColor, size: 30), + onPressed: () { + if (isDataChanged()) { + showConfirmDialog(context, "back.button_confirm", () { + Navigator.of(context).pop(); + }); + } else { Navigator.of(context).pop(); - }); - } else { - Navigator.of(context).pop(); - } - }, - ), - shadowColor: Colors.transparent, - backgroundColor: Colors.white, - title: widget.package == null - ? LocalText( - context, - "processing.package.create", - fontSize: 20, - color: primaryColor, - ) - : LocalText( - context, - "processing.package.update", - fontSize: 20, - color: primaryColor, - ), - ), + } + }, + ), + shadowColor: Colors.transparent, + backgroundColor: Colors.white, + title: LocalText(context, "processing.package.create", + fontSize: 20, color: primaryColor)), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( @@ -256,9 +251,8 @@ class _PackageEditorState extends State { _package!.desc = _descCtl.text; _package!.remark = _remarkCtl.text; _package!.photoFiles = multiImgController.getUpdatedFile; - _package!.fcsID = widget.consignee?.fcsID; - _package!.senderFCSID = - widget.sender?.fcsID != null ? widget.sender?.fcsID : ""; + _package!.fcsID = widget.consignee.fcsID; + _package!.senderFCSID = widget.sender.fcsID ?? ""; await packageModel.updateProcessing(_package!, multiImgController.getAddedFile, multiImgController.getDeletedUrl); diff --git a/lib/pages/processing/processing_edit_editor.dart b/lib/pages/processing/processing_edit_editor.dart index ca21d0a..e286bd2 100644 --- a/lib/pages/processing/processing_edit_editor.dart +++ b/lib/pages/processing/processing_edit_editor.dart @@ -9,7 +9,6 @@ import 'package:fcs/pages/package/tracking_id_page.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/user_search/user_search.dart'; import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_text.dart'; @@ -22,22 +21,32 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/fcs_shipment.dart'; +import '../fcs_shipment/model/fcs_shipment_model.dart'; +import '../widgets/local_dropdown.dart'; + class ProcessingEditEditor extends StatefulWidget { - final Package? package; - ProcessingEditEditor({this.package}); + final Package package; + const ProcessingEditEditor({super.key, required this.package}); @override _ProcessingEditEditorState createState() => _ProcessingEditEditorState(); } class _ProcessingEditEditorState extends State { - TextEditingController _remarkCtl = new TextEditingController(); - TextEditingController _descCtl = new TextEditingController(); + final DateFormat dateFormat = DateFormat("d MMM yyyy"); + + TextEditingController _remarkCtl = TextEditingController(); + TextEditingController _descCtl = TextEditingController(); Package? _package; User? _consignee; User? _sender; bool _isLoading = false; + List _shipments = []; + FcsShipment? _shipment; + + MultiImgController multiImgController = MultiImgController(); @override void initState() { @@ -56,57 +65,47 @@ class _ProcessingEditEditorState extends State { fcsID: _package!.senderFCSID ?? "", name: _package!.senderName ?? "", phoneNumber: _package!.senderPhoneNumber ?? ""); + _loadShipment(); } - final DateFormat dateFormat = DateFormat("d MMM yyyy"); + _loadShipment() async { + var fcsShipments = + await context.read().getActiveFcsShipments(); + _shipments = fcsShipments; - bool isNew = false; - MultiImgController multiImgController = MultiImgController(); + var s = FcsShipment( + id: widget.package.id, shipmentNumber: widget.package.shipmentNumber); + + if (_shipments.contains(s)) { + _shipment = s; + } else { + _shipment = null; + } + + if (mounted) { + setState(() {}); + } + } @override Widget build(BuildContext context) { - var fcsIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: _consignee!.fcsID, - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this._consignee = u; - }); - })), - ], - ); - final namebox = DisplayText( - text: _consignee!.name, - labelTextKey: "processing.consignee.name", - iconData: Icons.person, - ); - final phoneNumberBox = DisplayText( - text: _consignee!.phoneNumber, - labelTextKey: "processing.phone", - iconData: Icons.phone, - ); - final trackingIdBox = DisplayText( text: _package!.trackingID, labelTextKey: "processing.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); + final completeProcessingBtn = fcsButton( context, getLocalString(context, 'processing.edit.complete.btn'), callack: _completeProcessing, ); + final descBox = InputText( labelTextKey: 'processing.desc', iconData: MaterialCommunityIcons.message_text_outline, controller: _descCtl); + final remarkBox = InputText( labelTextKey: 'processing.remark', iconData: Entypo.new_message, @@ -118,57 +117,40 @@ class _ProcessingEditEditorState extends State { title: "Receipt File", ); - final consigneeBox = Container( - child: Column( - children: [ - fcsIDBox, - phoneNumberBox, - namebox, - ], - ), - ); + final consigneeBox = userSearchBox(context, + lableKey: 'box.consignee.title', + icon: MaterialCommunityIcons.account_arrow_left, + user: _consignee, + onSearch: () => searchUser(context, onUserSelect: (u) { + setState(() { + _consignee = u; + }); + }, popPage: true)); - var shipperIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: _sender != null ? _sender!.fcsID : "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this._sender = u; - }); - }, popPage: true)), - ], - ); + final senderBox = userSearchBox(context, + lableKey: 'box.sender.title', + icon: MaterialCommunityIcons.account_arrow_right, + user: _sender, + onSearch: () => searchUser(context, onUserSelect: (u) { + setState(() { + _sender = u; + }); + }, popPage: true)); - final shipperPhoneNumberBox = DisplayText( - text: _sender != null ? _sender!.phoneNumber : "", - labelTextKey: "processing.phone", - maxLines: 2, - iconData: Icons.phone, - ); - - final shipperNamebox = DisplayText( - text: _sender != null ? _sender!.name : "", - labelTextKey: "processing.shipper.name", - maxLines: 2, - iconData: Icons.person, - ); - - final shipperBox = Container( - child: Column( - children: [ - shipperIDBox, - shipperPhoneNumberBox, - shipperNamebox, - ], - ), - ); + final fcsShipmentsBox = Container( + padding: EdgeInsets.symmetric(vertical: 15), + child: LocalDropdown( + callback: (v) { + setState(() { + _shipment = v; + }); + }, + labelKey: "box.shipment", + iconData: Ionicons.ios_airplane, + display: (u) => u.shipmentNumber, + selectedValue: _shipment, + values: _shipments, + )); return LocalProgress( inAsyncCall: _isLoading, @@ -189,24 +171,26 @@ class _ProcessingEditEditorState extends State { }, ), body: Padding( - padding: const EdgeInsets.all(8.0), + padding: const EdgeInsets.only(left: 12.0, right: 12, top: 10), child: ListView( children: [ trackingIdBox, Row( children: [ Flexible(child: consigneeBox), - Flexible(child: shipperBox) + Flexible(child: senderBox) ], ), + const SizedBox(height: 8), + fcsShipmentsBox, marketDropdown(), descBox, remarkBox, + const SizedBox(height: 10), img, + SizedBox(height: 20), completeProcessingBtn, - SizedBox( - height: 20, - ) + SizedBox(height: 30) ], ), ), @@ -319,23 +303,16 @@ class _ProcessingEditEditorState extends State { } isDataChanged() { - if (isNew) { - return _consignee!.fcsID != "" || - selectedMarket != null || - _descCtl.text != "" || - _remarkCtl.text != "" || - multiImgController.getAddedFile.isNotEmpty; - } else { - var _package = Package( - fcsID: _consignee!.fcsID, - senderFCSID: _sender!.fcsID, - market: selectedMarket, - desc: _descCtl.text, - remark: _remarkCtl.text, - photoUrls: widget.package!.photoUrls); - return widget.package!.isChangedForEditProcessing(_package) || - multiImgController.getAddedFile.isNotEmpty || - multiImgController.getDeletedUrl.isNotEmpty; - } + var package = Package( + fcsID: _consignee!.fcsID, + senderFCSID: _sender!.fcsID, + market: selectedMarket, + desc: _descCtl.text, + remark: _remarkCtl.text, + photoUrls: widget.package.photoUrls, + shipmentId: _shipment?.id); + return widget.package.isChangedForEditProcessing(package) || + multiImgController.getAddedFile.isNotEmpty || + multiImgController.getDeletedUrl.isNotEmpty; } } diff --git a/lib/pages/processing/processing_editor.dart b/lib/pages/processing/processing_editor.dart index 3c4f637..a7a61cc 100644 --- a/lib/pages/processing/processing_editor.dart +++ b/lib/pages/processing/processing_editor.dart @@ -1,3 +1,5 @@ +// ignore_for_file: use_build_context_synchronously + import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/processing.dart'; import 'package:fcs/domain/entities/user.dart'; @@ -6,7 +8,6 @@ import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/package_info.dart'; import 'package:fcs/pages/user_search/user_search.dart'; import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/progress.dart'; import 'package:flutter/cupertino.dart'; @@ -14,12 +15,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:provider/provider.dart'; +import '../../domain/entities/fcs_shipment.dart'; +import '../fcs_shipment/model/fcs_shipment_model.dart'; +import '../widgets/local_dropdown.dart'; import 'model/processing_model.dart'; import 'package_editor.dart'; class ProcesingEditor extends StatefulWidget { - final Processing? processing; - const ProcesingEditor({this.processing}); + const ProcesingEditor({super.key}); @override _ProcesingEditorState createState() => _ProcesingEditorState(); } @@ -27,147 +30,105 @@ class ProcesingEditor extends StatefulWidget { class _ProcesingEditorState extends State { Processing processing = Processing(); bool _isLoading = false; - late bool _isNew; - User? consignee; - User? sender; + User? _consignee; + User? _sender; List packages = []; + List _shipments = []; + FcsShipment? _shipment; @override void initState() { + _loadShipment(); super.initState(); - _isNew = widget.processing == null; - if (!_isNew) { - processing = widget.processing!; - consignee = User( - fcsID: processing.userID, - name: processing.userName, - phoneNumber: processing.userPhoneNumber); - sender = User( - fcsID: processing.fcsID, - name: processing.shipperName, - phoneNumber: processing.shipperPhoneNumber); - packages = processing.packages; + } + + _loadShipment() async { + var fcsShipments = + await context.read().getActiveFcsShipments(); + _shipments = fcsShipments; + + if (mounted) { + setState(() {}); } } @override Widget build(BuildContext context) { - var fcsIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: consignee != null ? consignee!.fcsID : "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - )), + final consigneeBox = userSearchBox(context, + lableKey: 'box.consignee.title', + icon: MaterialCommunityIcons.account_arrow_left, + user: _consignee, + onSearch: () => searchUser(context, onUserSelect: (u) { + setState(() { + _consignee = u; + }); + }, popPage: true)); + + final senderBox = userSearchBox(context, + lableKey: 'box.sender.title', + icon: MaterialCommunityIcons.account_arrow_right, + user: _sender, + onSearch: () => searchUser(context, onUserSelect: (u) { + setState(() { + _sender = u; + }); + }, popPage: true)); + + final fcsShipmentsBox = Container( + padding: EdgeInsets.symmetric(vertical: 15), + child: LocalDropdown( + callback: (v) { + setState(() { + _shipment = v; + }); + }, + labelKey: "box.shipment", + iconData: Ionicons.ios_airplane, + display: (u) => u.shipmentNumber, + selectedValue: _shipment, + values: _shipments, + )); + + final packageTitleBox = Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text("Packages (${packages.length})"), IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this.consignee = u; - }); - }, popPage: true)), + icon: Icon( + Icons.add_circle, + color: primaryColor, + ), + onPressed: () async { + if (_consignee == null) { + showMsgDialog(context, "Error", "Please select consignee"); + return; + } + + if (_sender == null) { + showMsgDialog(context, "Error", "Please select sender"); + return; + } + + if (_shipment == null) { + showMsgDialog(context, "Error", "Please select shipment"); + return; + } + + Package? package = await Navigator.push( + context, + CupertinoPageRoute( + builder: (context) => PackageEditor( + sender: _sender!, + consignee: _consignee!, + shipment: _shipment!)), + ); + + _addPackage(package); + // _savePackage(_package); + }), ], ); - final phoneNumberBox = DisplayText( - text: consignee != null ? consignee!.phoneNumber : "", - labelTextKey: "processing.phone", - maxLines: 2, - iconData: Icons.phone, - ); - - final namebox = DisplayText( - text: consignee != null ? consignee!.name : "", - labelTextKey: "processing.consignee.name", - maxLines: 2, - iconData: Icons.person, - ); - - final consigneeBox = Container( - child: Column( - children: [ - fcsIDBox, - phoneNumberBox, - namebox, - ], - ), - ); - - var shipperIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: sender != null ? sender!.fcsID : "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this.sender = u; - }); - }, popPage: true)), - ], - ); - - final shipperPhoneNumberBox = DisplayText( - text: sender != null ? sender!.phoneNumber : "", - labelTextKey: "processing.phone", - maxLines: 2, - iconData: Icons.phone, - ); - - final shipperNamebox = DisplayText( - text: sender != null ? sender!.name : "", - labelTextKey: "processing.shipper.name", - maxLines: 2, - iconData: Icons.person, - ); - - final shipperBox = Container( - child: Column( - children: [ - shipperIDBox, - shipperPhoneNumberBox, - shipperNamebox, - ], - ), - ); - - final packageTitleBox = Container( - child: Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - Text("Packages (${packages.length})"), - IconButton( - icon: Icon( - Icons.add_circle, - color: primaryColor, - ), - onPressed: () async { - if (this.consignee == null) { - showMsgDialog( - context, "Warning", "Please select 'Consignee'"); - return; - } - Package? _package = await Navigator.push( - context, - CupertinoPageRoute( - builder: (context) => PackageEditor( - sender: this.sender, - consignee: this.consignee, - )), - ); - - _addPackage(_package); - // _savePackage(_package); - }), - ], - ), - ); - final createButton = fcsButton( context, getLocalString(context, 'processing.edit.complete.btn'), @@ -178,7 +139,7 @@ class _ProcesingEditorState extends State { inAsyncCall: _isLoading, child: Scaffold( appBar: LocalAppBar( - labelKey: _isNew ? "processing.create" : "processing.update", + labelKey: "processing.create", backgroundColor: Colors.white, labelColor: primaryColor, arrowColor: primaryColor, @@ -193,10 +154,11 @@ class _ProcesingEditorState extends State { Row( children: [ Flexible(child: consigneeBox), - Flexible(child: shipperBox) + Flexible(child: senderBox) ], ), - Divider(), + const SizedBox(height: 10), + fcsShipmentsBox, packageTitleBox, Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -206,9 +168,7 @@ class _ProcesingEditorState extends State { height: 20, ), createButton, - SizedBox( - height: 10, - ), + SizedBox(height: 10), ], ), ), @@ -236,7 +196,7 @@ class _ProcesingEditorState extends State { _addPackage(Package? package) { if (package == null) return; - this.packages.add(package); + packages.add(package); setState(() {}); } @@ -253,12 +213,7 @@ class _ProcesingEditorState extends State { ProcessingModel processingModel = Provider.of(context, listen: false); try { - if (_isNew) { - await processingModel.createProcessing(processing); - } else { - processing.id = widget.processing!.id; - await processingModel.updateProcessing(processing); - } + await processingModel.createProcessing(processing); Navigator.pop(context); } catch (e) { showMsgDialog(context, "Error", e.toString()); diff --git a/lib/pages/processing/processing_info.dart b/lib/pages/processing/processing_info.dart index cbd5eb6..4eedacd 100644 --- a/lib/pages/processing/processing_info.dart +++ b/lib/pages/processing/processing_info.dart @@ -1,10 +1,11 @@ +import 'package:fcs/domain/entities/fcs_shipment.dart'; import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/helpers/theme.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; +import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/multi_img_file.dart'; import 'package:fcs/pages/widgets/progress.dart'; @@ -15,13 +16,14 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; +import '../fcs_shipment/model/fcs_shipment_model.dart'; import 'processing_edit_editor.dart'; final DateFormat dateFormat = DateFormat("d MMM yyyy"); class ProcessingInfo extends StatefulWidget { - final Package? package; - ProcessingInfo({this.package}); + final Package package; + const ProcessingInfo({super.key, required this.package}); @override _ProcessingInfoState createState() => _ProcessingInfoState(); @@ -32,21 +34,33 @@ class _ProcessingInfoState extends State { Package? _package; bool _isLoading = false; MultiImgController multiImgController = MultiImgController(); + FcsShipment? _shipment; @override void initState() { super.initState(); - initPackage(widget.package!); + _initPackage(widget.package); + _loadShipment(); } - initPackage(Package? package) { - if (package == null) return; + _initPackage(Package package) { setState(() { _package = package; multiImgController.setImageUrls = package.photoUrls; }); } + _loadShipment() async { + if (widget.package.shipmentId == null) return; + var s = await context + .read() + .getFcsShipment(widget.package.shipmentId!); + _shipment = s; + if (mounted) { + setState(() {}); + } + } + @override void dispose() { super.dispose(); @@ -59,36 +73,7 @@ class _ProcessingInfoState extends State { labelTextKey: "processing.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); - var fcsIDBox = DisplayText( - text: _package != null ? _package!.fcsID : "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - ); - final phoneNumberBox = DisplayText( - text: _package != null ? _package!.phoneNumber : "", - labelTextKey: "processing.phone", - iconData: Icons.phone, - ); - final customerNameBox = DisplayText( - text: _package != null ? _package!.userName : "", - labelTextKey: "processing.consignee.name", - iconData: Icons.perm_identity, - ); - var senderFcsIDBox = DisplayText( - text: _package != null ? _package!.senderFCSID : "", - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - ); - final senderPhoneNumberBox = DisplayText( - text: _package != null ? _package!.senderPhoneNumber : "", - labelTextKey: "processing.phone", - iconData: Icons.phone, - ); - final senderNameBox = DisplayText( - text: _package != null ? _package!.senderName : "", - labelTextKey: "processing.shipper.name", - iconData: Icons.perm_identity, - ); + final marketBox = DisplayText( text: _package != null ? _package!.market : "-", labelTextKey: "processing.market", @@ -110,24 +95,77 @@ class _ProcessingInfoState extends State { title: "Receipt File", ); - final consigneeBox = Container( + final consigneeBox = userDisplayBox(context, + lableKey: "box.consignee.title", + icon: MaterialCommunityIcons.account_arrow_left, + name: _package?.userName ?? "", + fcsID: _package?.fcsID ?? ""); + + final senderBox = userDisplayBox(context, + lableKey: "box.sender.title", + icon: MaterialCommunityIcons.account_arrow_right, + name: _package?.senderName ?? "", + fcsID: _package?.senderFCSID ?? ""); + + final shipmentBox = Padding( + padding: const EdgeInsets.only(top: 15), child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - fcsIDBox, - phoneNumberBox, - customerNameBox, - ], - ), - ); - final shipperBox = Container( - child: Column( - children: [ - senderFcsIDBox, - senderPhoneNumberBox, - senderNameBox, + LocalText(context, "package.shipment.title", + color: primaryColor, fontSize: 17, fontWeight: FontWeight.normal), + Row( + children: [ + Flexible( + child: DisplayText( + text: _shipment?.shipmentNumber ?? '', + labelTextKey: "FCSshipment.number", + iconData: Ionicons.ios_airplane, + ), + ), + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.processingDate != null + ? dateFormatter.format(_shipment!.processingDate!) + : "" + : "", + labelTextKey: "package.processing.date", + iconData: Icons.date_range, + ), + ), + ], + ), + Row( + children: [ + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.cutoffDate != null + ? dateFormatter.format(_shipment!.cutoffDate!) + : "" + : "", + labelTextKey: "FCSshipment.cutoff_date", + iconData: Icons.date_range, + ), + ), + Flexible( + child: DisplayText( + text: _shipment != null + ? _shipment!.etaDate != null + ? dateFormatter.format(_shipment!.etaDate!) + : "" + : "", + labelTextKey: "FCSshipment.ETA", + iconData: Icons.date_range, + ), + ), + ], + ), ], ), ); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -148,31 +186,32 @@ class _ProcessingInfoState extends State { ]), body: Card( elevation: 0, - child: Column( - children: [ - Expanded( - child: Padding( - padding: const EdgeInsets.all(10.0), - child: ListView(children: [ - trackingIdBox, - Row( - children: [ - Flexible(child: consigneeBox), - Flexible(child: shipperBox) - ], - ), - marketBox, - descBox, - remarkBox, - _package!.photoUrls.length == 0 ? Container() : img, - StatusTree( - shipmentHistory: _package!.shipmentHistory, - currentStatus: _package!.status ?? ""), - SizedBox(height: 20) - ]), - )), - ], - ), + child: + ListView(padding: const EdgeInsets.all(10.0), children: [ + trackingIdBox, + Row( + children: [ + Flexible(child: consigneeBox), + Flexible( + child: _package?.senderFCSID != null && + _package?.senderFCSID != "" + ? senderBox + : const SizedBox()) + ], + ), + marketBox, + descBox, + remarkBox, + _package!.photoUrls.isEmpty ? Container() : img, + shipmentBox, + Padding( + padding: const EdgeInsets.only(top: 15), + child: StatusTree( + shipmentHistory: _package!.shipmentHistory, + currentStatus: _package!.status ?? ""), + ), + SizedBox(height: 20) + ]), ), ), ); @@ -201,10 +240,11 @@ class _ProcessingInfoState extends State { } _gotoEditor() async { + if (_package == null) return; bool? deleted = await Navigator.push( context, CupertinoPageRoute( - builder: (context) => ProcessingEditEditor(package: _package))); + builder: (context) => ProcessingEditEditor(package: _package!))); if (deleted ?? false) { Navigator.pop(context); } else { @@ -212,7 +252,7 @@ class _ProcessingInfoState extends State { Provider.of(context, listen: false); Package? p = await packageModel.getPackage(_package!.id!); if (p == null) return; - initPackage(p); + _initPackage(p); } } } diff --git a/lib/pages/profile/profile_page.dart b/lib/pages/profile/profile_page.dart index 81f5181..50396ca 100644 --- a/lib/pages/profile/profile_page.dart +++ b/lib/pages/profile/profile_page.dart @@ -76,12 +76,6 @@ class _ProfileState extends State { buildLanguage(languageModel); var deliveryAddressModel = Provider.of(context); - final namebox = DisplayText( - text: "${user.name ?? ''}" + " (${user.status ?? ''})", - labelTextKey: "profile.name", - iconData: Icons.person, - ); - final currencyBox = Row( children: [ Expanded( @@ -104,24 +98,6 @@ class _ProfileState extends State { iconData: MaterialCommunityIcons.account_remove, ); - final phonenumberBox = Row( - children: [ - Expanded( - child: DisplayText( - text: user.phone, - labelTextKey: "profile.phone", - iconData: Icons.phone), - ), - // IconButton( - // icon: Icon(Icons.edit, color: Colors.grey), - // onPressed: () { - // Navigator.of(context, rootNavigator: true).push( - // CupertinoPageRoute( - // builder: (context) => ChangePhoneNumber(user: user))); - // }) - ], - ); - final fcsIDBox = Row( children: [ Expanded( @@ -187,31 +163,48 @@ class _ProfileState extends State { }) ], ); + + final titleBox = Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.center, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + user.name ?? "", + style: TextStyle(fontSize: 18, color: Colors.black), + ), + const SizedBox(width: 5), + InkResponse( + radius: 20, + onTap: _editName, + child: Icon(Icons.edit, color: Colors.grey, size: 23)) + ], + ), + const SizedBox(height: 1), + Text( + user.phone, + style: TextStyle(fontSize: 15, color: labelColor), + ), + ], + ); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( key: key, appBar: LocalAppBar( - labelKey: "profile.title", - backgroundColor: Colors.white, - labelColor: primaryColor, - arrowColor: primaryColor), + backgroundColor: Colors.white, + labelColor: primaryColor, + arrowColor: primaryColor, + titleWidget: titleBox + ), body: Padding( padding: const EdgeInsets.all(8.0), child: ListView( children: [ - Row( - children: [ - Expanded(child: namebox), - Padding( - padding: const EdgeInsets.only(right: 0), - child: IconButton( - icon: Icon(Icons.edit, color: Colors.grey), - onPressed: _editName), - ) - ], - ), - phonenumberBox, + const SizedBox(height: 5), fcsIDBox, usaShippingAddressBox, currencyBox, @@ -327,13 +320,13 @@ class _ProfileState extends State { if (user == null || user.isCustomer()) return Container(); List privileges = []; - user.privileges.forEach((e) { + for (var e in user.privileges) { Privilege? p = _privileges.firstWhereOrNull((p) => p.id == e); if (p != null) { privileges.add(p); } - }); + } return privileges.isEmpty ? const SizedBox() @@ -373,10 +366,9 @@ class _ProfileState extends State { children: [ Text("${p.name}", style: TextStyle( - fontSize: 16.0, - fontStyle: FontStyle.normal, - color: primaryColor, - )), + fontSize: 16.0, + fontStyle: FontStyle.normal, + color: primaryColor)), Text( "${p.desc}", style: TextStyle( @@ -401,9 +393,7 @@ class _ProfileState extends State { _showToast(String title) { ScaffoldMessengerState? scaffold = key.currentState; - if (scaffold == null) { - scaffold = ScaffoldMessenger.of(context); - } + scaffold ??= ScaffoldMessenger.of(context); scaffold.showSnackBar( SnackBar( diff --git a/lib/pages/receiving/receiving_editor.dart b/lib/pages/receiving/receiving_editor.dart index 78e9b92..d3f4ec9 100644 --- a/lib/pages/receiving/receiving_editor.dart +++ b/lib/pages/receiving/receiving_editor.dart @@ -5,8 +5,6 @@ import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/user_search/user_search.dart'; import 'package:fcs/pages/widgets/barcode_scanner.dart'; -import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; @@ -16,11 +14,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:provider/provider.dart'; -typedef void FindCallBack(); - class ReceivingEditor extends StatefulWidget { final Package? package; - const ReceivingEditor({this.package}); + const ReceivingEditor({super.key, this.package}); @override _ReceivingEditorState createState() => _ReceivingEditorState(); } @@ -29,8 +25,8 @@ class _ReceivingEditorState extends State { Package package = Package(); bool _isLoading = false; late bool _isNew; - User? user; - final _receiveFormKey=GlobalKey(); + User? _consignee; + final _receiveFormKey = GlobalKey(); TextEditingController _trackingIDCtl = new TextEditingController(); TextEditingController _remarkCtl = new TextEditingController(); MultiImgController _multiImgController = MultiImgController(); @@ -44,12 +40,12 @@ class _ReceivingEditorState extends State { _trackingIDCtl.text = package.trackingID!; _remarkCtl.text = package.remark!; _multiImgController.setImageUrls = package.photoUrls; - user = User( + _consignee = User( fcsID: package.fcsID, name: package.userName, phoneNumber: package.phoneNumber); } else { - package = new Package(); + package = Package(); } _trackingIDCtl.addListener(() { var text = _trackingIDCtl.text; @@ -66,24 +62,6 @@ class _ReceivingEditorState extends State { @override Widget build(BuildContext context) { - var fcsIDBox = Row( - children: [ - Expanded( - child: DisplayText( - text: user != null ? user!.fcsID : "", - labelTextKey: "receiving.fcs.id", - icon: FcsIDIcon(), - )), - IconButton( - icon: Icon(Icons.search, color: primaryColor), - onPressed: () => searchUser(context, onUserSelect: (u) { - setState(() { - this.user = u; - }); - }, popPage: true)), - ], - ); - final trackingIDBox = Container( padding: EdgeInsets.only(left: 6), child: Row( @@ -95,13 +73,12 @@ class _ReceivingEditorState extends State { labelTextKey: "receiving.tracking.id", controller: _trackingIDCtl, autovalidateMode: AutovalidateMode.onUserInteraction, - validator: (value){ - if(value==null || value.isEmpty){ + validator: (value) { + if (value == null || value.isEmpty) { return "invalid tracking ID"; } return null; }, - )), InkWell( onTap: _scan, @@ -130,11 +107,6 @@ class _ReceivingEditorState extends State { controller: _multiImgController, title: "Receiving", ); - final namebox = DisplayText( - text: user != null ? user!.name : "", - labelTextKey: "receiving.consignee.name", - iconData: Icons.person, - ); final createButton = fcsButton( context, @@ -148,6 +120,17 @@ class _ReceivingEditorState extends State { callack: _save, ); + final consigneeBox = userSearchBox(context, + lableKey: 'box.consignee.title', + icon: MaterialCommunityIcons.account_arrow_left, + rowMainAxisAlignment: MainAxisAlignment.spaceBetween, + user: _consignee, + onSearch: () => searchUser(context, onUserSelect: (u) { + setState(() { + _consignee = u; + }); + }, popPage: true)); + return LocalProgress( inAsyncCall: _isLoading, child: Scaffold( @@ -183,11 +166,8 @@ class _ReceivingEditorState extends State { SizedBox( height: 10, ), - fcsIDBox, - namebox, - SizedBox( - height: 20, - ), + consigneeBox, + SizedBox(height: 20), _isNew ? createButton : updateButton, SizedBox( height: 10, @@ -236,8 +216,8 @@ class _ReceivingEditorState extends State { return; } - if (user == null) { - showMsgDialog(context, "Error", "Please select FCS ID"); + if (_consignee == null) { + showMsgDialog(context, "Error", "Please select consignee"); return; } setState(() { @@ -248,12 +228,12 @@ class _ReceivingEditorState extends State { try { if (_isNew) { await packageModel.createReceiving( - user!, _p, _multiImgController.getAddedFile); + _consignee!, _p, _multiImgController.getAddedFile); } else { _p.id = widget.package!.id; _p.photoUrls = package.photoUrls; await packageModel.updateReceiving( - user!, + _consignee!, _p, _multiImgController.getAddedFile, _multiImgController.getDeletedUrl); @@ -272,15 +252,15 @@ class _ReceivingEditorState extends State { if (_isNew) { return _trackingIDCtl.text != "" || _remarkCtl.text != "" || - user != null || + _consignee != null || _multiImgController.getAddedFile.isNotEmpty; } else { - var _package = Package( + var package = Package( trackingID: _trackingIDCtl.text, remark: _remarkCtl.text, - fcsID: user!.fcsID, + fcsID: _consignee!.fcsID, photoUrls: widget.package!.photoUrls); - return widget.package!.isChangedForEdit(_package) || + return widget.package!.isChangedForEditReceiving(package) || _multiImgController.getAddedFile.isNotEmpty || _multiImgController.getDeletedUrl.isNotEmpty; } diff --git a/lib/pages/receiving/receiving_info.dart b/lib/pages/receiving/receiving_info.dart index 689a200..cda433c 100644 --- a/lib/pages/receiving/receiving_info.dart +++ b/lib/pages/receiving/receiving_info.dart @@ -4,7 +4,6 @@ import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/widgets/display_text.dart'; -import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/multi_img_controller.dart'; import 'package:fcs/pages/widgets/multi_img_file.dart'; @@ -61,16 +60,13 @@ class _ReceivingInfoState extends State { labelTextKey: "package.tracking.id", iconData: MaterialCommunityIcons.barcode_scan, ); - var fcsIDBox = DisplayText( - text: _package!.fcsID, - labelTextKey: "processing.fcs.id", - icon: FcsIDIcon(), - ); - final customerNameBox = DisplayText( - text: _package!.userName, - labelTextKey: "package.create.name", - iconData: Icons.perm_identity, - ); + + final consigneeBox = userDisplayBox(context, + lableKey: "box.consignee.title", + icon: MaterialCommunityIcons.account_arrow_left, + name: _package?.userName ?? "", + fcsID: _package?.fcsID ?? ""); + final remarkBox = DisplayText( text: _package!.remark ?? "-", labelTextKey: "package.edit.remark", @@ -112,16 +108,21 @@ class _ReceivingInfoState extends State { padding: const EdgeInsets.all(10.0), child: ListView(children: [ trackingIdBox, - fcsIDBox, - customerNameBox, + consigneeBox, remarkBox, - _package!.photoUrls.length == 0 ? Container() : img, - StatusTree( - shipmentHistory: _package!.shipmentHistory, - currentStatus: _package!.status), - SizedBox( - height: 20, - ) + _package!.photoUrls.isEmpty + ? Container() + : Padding( + padding: const EdgeInsets.only(top: 5), + child: img, + ), + Padding( + padding: const EdgeInsets.only(top: 15), + child: StatusTree( + shipmentHistory: _package!.shipmentHistory, + currentStatus: _package!.status), + ), + SizedBox(height: 20) ]), )), ], diff --git a/lib/pages/widgets/status_tree.dart b/lib/pages/widgets/status_tree.dart index f29a025..d12a779 100644 --- a/lib/pages/widgets/status_tree.dart +++ b/lib/pages/widgets/status_tree.dart @@ -51,7 +51,7 @@ class StatusTree extends StatelessWidget { children: [ Text( 'Status', - style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold), + style: TextStyle(color: primaryColor, fontSize: 17), ), Container( child: Timeline.builder( @@ -76,16 +76,20 @@ class StatusTree extends StatelessWidget { Text(e.status, style: TextStyle( color: e.done! ? primaryColor : Colors.grey, - fontSize: 16, + fontSize: 15, fontWeight: FontWeight.bold)), e.done! || isPacked ? e.date != null - ? Text(dateFormatter.format(e.date!)) + ? Text( + dateFormatter.format(e.date!), + style: TextStyle(fontSize: 13), + ) : const SizedBox() : Container(), e.staffName == null ? Container() - : Text(e.staffName!) + : Text(e.staffName!, + style: TextStyle(fontSize: 13)) ], ), ),