Merge branch 'master' of tzw/fcs into master

This commit is contained in:
2025-03-18 10:13:09 +06:30
committed by Gogs
32 changed files with 1141 additions and 462 deletions

View File

@@ -371,7 +371,7 @@
"box.crete.carton":"Create carton", "box.crete.carton":"Create carton",
"box.carton.type":"Carton type", "box.carton.type":"Carton type",
"box.select.delivery":"Last mile", "box.select.delivery":"Last mile",
"box.select.package":"Select packages", "box.select.package":"Packages",
"box.no_package":"There is no packages.", "box.no_package":"There is no packages.",
"box.input_cargo_weight":"Cargo type (lb)", "box.input_cargo_weight":"Cargo type (lb)",
"box.input_surcharge_item":"Surcharge items", "box.input_surcharge_item":"Surcharge items",
@@ -523,6 +523,7 @@
"rate.discount.rate":"Discount rate", "rate.discount.rate":"Discount rate",
"rate.custom_duty.title":"Custom Fee", "rate.custom_duty.title":"Custom Fee",
"rate.custom_duty":"Custom Fee", "rate.custom_duty":"Custom Fee",
"rate.custom_new":"New custom fee",
"rate.cargo.type":"Cargo Types", "rate.cargo.type":"Cargo Types",
"rate.discount_by_weight":"Discounts by weight", "rate.discount_by_weight":"Discounts by weight",
"rate.discount_by_weight.edit.delete.confirm":"Delete this discount by weight?", "rate.discount_by_weight.edit.delete.confirm":"Delete this discount by weight?",
@@ -530,6 +531,8 @@
"Rate End ================================================================":"", "Rate End ================================================================":"",
"Cargo Start ================================================================":"", "Cargo Start ================================================================":"",
"cargo.title":"Cargoes",
"cargo.new":"New cargo",
"cargo.form.title":"Cargo", "cargo.form.title":"Cargo",
"cargo.type":"Cargo type", "cargo.type":"Cargo type",
"cargo.weight":"Weight", "cargo.weight":"Weight",
@@ -539,6 +542,7 @@
"cargo.edit.delete.confirm":"Delete this cargo type?", "cargo.edit.delete.confirm":"Delete this cargo type?",
"cargo.display_index":"Display index", "cargo.display_index":"Display index",
"cargo.is_default":"Default Cargo", "cargo.is_default":"Default Cargo",
"cargo.is_mix":"Mix cargo",
"Cargo End ================================================================":"", "Cargo End ================================================================":"",
"Invoices Start ================================================================":"", "Invoices Start ================================================================":"",

View File

@@ -371,7 +371,7 @@
"box.crete.carton":"Create carton", "box.crete.carton":"Create carton",
"box.carton.type":"ပုံး အမျိုးအစား", "box.carton.type":"ပုံး အမျိုးအစား",
"box.select.delivery":"Last mile", "box.select.delivery":"Last mile",
"box.select.package":"Select packages", "box.select.package":"Packages",
"box.no_package":"There is no packages.", "box.no_package":"There is no packages.",
"box.input_cargo_weight":"Cargo type (lb)", "box.input_cargo_weight":"Cargo type (lb)",
"box.input_surcharge_item":"Surcharge items", "box.input_surcharge_item":"Surcharge items",
@@ -526,6 +526,7 @@
"rate.discount.rate":"လျှော့စျေးနှုန်း", "rate.discount.rate":"လျှော့စျေးနှုန်း",
"rate.custom_duty.title":"အကောက်ခွန်များ", "rate.custom_duty.title":"အကောက်ခွန်များ",
"rate.custom_duty":"အကောက်ခွန်", "rate.custom_duty":"အကောက်ခွန်",
"rate.custom_new":"အကောက်ခွန်အသစ်",
"rate.cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား", "rate.cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား",
"rate.discount_by_weight":"အထူးလျှော့စျေး", "rate.discount_by_weight":"အထူးလျှော့စျေး",
"rate.discount_by_weight.edit.delete.confirm":"လျှော့စျေးနှုန်းကို ဖျက်မလား?", "rate.discount_by_weight.edit.delete.confirm":"လျှော့စျေးနှုန်းကို ဖျက်မလား?",
@@ -533,6 +534,8 @@
"Rate End ================================================================":"", "Rate End ================================================================":"",
"Cargo Start ================================================================":"", "Cargo Start ================================================================":"",
"cargo.title":"ကုန်ပစ္စည်းများ",
"cargo.new":"ကုန်ပစ္စည်းအသစ်",
"cargo.form.title":"ကုန်ပစ္စည်း", "cargo.form.title":"ကုန်ပစ္စည်း",
"cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား", "cargo.type":"ကုန်ပစ္စည်းအမျိုးအစား",
"cargo.weight":"အလေးချိန်", "cargo.weight":"အလေးချိန်",
@@ -542,6 +545,7 @@
"cargo.edit.delete.confirm":"ကုန်ပစ္စည်းကို ဖျက်မလား?", "cargo.edit.delete.confirm":"ကုန်ပစ္စည်းကို ဖျက်မလား?",
"cargo.display_index":"Display index", "cargo.display_index":"Display index",
"cargo.is_default":"Default Cargo", "cargo.is_default":"Default Cargo",
"cargo.is_mix":"Mix cargo",
"Cargo End ================================================================":"", "Cargo End ================================================================":"",
"Invoices Start ================================================================":"", "Invoices Start ================================================================":"",

View File

@@ -46,35 +46,34 @@ class App extends StatefulWidget {
} }
class _AppState extends State<App> { class _AppState extends State<App> {
final MainModel mainModel = new MainModel(); final MainModel mainModel = MainModel();
final ContactModel contactModel = new ContactModel(); final ContactModel contactModel = ContactModel();
final TermModel termModel = new TermModel(); final TermModel termModel = TermModel();
final FAQModel faqModel = new FAQModel(); final FAQModel faqModel = FAQModel();
final PaymentMethodModel paymentMethodModel = new PaymentMethodModel(); final PaymentMethodModel paymentMethodModel = PaymentMethodModel();
final FcsShipmentModel fcsShipmentModel = new FcsShipmentModel(); final FcsShipmentModel fcsShipmentModel = FcsShipmentModel();
final LanguageModel lanuguageModel = new LanguageModel(); final LanguageModel lanuguageModel = LanguageModel();
final ShipmentRateModel shipmentRateModel = new ShipmentRateModel(); final ShipmentRateModel shipmentRateModel = ShipmentRateModel();
final CartonModel boxModel = new CartonModel(); final CartonModel boxModel = CartonModel();
final MessageModel messageModel = new MessageModel(); final MessageModel messageModel = MessageModel();
final InvoiceModel invoiceModel = new InvoiceModel(); final InvoiceModel invoiceModel = InvoiceModel();
final CustomerModel customerModel = new CustomerModel(); final CustomerModel customerModel = CustomerModel();
final DiscountModel discountModel = new DiscountModel(); final DiscountModel discountModel = DiscountModel();
final StaffModel staffModel = new StaffModel(); final StaffModel staffModel = StaffModel();
final DeliveryAddressModel deliveryAddressModel = new DeliveryAddressModel(); final DeliveryAddressModel deliveryAddressModel = DeliveryAddressModel();
final PackageModel packageModel = new PackageModel(); final PackageModel packageModel = PackageModel();
final MarketModel marketModel = new MarketModel(); final MarketModel marketModel = MarketModel();
final DeliveryModel deliveryModel = new DeliveryModel(); final DeliveryModel deliveryModel = DeliveryModel();
final CartonSizeModel cartonSizeModel = new CartonSizeModel(); final CartonSizeModel cartonSizeModel = CartonSizeModel();
final ProcessingModel processingModel = new ProcessingModel(); final ProcessingModel processingModel = ProcessingModel();
final PickupModel pickupModel = new PickupModel(); final PickupModel pickupModel = PickupModel();
final CartonSelectionModel cartonSelectionModel = new CartonSelectionModel(); final CartonSelectionModel cartonSelectionModel = CartonSelectionModel();
final PackageSelectionModel packageSelectionModel = final PackageSelectionModel packageSelectionModel = PackageSelectionModel();
new PackageSelectionModel();
final ConsigneeSelectionModel consigneeSelectionModel = final ConsigneeSelectionModel consigneeSelectionModel =
new ConsigneeSelectionModel(); ConsigneeSelectionModel();
final SenderSelectionModel senderSelectionModel = new SenderSelectionModel(); final SenderSelectionModel senderSelectionModel = SenderSelectionModel();
final ShipmentSelectionModel shipmentSelectionModel = final ShipmentSelectionModel shipmentSelectionModel =
new ShipmentSelectionModel(); ShipmentSelectionModel();
late AppTranslationsDelegate _newLocaleDelegate; late AppTranslationsDelegate _newLocaleDelegate;

View File

@@ -11,6 +11,7 @@ class CargoType {
double calWeight; double calWeight;
int displayIndex; int displayIndex;
bool isDefault; bool isDefault;
bool isMixCargo;
double get calAmount => calRate * calWeight; double get calAmount => calRate * calWeight;
@@ -26,7 +27,8 @@ class CargoType {
this.isCutomDuty = false, this.isCutomDuty = false,
this.customDutyFee = 0, this.customDutyFee = 0,
this.displayIndex = 0, this.displayIndex = 0,
this.isDefault = false}); this.isDefault = false,
this.isMixCargo = false});
factory CargoType.fromMap(Map<String, dynamic> map, String id) { factory CargoType.fromMap(Map<String, dynamic> map, String id) {
return CargoType( return CargoType(
@@ -39,7 +41,8 @@ class CargoType {
isCutomDuty: map['custom_duty'] ?? false, isCutomDuty: map['custom_duty'] ?? false,
customDutyFee: (map['custom_duty_fee'] ?? 0).toDouble(), customDutyFee: (map['custom_duty_fee'] ?? 0).toDouble(),
displayIndex: map['display_index'] ?? 0, displayIndex: map['display_index'] ?? 0,
isDefault: map['is_defalut'] ?? false); isDefault: map['is_defalut'] ?? false,
isMixCargo: map['is_mix_cargo'] ?? false);
} }
factory CargoType.fromMapForCargo(Map<String, dynamic> map, String id) { factory CargoType.fromMapForCargo(Map<String, dynamic> map, String id) {
@@ -62,18 +65,19 @@ class CargoType {
"id": id, "id": id,
'name': name, 'name': name,
'rate': rate, 'rate': rate,
'weight': weight, // 'weight': weight,
'cal_weight': calWeight, // 'cal_weight': calWeight,
'cal_rate': calRate, // 'cal_rate': calRate,
'custom_duty': isCutomDuty, // 'custom_duty': isCutomDuty,
'custom_duty_fee': customDutyFee, // 'custom_duty_fee': customDutyFee,
'qty': qty, // 'qty': qty,
'is_defalut': isDefault, 'is_defalut': isDefault,
'display_index': displayIndex 'display_index': displayIndex,
'is_mix_cargo': isMixCargo
}; };
} }
Map<String, dynamic> toMapForCargo() { Map<String, dynamic> toMapForCarton() {
return {"id": id, 'weight': weight}; return {"id": id, 'weight': weight};
} }
@@ -82,7 +86,7 @@ class CargoType {
} }
CargoType clone() { CargoType clone() {
return CargoType.fromMap(toMap(), this.id!); return CargoType.fromMap(toMap(), id!);
} }
@override @override
@@ -97,12 +101,16 @@ class CargoType {
} }
bool isChangedForEdit(CargoType cargoType) { bool isChangedForEdit(CargoType cargoType) {
return cargoType.name != this.name || cargoType.rate != this.rate; return cargoType.name != name ||
cargoType.rate != rate ||
cargoType.displayIndex != displayIndex ||
cargoType.isDefault != isDefault ||
cargoType.isMixCargo != isMixCargo;
} }
bool isChangedForEditCustomDuty(CargoType cargoType) { bool isChangedForEditCustomDuty(CargoType cargoType) {
return cargoType.name != this.name || return cargoType.name != name ||
cargoType.customDutyFee != this.customDutyFee || cargoType.customDutyFee != customDutyFee ||
cargoType.rate != this.rate; cargoType.rate != rate;
} }
} }

View File

@@ -166,7 +166,7 @@ class Carton {
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
var _types = cargoTypes.where((t) => t.weight != 0).toList(); var _types = cargoTypes.where((t) => t.weight != 0).toList();
var _cargoTypes = _types.map((c) => c.toMapForCargo()).toList(); var _cargoTypes = _types.map((c) => c.toMapForCarton()).toList();
var _packagesIds = packages.map((c) => c.id).toList(); var _packagesIds = packages.map((c) => c.id).toList();

View File

@@ -24,3 +24,12 @@ List<LocalPopupMenu> shipFiteringMenu = <LocalPopupMenu>[
LocalPopupMenu(id: 7, text: "Delivered"), LocalPopupMenu(id: 7, text: "Delivered"),
LocalPopupMenu(id: 6, text: "Canceled"), LocalPopupMenu(id: 6, text: "Canceled"),
]; ];
List<LocalPopupMenu> packageFiteringMenu = <LocalPopupMenu>[
LocalPopupMenu(id: 0, text: "All"),
LocalPopupMenu(id: 1, text: "Received"),
LocalPopupMenu(id: 2, text: "Processed"),
LocalPopupMenu(id: 3, text: "Packed"),
LocalPopupMenu(id: 4, text: "Shipped"),
LocalPopupMenu(id: 5, text: "Delivered"),
];

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/constants.dart'; import 'package:fcs/constants.dart';
import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
@@ -24,12 +26,14 @@ import '../fcs_shipment/model/fcs_shipment_model.dart';
import '../widgets/local_button.dart'; import '../widgets/local_button.dart';
import 'carton_package_editor.dart'; import 'carton_package_editor.dart';
import 'mix_carton/mix_carton_editor.dart'; import 'mix_carton/mix_carton_editor.dart';
import 'mix_carton_detail_list.dart';
import 'model/carton_model.dart'; import 'model/carton_model.dart';
import 'package_detail_list.dart';
import 'print_qr_code_page.dart'; import 'print_qr_code_page.dart';
class CartonInfo extends StatefulWidget { class CartonInfo extends StatefulWidget {
final Carton carton; final Carton carton;
CartonInfo({required this.carton}); const CartonInfo({super.key, required this.carton});
@override @override
_CartonInfoState createState() => _CartonInfoState(); _CartonInfoState createState() => _CartonInfoState();
@@ -176,14 +180,28 @@ class _CartonInfoState extends State<CartonInfo> {
showLabelLink: true, showLabelLink: true,
subText: Text(numberFormatter.format(_packages.length)), subText: Text(numberFormatter.format(_packages.length)),
labelTextKey: "box.package", labelTextKey: "box.package",
onTapLabel: () {}, onTapLabel: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => PackageDetailList(
cartonNumber: _carton.cartonNumber ?? '',
packages: _packages)));
},
); );
final mixCartonLengthBox = DisplayText( final mixCartonLengthBox = DisplayText(
showLabelLink: true, showLabelLink: true,
subText: Text(numberFormatter.format(_mixCartons.length)), subText: Text(numberFormatter.format(_mixCartons.length)),
labelTextKey: "box.shipment.boxes", labelTextKey: "box.shipment.boxes",
onTapLabel: () {}, onTapLabel: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => MixCartonDetailList(
cartonNumber: _carton.cartonNumber ?? '',
cartons: _mixCartons)));
},
); );
final senderBox = userDisplayBox(context, final senderBox = userDisplayBox(context,
@@ -315,18 +333,20 @@ class _CartonInfoState extends State<CartonInfo> {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 2), padding: const EdgeInsets.symmetric(vertical: 2),
child: Container( child: Container(
color: e.key.isEven ? Colors.grey.shade300 : oddColor, color: e.key.isEven ? Colors.grey.shade300 : oddColor,
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
e.value.name ?? "", e.value.name ?? "",
style: TextStyle(color: Colors.black, fontSize: 15), style:
TextStyle(color: Colors.black, fontSize: 15),
), ),
Text("${removeTrailingZeros((e.value.qty).toDouble())} pc", Text(
"${removeTrailingZeros((e.value.qty).toDouble())} pc",
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: style: TextStyle(
TextStyle(color: Colors.black, fontSize: 15)) color: Colors.black, fontSize: 15))
], ],
), ),
), ),
@@ -482,10 +502,16 @@ class _CartonInfoState extends State<CartonInfo> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Flexible(child: cartonSizeBox), Flexible(child: cartonSizeBox),
Flexible(child: packageLengthBox), _packages.isEmpty
? const SizedBox()
: Flexible(child: packageLengthBox),
], ],
), ),
fromPackage ? const SizedBox() : mixCartonLengthBox, fromPackage
? const SizedBox()
: _mixCartons.isEmpty
? const SizedBox()
: mixCartonLengthBox,
shipmentBox, shipmentBox,
// _packages.isEmpty // _packages.isEmpty
// ? const SizedBox() // ? const SizedBox()
@@ -541,9 +567,7 @@ class _CartonInfoState extends State<CartonInfo> {
return list.map((p) { return list.map((p) {
return Container( return Container(
padding: EdgeInsets.only(top: 0), padding: EdgeInsets.only(top: 0),
child: Container( child: Row(children: <Widget>[Text(p.trackingID ?? "")]));
child: Row(children: <Widget>[new Text(p.trackingID ?? "")]),
));
}).toList(); }).toList();
} }
@@ -551,9 +575,7 @@ class _CartonInfoState extends State<CartonInfo> {
return list.map((c) { return list.map((c) {
return Container( return Container(
padding: EdgeInsets.only(top: 0), padding: EdgeInsets.only(top: 0),
child: Container( child: Row(children: <Widget>[Text(c.cartonNumber ?? '')]));
child: Row(children: <Widget>[new Text(c.cartonNumber ?? '')]),
));
}).toList(); }).toList();
} }

View File

@@ -134,9 +134,9 @@ class _CartonListState extends State<CartonList> {
FadeTransition( FadeTransition(
opacity: animation, opacity: animation,
child: SizeTransition( child: SizeTransition(
child: child,
sizeFactor: animation, sizeFactor: animation,
axis: Axis.vertical, axis: Axis.vertical,
child: child,
), ),
), ),
child: _down child: _down
@@ -289,36 +289,43 @@ class _CartonListState extends State<CartonList> {
Widget _filterWidget(BuildContext context) { Widget _filterWidget(BuildContext context) {
var model = Provider.of<CartonModel>(context); var model = Provider.of<CartonModel>(context);
return IconButton( return Padding(
icon: Stack( padding: const EdgeInsets.only(right: 5),
alignment: Alignment.center, child: IconButton(
children: <Widget>[ icon: SizedBox(
const Icon( width: 30,
Icons.filter_list, height: 30,
color: Colors.white, child: Stack(
alignment: Alignment.center,
children: <Widget>[
const Icon(
Icons.filter_list,
color: Colors.white,
),
model.filterByStatus != null ||
model.filterBySender != null ||
model.filterByConsingee != null ||
model.shipment != null
? Positioned(
bottom: 15,
right: 0,
child: Container(
width: 10,
height: 10,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
)
: Container()
],
), ),
model.filterByStatus != null || ),
model.filterBySender != null || onPressed: () {
model.filterByConsingee != null || _showFilter();
model.shipment != null }),
? Positioned( );
bottom: 15,
right: 0,
child: Container(
width: 10,
height: 10,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
)
: Container()
],
),
onPressed: () {
_showFilter();
});
} }
_showFilter() async { _showFilter() async {

View File

@@ -1,4 +1,4 @@
// ignore_for_file: deprecated_member_use // ignore_for_file: deprecated_member_use, use_build_context_synchronously
import 'package:fcs/pages/carton/model/carton_model.dart'; import 'package:fcs/pages/carton/model/carton_model.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
@@ -26,7 +26,7 @@ import 'cargo_widget.dart';
import 'carton_size_widget.dart'; import 'carton_size_widget.dart';
import 'carton_submit.dart'; import 'carton_submit.dart';
import 'model/package_selection_model.dart'; import 'model/package_selection_model.dart';
import 'package_selection_widget.dart'; import 'packages_widget.dart';
class CartonPackageEditor extends StatefulWidget { class CartonPackageEditor extends StatefulWidget {
final Carton carton; final Carton carton;
@@ -233,11 +233,10 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
)); ));
} else if (step.stepType == StepType.PACKAGES) { } else if (step.stepType == StepType.PACKAGES) {
return Expanded( return Expanded(
child: PackageSelectionWidget( child: PackagesWidget(
sender: _sender!, sender: _sender!,
consignee: _consignee!, consignee: _consignee!,
shipment: _shipment!, shipment: _shipment!,
packages: _packages,
onContinue: (packages) { onContinue: (packages) {
setState(() { setState(() {
_packages = List.from(packages); _packages = List.from(packages);

View File

@@ -23,7 +23,7 @@ import 'carton_size_widget.dart';
import 'carton_submit.dart'; import 'carton_submit.dart';
import 'model/carton_model.dart'; import 'model/carton_model.dart';
import 'model/package_selection_model.dart'; import 'model/package_selection_model.dart';
import 'package_selection_widget.dart'; import 'packages_widget.dart';
class CartonPackageForm extends StatefulWidget { class CartonPackageForm extends StatefulWidget {
final User sender; final User sender;
@@ -166,11 +166,10 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
)); ));
} else if (step.stepType == StepType.PACKAGES) { } else if (step.stepType == StepType.PACKAGES) {
return Expanded( return Expanded(
child: PackageSelectionWidget( child: PackagesWidget(
sender: widget.sender, sender: widget.sender,
consignee: widget.consignee, consignee: widget.consignee,
shipment: _shipment!, shipment: _shipment!,
packages: _packages,
onContinue: (packages) { onContinue: (packages) {
setState(() { setState(() {
_packages = List.from(packages); _packages = List.from(packages);

View File

@@ -522,7 +522,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
children: [ children: [
const SizedBox(height: 8), const SizedBox(height: 8),
userRow, userRow,
LocalTitle(textKey: "box.bill_to", topPadding: 8), LocalTitle(textKey: "box.bill_to", topPadding: 5),
const SizedBox(height: 5), const SizedBox(height: 5),
billRadioBox, billRadioBox,
const SizedBox(height: 8), const SizedBox(height: 8),

View File

@@ -0,0 +1,114 @@
import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart';
import '../widgets/local_text.dart';
import 'carton_info.dart';
class MixCartonDetailList extends StatelessWidget {
final String cartonNumber;
final List<Carton> cartons;
MixCartonDetailList(
{super.key, required this.cartonNumber, required this.cartons});
final NumberFormat numberFormatter = NumberFormat("#,###");
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: LocalAppBar(
backgroundColor: Colors.white,
arrowColor: primaryColor,
labelColor: primaryColor,
titleWidget: Column(
children: [
LocalText(
context,
"box.cartion.count",
fontSize: 20,
color: primaryColor,
translationVariables: [numberFormatter.format(cartons.length)],
),
Text(cartonNumber,
style: TextStyle(fontSize: 15, color: Colors.black))
],
),
),
body: ListView.separated(
separatorBuilder: (context, index) =>
Divider(height: 1, color: dividerColor),
itemCount: cartons.length,
itemBuilder: (BuildContext context, int index) {
var carton = cartons[index];
return InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => CartonInfo(carton: carton)),
);
},
child: Container(
padding: EdgeInsets.only(left: 15, right: 15),
child: Column(
children: [
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
children: <Widget>[
Icon(MaterialCommunityIcons.package,
color: primaryColor),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
carton.cartonNumber == null
? ''
: carton.cartonNumber!,
style: TextStyle(
fontSize: 15.0,
color: Colors.black),
),
Padding(
padding:
const EdgeInsets.only(top: 5),
child: Text(
carton.consigneeName ?? '',
style: TextStyle(
fontSize: 15.0,
color: Colors.grey),
),
),
],
),
),
),
],
),
),
),
Text(
"${carton.cartonWeight.toStringAsFixed(2)} lb",
style: TextStyle(fontSize: 14.0, color: Colors.grey),
)
],
),
],
),
),
);
},
));
}
}

View File

@@ -145,4 +145,33 @@ class PackageSelectionModel extends BaseModel {
} }
return list; return list;
} }
Future<List<Package>> getActivePackages(
{required String shipmentId,
required String senderId,
required String consigneeId}) async {
List<Package> list = [];
try {
String path = "/$packages_collection";
var snaps = await FirebaseFirestore.instance
.collection(path)
.where("status",
whereIn: [package_processed_status, package_packed_status])
.where("sender_id", isEqualTo: senderId)
.where("user_id", isEqualTo: consigneeId)
// .where("fcs_shipment_id", isEqualTo: shipmentId)
.where("is_deleted", isEqualTo: false)
.orderBy("created_date", descending: true)
.get(const GetOptions(source: Source.server));
list = snaps.docs
.map((documentSnapshot) =>
Package.fromMap(documentSnapshot.data(), documentSnapshot.id))
.toList();
} catch (e) {
log.warning("Error!! $e");
list = [];
}
return list;
}
} }

View File

@@ -0,0 +1,111 @@
import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/package/package_info.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart';
import '../widgets/local_text.dart';
class PackageDetailList extends StatelessWidget {
final String cartonNumber;
final List<Package> packages;
PackageDetailList(
{super.key, required this.cartonNumber, required this.packages});
final NumberFormat numberFormatter = NumberFormat("#,###");
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: LocalAppBar(
backgroundColor: Colors.white,
arrowColor: primaryColor,
labelColor: primaryColor,
titleWidget: Column(
children: [
LocalText(
context,
"box.package.count",
fontSize: 20,
color: primaryColor,
translationVariables: [numberFormatter.format(packages.length)],
),
Text(cartonNumber,
style: TextStyle(fontSize: 15, color: Colors.black))
],
),
),
body: ListView.separated(
separatorBuilder: (context, index) =>
Divider(height: 1, color: dividerColor),
itemCount: packages.length,
itemBuilder: (BuildContext context, int index) {
var package = packages[index];
return InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => PackageInfo(package: package)),
);
},
child: Container(
padding: EdgeInsets.only(left: 15, right: 15),
child: Column(
children: [
Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(
children: <Widget>[
Icon(Octicons.package, color: primaryColor),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 15),
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: <Widget>[
Text(
package.id == null
? ''
: package.trackingID!,
style: TextStyle(
fontSize: 15.0,
color: Colors.black),
),
Padding(
padding:
const EdgeInsets.only(top: 5),
child: Text(
package.market == null
? ''
: package.market!,
style: TextStyle(
fontSize: 15.0,
color: Colors.grey),
),
),
],
),
),
),
],
),
),
),
],
),
],
),
),
);
},
));
}
}

View File

@@ -0,0 +1,211 @@
import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
import 'package:provider/provider.dart';
import '../../domain/entities/package.dart';
import '../../domain/entities/user.dart';
import '../main/util.dart';
import '../widgets/continue_button.dart';
import '../widgets/local_title.dart';
import '../widgets/previous_button.dart';
import 'model/package_selection_model.dart';
import 'package_selection_result.dart';
typedef OnPrevious = Function(List<Package> packages);
typedef OnContinue = Function(List<Package> packages);
class PackagesWidget extends StatefulWidget {
final User sender;
final User consignee;
final FcsShipment shipment;
final OnPrevious? onPrevious;
final OnContinue? onContinue;
const PackagesWidget({
super.key,
this.onPrevious,
this.onContinue,
required this.shipment,
required this.sender,
required this.consignee,
});
@override
State<PackagesWidget> createState() => _PackagesWidgetState();
}
class _PackagesWidgetState extends State<PackagesWidget> {
final _scrollController = ScrollController();
bool _down = true;
List<Package> _packages = [];
@override
void initState() {
_init();
super.initState();
_scrollController.addListener(() {
setState(() {
_down = _scrollController.position.userScrollDirection ==
ScrollDirection.forward;
});
});
}
_init() async {
_packages.clear();
var packageModel = context.read<PackageSelectionModel>();
var list = await packageModel.getActivePackages(
shipmentId: widget.shipment.id!,
senderId: widget.sender.id!,
consigneeId: widget.consignee.id!);
_packages = List.from(list);
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
final senderBox = userDisplayBox(context,
lableKey: "box.sender.title",
icon: MaterialCommunityIcons.account_arrow_right,
showLink: false,
name: widget.sender.name ?? "",
fcsID: widget.sender.fcsID ?? "");
final consigneeBox = userDisplayBox(context,
showLink: false,
lableKey: "box.consignee.title",
icon: MaterialCommunityIcons.account_arrow_left,
name: widget.consignee.name,
fcsID: widget.consignee.fcsID);
final userRow = Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(flex: 2, child: consigneeBox),
Flexible(child: senderBox)
],
);
final continueBtn = ContinueButton(
onTap: () {
if (widget.onContinue != null) {
widget.onContinue!(_packages);
}
},
);
final previousBtn = PreviousButton(onTap: () {
if (widget.onPrevious != null) {
widget.onPrevious!(_packages);
}
});
return Column(
children: [
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 10, right: 10),
child: Column(
children: [
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder:
(Widget child, Animation<double> animation) =>
FadeTransition(
opacity: animation,
child: SizeTransition(
sizeFactor: animation,
axis: Axis.vertical,
child: child,
),
),
child: _down
? Column(children: [
const SizedBox(height: 8),
userRow,
LocalTitle(
textKey: "box.select.package", topPadding: 5),
const SizedBox(height: 10),
])
: const SizedBox(),
),
Expanded(
child: RefreshIndicator(
color: primaryColor,
onRefresh: () async {
_init();
},
child: ListView.builder(
padding: const EdgeInsets.only(top: 10),
controller: _scrollController,
shrinkWrap: true,
physics: const AlwaysScrollableScrollPhysics(),
itemBuilder: (context, index) {
Package package = _packages[index];
return packageRow(context, package);
},
itemCount: _packages.length)),
),
],
),
),
),
widget.onContinue != null
? Padding(
padding: const EdgeInsets.only(left: 15, right: 15, top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
previousBtn,
continueBtn,
],
),
)
: const SizedBox(),
const SizedBox(height: 20)
],
);
}
Widget packageRow(BuildContext context, Package package) {
return Padding(
padding: const EdgeInsets.only(top: 5, bottom: 5),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
border: Border.all(color: Colors.grey.shade300)),
padding: EdgeInsets.only(left: 10, right: 10),
child: Row(
children: <Widget>[
Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(package.trackingID ?? "",
style: TextStyle(fontSize: 15.0, color: Colors.black)),
Text(
package.cartonIds.isEmpty
? "-"
: "${numberFormatter.format(package.cartonIds.length)} Boxes",
style: TextStyle(fontSize: 15.0, color: Colors.grey),
),
],
),
),
),
package.isChecked
? Icon(Icons.check, color: primaryColor)
: const SizedBox()
],
),
),
);
}
}

View File

@@ -13,12 +13,14 @@ import 'fcs_shipment_editor.dart';
import 'fcs_shipment_list_row.dart'; import 'fcs_shipment_list_row.dart';
class FcsShipmentList extends StatefulWidget { class FcsShipmentList extends StatefulWidget {
const FcsShipmentList({super.key});
@override @override
_FcsShipmentListState createState() => _FcsShipmentListState(); _FcsShipmentListState createState() => _FcsShipmentListState();
} }
class _FcsShipmentListState extends State<FcsShipmentList> { class _FcsShipmentListState extends State<FcsShipmentList> {
bool _isLoading = false; bool isLoading = false;
int _selectedIndex = 0; int _selectedIndex = 0;
@override @override
@@ -41,7 +43,7 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
var shipmentModel = Provider.of<FcsShipmentModel>(context); var shipmentModel = Provider.of<FcsShipmentModel>(context);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar(labelKey: "FCSshipment.list.title", actions: [ appBar: LocalAppBar(labelKey: "FCSshipment.list.title", actions: [
_menuFilteringWidget(context), _menuFilteringWidget(context),
@@ -66,63 +68,68 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
} }
Widget _menuFilteringWidget(BuildContext context) { Widget _menuFilteringWidget(BuildContext context) {
return PopupMenuButton<LocalPopupMenu>( return Padding(
splashRadius: 25, padding: const EdgeInsets.only(right: 5),
padding: const EdgeInsets.only(right: 15), child: PopupMenuButton<LocalPopupMenu>(
elevation: 3.2, elevation: 3.2,
tooltip: 'This is tooltip', tooltip: '',
onSelected: (choice) async { onSelected: (choice) async {
setState(() { setState(() {
_selectedIndex = choice.id; _selectedIndex = choice.id;
}); });
await context.read<FcsShipmentModel>().onChanged(choice.id); await context.read<FcsShipmentModel>().onChanged(choice.id);
}, },
icon: Stack( icon: SizedBox(
alignment: Alignment.center, width: 30,
children: <Widget>[ height: 30,
const Icon( child: Stack(
Icons.filter_list, alignment: Alignment.center,
color: Colors.white, children: <Widget>[
const Icon(
Icons.filter_list,
color: Colors.white,
),
_selectedIndex != 0
? Positioned(
bottom: 15,
right: 0,
child: Container(
width: 10,
height: 10,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
)
: Container()
],
), ),
_selectedIndex != 0 ),
? Positioned( itemBuilder: (BuildContext context) {
bottom: 15, return shipFiteringMenu.map((LocalPopupMenu choice) {
right: 0, return PopupMenuItem<LocalPopupMenu>(
child: Container( value: choice,
child: Row(
children: <Widget>[
Flexible(
child: Text("${choice.text}",
style: TextStyle(color: Colors.black))),
const SizedBox(
width: 10, width: 10,
height: 10,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
), ),
) _selectedIndex == choice.id
: Container() ? const Icon(
], Icons.check,
), color: Colors.grey,
itemBuilder: (BuildContext context) { )
return shipFiteringMenu.map((LocalPopupMenu choice) { : const SizedBox(),
return PopupMenuItem<LocalPopupMenu>( ],
value: choice, ),
child: Row( );
children: <Widget>[ }).toList();
Flexible( }),
child: Text("${choice.text}", );
style: TextStyle(color: Colors.black))),
const SizedBox(
width: 10,
),
_selectedIndex == choice.id
? const Icon(
Icons.check,
color: Colors.grey,
)
: const SizedBox(),
],
),
);
}).toList();
});
} }
} }

View File

@@ -8,8 +8,8 @@ import 'fcs_shipment_info.dart';
class FcsShipmentListRow extends StatelessWidget { class FcsShipmentListRow extends StatelessWidget {
final FcsShipment shipment; final FcsShipment shipment;
final dateFormatter = new DateFormat('dd MMM yyyy'); final dateFormatter = DateFormat('dd MMM yyyy');
FcsShipmentListRow({Key? key, required this.shipment}) : super(key: key); FcsShipmentListRow({super.key, required this.shipment});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -23,31 +23,31 @@ class FcsShipmentListRow extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 13), padding: const EdgeInsets.symmetric(vertical: 13),
child: new Row( child: Row(
children: <Widget>[ children: <Widget>[
Icon( Icon(
Ionicons.ios_airplane, Ionicons.ios_airplane,
color: primaryColor, color: primaryColor,
size: 30, size: 30,
), ),
new Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 15), padding: const EdgeInsets.only(left: 15),
child: new Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new Text( Text(
shipment.shipmentNumber ?? '', shipment.shipmentNumber ?? '',
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
dateFormatter.format(shipment.cutoffDate!), dateFormatter.format(shipment.cutoffDate!),
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),
) )

View File

@@ -23,17 +23,20 @@ class PackageModel extends BaseModel {
PaginatorListener<Package>? activePackages; PaginatorListener<Package>? activePackages;
bool isLoading = false; bool isLoading = false;
int selectedIndex = 1; int selectedIndexForCustomer = 1;
int selectedIndex = 0;
initData(int index, bool isCustomer) { initDataForCustomer(int index) {
selectedIndex = index; selectedIndexForCustomer = index;
if (isCustomer) { _loadPaginationCustomerPackages(selectedIndexForCustomer == 2);
_loadPaginationCustomerPackages(selectedIndex == 2);
} else {
_loadPaginationPackages(selectedIndex == 2);
}
} }
initData(int index) {
selectedIndex = index;
_loadPaginationPackages(selectedIndex);
}
@override
void privilegeChanged() { void privilegeChanged() {
if (user != null) { if (user != null) {
_loadPaginationActivePackages(); _loadPaginationActivePackages();
@@ -47,30 +50,57 @@ class PackageModel extends BaseModel {
if (activePackages != null) activePackages!.close(); if (activePackages != null) activePackages!.close();
} }
onChanged(int index, bool isCustomer) { onChangedForCustomer(int index) {
selectedIndex = index; selectedIndexForCustomer = index;
if (isCustomer) { _loadPaginationCustomerPackages(selectedIndexForCustomer == 2);
_loadPaginationCustomerPackages(selectedIndex == 2);
} else {
_loadPaginationPackages(selectedIndex == 2);
}
notifyListeners(); notifyListeners();
} }
_loadPaginationPackages(bool isDelivered) { _loadPaginationPackages(int index) {
if (user == null) return; if (user == null) return;
if (!((user!.hasPackages() || if (!((user!.hasPackages() ||
user!.hasReceiving() || user!.hasReceiving() ||
user!.hasProcessing()))) return; user!.hasProcessing()))) {
return;
}
String path = "/$packages_collection"; String path = "/$packages_collection";
Query col = FirebaseFirestore.instance Query col = FirebaseFirestore.instance.collection(path);
.collection(path) Query pageQuery = FirebaseFirestore.instance.collection(path);
.where("is_delivered", isEqualTo: isDelivered);
Query pageQuery = FirebaseFirestore.instance // received status
.collection(path) if (index == 1) {
.where("is_delivered", isEqualTo: isDelivered) col = col.where("status", isEqualTo: package_received_status);
.orderBy("update_time", descending: true); pageQuery = pageQuery.where("status", isEqualTo: package_received_status);
}
// processed status
if (index == 2) {
col = col.where("status", isEqualTo: package_processed_status);
pageQuery =
pageQuery.where("status", isEqualTo: package_processed_status);
}
// packed status
if (index == 3) {
col = col.where("status", isEqualTo: package_packed_status);
pageQuery = pageQuery.where("status", isEqualTo: package_packed_status);
}
// shipped status
if (index == 4) {
col = col.where("status", isEqualTo: package_shipped_status);
pageQuery = pageQuery.where("status", isEqualTo: package_shipped_status);
}
// delivered status
if (index == 5) {
col = col.where("status", isEqualTo: package_delivered_status);
pageQuery =
pageQuery.where("status", isEqualTo: package_delivered_status);
}
pageQuery = pageQuery.orderBy("update_time", descending: true);
packages?.close(); packages?.close();
packages = PaginatorListener<Package>( packages = PaginatorListener<Package>(
@@ -78,6 +108,12 @@ class PackageModel extends BaseModel {
rowPerLoad: 30); rowPerLoad: 30);
} }
onChanged(int index) {
selectedIndex = index;
_loadPaginationPackages(index);
notifyListeners();
}
_loadPaginationCustomerPackages(bool isDelivered) { _loadPaginationCustomerPackages(bool isDelivered) {
if (user == null) return; if (user == null) return;
String path = "/$packages_collection"; String path = "/$packages_collection";
@@ -102,7 +138,9 @@ class PackageModel extends BaseModel {
if (user == null) return; if (user == null) return;
if (!((user!.hasPackages() || if (!((user!.hasPackages() ||
user!.hasReceiving() || user!.hasReceiving() ||
user!.hasProcessing()))) return; user!.hasProcessing()))) {
return;
}
String path = "/$packages_collection"; String path = "/$packages_collection";
Query col = FirebaseFirestore.instance Query col = FirebaseFirestore.instance
@@ -142,7 +180,7 @@ class PackageModel extends BaseModel {
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
var snaps = await FirebaseFirestore.instance var snaps = await FirebaseFirestore.instance
.collection("$path") .collection(path)
.where("tracking_id", isEqualTo: trackingID) .where("tracking_id", isEqualTo: trackingID)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.get(const GetOptions(source: Source.server)); .get(const GetOptions(source: Source.server));

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/package/model/package_model.dart'; import 'package:fcs/pages/package/model/package_model.dart';
@@ -16,14 +18,15 @@ import 'package:provider/provider.dart';
class PackageList extends StatefulWidget { class PackageList extends StatefulWidget {
final bool forCustomer; final bool forCustomer;
const PackageList({Key? key, this.forCustomer = true}) : super(key: key); const PackageList({super.key, this.forCustomer = true});
@override @override
_PackageListState createState() => _PackageListState(); _PackageListState createState() => _PackageListState();
} }
class _PackageListState extends State<PackageList> { class _PackageListState extends State<PackageList> {
bool _isLoading = false; bool isLoading = false;
int _selectedIndex = 1; int _selectedIndexForCustomer = 1;
int _selectedIndex = 0;
@override @override
void initState() { void initState() {
@@ -33,8 +36,13 @@ class _PackageListState extends State<PackageList> {
_init() { _init() {
var model = context.read<PackageModel>(); var model = context.read<PackageModel>();
_selectedIndex = model.selectedIndex; if (widget.forCustomer) {
model.initData(_selectedIndex, widget.forCustomer); _selectedIndexForCustomer = model.selectedIndexForCustomer;
model.initDataForCustomer(_selectedIndexForCustomer);
} else {
_selectedIndex = model.selectedIndex;
model.initData(_selectedIndex);
}
if (mounted) { if (mounted) {
setState(() {}); setState(() {});
@@ -53,23 +61,23 @@ class _PackageListState extends State<PackageList> {
LocalPopupMenu( LocalPopupMenu(
id: 1, id: 1,
textKey: "package.popupmenu.active", textKey: "package.popupmenu.active",
selected: packageModel.selectedIndex == 1), selected: packageModel.selectedIndexForCustomer == 1),
LocalPopupMenu( LocalPopupMenu(
id: 2, id: 2,
textKey: "package.popupmenu.delivered", textKey: "package.popupmenu.delivered",
selected: packageModel.selectedIndex == 2) selected: packageModel.selectedIndexForCustomer == 2)
], ],
popupMenuCallback: (p) { popupMenuCallback: (p) {
this.setState(() { setState(() {
_selectedIndex = p.id; _selectedIndexForCustomer = p.id;
}); });
context context
.read<PackageModel>() .read<PackageModel>()
.onChanged(_selectedIndex, widget.forCustomer); .onChangedForCustomer(_selectedIndexForCustomer);
}); });
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar( appBar: LocalAppBar(
labelKey: 'package.title', labelKey: 'package.title',
@@ -84,7 +92,7 @@ class _PackageListState extends State<PackageList> {
iconSize: 30, iconSize: 30,
onPressed: () => searchPackage(context, onPressed: () => searchPackage(context,
callbackPackageSelect: _searchCallback)), callbackPackageSelect: _searchCallback)),
popupMenu widget.forCustomer ? popupMenu : _menuFilteringWidget(context)
], ],
), ),
body: PaginatorListView<Package>( body: PaginatorListView<Package>(
@@ -98,11 +106,77 @@ class _PackageListState extends State<PackageList> {
_searchCallback(Package package) async { _searchCallback(Package package) async {
var packageModel = Provider.of<PackageModel>(context, listen: false); var packageModel = Provider.of<PackageModel>(context, listen: false);
Package? _package = await packageModel.getPackage(package.id!); Package? package0 = await packageModel.getPackage(package.id!);
if (_package == null) return; if (package0 == null) return;
Navigator.push( Navigator.push(
context, context,
CupertinoPageRoute(builder: (context) => PackageInfo(package: _package)), CupertinoPageRoute(builder: (context) => PackageInfo(package: package0)),
);
}
Widget _menuFilteringWidget(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(right: 5),
child: PopupMenuButton<LocalPopupMenu>(
elevation: 3.2,
tooltip: '',
onSelected: (choice) async {
setState(() {
_selectedIndex = choice.id;
});
await context.read<PackageModel>().onChanged(choice.id);
},
icon: SizedBox(
width: 30,
height: 30,
child: Stack(
alignment: Alignment.center,
children: <Widget>[
const Icon(
Icons.filter_list,
color: Colors.white,
),
_selectedIndex != 0
? Positioned(
bottom: 15,
right: 0,
child: Container(
width: 10,
height: 10,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: Colors.red,
),
),
)
: Container()
],
),
),
itemBuilder: (BuildContext context) {
return packageFiteringMenu.map((LocalPopupMenu choice) {
return PopupMenuItem<LocalPopupMenu>(
value: choice,
child: Row(
children: <Widget>[
Flexible(
child: Text("${choice.text}",
style: TextStyle(color: Colors.black))),
const SizedBox(
width: 10,
),
_selectedIndex == choice.id
? const Icon(
Icons.check,
color: Colors.grey,
)
: const SizedBox(),
],
),
);
}).toList();
}),
); );
} }
} }

View File

@@ -6,21 +6,20 @@ import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
typedef CallbackPackageSelect(Package package); typedef CallbackPackageSelect = Function(Package package);
class PackageListRow extends StatelessWidget { class PackageListRow extends StatelessWidget {
final bool isCustomer; final bool isCustomer;
final Package package; final Package package;
final CallbackPackageSelect? callbackPackageSelect; final CallbackPackageSelect? callbackPackageSelect;
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = DateFormat("dd MMM yyyy");
PackageListRow( PackageListRow(
{Key? key, {super.key,
required this.package, required this.package,
this.callbackPackageSelect, this.callbackPackageSelect,
this.isCustomer = false}) this.isCustomer = false});
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -44,30 +43,30 @@ class PackageListRow extends StatelessWidget {
Row( Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 13), padding: const EdgeInsets.symmetric(vertical: 13),
child: new Row( child: Row(
children: <Widget>[ children: <Widget>[
Icon(Octicons.package, color: primaryColor), Icon(Octicons.package, color: primaryColor),
new Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 15), padding: const EdgeInsets.only(left: 15),
child: new Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new Text( Text(
package.id == null ? '' : package.trackingID!, package.id == null ? '' : package.trackingID!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
package.market == null package.market == null
? '' ? ''
: package.market!, : package.market!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.grey),
), ),
), ),
], ],
@@ -88,12 +87,11 @@ class PackageListRow extends StatelessWidget {
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
package.currentStatusDate != null package.currentStatusDate != null
? dateFormat.format(package.currentStatusDate!) ? dateFormat.format(package.currentStatusDate!)
: '', : '',
style: style: TextStyle(fontSize: 14.0, color: Colors.grey),
new TextStyle(fontSize: 14.0, color: Colors.grey),
), ),
), ),
], ],

View File

@@ -7,17 +7,16 @@ import 'package:intl/intl.dart';
import 'processing_info.dart'; import 'processing_info.dart';
typedef CallbackPackageSelect(Package package); typedef CallbackPackageSelect = Function(Package package);
class ProcessingListRow extends StatelessWidget { class ProcessingListRow extends StatelessWidget {
final Package package; final Package package;
final CallbackPackageSelect? callbackPackageSelect; final CallbackPackageSelect? callbackPackageSelect;
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = DateFormat("dd MMM yyyy");
ProcessingListRow( ProcessingListRow(
{Key? key, required this.package, this.callbackPackageSelect}) {super.key, required this.package, this.callbackPackageSelect});
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -38,30 +37,30 @@ class ProcessingListRow extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 13.0), padding: const EdgeInsets.symmetric(vertical: 13.0),
child: new Row( child: Row(
children: <Widget>[ children: <Widget>[
Icon(FontAwesome.dropbox, color: primaryColor, size: 30), Icon(FontAwesome.dropbox, color: primaryColor, size: 30),
new Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 15), padding: const EdgeInsets.only(left: 15),
child: new Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new Text( Text(
package.trackingID == null package.trackingID == null
? '' ? ''
: package.trackingID!, : package.trackingID!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 5.0), padding: const EdgeInsets.only(top: 5.0),
child: new Text( child: Text(
package.market == null ? '' : package.market!, package.market == null ? '' : package.market!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.grey),
), ),
), ),
], ],
@@ -82,11 +81,11 @@ class ProcessingListRow extends StatelessWidget {
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
package.currentStatusDate != null package.currentStatusDate != null
? dateFormat.format(package.currentStatusDate!) ? dateFormat.format(package.currentStatusDate!)
: '', : '',
style: new TextStyle(fontSize: 14.0, color: Colors.grey), style: TextStyle(fontSize: 14.0, color: Colors.grey),
), ),
), ),
], ],

View File

@@ -28,9 +28,11 @@ import 'account_delection_page.dart';
import 'add_recovery_email.dart'; import 'add_recovery_email.dart';
import 'change_phone_number.dart'; import 'change_phone_number.dart';
typedef void ProfileCallback(); typedef ProfileCallback = void Function();
class Profile extends StatefulWidget { class Profile extends StatefulWidget {
const Profile({super.key});
@override @override
_ProfileState createState() => _ProfileState(); _ProfileState createState() => _ProfileState();
} }
@@ -52,9 +54,9 @@ class _ProfileState extends State<Profile> {
buildLanguage(LanguageModel languageModel) async { buildLanguage(LanguageModel languageModel) async {
var lan = await languageModel.load(); var lan = await languageModel.load();
if (this.selectedLanguage != lan) { if (selectedLanguage != lan) {
setState(() { setState(() {
this.selectedLanguage = lan; selectedLanguage = lan;
}); });
} }
} }

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
@@ -6,6 +8,7 @@ import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../widgets/local_text.dart'; import '../widgets/local_text.dart';
@@ -13,32 +16,34 @@ import 'model/shipment_rate_model.dart';
class CargoEditor extends StatefulWidget { class CargoEditor extends StatefulWidget {
final CargoType? cargo; final CargoType? cargo;
CargoEditor({this.cargo}); const CargoEditor({super.key, this.cargo});
@override @override
_CargoEditorState createState() => _CargoEditorState(); _CargoEditorState createState() => _CargoEditorState();
} }
class _CargoEditorState extends State<CargoEditor> { class _CargoEditorState extends State<CargoEditor> {
TextEditingController _descController = new TextEditingController(); TextEditingController descController = TextEditingController();
TextEditingController _rateController = new TextEditingController(); TextEditingController rateController = TextEditingController();
TextEditingController _displayIndexController = new TextEditingController(); TextEditingController displayIndexController = TextEditingController();
bool _isLoading = false; bool _isLoading = false;
late CargoType _cargo; late CargoType _cargo;
bool _isNew = false; bool _isNew = false;
final _cargoFormKey = GlobalKey<FormState>(); final _cargoFormKey = GlobalKey<FormState>();
bool _isDefault = false; bool _isDefault = false;
bool _isMixCargo = false;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.cargo != null) { if (widget.cargo != null) {
_cargo = widget.cargo!; _cargo = widget.cargo!;
_descController.text = _cargo.name ?? ""; descController.text = _cargo.name ?? "";
_rateController.text = _cargo.rate.toStringAsFixed(2); rateController.text = _cargo.rate.toStringAsFixed(2);
_displayIndexController.text = _cargo.displayIndex.toString(); displayIndexController.text = _cargo.displayIndex.toString();
_isDefault = _cargo.isDefault; _isDefault = _cargo.isDefault;
_isMixCargo = _cargo.isMixCargo;
} else { } else {
_isNew = true; _isNew = true;
} }
@@ -53,8 +58,8 @@ class _CargoEditorState extends State<CargoEditor> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final typeBox = InputText( final typeBox = InputText(
labelTextKey: 'cargo.type', labelTextKey: 'cargo.type',
iconData: Icons.text_format, iconData: Ionicons.text,
controller: _descController, controller: descController,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -66,8 +71,8 @@ class _CargoEditorState extends State<CargoEditor> {
final rateBox = InputText( final rateBox = InputText(
labelTextKey: 'cargo.rate', labelTextKey: 'cargo.rate',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _rateController, controller: rateController,
textInputType: TextInputType.number, textInputType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
@@ -80,8 +85,8 @@ class _CargoEditorState extends State<CargoEditor> {
final displayIndexBox = InputText( final displayIndexBox = InputText(
labelTextKey: 'cargo.display_index', labelTextKey: 'cargo.display_index',
iconData: Icons.numbers, iconData: FontAwesome.sort_numeric_asc,
controller: _displayIndexController, controller: displayIndexController,
textInputType: TextInputType.number, textInputType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
// validator: (value) { // validator: (value) {
@@ -93,7 +98,7 @@ class _CargoEditorState extends State<CargoEditor> {
); );
final defaultBox = Padding( final defaultBox = Padding(
padding: const EdgeInsets.symmetric(vertical: 20), padding: const EdgeInsets.symmetric(vertical: 10),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Flexible( Flexible(
child: Column( child: Column(
@@ -112,7 +117,7 @@ class _CargoEditorState extends State<CargoEditor> {
scale: 0.7, scale: 0.7,
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: CupertinoSwitch( child: CupertinoSwitch(
activeColor: primaryColor, activeTrackColor: primaryColor,
value: _isDefault, value: _isDefault,
onChanged: (v) { onChanged: (v) {
setState(() { setState(() {
@@ -122,6 +127,34 @@ class _CargoEditorState extends State<CargoEditor> {
]), ]),
); );
final mixCargoBox =
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocalText(
context,
'cargo.is_mix',
color: Colors.black54,
fontSize: 15,
),
],
),
),
Transform.scale(
scale: 0.7,
alignment: Alignment.centerRight,
child: CupertinoSwitch(
activeTrackColor: primaryColor,
value: _isMixCargo,
onChanged: (v) {
setState(() {
_isMixCargo = v;
});
}))
]);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: _isLoading,
child: Scaffold( child: Scaffold(
@@ -160,14 +193,16 @@ class _CargoEditorState extends State<CargoEditor> {
typeBox, typeBox,
rateBox, rateBox,
displayIndexBox, displayIndexBox,
SizedBox(height: 10),
defaultBox, defaultBox,
mixCargoBox,
SizedBox(height: 30), SizedBox(height: 30),
], ],
), ),
), ),
fcsButton(context, getLocalString(context, "btn.save"), fcsButton(context, getLocalString(context, "btn.save"),
callack: _save), callack: _save),
SizedBox(height: 10) SizedBox(height: 30)
], ],
), ),
), ),
@@ -186,18 +221,19 @@ class _CargoEditorState extends State<CargoEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
CargoType _cargo = CargoType( CargoType cargo = CargoType(
name: _descController.text, name: descController.text,
rate: double.parse(_rateController.text), rate: double.parse(rateController.text),
displayIndex: _displayIndexController.text == '' displayIndex: displayIndexController.text == ''
? 0 ? 0
: int.parse(_displayIndexController.text), : int.parse(displayIndexController.text),
isDefault: _isDefault); isDefault: _isDefault,
isMixCargo: _isMixCargo);
if (_isNew) { if (_isNew) {
await shipmentRateModel.addCargoType(_cargo); await shipmentRateModel.addCargoType(cargo);
} else { } else {
_cargo.id = this._cargo.id; cargo.id = _cargo.id;
await shipmentRateModel.updateCargoType(_cargo); await shipmentRateModel.updateCargoType(cargo);
} }
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
@@ -220,7 +256,7 @@ class _CargoEditorState extends State<CargoEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
await shipmentRateModel.deleteCargoType(this._cargo.id!); await shipmentRateModel.deleteCargoType(_cargo.id!);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -233,11 +269,19 @@ class _CargoEditorState extends State<CargoEditor> {
isDataChanged() { isDataChanged() {
if (_isNew) { if (_isNew) {
return _descController.text != "" || _rateController.text != ""; return descController.text != "" ||
rateController.text != "" ||
displayIndexController.text != "" ||
_isDefault != false ||
_isMixCargo != false;
} else { } else {
CargoType _cargo = CargoType( CargoType cargo = CargoType(
name: _descController.text, rate: double.parse(_rateController.text)); name: descController.text,
return this._cargo.isChangedForEdit(_cargo); rate: double.parse(rateController.text),
displayIndex: int.parse(displayIndexController.text),
isDefault: _isDefault,
isMixCargo: _isMixCargo);
return _cargo.isChangedForEdit(cargo);
} }
} }
} }

View File

@@ -11,13 +11,13 @@ import 'cargo_editor.dart';
import 'model/shipment_rate_model.dart'; import 'model/shipment_rate_model.dart';
class CargoTypeList extends StatefulWidget { class CargoTypeList extends StatefulWidget {
const CargoTypeList({Key? key}) : super(key: key); const CargoTypeList({super.key});
@override @override
_CargoTypeListState createState() => _CargoTypeListState(); _CargoTypeListState createState() => _CargoTypeListState();
} }
class _CargoTypeListState extends State<CargoTypeList> { class _CargoTypeListState extends State<CargoTypeList> {
bool _isLoading = false; bool isLoading = false;
@override @override
void initState() { void initState() {
@@ -34,9 +34,9 @@ class _CargoTypeListState extends State<CargoTypeList> {
var shipmentRateModel = Provider.of<ShipmentRateModel>(context); var shipmentRateModel = Provider.of<ShipmentRateModel>(context);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar(labelKey: "cargo.form.title"), appBar: LocalAppBar(labelKey: "cargo.title"),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
onPressed: () { onPressed: () {
Navigator.of(context).push( Navigator.of(context).push(
@@ -44,8 +44,7 @@ class _CargoTypeListState extends State<CargoTypeList> {
}, },
icon: Icon(Icons.add, color: Colors.white), icon: Icon(Icons.add, color: Colors.white),
backgroundColor: primaryColor, backgroundColor: primaryColor,
label: label: LocalText(context, 'cargo.new', color: Colors.white)),
LocalText(context, 'cargo.form.title', color: Colors.white)),
body: Padding( body: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ListView.separated( child: ListView.separated(
@@ -64,7 +63,7 @@ class _CargoTypeListState extends State<CargoTypeList> {
}, },
child: Container( child: Container(
child: _row(cargo.name ?? "", child: _row(cargo.name ?? "",
"\$ " + cargo.rate.toStringAsFixed(2), 'per pound'), "\$ ${cargo.rate.toStringAsFixed(2)}", 'per pound'),
), ),
); );
}), }),
@@ -85,12 +84,12 @@ class _CargoTypeListState extends State<CargoTypeList> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 3.0), padding: const EdgeInsets.only(bottom: 3.0),
child: Text( child: Text(
'$price', price,
style: TextStyle(color: primaryColor, fontSize: 14), style: TextStyle(color: primaryColor, fontSize: 14),
), ),
), ),
Text( Text(
'$unit', unit,
style: TextStyle(color: Colors.grey, fontSize: 14), style: TextStyle(color: Colors.grey, fontSize: 14),
), ),
], ],

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
@@ -5,6 +7,7 @@ import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -12,19 +15,19 @@ import 'model/shipment_rate_model.dart';
class CustomEditor extends StatefulWidget { class CustomEditor extends StatefulWidget {
final CargoType? custom; final CargoType? custom;
CustomEditor({this.custom}); const CustomEditor({super.key, this.custom});
@override @override
_CustomEditorState createState() => _CustomEditorState(); _CustomEditorState createState() => _CustomEditorState();
} }
class _CustomEditorState extends State<CustomEditor> { class _CustomEditorState extends State<CustomEditor> {
TextEditingController _productController = new TextEditingController(); TextEditingController productController = TextEditingController();
TextEditingController _feeController = new TextEditingController(); TextEditingController feeController = TextEditingController();
TextEditingController _shipmentRateController = new TextEditingController(); TextEditingController shipmentRateController = TextEditingController();
bool _isLoading = false; bool _isLoading = false;
CargoType _custom = new CargoType(); CargoType _custom = CargoType();
bool _isNew = false; bool _isNew = false;
final _customFormKey = GlobalKey<FormState>(); final _customFormKey = GlobalKey<FormState>();
@@ -33,9 +36,9 @@ class _CustomEditorState extends State<CustomEditor> {
super.initState(); super.initState();
if (widget.custom != null) { if (widget.custom != null) {
_custom = widget.custom!; _custom = widget.custom!;
_productController.text = _custom.name ?? ""; productController.text = _custom.name ?? "";
_feeController.text = _custom.customDutyFee.toStringAsFixed(2); feeController.text = _custom.customDutyFee.toStringAsFixed(2);
_shipmentRateController.text = _custom.rate.toStringAsFixed(2); shipmentRateController.text = _custom.rate.toStringAsFixed(2);
} else { } else {
_isNew = true; _isNew = true;
} }
@@ -49,20 +52,22 @@ class _CustomEditorState extends State<CustomEditor> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final productBox = InputText( final productBox = InputText(
labelTextKey: 'rate.cutom.product_type', labelTextKey: 'rate.cutom.product_type',
iconData: FontAwesomeIcons.weightHanging, iconData: FontAwesomeIcons.weightHanging,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
controller: _productController, controller: productController,
validator: (value){ validator: (value) {
if(value==null || value.isEmpty){ if (value == null || value.isEmpty) {
return "Please insert product type"; return "Please insert product type";
} }
return null; return null;
},); },
);
final feeBox = InputText( final feeBox = InputText(
labelTextKey: 'rate.custom.fee', labelTextKey: 'rate.custom.fee',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _feeController, controller: feeController,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -74,8 +79,8 @@ class _CustomEditorState extends State<CustomEditor> {
final shipmentRateBox = InputText( final shipmentRateBox = InputText(
labelTextKey: 'rate.custom.shipment_rate', labelTextKey: 'rate.custom.shipment_rate',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _shipmentRateController, controller: shipmentRateController,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -128,7 +133,7 @@ class _CustomEditorState extends State<CustomEditor> {
), ),
fcsButton(context, getLocalString(context, "btn.save"), fcsButton(context, getLocalString(context, "btn.save"),
callack: _save), callack: _save),
SizedBox(height: 10) SizedBox(height: 30)
], ],
), ),
), ),
@@ -148,15 +153,15 @@ class _CustomEditorState extends State<CustomEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
CargoType _customduty = CargoType( CargoType customduty = CargoType(
name: _productController.text, name: productController.text,
customDutyFee: double.parse(_feeController.text), customDutyFee: double.parse(feeController.text),
rate: double.parse(_shipmentRateController.text)); rate: double.parse(shipmentRateController.text));
if (_isNew) { if (_isNew) {
await shipmentRateModel.addCustomDuty(_customduty); await shipmentRateModel.addCustomDuty(customduty);
} else { } else {
_customduty.id = this._custom.id; customduty.id = _custom.id;
await shipmentRateModel.updateCustomDuty(_customduty); await shipmentRateModel.updateCustomDuty(customduty);
} }
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
@@ -180,7 +185,7 @@ class _CustomEditorState extends State<CustomEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
await shipmentRateModel.deleteCustomDuty(this._custom.id!); await shipmentRateModel.deleteCustomDuty(_custom.id!);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -193,15 +198,15 @@ class _CustomEditorState extends State<CustomEditor> {
isDataChanged() { isDataChanged() {
if (_isNew) { if (_isNew) {
return _productController.text != "" || return productController.text != "" ||
_feeController.text != "" || feeController.text != "" ||
_shipmentRateController.text != ""; shipmentRateController.text != "";
} else { } else {
CargoType _customduty = CargoType( CargoType customduty = CargoType(
name: _productController.text, name: productController.text,
customDutyFee: double.parse(_feeController.text), customDutyFee: double.parse(feeController.text),
rate: double.parse(_shipmentRateController.text)); rate: double.parse(shipmentRateController.text));
return this._custom.isChangedForEditCustomDuty(_customduty); return _custom.isChangedForEditCustomDuty(customduty);
} }
} }
} }

View File

@@ -11,13 +11,13 @@ import 'model/shipment_rate_model.dart';
class CustomList extends StatefulWidget { class CustomList extends StatefulWidget {
final bool? selected; final bool? selected;
const CustomList({Key? key, this.selected}) : super(key: key); const CustomList({super.key, this.selected});
@override @override
_CustomListState createState() => _CustomListState(); _CustomListState createState() => _CustomListState();
} }
class _CustomListState extends State<CustomList> { class _CustomListState extends State<CustomList> {
bool _isLoading = false; bool isLoading = false;
bool _selected = false; bool _selected = false;
@override @override
@@ -38,7 +38,7 @@ class _CustomListState extends State<CustomList> {
var shipmentRateModel = Provider.of<ShipmentRateModel>(context); var shipmentRateModel = Provider.of<ShipmentRateModel>(context);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar(labelKey: 'rate.custom_duty.title'), appBar: LocalAppBar(labelKey: 'rate.custom_duty.title'),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
@@ -49,7 +49,7 @@ class _CustomListState extends State<CustomList> {
icon: Icon(Icons.add, color: Colors.white), icon: Icon(Icons.add, color: Colors.white),
backgroundColor: primaryColor, backgroundColor: primaryColor,
label: label:
LocalText(context, 'rate.custom_duty', color: Colors.white)), LocalText(context, 'rate.custom_new', color: Colors.white)),
body: Padding( body: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: ListView.separated( child: ListView.separated(
@@ -70,13 +70,11 @@ class _CustomListState extends State<CustomList> {
child: Container( child: Container(
child: _row( child: _row(
custom.name ?? "", custom.name ?? "",
"Custom Fee \$ " + "Custom Fee \$ ${custom.customDutyFee.toStringAsFixed(2)}",
custom.customDutyFee.toStringAsFixed(2),
// ignore: unnecessary_null_comparison // ignore: unnecessary_null_comparison
custom.rate == null custom.rate == null
? "" ? ""
: "Shipment rate \$ " + : "Shipment rate \$ ${custom.rate.toStringAsFixed(2)}"),
custom.rate.toStringAsFixed(2)),
), ),
); );
}), }),
@@ -97,7 +95,7 @@ class _CustomListState extends State<CustomList> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 3.0), padding: const EdgeInsets.only(bottom: 3.0),
child: Text( child: Text(
'$fee', fee,
style: TextStyle(color: primaryColor, fontSize: 14), style: TextStyle(color: primaryColor, fontSize: 14),
), ),
), ),
@@ -106,7 +104,7 @@ class _CustomListState extends State<CustomList> {
: Padding( : Padding(
padding: const EdgeInsets.only(top: 3.0), padding: const EdgeInsets.only(top: 3.0),
child: Text( child: Text(
"$shipmentRate", shipmentRate,
style: TextStyle(color: Colors.grey, fontSize: 14), style: TextStyle(color: Colors.grey, fontSize: 14),
), ),
) )

View File

@@ -11,30 +11,20 @@ import 'package:provider/provider.dart';
import 'model/shipment_rate_model.dart'; import 'model/shipment_rate_model.dart';
class DiscountByWeightList extends StatefulWidget { class DiscountByWeightList extends StatefulWidget {
const DiscountByWeightList({Key? key}) : super(key: key); const DiscountByWeightList({super.key});
@override @override
_DiscountByWeightListState createState() => _DiscountByWeightListState(); _DiscountByWeightListState createState() => _DiscountByWeightListState();
} }
class _DiscountByWeightListState extends State<DiscountByWeightList> { class _DiscountByWeightListState extends State<DiscountByWeightList> {
bool _isLoading = false; bool isLoading = false;
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
var shipmentRateModel = Provider.of<ShipmentRateModel>(context); var shipmentRateModel = Provider.of<ShipmentRateModel>(context);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar(labelKey: 'rate.discount_by_weight'), appBar: LocalAppBar(labelKey: 'rate.discount_by_weight'),
floatingActionButton: FloatingActionButton.extended( floatingActionButton: FloatingActionButton.extended(
@@ -64,7 +54,7 @@ class _DiscountByWeightListState extends State<DiscountByWeightList> {
child: Container( child: Container(
child: _row( child: _row(
"${discountByWeight.weight.toStringAsFixed(2)} lb", "${discountByWeight.weight.toStringAsFixed(2)} lb",
"\$ " + discountByWeight.discount.toString()), "\$ ${discountByWeight.discount}"),
), ),
); );
}), }),
@@ -85,7 +75,7 @@ class _DiscountByWeightListState extends State<DiscountByWeightList> {
Padding( Padding(
padding: const EdgeInsets.only(bottom: 3.0), padding: const EdgeInsets.only(bottom: 3.0),
child: Text( child: Text(
'$price', price,
style: TextStyle(color: primaryColor, fontSize: 14), style: TextStyle(color: primaryColor, fontSize: 14),
), ),
), ),

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'package:fcs/domain/entities/discount_by_weight.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
@@ -6,24 +8,25 @@ import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class DiscountByWeightEditor extends StatefulWidget { class DiscountByWeightEditor extends StatefulWidget {
final DiscountByWeight? discountByWeight; final DiscountByWeight? discountByWeight;
DiscountByWeightEditor({this.discountByWeight}); const DiscountByWeightEditor({super.key, this.discountByWeight});
@override @override
_DiscountByWeightEditorState createState() => _DiscountByWeightEditorState(); _DiscountByWeightEditorState createState() => _DiscountByWeightEditorState();
} }
class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> { class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
TextEditingController _weightController = new TextEditingController(); TextEditingController weightController = TextEditingController();
TextEditingController _discountController = new TextEditingController(); TextEditingController discountController = TextEditingController();
bool _isLoading = false; bool _isLoading = false;
bool _isNew = false; bool _isNew = false;
DiscountByWeight _discountByWeight = new DiscountByWeight(); DiscountByWeight _discountByWeight = DiscountByWeight();
final _discountFormKey = GlobalKey<FormState>(); final _discountFormKey = GlobalKey<FormState>();
@override @override
@@ -31,8 +34,8 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
super.initState(); super.initState();
if (widget.discountByWeight != null) { if (widget.discountByWeight != null) {
_discountByWeight = widget.discountByWeight!; _discountByWeight = widget.discountByWeight!;
_weightController.text = _discountByWeight.weight.toStringAsFixed(2); weightController.text = _discountByWeight.weight.toStringAsFixed(2);
_discountController.text = _discountByWeight.discount.toString(); discountController.text = _discountByWeight.discount.toString();
_isNew = false; _isNew = false;
} else { } else {
_isNew = true; _isNew = true;
@@ -49,7 +52,7 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
final weightBox = InputText( final weightBox = InputText(
labelTextKey: 'rate.discount.weight', labelTextKey: 'rate.discount.weight',
iconData: FontAwesomeIcons.weightHanging, iconData: FontAwesomeIcons.weightHanging,
controller: _weightController, controller: weightController,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -60,8 +63,8 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
); );
final discountRateBox = InputText( final discountRateBox = InputText(
labelTextKey: 'rate.discount.rate', labelTextKey: 'rate.discount.rate',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _discountController, controller: discountController,
autovalidateMode: AutovalidateMode.onUserInteraction, autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
@@ -75,7 +78,7 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
inAsyncCall: _isLoading, inAsyncCall: _isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar( appBar: LocalAppBar(
labelKey: 'discount.new', labelKey: 'discount.form',
backgroundColor: Colors.white, backgroundColor: Colors.white,
labelColor: primaryColor, labelColor: primaryColor,
arrowColor: primaryColor, arrowColor: primaryColor,
@@ -114,7 +117,7 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
), ),
fcsButton(context, getLocalString(context, "btn.save"), fcsButton(context, getLocalString(context, "btn.save"),
callack: _save), callack: _save),
SizedBox(height: 10) SizedBox(height: 30)
], ],
), ),
), ),
@@ -134,14 +137,14 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
DiscountByWeight _discount = DiscountByWeight( DiscountByWeight discount = DiscountByWeight(
weight: double.parse(_weightController.text), weight: double.parse(weightController.text),
discount: double.parse(_discountController.text)); discount: double.parse(discountController.text));
if (_isNew) { if (_isNew) {
await shipmentRateModel.addDiscountByWeight(_discount); await shipmentRateModel.addDiscountByWeight(discount);
} else { } else {
_discount.id = this._discountByWeight.id; discount.id = _discountByWeight.id;
await shipmentRateModel.updateDiscountByWeight(_discount); await shipmentRateModel.updateDiscountByWeight(discount);
} }
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
@@ -165,8 +168,7 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
await shipmentRateModel await shipmentRateModel.deleteDiscountByWeight(_discountByWeight.id!);
.deleteDiscountByWeight(this._discountByWeight.id!);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -179,12 +181,12 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
isDataChanged() { isDataChanged() {
if (_isNew) { if (_isNew) {
return _weightController.text != "" || _discountController.text != ""; return weightController.text != "" || discountController.text != "";
} else { } else {
DiscountByWeight _discount = DiscountByWeight( DiscountByWeight discount = DiscountByWeight(
weight: double.parse(_weightController.text), weight: double.parse(weightController.text),
discount: double.parse(_discountController.text)); discount: double.parse(discountController.text));
return this._discountByWeight.isChangedForEdit(_discount); return _discountByWeight.isChangedForEdit(discount);
} }
} }
} }

View File

@@ -11,23 +11,24 @@ import 'package:fcs/pages/widgets/local_dropdown.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class ShipmentRatesCal extends StatefulWidget { class ShipmentRatesCal extends StatefulWidget {
ShipmentRatesCal(); const ShipmentRatesCal({super.key});
@override @override
_ShipmentRatesCalState createState() => _ShipmentRatesCalState(); _ShipmentRatesCalState createState() => _ShipmentRatesCalState();
} }
class _ShipmentRatesCalState extends State<ShipmentRatesCal> { class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
bool _isLoading = false; bool isLoading = false;
late CargoType _cargoType; late CargoType _cargoType;
TextEditingController _widthController = new TextEditingController(); TextEditingController widthController = TextEditingController();
TextEditingController _heightController = new TextEditingController(); TextEditingController heightController = TextEditingController();
TextEditingController _lengthController = new TextEditingController(); TextEditingController lengthController = TextEditingController();
TextEditingController _actualWeightCtl = new TextEditingController(); TextEditingController actualWeightCtl = TextEditingController();
double _shipmentWeight = 0; double _shipmentWeight = 0;
double _amount = 0; double _amount = 0;
double _deliveryFee = 0; double _deliveryFee = 0;
@@ -38,25 +39,25 @@ class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
//for shipment weight //for shipment weight
Rate rate = Provider.of<ShipmentRateModel>(context, listen: false).rate; Rate rate = Provider.of<ShipmentRateModel>(context, listen: false).rate;
_lengthController.addListener(_calShipmentWeight); lengthController.addListener(_calShipmentWeight);
_widthController.addListener(_calShipmentWeight); widthController.addListener(_calShipmentWeight);
_heightController.addListener(_calShipmentWeight); heightController.addListener(_calShipmentWeight);
_actualWeightCtl.addListener(_calShipmentWeight); actualWeightCtl.addListener(_calShipmentWeight);
_cargoType = rate.defaultCargoType; _cargoType = rate.defaultCargoType;
_lengthController.text = '12'; lengthController.text = '12';
_widthController.text = '12'; widthController.text = '12';
_heightController.text = '12'; heightController.text = '12';
_actualWeightCtl.text = "10.00"; actualWeightCtl.text = "10.00";
_calShipmentWeight(); _calShipmentWeight();
} }
_calShipmentWeight() { _calShipmentWeight() {
Rate rate = Provider.of<ShipmentRateModel>(context, listen: false).rate; Rate rate = Provider.of<ShipmentRateModel>(context, listen: false).rate;
double l = double.tryParse(_lengthController.text) ?? 0; double l = double.tryParse(lengthController.text) ?? 0;
double w = double.tryParse(_widthController.text) ?? 0; double w = double.tryParse(widthController.text) ?? 0;
double h = double.tryParse(_heightController.text) ?? 0; double h = double.tryParse(heightController.text) ?? 0;
_cargoType.weight = double.tryParse(_actualWeightCtl.text) ?? 0; _cargoType.weight = double.tryParse(actualWeightCtl.text) ?? 0;
Carton box = Carton box =
Carton(cargoTypes: [_cargoType], length: l, width: w, height: h); Carton(cargoTypes: [_cargoType], length: l, width: w, height: h);
var amount = box.calAmount(rate); var amount = box.calAmount(rate);
@@ -83,15 +84,15 @@ class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
List<CargoType> cargos = shipmentRateModel.rate.cargoTypes; List<CargoType> cargos = shipmentRateModel.rate.cargoTypes;
final lengthBox = LengthPicker( final lengthBox = LengthPicker(
controller: _lengthController, controller: lengthController,
lableKey: "box.length", lableKey: "box.length",
); );
final widthBox = LengthPicker( final widthBox = LengthPicker(
controller: _widthController, controller: widthController,
lableKey: "box.width", lableKey: "box.width",
); );
final heightBox = LengthPicker( final heightBox = LengthPicker(
controller: _heightController, controller: heightController,
lableKey: "box.height", lableKey: "box.height",
); );
@@ -102,9 +103,9 @@ class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0),
child: Icon(FontAwesome.arrow_circle_right, color: primaryColor), child: Icon(FontAwesome.arrow_circle_right, color: primaryColor),
), ),
SizedBox(child: lengthBox, width: 80), SizedBox(width: 80, child: lengthBox),
SizedBox(child: widthBox, width: 80), SizedBox(width: 80, child: widthBox),
SizedBox(child: heightBox, width: 80), SizedBox(width: 80, child: heightBox),
], ],
); );
@@ -115,7 +116,7 @@ class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
); );
final actualWeightBox = InputText( final actualWeightBox = InputText(
controller: _actualWeightCtl, controller: actualWeightCtl,
labelTextKey: "box.actual_weight", labelTextKey: "box.actual_weight",
iconData: MaterialCommunityIcons.weight, iconData: MaterialCommunityIcons.weight,
textInputType: TextInputType.numberWithOptions(decimal: true), textInputType: TextInputType.numberWithOptions(decimal: true),
@@ -129,13 +130,13 @@ class _ShipmentRatesCalState extends State<ShipmentRatesCal> {
}); });
}, },
labelKey: "cargo.type", labelKey: "cargo.type",
iconData: Icons.text_format, iconData: Ionicons.text,
selectedValue: _cargoType, selectedValue: _cargoType,
values: cargos, values: cargos,
); );
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: isLoading,
child: Scaffold( child: Scaffold(
appBar: LocalAppBar( appBar: LocalAppBar(
labelKey: "rate.cal.title", labelKey: "rate.cal.title",

View File

@@ -1,3 +1,5 @@
// ignore_for_file: use_build_context_synchronously
import 'package:fcs/domain/entities/rate.dart'; import 'package:fcs/domain/entities/rate.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart'; import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
@@ -5,13 +7,14 @@ import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart'; import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import '../main/util.dart'; import '../main/util.dart';
class ShipmentRatesEdit extends StatefulWidget { class ShipmentRatesEdit extends StatefulWidget {
ShipmentRatesEdit(); const ShipmentRatesEdit({super.key});
@override @override
_ShipmentRatesEditState createState() => _ShipmentRatesEditState(); _ShipmentRatesEditState createState() => _ShipmentRatesEditState();
@@ -19,11 +22,11 @@ class ShipmentRatesEdit extends StatefulWidget {
class _ShipmentRatesEditState extends State<ShipmentRatesEdit> { class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
bool _isLoading = false; bool _isLoading = false;
TextEditingController _minWeight = new TextEditingController(); TextEditingController minWeight = TextEditingController();
TextEditingController _deliveryFee = new TextEditingController(); TextEditingController deliveryFee = TextEditingController();
TextEditingController _volumetricRatio = new TextEditingController(); TextEditingController volumetricRatio = TextEditingController();
TextEditingController _diffDiscountWeight = new TextEditingController(); TextEditingController diffDiscountWeight = TextEditingController();
TextEditingController _diffWeightRate = new TextEditingController(); TextEditingController diffWeightRate = TextEditingController();
late Rate rate; late Rate rate;
@@ -34,11 +37,11 @@ class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
rate = shipmentRateModel.rate; rate = shipmentRateModel.rate;
_minWeight.text = rate.freeDeliveryWeight.toStringAsFixed(2); minWeight.text = rate.freeDeliveryWeight.toStringAsFixed(2);
_deliveryFee.text = rate.deliveryFee.toStringAsFixed(2); deliveryFee.text = rate.deliveryFee.toStringAsFixed(2);
_volumetricRatio.text = rate.volumetricRatio.toStringAsFixed(2); volumetricRatio.text = rate.volumetricRatio.toStringAsFixed(2);
_diffDiscountWeight.text = rate.diffDiscountWeight.toStringAsFixed(2); diffDiscountWeight.text = rate.diffDiscountWeight.toStringAsFixed(2);
_diffWeightRate.text = rate.diffWeightRate.toStringAsFixed(2); diffWeightRate.text = rate.diffWeightRate.toStringAsFixed(2);
} }
@override @override
@@ -51,23 +54,27 @@ class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
final minWigBox = InputText( final minWigBox = InputText(
labelTextKey: 'rate.min_weight', labelTextKey: 'rate.min_weight',
iconData: FontAwesomeIcons.weightHanging, iconData: FontAwesomeIcons.weightHanging,
controller: _minWeight); controller: minWeight);
final feeBox = InputText( final feeBox = InputText(
labelTextKey: 'rate.delivery_fee', labelTextKey: 'rate.delivery_fee',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _deliveryFee); controller: deliveryFee);
final ratioBox = InputText( final ratioBox = InputText(
labelTextKey: 'rate.volumetric_ratio', labelTextKey: 'rate.volumetric_ratio',
iconData: FontAwesomeIcons.weightHanging, iconData: FontAwesomeIcons.weightHanging,
controller: _volumetricRatio); controller: volumetricRatio);
final diffDiscountWeightBox = InputText( final diffDiscountWeightBox = InputText(
labelTextKey: 'rate.diff_discount_weight', labelTextKey: 'rate.diff_discount_weight',
iconData: FontAwesomeIcons.weightHanging, iconData: FontAwesomeIcons.weightHanging,
controller: _diffDiscountWeight); controller: diffDiscountWeight);
final diffWeightRateBox = InputText( final diffWeightRateBox = InputText(
labelTextKey: 'rate.diff_weight_rate', labelTextKey: 'rate.diff_weight_rate',
iconData: Icons.attach_money, iconData: Fontisto.dollar,
controller: _diffWeightRate); controller: diffWeightRate);
return LocalProgress( return LocalProgress(
inAsyncCall: _isLoading, inAsyncCall: _isLoading,
@@ -105,7 +112,7 @@ class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
), ),
fcsButton(context, getLocalString(context, "btn.save"), fcsButton(context, getLocalString(context, "btn.save"),
callack: _save), callack: _save),
SizedBox(height: 10) SizedBox(height: 30)
], ],
), ),
), ),
@@ -120,15 +127,14 @@ class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
try { try {
var shipmentRateModel = var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false); Provider.of<ShipmentRateModel>(context, listen: false);
Rate _rate = new Rate( Rate rate = Rate(
deliveryFee: double.parse(_deliveryFee.text), deliveryFee: double.parse(deliveryFee.text),
freeDeliveryWeight: double.parse(_minWeight.text), freeDeliveryWeight: double.parse(minWeight.text),
volumetricRatio: double.parse(_volumetricRatio.text), volumetricRatio: double.parse(volumetricRatio.text),
diffDiscountWeight: double.parse(_diffDiscountWeight.text), diffDiscountWeight: double.parse(diffDiscountWeight.text),
diffWeightRate: double.parse(_diffWeightRate.text)); diffWeightRate: double.parse(diffWeightRate.text));
Rate r = new Rate();
print('_rate =>$r'); await shipmentRateModel.updateRate(rate);
await shipmentRateModel.updateRate(_rate);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -140,13 +146,13 @@ class _ShipmentRatesEditState extends State<ShipmentRatesEdit> {
} }
isDataChanged() { isDataChanged() {
Rate _rate = new Rate( Rate rate = Rate(
deliveryFee: double.parse(_deliveryFee.text), deliveryFee: double.parse(deliveryFee.text),
freeDeliveryWeight: double.parse(_minWeight.text), freeDeliveryWeight: double.parse(minWeight.text),
volumetricRatio: double.parse(_volumetricRatio.text), volumetricRatio: double.parse(volumetricRatio.text),
diffDiscountWeight: double.parse(_diffDiscountWeight.text), diffDiscountWeight: double.parse(diffDiscountWeight.text),
diffWeightRate: double.parse(_diffWeightRate.text), diffWeightRate: double.parse(diffWeightRate.text),
); );
return rate.isChangedForEdit(_rate); return rate.isChangedForEdit(rate);
} }
} }

View File

@@ -7,17 +7,16 @@ import 'package:intl/intl.dart';
import 'receiving_info.dart'; import 'receiving_info.dart';
typedef CallbackPackageSelect(Package package); typedef CallbackPackageSelect = Function(Package package);
class ReceivingListRow extends StatelessWidget { class ReceivingListRow extends StatelessWidget {
final Package package; final Package package;
final CallbackPackageSelect? callbackPackageSelect; final CallbackPackageSelect? callbackPackageSelect;
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = DateFormat("dd MMM yyyy");
ReceivingListRow( ReceivingListRow(
{Key? key, required this.package, this.callbackPackageSelect}) {super.key, required this.package, this.callbackPackageSelect});
: super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -38,29 +37,29 @@ class ReceivingListRow extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 13.0), padding: const EdgeInsets.symmetric(vertical: 13.0),
child: new Row( child: Row(
children: <Widget>[ children: <Widget>[
Icon(MaterialCommunityIcons.inbox_arrow_down, Icon(MaterialCommunityIcons.inbox_arrow_down,
color: primaryColor), color: primaryColor),
new Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 15), padding: const EdgeInsets.only(left: 15),
child: new Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[ children: <Widget>[
new Text( Text(
package.id == null ? '' : package.trackingID!, package.id == null ? '' : package.trackingID!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
package.market == null ? '' : package.market!, package.market == null ? '' : package.market!,
style: new TextStyle( style: TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.grey),
), ),
), ),
], ],
@@ -81,11 +80,11 @@ class ReceivingListRow extends StatelessWidget {
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
Padding( Padding(
padding: const EdgeInsets.only(top: 5), padding: const EdgeInsets.only(top: 5),
child: new Text( child: Text(
package.currentStatusDate != null package.currentStatusDate != null
? dateFormat.format(package.currentStatusDate!) ? dateFormat.format(package.currentStatusDate!)
: '', : '',
style: new TextStyle(fontSize: 14.0, color: Colors.grey), style: TextStyle(fontSize: 14.0, color: Colors.grey),
), ),
), ),
], ],

View File

@@ -15,14 +15,13 @@ class LocalPopupMenuButton extends StatefulWidget {
final Color buttonColor; final Color buttonColor;
const LocalPopupMenuButton( const LocalPopupMenuButton(
{Key? key, {super.key,
this.popupMenuCallback, this.popupMenuCallback,
this.popmenus, this.popmenus,
this.buttonIcon, this.buttonIcon,
this.selectable = true, this.selectable = true,
this.multiSelect = false, this.multiSelect = false,
this.buttonColor = primaryColor}) this.buttonColor = primaryColor});
: super(key: key);
@override @override
_LocalPopupMenuButtonState createState() => _LocalPopupMenuButtonState(); _LocalPopupMenuButtonState createState() => _LocalPopupMenuButtonState();
@@ -46,30 +45,32 @@ class _LocalPopupMenuButtonState extends State<LocalPopupMenuButton> {
if (widget.selectable) { if (widget.selectable) {
if (!widget.multiSelect) { if (!widget.multiSelect) {
setState(() { setState(() {
popmenus.forEach((e) { for (var e in popmenus) {
if (e.id != selected.id) if (e.id != selected.id) {
e.selected = false; e.selected = false;
else } else {
e.selected = true; e.selected = true;
}); }
}
}); });
selected.selected = true; selected.selected = true;
} else { } else {
setState(() { setState(() {
popmenus.forEach((e) { for (var e in popmenus) {
if (e.id == selected.id) e.selected = !e.selected; if (e.id == selected.id) e.selected = !e.selected;
}); }
}); });
selected.selected = !selected.selected; selected.selected = !selected.selected;
} }
} }
if (selected.enabled && widget.popupMenuCallback != null) if (selected.enabled && widget.popupMenuCallback != null) {
widget.popupMenuCallback!(selected); widget.popupMenuCallback!(selected);
}
}, },
icon: Container( icon: Container(
width: 30, width: 30,
height: 30, height: 30,
decoration: new BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
//color: Colors.white, //color: Colors.white,
), ),
@@ -87,7 +88,7 @@ class _LocalPopupMenuButtonState extends State<LocalPopupMenuButton> {
child: Container( child: Container(
width: 10, width: 10,
height: 10, height: 10,
decoration: new BoxDecoration( decoration: BoxDecoration(
shape: BoxShape.circle, shape: BoxShape.circle,
color: secondaryColor, color: secondaryColor,
), ),
@@ -109,7 +110,7 @@ class _LocalPopupMenuButtonState extends State<LocalPopupMenuButton> {
color: color:
choice.enabled ? Colors.black : Colors.grey)) choice.enabled ? Colors.black : Colors.grey))
: LocalText(context, choice.textKey ?? "", : LocalText(context, choice.textKey ?? "",
color: choice.enabled ? Colors.black : Colors.grey, color: choice.enabled ? Colors.black : Colors.grey,
fontSize: 14), fontSize: 14),
SizedBox( SizedBox(
width: 10, width: 10,
@@ -128,9 +129,9 @@ class _LocalPopupMenuButtonState extends State<LocalPopupMenuButton> {
} }
bool _needHighlight() { bool _needHighlight() {
popmenus.forEach((e) { for (var e in popmenus) {
if (e.selected && e.highlight) return; if (e.selected && e.highlight) continue;
}); }
return false; return false;
} }
} }