add carton editor for package
This commit is contained in:
@@ -329,6 +329,11 @@
|
|||||||
"box.crete.carton":"Create carton",
|
"box.crete.carton":"Create carton",
|
||||||
"box.carton.type":"Carton Type",
|
"box.carton.type":"Carton Type",
|
||||||
"box.select.delivery":"Select delivery type",
|
"box.select.delivery":"Select delivery type",
|
||||||
|
"box.select.package":"Select packages",
|
||||||
|
"box.no_package":"There is no packages.",
|
||||||
|
"box.input_cargo_weight":"Input cargo weight (lb)",
|
||||||
|
"box.input_surcharge_item":"Input surcharge items",
|
||||||
|
"box.select.cargo_type":"Select surcharge item",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
|
|||||||
@@ -328,6 +328,11 @@
|
|||||||
"box.crete.carton":"Create carton",
|
"box.crete.carton":"Create carton",
|
||||||
"box.carton.type":"Carton Type",
|
"box.carton.type":"Carton Type",
|
||||||
"box.select.delivery":"Select delivery type",
|
"box.select.delivery":"Select delivery type",
|
||||||
|
"box.select.package":"Select packages",
|
||||||
|
"box.no_package":"There is no packages.",
|
||||||
|
"box.input_cargo_weight":"Input cargo weight (lb)",
|
||||||
|
"box.input_surcharge_item":"Input surcharge items",
|
||||||
|
"box.select.cargo_type":"Select surcharge item",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import 'package:flutter_localizations/flutter_localizations.dart';
|
|||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'pages/carton/model/carton_selection_model.dart';
|
import 'pages/carton/model/carton_selection_model.dart';
|
||||||
|
import 'pages/carton/model/package_selection_model.dart';
|
||||||
import 'pages/delivery/model/delivery_model.dart';
|
import 'pages/delivery/model/delivery_model.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
@@ -64,6 +65,7 @@ class _AppState extends State<App> {
|
|||||||
final ProcessingModel processingModel = new ProcessingModel();
|
final ProcessingModel processingModel = new ProcessingModel();
|
||||||
final PickupModel pickupModel = new PickupModel();
|
final PickupModel pickupModel = new PickupModel();
|
||||||
final CartonSelectionModel cartonSelectionModel = new CartonSelectionModel();
|
final CartonSelectionModel cartonSelectionModel = new CartonSelectionModel();
|
||||||
|
final PackageSelectionModel packageSelectionModel = new PackageSelectionModel();
|
||||||
|
|
||||||
late AppTranslationsDelegate _newLocaleDelegate;
|
late AppTranslationsDelegate _newLocaleDelegate;
|
||||||
|
|
||||||
@@ -87,7 +89,8 @@ class _AppState extends State<App> {
|
|||||||
..addModel(cartonSizeModel)
|
..addModel(cartonSizeModel)
|
||||||
..addModel(processingModel)
|
..addModel(processingModel)
|
||||||
..addModel(pickupModel)
|
..addModel(pickupModel)
|
||||||
..addModel(cartonSelectionModel);
|
..addModel(cartonSelectionModel)
|
||||||
|
..addModel(packageSelectionModel);
|
||||||
|
|
||||||
_newLocaleDelegate = AppTranslationsDelegate(
|
_newLocaleDelegate = AppTranslationsDelegate(
|
||||||
newLocale: Translation().supportedLocales().first);
|
newLocale: Translation().supportedLocales().first);
|
||||||
@@ -137,6 +140,7 @@ class _AppState extends State<App> {
|
|||||||
ChangeNotifierProvider.value(value: processingModel),
|
ChangeNotifierProvider.value(value: processingModel),
|
||||||
ChangeNotifierProvider.value(value: pickupModel),
|
ChangeNotifierProvider.value(value: pickupModel),
|
||||||
ChangeNotifierProvider.value(value: cartonSelectionModel),
|
ChangeNotifierProvider.value(value: cartonSelectionModel),
|
||||||
|
ChangeNotifierProvider.value(value: packageSelectionModel),
|
||||||
],
|
],
|
||||||
child: Consumer<LanguageModel>(
|
child: Consumer<LanguageModel>(
|
||||||
builder: (context, value, child) {
|
builder: (context, value, child) {
|
||||||
|
|||||||
@@ -133,3 +133,7 @@ const invoice_paid_status = "paid";
|
|||||||
const payment_pending_status = "pending";
|
const payment_pending_status = "pending";
|
||||||
const payment_confirmed_status = "confirmed";
|
const payment_confirmed_status = "confirmed";
|
||||||
const payment_canceled_status = "canceled";
|
const payment_canceled_status = "canceled";
|
||||||
|
|
||||||
|
//Delivery types
|
||||||
|
const delivery_caton = "Delivery carton";
|
||||||
|
const pickup_carton = "Pick-up carton";
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class Package {
|
|||||||
DateTime? currentStatusDate;
|
DateTime? currentStatusDate;
|
||||||
List<String> photoUrls;
|
List<String> photoUrls;
|
||||||
List<ShipmentStatus> shipmentHistory;
|
List<ShipmentStatus> shipmentHistory;
|
||||||
|
List<String> cartonIds;
|
||||||
String? desc;
|
String? desc;
|
||||||
|
|
||||||
String? status;
|
String? status;
|
||||||
@@ -69,7 +70,8 @@ class Package {
|
|||||||
this.deliveryAddress,
|
this.deliveryAddress,
|
||||||
this.isChecked = false,
|
this.isChecked = false,
|
||||||
this.photoFiles = const [],
|
this.photoFiles = const [],
|
||||||
this.senderPhoneNumber});
|
this.senderPhoneNumber,
|
||||||
|
this.cartonIds = const []});
|
||||||
|
|
||||||
factory Package.fromMap(Map<String, dynamic> map, String docID) {
|
factory Package.fromMap(Map<String, dynamic> map, String docID) {
|
||||||
var _currentStatusDate = (map['status_date'] as Timestamp);
|
var _currentStatusDate = (map['status_date'] as Timestamp);
|
||||||
@@ -82,6 +84,9 @@ class Package {
|
|||||||
var da = map['delivery_address'];
|
var da = map['delivery_address'];
|
||||||
var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null;
|
var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null;
|
||||||
|
|
||||||
|
List<String> cartonIds =
|
||||||
|
map['carton_ids'] == null ? [] : List.from(map['carton_ids']);
|
||||||
|
|
||||||
return Package(
|
return Package(
|
||||||
id: docID,
|
id: docID,
|
||||||
userID: map['user_id'],
|
userID: map['user_id'],
|
||||||
@@ -99,7 +104,8 @@ class Package {
|
|||||||
deliveryAddress: _da,
|
deliveryAddress: _da,
|
||||||
currentStatusDate: _currentStatusDate.toDate().toLocal(),
|
currentStatusDate: _currentStatusDate.toDate().toLocal(),
|
||||||
photoUrls: _photoUrls,
|
photoUrls: _photoUrls,
|
||||||
shipmentHistory: _shipmentStatus);
|
shipmentHistory: _shipmentStatus,
|
||||||
|
cartonIds: cartonIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
|
|||||||
356
lib/pages/carton/cargo_widget.dart
Normal file
356
lib/pages/carton/cargo_widget.dart
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/cargo_type.dart';
|
||||||
|
import '../../domain/entities/user.dart';
|
||||||
|
import '../rates/model/shipment_rate_model.dart';
|
||||||
|
import '../widgets/continue_button.dart';
|
||||||
|
import '../widgets/display_text.dart';
|
||||||
|
import '../widgets/local_title.dart';
|
||||||
|
import '../widgets/previous_button.dart';
|
||||||
|
import 'custom_duty_addition.dart';
|
||||||
|
|
||||||
|
typedef OnPrevious = Function(
|
||||||
|
List<CargoType> cargoTypes, List<CargoType> customDuties);
|
||||||
|
typedef OnContinue = Function(
|
||||||
|
List<CargoType> cargoTypes, List<CargoType> customDuties);
|
||||||
|
|
||||||
|
class CargoWidget extends StatefulWidget {
|
||||||
|
final User sender;
|
||||||
|
final User consignee;
|
||||||
|
final List<CargoType> cargoTypes;
|
||||||
|
final List<CargoType> customDuties;
|
||||||
|
final OnPrevious? onPrevious;
|
||||||
|
final OnContinue? onContinue;
|
||||||
|
|
||||||
|
const CargoWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.cargoTypes,
|
||||||
|
required this.customDuties,
|
||||||
|
this.onPrevious,
|
||||||
|
this.onContinue,
|
||||||
|
required this.sender,
|
||||||
|
required this.consignee,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CargoWidget> createState() => _CargoWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CargoWidgetState extends State<CargoWidget> {
|
||||||
|
List<CargoType> _cargoTypes = [];
|
||||||
|
List<CargoType> _customDuties = [];
|
||||||
|
TextEditingController _totalCtl = TextEditingController();
|
||||||
|
List<TextEditingController> _cargoTypeControllers = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
var model = context.read<ShipmentRateModel>();
|
||||||
|
_cargoTypes = model.rate.cargoTypes.map((e) => e.clone()).toList();
|
||||||
|
|
||||||
|
if (widget.cargoTypes.isNotEmpty) {
|
||||||
|
} else {
|
||||||
|
_cargoTypes.forEach((e) {
|
||||||
|
var editor = new TextEditingController();
|
||||||
|
editor.text = '';
|
||||||
|
editor.addListener(inputChangeListener);
|
||||||
|
_cargoTypeControllers.add(editor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isFieldEmpty(int index) {
|
||||||
|
return _cargoTypeControllers[index].text.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> getEmptyFields() {
|
||||||
|
List<int> emptyFields = [];
|
||||||
|
for (int i = 0; i < _cargoTypeControllers.length; i++) {
|
||||||
|
if (isFieldEmpty(i)) {
|
||||||
|
emptyFields.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emptyFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
inputChangeListener() {
|
||||||
|
List<int> emptyFields = getEmptyFields();
|
||||||
|
print("emptyFields:$emptyFields");
|
||||||
|
|
||||||
|
// if (emptyFields.isNotEmpty && emptyFields.length == 1) {
|
||||||
|
// // _cargoTypeControllers[emptyFields.first].text =
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (emptyFields.isEmpty) {
|
||||||
|
_cargoTypes.asMap().entries.forEach((e) {
|
||||||
|
_cargoTypes[e.key].weight =
|
||||||
|
double.tryParse(_cargoTypeControllers[e.key].text) ?? 0;
|
||||||
|
});
|
||||||
|
double total = _cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||||
|
setState(() {
|
||||||
|
_totalCtl.text = total.toString();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// if (emptyFields.length == 1) {
|
||||||
|
// print("_totalCtl.text:${_totalCtl.text}");
|
||||||
|
|
||||||
|
// if (_totalCtl.text.isNotEmpty) {
|
||||||
|
// double t = double.tryParse(_totalCtl.text) ?? 0;
|
||||||
|
|
||||||
|
// _cargoTypes.asMap().entries.forEach((e) {
|
||||||
|
// _cargoTypes[e.key].weight =
|
||||||
|
// double.tryParse(_cargoTypeControllers[e.key].text) ?? 0;
|
||||||
|
// });
|
||||||
|
// double result =
|
||||||
|
// _cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||||
|
|
||||||
|
// double remaining = t - result;
|
||||||
|
// setState(() {
|
||||||
|
// _cargoTypeControllers[emptyFields.first].text =
|
||||||
|
// remaining.toString();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final senderBox = DisplayText(
|
||||||
|
text: widget.sender.name,
|
||||||
|
labelTextKey: "box.sender.title",
|
||||||
|
iconData: MaterialCommunityIcons.account_arrow_right,
|
||||||
|
subText: Text(widget.sender.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final consigneeBox = DisplayText(
|
||||||
|
text: widget.consignee.name,
|
||||||
|
labelTextKey: "box.consignee.title",
|
||||||
|
iconData: MaterialCommunityIcons.account_arrow_left,
|
||||||
|
subText: Text(widget.consignee.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final userRow = Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: senderBox,
|
||||||
|
flex: 2,
|
||||||
|
),
|
||||||
|
Flexible(child: consigneeBox)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final cargosBox = Wrap(
|
||||||
|
alignment: WrapAlignment.spaceBetween,
|
||||||
|
runSpacing: 15,
|
||||||
|
children: _cargoTypes.asMap().entries.map((e) {
|
||||||
|
var key = e.key;
|
||||||
|
var c = e.value;
|
||||||
|
return SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.3,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
InkResponse(
|
||||||
|
radius: 25,
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_cargoTypeControllers[key].clear();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(MaterialIcons.clear)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Flexible(
|
||||||
|
child: inputTextFieldWidget(context,
|
||||||
|
lableText: c.name ?? "",
|
||||||
|
controller: _cargoTypeControllers[key]
|
||||||
|
// onChanged: (newValue) {
|
||||||
|
// setState(() {
|
||||||
|
// _cargoTypes[key].weight = double.tryParse(newValue) ?? 0;
|
||||||
|
// });
|
||||||
|
// double total =
|
||||||
|
// _cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||||
|
// setState(() {
|
||||||
|
// _totalCtl.text = total.toString();
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList());
|
||||||
|
|
||||||
|
final totalBox = Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.3,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
InkResponse(
|
||||||
|
radius: 25,
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_totalCtl.clear();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(MaterialIcons.clear)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Flexible(
|
||||||
|
child: inputTextFieldWidget(context,
|
||||||
|
lableText: "Total", controller: _totalCtl),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final subchargeItemTitleBox = LocalTitle(
|
||||||
|
textKey: "box.input_surcharge_item",
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: Icon(
|
||||||
|
Icons.add_circle,
|
||||||
|
color: primaryColor,
|
||||||
|
),
|
||||||
|
onPressed: () async {
|
||||||
|
List<CargoType>? customList = await Navigator.push<List<CargoType>>(
|
||||||
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
CustomDutyAddition(customDuties: _customDuties)));
|
||||||
|
if (customList == null) return;
|
||||||
|
|
||||||
|
_customDuties = List.from(customList);
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
final subChargeItemsBox = Wrap(
|
||||||
|
alignment: WrapAlignment.spaceBetween,
|
||||||
|
runSpacing: 15,
|
||||||
|
children: _customDuties.asMap().entries.map((e) {
|
||||||
|
var key = e.key;
|
||||||
|
var c = e.value;
|
||||||
|
return SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width / 2.3,
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
InkResponse(
|
||||||
|
radius: 25,
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
_customDuties.removeAt(key);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Icon(Feather.minus_circle)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Flexible(
|
||||||
|
child: inputTextFieldWidget(
|
||||||
|
context,
|
||||||
|
lableText: c.name ?? "",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList());
|
||||||
|
|
||||||
|
final continueBtn = ContinueButton(
|
||||||
|
onTap: () {
|
||||||
|
// if (selectedPackageList.isEmpty || searchResults.isEmpty) {
|
||||||
|
// showMsgDialog(context, 'Error', "Please select the packages");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (widget.onContinue != null) {
|
||||||
|
// widget.onContinue!(selectedPackageList);
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
|
if (widget.onPrevious != null) {
|
||||||
|
widget.onPrevious!(_cargoTypes, _customDuties);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
userRow,
|
||||||
|
LocalTitle(textKey: "box.input_cargo_weight", topPadding: 10),
|
||||||
|
cargosBox,
|
||||||
|
const SizedBox(height: 15),
|
||||||
|
Divider(),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
totalBox,
|
||||||
|
subchargeItemTitleBox,
|
||||||
|
subChargeItemsBox,
|
||||||
|
const SizedBox(height: 30),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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 inputTextFieldWidget(BuildContext context,
|
||||||
|
{required String lableText,
|
||||||
|
TextEditingController? controller,
|
||||||
|
Function(String)? onChanged}) {
|
||||||
|
return TextFormField(
|
||||||
|
controller: controller,
|
||||||
|
style: textStyle,
|
||||||
|
cursorColor: primaryColor,
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
onChanged: onChanged,
|
||||||
|
decoration: new InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(0),
|
||||||
|
labelText: lableText,
|
||||||
|
labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17),
|
||||||
|
enabledBorder: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||||
|
focusedBorder: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||||
|
disabledBorder: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: primaryColor, width: 1.0)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -90,7 +90,7 @@ class _CargoTableState extends State<CargoTable> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
c.isCutomDuty!
|
c.isCutomDuty
|
||||||
? GestureDetector(
|
? GestureDetector(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
String? _t = await showDialog(
|
String? _t = await showDialog(
|
||||||
|
|||||||
@@ -3,25 +3,31 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import '../../../domain/constants.dart';
|
import '../../../domain/constants.dart';
|
||||||
import '../../../domain/entities/carton.dart';
|
|
||||||
import '../../../domain/entities/carton_size.dart';
|
import '../../../domain/entities/carton_size.dart';
|
||||||
import '../../../domain/entities/fcs_shipment.dart';
|
import '../../../domain/entities/fcs_shipment.dart';
|
||||||
import '../../../domain/vo/local_step.dart';
|
import '../../../domain/vo/local_step.dart';
|
||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.dart';
|
||||||
|
import '../../domain/entities/cargo_type.dart';
|
||||||
|
import '../../domain/entities/package.dart';
|
||||||
import '../../domain/entities/user.dart';
|
import '../../domain/entities/user.dart';
|
||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
import '../widgets/local_text.dart';
|
import '../widgets/local_text.dart';
|
||||||
import '../widgets/progress.dart';
|
import '../widgets/progress.dart';
|
||||||
import '../widgets/step_widget.dart';
|
import '../widgets/step_widget.dart';
|
||||||
|
import 'cargo_widget.dart';
|
||||||
import 'carton_size_widget.dart';
|
import 'carton_size_widget.dart';
|
||||||
import 'mix_carton/mix_carton_submit.dart';
|
import 'model/package_selection_model.dart';
|
||||||
|
import 'package_selection_widget.dart';
|
||||||
|
|
||||||
class CartonEditorForPackage extends StatefulWidget {
|
class CartonEditorForPackage extends StatefulWidget {
|
||||||
final User sender;
|
final User sender;
|
||||||
final User consignee;
|
final User consignee;
|
||||||
const CartonEditorForPackage({Key? key, required this.sender, required this.consignee}) : super(key: key);
|
const CartonEditorForPackage(
|
||||||
|
{Key? key, required this.sender, required this.consignee})
|
||||||
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CartonEditorForPackage> createState() => _CartonEditorForPackageState();
|
State<CartonEditorForPackage> createState() => _CartonEditorForPackageState();
|
||||||
@@ -36,18 +42,27 @@ class _CartonEditorForPackageState extends State<CartonEditorForPackage> {
|
|||||||
LocalStep(lable: 'Cargos', stepType: StepType.CARGOS),
|
LocalStep(lable: 'Cargos', stepType: StepType.CARGOS),
|
||||||
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
||||||
];
|
];
|
||||||
List<Carton> _cartions = [];
|
List<Package> _packages = [];
|
||||||
|
List<CargoType> _cargoTypes = [];
|
||||||
|
List<CargoType> _customDuties = [];
|
||||||
|
|
||||||
int currentStep = 0;
|
int currentStep = 0;
|
||||||
double _length = 0;
|
double _length = 0;
|
||||||
double _width = 0;
|
double _width = 0;
|
||||||
double _height = 0;
|
double _height = 0;
|
||||||
|
|
||||||
|
String _selectedDeliveryType = delivery_caton;
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
String _cartonSizeType = standardCarton;
|
String _cartonSizeType = standardCarton;
|
||||||
CartonSize? _standardSize;
|
CartonSize? _standardSize;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
context.read<PackageSelectionModel>().clearSelection();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return WillPopScope(
|
return WillPopScope(
|
||||||
@@ -113,8 +128,9 @@ class _CartonEditorForPackageState extends State<CartonEditorForPackage> {
|
|||||||
if (step.stepType == StepType.SIZE) {
|
if (step.stepType == StepType.SIZE) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: CartonSizeWidget(
|
child: CartonSizeWidget(
|
||||||
sender: widget.sender,
|
deliveryType: _selectedDeliveryType,
|
||||||
consignee: widget.consignee,
|
sender: widget.sender,
|
||||||
|
consignee: widget.consignee,
|
||||||
shipment: _shipment,
|
shipment: _shipment,
|
||||||
cartonSizeType: _cartonSizeType,
|
cartonSizeType: _cartonSizeType,
|
||||||
standardSize: _standardSize,
|
standardSize: _standardSize,
|
||||||
@@ -124,9 +140,10 @@ class _CartonEditorForPackageState extends State<CartonEditorForPackage> {
|
|||||||
onPrevious: () {
|
onPrevious: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
onContinue: (shipment, cartonSizeType,
|
onContinue: (deliveryType, shipment, cartonSizeType,
|
||||||
{standardSize, length, width, height}) {
|
{standardSize, length, width, height}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_selectedDeliveryType = deliveryType;
|
||||||
_shipment = shipment;
|
_shipment = shipment;
|
||||||
_cartonSizeType = cartonSizeType;
|
_cartonSizeType = cartonSizeType;
|
||||||
_standardSize = standardSize;
|
_standardSize = standardSize;
|
||||||
@@ -139,64 +156,69 @@ class _CartonEditorForPackageState extends State<CartonEditorForPackage> {
|
|||||||
));
|
));
|
||||||
} else if (step.stepType == StepType.PACKAGES) {
|
} else if (step.stepType == StepType.PACKAGES) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Text("PACKAGES"),
|
child: PackageSelectionWidget(
|
||||||
// child: CartonSelectionWidget(
|
sender: widget.sender,
|
||||||
// shipment: _shipment!,
|
consignee: widget.consignee,
|
||||||
// cartons: _cartions,
|
|
||||||
// onContinue: (cartons) {
|
|
||||||
// setState(() {
|
|
||||||
// _cartions = List.from(cartons);
|
|
||||||
// currentStep += 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// onPrevious: (cartons) {
|
|
||||||
// setState(() {
|
|
||||||
// _cartions = List.from(cartons);
|
|
||||||
// currentStep -= 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
);
|
|
||||||
} else if (step.stepType == StepType.CARGOS) {
|
|
||||||
return Expanded(
|
|
||||||
child: Text("cargos"),
|
|
||||||
// child: CartonSelectionWidget(
|
|
||||||
// shipment: _shipment!,
|
|
||||||
// cartons: _cartions,
|
|
||||||
// onContinue: (cartons) {
|
|
||||||
// setState(() {
|
|
||||||
// _cartions = List.from(cartons);
|
|
||||||
// currentStep += 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// onPrevious: (cartons) {
|
|
||||||
// setState(() {
|
|
||||||
// _cartions = List.from(cartons);
|
|
||||||
// currentStep -= 1;
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
// ),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return Expanded(
|
|
||||||
child: MixCartonSubmit(
|
|
||||||
cartonSizeType: _cartonSizeType,
|
|
||||||
standardSize: _standardSize,
|
|
||||||
length: _length,
|
|
||||||
width: _width,
|
|
||||||
height: _height,
|
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
cartons: _cartions,
|
packages: _packages,
|
||||||
onCreate: () {
|
onContinue: (packages) {
|
||||||
_create();
|
|
||||||
},
|
|
||||||
onPrevious: () {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
|
_packages = List.from(packages);
|
||||||
|
currentStep += 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onPrevious: (packages) {
|
||||||
|
setState(() {
|
||||||
|
_packages = List.from(packages);
|
||||||
currentStep -= 1;
|
currentStep -= 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else if (step.stepType == StepType.CARGOS) {
|
||||||
|
return Expanded(
|
||||||
|
child: CargoWidget(
|
||||||
|
sender: widget.sender,
|
||||||
|
consignee: widget.consignee,
|
||||||
|
cargoTypes: _cargoTypes,
|
||||||
|
customDuties: _customDuties,
|
||||||
|
onContinue: (cargoTypes, customDuties) {
|
||||||
|
setState(() {
|
||||||
|
_cargoTypes = List.from(cargoTypes);
|
||||||
|
_customDuties = List.from(customDuties);
|
||||||
|
currentStep += 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onPrevious: (cargoTypes, customDuties) {
|
||||||
|
setState(() {
|
||||||
|
_cargoTypes = List.from(cargoTypes);
|
||||||
|
_customDuties = List.from(customDuties);
|
||||||
|
currentStep -= 1;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return Expanded(
|
||||||
|
child: Text("Submit"),
|
||||||
|
// child: MixCartonSubmit(
|
||||||
|
// cartonSizeType: _cartonSizeType,
|
||||||
|
// standardSize: _standardSize,
|
||||||
|
// length: _length,
|
||||||
|
// width: _width,
|
||||||
|
// height: _height,
|
||||||
|
// shipment: _shipment!,
|
||||||
|
// cartons: _packages,
|
||||||
|
// onCreate: () {
|
||||||
|
// _create();
|
||||||
|
// },
|
||||||
|
// onPrevious: () {
|
||||||
|
// setState(() {
|
||||||
|
// currentStep -= 1;
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// ),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,14 @@ import '../widgets/box_size_picker.dart';
|
|||||||
import '../widgets/continue_button.dart';
|
import '../widgets/continue_button.dart';
|
||||||
import '../widgets/display_text.dart';
|
import '../widgets/display_text.dart';
|
||||||
import '../widgets/local_dropdown.dart';
|
import '../widgets/local_dropdown.dart';
|
||||||
|
import '../widgets/local_radio_buttons.dart';
|
||||||
import '../widgets/local_text.dart';
|
import '../widgets/local_text.dart';
|
||||||
import '../widgets/local_title.dart';
|
import '../widgets/local_title.dart';
|
||||||
import '../widgets/previous_button.dart';
|
import '../widgets/previous_button.dart';
|
||||||
|
|
||||||
typedef OnPrevious = Function();
|
typedef OnPrevious = Function();
|
||||||
|
|
||||||
typedef OnContinue = Function(FcsShipment shipment, String cartonSizeType,
|
typedef OnContinue = Function(String deliveryType,FcsShipment shipment, String cartonSizeType,
|
||||||
{CartonSize? standardSize, double? length, double? width, double? height});
|
{CartonSize? standardSize, double? length, double? width, double? height});
|
||||||
|
|
||||||
class CartonSizeWidget extends StatefulWidget {
|
class CartonSizeWidget extends StatefulWidget {
|
||||||
@@ -28,6 +29,7 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
final OnContinue? onContinue;
|
final OnContinue? onContinue;
|
||||||
final User sender;
|
final User sender;
|
||||||
final User consignee;
|
final User consignee;
|
||||||
|
final String deliveryType;
|
||||||
final FcsShipment? shipment;
|
final FcsShipment? shipment;
|
||||||
final String cartonSizeType;
|
final String cartonSizeType;
|
||||||
final CartonSize? standardSize;
|
final CartonSize? standardSize;
|
||||||
@@ -46,7 +48,8 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
this.width,
|
this.width,
|
||||||
this.height,
|
this.height,
|
||||||
required this.sender,
|
required this.sender,
|
||||||
required this.consignee})
|
required this.consignee,
|
||||||
|
required this.deliveryType})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -54,11 +57,14 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
||||||
|
List<String> _deliveryTypes = [delivery_caton, pickup_carton];
|
||||||
|
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
String _cartionSizeType = standardCarton;
|
String _cartionSizeType = standardCarton;
|
||||||
|
|
||||||
List<FcsShipment> _shipments = [];
|
List<FcsShipment> _shipments = [];
|
||||||
CartonSize? _selectStandardSize;
|
CartonSize? _selectStandardSize;
|
||||||
|
late String _selectedDeliveryType;
|
||||||
|
|
||||||
TextEditingController _widthController = new TextEditingController();
|
TextEditingController _widthController = new TextEditingController();
|
||||||
TextEditingController _heightController = new TextEditingController();
|
TextEditingController _heightController = new TextEditingController();
|
||||||
@@ -71,6 +77,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() async {
|
_init() async {
|
||||||
|
_selectedDeliveryType = widget.deliveryType;
|
||||||
_shipment = widget.shipment;
|
_shipment = widget.shipment;
|
||||||
_cartionSizeType = widget.cartonSizeType;
|
_cartionSizeType = widget.cartonSizeType;
|
||||||
|
|
||||||
@@ -104,17 +111,21 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
text: widget.sender.name,
|
text: widget.sender.name,
|
||||||
labelTextKey: "box.sender.title",
|
labelTextKey: "box.sender.title",
|
||||||
iconData: MaterialCommunityIcons.account_arrow_right,
|
iconData: MaterialCommunityIcons.account_arrow_right,
|
||||||
|
subText: Text(widget.sender.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
);
|
);
|
||||||
|
|
||||||
final consigneeBox = DisplayText(
|
final consigneeBox = DisplayText(
|
||||||
text: widget.consignee.name,
|
text: widget.consignee.name,
|
||||||
labelTextKey: "box.consignee.title",
|
labelTextKey: "box.consignee.title",
|
||||||
iconData: MaterialCommunityIcons.account_arrow_left,
|
iconData: MaterialCommunityIcons.account_arrow_left,
|
||||||
|
subText: Text(widget.consignee.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
);
|
);
|
||||||
|
|
||||||
final userRow = Row(
|
final userRow = Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(
|
Expanded(
|
||||||
child: senderBox,
|
child: senderBox,
|
||||||
flex: 2,
|
flex: 2,
|
||||||
),
|
),
|
||||||
@@ -122,6 +133,15 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final deliveryTypeBox = LocalRadioButtons(
|
||||||
|
values: _deliveryTypes,
|
||||||
|
selectedValue: _selectedDeliveryType,
|
||||||
|
callback: (String? v) {
|
||||||
|
setState(() {
|
||||||
|
_selectedDeliveryType = v!;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
final continueBtn = ContinueButton(onTap: () {
|
final continueBtn = ContinueButton(onTap: () {
|
||||||
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;
|
||||||
@@ -137,7 +157,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
!isCustomSize &&
|
!isCustomSize &&
|
||||||
!isNoneDefinedSize) {
|
!isNoneDefinedSize) {
|
||||||
showMsgDialog(
|
showMsgDialog(
|
||||||
context, "Error", "Please select the standard cartion size");
|
context, "Error", "Please select the standard carton size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,12 +165,12 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
!isStandardSize &&
|
!isStandardSize &&
|
||||||
!isNoneDefinedSize &&
|
!isNoneDefinedSize &&
|
||||||
(l == 0 || w == 0 || h == 0)) {
|
(l == 0 || w == 0 || h == 0)) {
|
||||||
showMsgDialog(context, "Error", "Please add the cartion size");
|
showMsgDialog(context, "Error", "Please add the carton size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.onContinue != null) {
|
if (widget.onContinue != null) {
|
||||||
widget.onContinue!(_shipment!, _cartionSizeType,
|
widget.onContinue!(_selectedDeliveryType,_shipment!, _cartionSizeType,
|
||||||
standardSize: _selectStandardSize, length: l, width: w, height: h);
|
standardSize: _selectStandardSize, length: l, width: w, height: h);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -346,13 +366,18 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
userRow,
|
userRow,
|
||||||
|
LocalTitle(textKey: "box.select.delivery", topPadding: 10),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
deliveryTypeBox,
|
||||||
|
const SizedBox(height: 5),
|
||||||
LocalTitle(textKey: "box.select_carton_size"),
|
LocalTitle(textKey: "box.select_carton_size"),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
cartonSizedBox,
|
cartonSizedBox,
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
LocalTitle(textKey: "box.select_shipment"),
|
LocalTitle(textKey: "box.select_shipment"),
|
||||||
const SizedBox(height: 5),
|
const SizedBox(height: 5),
|
||||||
fcsShipmentsBox
|
fcsShipmentsBox,
|
||||||
|
const SizedBox(height: 30)
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
127
lib/pages/carton/custom_duty_addition.dart
Normal file
127
lib/pages/carton/custom_duty_addition.dart
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
import 'package:fcs/domain/entities/cargo_type.dart';
|
||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:fcs/pages/main/util.dart';
|
||||||
|
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
|
||||||
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
|
import 'package:fcs/pages/widgets/local_title.dart';
|
||||||
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../widgets/local_button.dart';
|
||||||
|
|
||||||
|
class CustomDutyAddition extends StatefulWidget {
|
||||||
|
final List<CargoType> customDuties;
|
||||||
|
|
||||||
|
const CustomDutyAddition({super.key, required this.customDuties});
|
||||||
|
@override
|
||||||
|
_CustomDutyAdditionState createState() => _CustomDutyAdditionState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CustomDutyAdditionState extends State<CustomDutyAddition> {
|
||||||
|
bool _isLoading = false;
|
||||||
|
List<CargoType> customDuties = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
var shipmentRateModel =
|
||||||
|
Provider.of<ShipmentRateModel>(context, listen: false);
|
||||||
|
customDuties =
|
||||||
|
shipmentRateModel.rate.customDuties.map((e) => e.clone()).toList();
|
||||||
|
|
||||||
|
for (var p in customDuties) {
|
||||||
|
if (widget.customDuties.any((e) => e.id == p.id)) {
|
||||||
|
p.isChecked = true;
|
||||||
|
} else {
|
||||||
|
p.isChecked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> getCargoRowList(List<CargoType> _c) {
|
||||||
|
return _c.map((c) {
|
||||||
|
return Container(
|
||||||
|
child: Container(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.only(left: 10.0, right: 5.0, top: 3.0, bottom: 3.0),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
c.isChecked = !c.isChecked;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
children: <Widget>[
|
||||||
|
Checkbox(
|
||||||
|
value: c.isChecked,
|
||||||
|
activeColor: primaryColor,
|
||||||
|
onChanged: (bool? check) {
|
||||||
|
setState(() {
|
||||||
|
c.isChecked = check ?? false;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
new Text(c.name ?? '', style: textStyle),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final saveBtn = Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
|
child: LocalButton(
|
||||||
|
textKey: "box.cargo.select.btn",
|
||||||
|
callBack: () {
|
||||||
|
List<CargoType> _cargos =
|
||||||
|
customDuties.where((c) => c.isChecked).toList();
|
||||||
|
if (_cargos.isEmpty) {
|
||||||
|
showMsgDialog(context, 'Error', "Please select the cargo type");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Navigator.pop(context, _cargos);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return LocalProgress(
|
||||||
|
inAsyncCall: _isLoading,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: LocalAppBar(
|
||||||
|
labelKey: 'box.select.cargo_type',
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
labelColor: primaryColor,
|
||||||
|
arrowColor: primaryColor),
|
||||||
|
body: Container(
|
||||||
|
padding: EdgeInsets.all(10),
|
||||||
|
child: ListView(
|
||||||
|
shrinkWrap: true,
|
||||||
|
children: <Widget>[
|
||||||
|
LocalTitle(
|
||||||
|
textKey: "box.select.cargo.title",
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: getCargoRowList(customDuties),
|
||||||
|
),
|
||||||
|
SizedBox(height: 30),
|
||||||
|
saveBtn,
|
||||||
|
SizedBox(height: 20),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,7 +37,7 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
LocalStep(lable: 'Cartons', stepType: StepType.CARTONS),
|
LocalStep(lable: 'Cartons', stepType: StepType.CARTONS),
|
||||||
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
||||||
];
|
];
|
||||||
List<Carton> _cartions = [];
|
List<Carton> _cartons = [];
|
||||||
|
|
||||||
int currentStep = 0;
|
int currentStep = 0;
|
||||||
double _length = 0;
|
double _length = 0;
|
||||||
@@ -146,16 +146,16 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
return Expanded(
|
return Expanded(
|
||||||
child: CartonSelectionWidget(
|
child: CartonSelectionWidget(
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
cartons: _cartions,
|
cartons: _cartons,
|
||||||
onContinue: (cartons) {
|
onContinue: (cartons) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartions = List.from(cartons);
|
_cartons = List.from(cartons);
|
||||||
currentStep += 1;
|
currentStep += 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onPrevious: (cartons) {
|
onPrevious: (cartons) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartions = List.from(cartons);
|
_cartons = List.from(cartons);
|
||||||
currentStep -= 1;
|
currentStep -= 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -170,7 +170,7 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
width: _width,
|
width: _width,
|
||||||
height: _height,
|
height: _height,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
cartons: _cartions,
|
cartons: _cartons,
|
||||||
onCreate: () {
|
onCreate: () {
|
||||||
_create();
|
_create();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
!isCustomSize &&
|
!isCustomSize &&
|
||||||
!isNoneDefinedSize) {
|
!isNoneDefinedSize) {
|
||||||
showMsgDialog(
|
showMsgDialog(
|
||||||
context, "Error", "Please select the standard cartion size");
|
context, "Error", "Please select the standard carton size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
!isStandardSize &&
|
!isStandardSize &&
|
||||||
!isNoneDefinedSize &&
|
!isNoneDefinedSize &&
|
||||||
(l == 0 || w == 0 || h == 0)) {
|
(l == 0 || w == 0 || h == 0)) {
|
||||||
showMsgDialog(context, "Error", "Please add the cartion size");
|
showMsgDialog(context, "Error", "Please add the carton size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class CartonSelectionModel extends BaseModel {
|
|||||||
bool reachEnd = false;
|
bool reachEnd = false;
|
||||||
List<Carton> cartons = [];
|
List<Carton> cartons = [];
|
||||||
|
|
||||||
bool isLoading= false;
|
bool isLoading = false;
|
||||||
|
|
||||||
// for default carton
|
// for default carton
|
||||||
DocumentSnapshot? _lastDocument;
|
DocumentSnapshot? _lastDocument;
|
||||||
@@ -102,7 +102,7 @@ class CartonSelectionModel extends BaseModel {
|
|||||||
String path = "/$cartons_collection";
|
String path = "/$cartons_collection";
|
||||||
Query query = FirebaseFirestore.instance
|
Query query = FirebaseFirestore.instance
|
||||||
.collection(path)
|
.collection(path)
|
||||||
.where("fcs_shipment_id", isEqualTo: shipmentId)
|
// .where("fcs_shipment_id", isEqualTo: shipmentId)
|
||||||
// .where("status", isEqualTo: carton_processing_status)
|
// .where("status", isEqualTo: carton_processing_status)
|
||||||
// .where("carton_type", isEqualTo: carton_mix_box)
|
// .where("carton_type", isEqualTo: carton_mix_box)
|
||||||
.where("is_deleted", isEqualTo: false)
|
.where("is_deleted", isEqualTo: false)
|
||||||
@@ -134,7 +134,7 @@ class CartonSelectionModel extends BaseModel {
|
|||||||
notifyListeners();
|
notifyListeners();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.warning("error:$e");
|
log.warning("error:$e");
|
||||||
}finally{
|
} finally {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
170
lib/pages/carton/model/package_selection_model.dart
Normal file
170
lib/pages/carton/model/package_selection_model.dart
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../../../domain/constants.dart';
|
||||||
|
import '../../../domain/entities/package.dart';
|
||||||
|
import '../../main/model/base_model.dart';
|
||||||
|
|
||||||
|
class PackageSelectionModel extends BaseModel {
|
||||||
|
final log = Logger("PackageSelectionModel");
|
||||||
|
// for search
|
||||||
|
String query = "";
|
||||||
|
int offset = 0;
|
||||||
|
bool reachEnd = false;
|
||||||
|
List<Package> packages = [];
|
||||||
|
|
||||||
|
bool isLoading = false;
|
||||||
|
|
||||||
|
// for default package
|
||||||
|
DocumentSnapshot? _lastDocument;
|
||||||
|
bool ended = false;
|
||||||
|
|
||||||
|
List<Package> selectedPackageList = [];
|
||||||
|
|
||||||
|
Timer? t;
|
||||||
|
search(String term,
|
||||||
|
{bool imm = false,
|
||||||
|
required String shipmentId,
|
||||||
|
required String senderId,
|
||||||
|
required String consigneeId}) async {
|
||||||
|
query = term;
|
||||||
|
packages.clear();
|
||||||
|
offset = 0;
|
||||||
|
reachEnd = false;
|
||||||
|
t?.cancel();
|
||||||
|
t = Timer(Duration(milliseconds: imm ? 0 : 800), () async {
|
||||||
|
await loadMoreSearch(
|
||||||
|
term: term,
|
||||||
|
shipmentId: shipmentId,
|
||||||
|
consigneeId: consigneeId,
|
||||||
|
senderId: senderId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadMoreSearch(
|
||||||
|
{required String term,
|
||||||
|
required String shipmentId,
|
||||||
|
required String senderId,
|
||||||
|
required String consigneeId}) async {
|
||||||
|
if (term == "") {
|
||||||
|
await _refresh(
|
||||||
|
shipmentId: shipmentId, senderId: senderId, consigneeId: consigneeId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// int rowPerPage = 21;
|
||||||
|
// List<Carton> list = [];
|
||||||
|
// SearchPara searchPara = SearchPara(filters: [], term: term);
|
||||||
|
// isLoading = true;
|
||||||
|
|
||||||
|
// var path =
|
||||||
|
// "/search/$cartons_collection/${searchPara.escapeTerm}/$rowPerPage/$offset/${searchPara.escapeFilters}";
|
||||||
|
|
||||||
|
// var result = await requestAPI(path, "GET",
|
||||||
|
// token: await getToken(), url: Config.instance.searchURL);
|
||||||
|
|
||||||
|
// if (result != null) {
|
||||||
|
// for (var row in result) {
|
||||||
|
// var item = ArtistExt.fromMapForSearch(row);
|
||||||
|
// list.add(item);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// for (var p in list) {
|
||||||
|
// selectedArtistList.contains(p)
|
||||||
|
// ? p.isSelected = true
|
||||||
|
// : p.isSelected = false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// artists.addAll(list);
|
||||||
|
// offset += rowPerPage;
|
||||||
|
// if (list.length < rowPerPage) {
|
||||||
|
// reachEnd = true;
|
||||||
|
// }
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
addDefaultPackages(
|
||||||
|
{required String shipmentId,
|
||||||
|
required String senderId,
|
||||||
|
required String consigneeId}) async {
|
||||||
|
packages.clear();
|
||||||
|
await _refresh(
|
||||||
|
shipmentId: shipmentId, senderId: senderId, consigneeId: consigneeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
selectPackage(Package a) {
|
||||||
|
if (a.isChecked) {
|
||||||
|
selectedPackageList.add(a);
|
||||||
|
} else {
|
||||||
|
selectedPackageList.remove(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _refresh(
|
||||||
|
{required String shipmentId,
|
||||||
|
required String senderId,
|
||||||
|
required String consigneeId}) async {
|
||||||
|
packages.clear();
|
||||||
|
_lastDocument = null;
|
||||||
|
ended = false;
|
||||||
|
await loadMoreData(
|
||||||
|
shipmentId: shipmentId, senderId: senderId, consigneeId: consigneeId);
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loadMoreData(
|
||||||
|
{required String shipmentId,
|
||||||
|
required String senderId,
|
||||||
|
required String consigneeId}) async {
|
||||||
|
int rowPerPage = 20;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isLoading = true;
|
||||||
|
String path = "/$packages_collection";
|
||||||
|
Query query = FirebaseFirestore.instance
|
||||||
|
.collection(path)
|
||||||
|
// .where("fcs_shipment_id", isEqualTo: shipmentId)
|
||||||
|
// .where("status", isEqualTo: package_processed_status)
|
||||||
|
.where("user_id", whereIn: [senderId, consigneeId])
|
||||||
|
.where("is_deleted", isEqualTo: false)
|
||||||
|
.orderBy("created_date", descending: true);
|
||||||
|
|
||||||
|
if (_lastDocument != null) {
|
||||||
|
query = query.startAfterDocument(_lastDocument!);
|
||||||
|
}
|
||||||
|
|
||||||
|
QuerySnapshot querySnap = await query.limit(rowPerPage).get();
|
||||||
|
|
||||||
|
if (querySnap.docs.isEmpty) return;
|
||||||
|
_lastDocument = querySnap.docs[querySnap.docs.length - 1];
|
||||||
|
|
||||||
|
List<Package> list = querySnap.docs.map((documentSnapshot) {
|
||||||
|
var p = Package.fromMap(documentSnapshot.data() as Map<String, dynamic>,
|
||||||
|
documentSnapshot.id);
|
||||||
|
return p;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
for (var p in list) {
|
||||||
|
selectedPackageList.contains(p)
|
||||||
|
? p.isChecked = true
|
||||||
|
: p.isChecked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
packages.addAll(list);
|
||||||
|
if (list.length < rowPerPage) ended = true;
|
||||||
|
notifyListeners();
|
||||||
|
} catch (e) {
|
||||||
|
log.warning("error:$e");
|
||||||
|
} finally {
|
||||||
|
isLoading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSelection() {
|
||||||
|
selectedPackageList.clear();
|
||||||
|
packages.clear();
|
||||||
|
query = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
120
lib/pages/carton/package_selection_result.dart
Normal file
120
lib/pages/carton/package_selection_result.dart
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../../helpers/theme.dart';
|
||||||
|
import '../../domain/entities/package.dart';
|
||||||
|
import 'model/package_selection_model.dart';
|
||||||
|
|
||||||
|
typedef OnAction = Future<void> Function();
|
||||||
|
final NumberFormat numberFormatter = NumberFormat("#,###");
|
||||||
|
|
||||||
|
class PackageSelectionResult extends StatelessWidget {
|
||||||
|
final bool isLoadingMore;
|
||||||
|
final OnAction onLoadMore;
|
||||||
|
final OnAction onRefresh;
|
||||||
|
final Function(Package)? onTap;
|
||||||
|
final ScrollController controller;
|
||||||
|
|
||||||
|
const PackageSelectionResult(
|
||||||
|
{super.key,
|
||||||
|
required this.isLoadingMore,
|
||||||
|
required this.onLoadMore,
|
||||||
|
required this.onRefresh,
|
||||||
|
this.onTap,
|
||||||
|
required this.controller});
|
||||||
|
|
||||||
|
bool _scrollNotification(ScrollNotification scrollInfo) {
|
||||||
|
if (!isLoadingMore &&
|
||||||
|
scrollInfo.metrics.pixels == scrollInfo.metrics.maxScrollExtent) {
|
||||||
|
onLoadMore();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var model = context.watch<PackageSelectionModel>();
|
||||||
|
List<Package> searchResults = model.packages;
|
||||||
|
|
||||||
|
return searchResults.isEmpty && !model.isLoading
|
||||||
|
? Center(
|
||||||
|
child: LocalText(context, 'box.no_package',
|
||||||
|
color: Colors.black, fontSize: 15))
|
||||||
|
: Column(children: [
|
||||||
|
Expanded(
|
||||||
|
child: NotificationListener<ScrollNotification>(
|
||||||
|
onNotification: _scrollNotification,
|
||||||
|
child: RefreshIndicator(
|
||||||
|
color: primaryColor,
|
||||||
|
onRefresh: () => onRefresh(),
|
||||||
|
child: ListView.builder(
|
||||||
|
controller: controller,
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
Package package = searchResults[index];
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 5, bottom: 5),
|
||||||
|
child: InkWell(
|
||||||
|
onTap: () {
|
||||||
|
if (onTap != null) {
|
||||||
|
onTap!(package);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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: new Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 8.0),
|
||||||
|
child: new Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
new Text(package.trackingID ?? "",
|
||||||
|
style: new TextStyle(
|
||||||
|
fontSize: 15.0,
|
||||||
|
color: Colors.black)),
|
||||||
|
new Text(
|
||||||
|
package.cartonIds.isEmpty
|
||||||
|
? "-"
|
||||||
|
: "${numberFormatter.format(package.cartonIds.length)} Boxes",
|
||||||
|
style: new TextStyle(
|
||||||
|
fontSize: 15.0,
|
||||||
|
color: Colors.grey),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
package.isChecked
|
||||||
|
? Icon(Icons.check, color: primaryColor)
|
||||||
|
: const SizedBox()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
itemCount: searchResults.length)),
|
||||||
|
)),
|
||||||
|
Container(
|
||||||
|
height: isLoadingMore ? 50.0 : 0,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: const Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
valueColor: AlwaysStoppedAnimation<Color>(primaryColor)),
|
||||||
|
)),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
289
lib/pages/carton/package_selection_widget.dart
Normal file
289
lib/pages/carton/package_selection_widget.dart
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
||||||
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:flutter/material.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/barcode_scanner.dart';
|
||||||
|
import '../widgets/continue_button.dart';
|
||||||
|
import '../widgets/display_text.dart';
|
||||||
|
import '../widgets/local_title.dart';
|
||||||
|
import '../widgets/previous_button.dart';
|
||||||
|
import 'model/carton_selection_model.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 PackageSelectionWidget extends StatefulWidget {
|
||||||
|
final User sender;
|
||||||
|
final User consignee;
|
||||||
|
final FcsShipment shipment;
|
||||||
|
final List<Package> packages;
|
||||||
|
final OnPrevious? onPrevious;
|
||||||
|
final OnContinue? onContinue;
|
||||||
|
|
||||||
|
const PackageSelectionWidget({
|
||||||
|
Key? key,
|
||||||
|
required this.packages,
|
||||||
|
this.onPrevious,
|
||||||
|
this.onContinue,
|
||||||
|
required this.shipment,
|
||||||
|
required this.sender,
|
||||||
|
required this.consignee,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<PackageSelectionWidget> createState() => _PackageSelectionWidgetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
String _query = "";
|
||||||
|
bool _isLoadMore = false;
|
||||||
|
final _scrollController = ScrollController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() {
|
||||||
|
var searchModel = context.read<PackageSelectionModel>();
|
||||||
|
searchModel.addDefaultPackages(
|
||||||
|
shipmentId: widget.shipment.id!,
|
||||||
|
consigneeId: widget.consignee.id!,
|
||||||
|
senderId: widget.sender.id!);
|
||||||
|
|
||||||
|
_controller.text = searchModel.query;
|
||||||
|
_query = searchModel.query;
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didUpdateWidget(covariant PackageSelectionWidget oldWidget) {
|
||||||
|
_init();
|
||||||
|
super.didUpdateWidget(oldWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _loadMoreData() async {
|
||||||
|
if (_isLoadMore) return;
|
||||||
|
var model = context.read<PackageSelectionModel>();
|
||||||
|
if (model.reachEnd || model.ended) return;
|
||||||
|
setState(() {
|
||||||
|
_isLoadMore = true;
|
||||||
|
});
|
||||||
|
if (_query != "") {
|
||||||
|
await model.loadMoreSearch(
|
||||||
|
term: _query,
|
||||||
|
shipmentId: widget.shipment.id!,
|
||||||
|
consigneeId: widget.consignee.id!,
|
||||||
|
senderId: widget.sender.id!);
|
||||||
|
} else {
|
||||||
|
await model.loadMoreData(
|
||||||
|
shipmentId: widget.shipment.id!,
|
||||||
|
consigneeId: widget.consignee.id!,
|
||||||
|
senderId: widget.sender.id!);
|
||||||
|
}
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_isLoadMore = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var model = context.watch<PackageSelectionModel>();
|
||||||
|
List<Package> searchResults = model.packages;
|
||||||
|
List<Package> selectedPackageList = model.selectedPackageList;
|
||||||
|
|
||||||
|
final senderBox = DisplayText(
|
||||||
|
text: widget.sender.name,
|
||||||
|
labelTextKey: "box.sender.title",
|
||||||
|
iconData: MaterialCommunityIcons.account_arrow_right,
|
||||||
|
subText: Text(widget.sender.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final consigneeBox = DisplayText(
|
||||||
|
text: widget.consignee.name,
|
||||||
|
labelTextKey: "box.consignee.title",
|
||||||
|
iconData: MaterialCommunityIcons.account_arrow_left,
|
||||||
|
subText: Text(widget.consignee.fcsID!,
|
||||||
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
|
);
|
||||||
|
|
||||||
|
final userRow = Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: senderBox,
|
||||||
|
flex: 2,
|
||||||
|
),
|
||||||
|
Flexible(child: consigneeBox)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
final continueBtn = ContinueButton(
|
||||||
|
onTap: () {
|
||||||
|
if (selectedPackageList.isEmpty || searchResults.isEmpty) {
|
||||||
|
showMsgDialog(context, 'Error', "Please select the packages");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget.onContinue != null) {
|
||||||
|
widget.onContinue!(selectedPackageList);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
|
if (widget.onPrevious != null) {
|
||||||
|
widget.onPrevious!(selectedPackageList);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final searchBox = SizedBox(
|
||||||
|
height: 40,
|
||||||
|
child: TextField(
|
||||||
|
controller: _controller,
|
||||||
|
cursorColor: primaryColor,
|
||||||
|
onSubmitted: (value) {
|
||||||
|
setState(() {
|
||||||
|
_query = value;
|
||||||
|
});
|
||||||
|
_search(imm: true);
|
||||||
|
},
|
||||||
|
onChanged: (v) {
|
||||||
|
setState(() {
|
||||||
|
_query = v;
|
||||||
|
});
|
||||||
|
_search();
|
||||||
|
},
|
||||||
|
decoration: InputDecoration(
|
||||||
|
enabledBorder: const OutlineInputBorder(
|
||||||
|
borderSide: BorderSide(color: labelColor),
|
||||||
|
),
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5.0),
|
||||||
|
borderSide:
|
||||||
|
BorderSide(color: labelColor.withOpacity(0.3), width: 0)),
|
||||||
|
focusedBorder: const OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(5.0)),
|
||||||
|
borderSide: BorderSide(color: labelColor),
|
||||||
|
),
|
||||||
|
hintText: "Search by tracking number",
|
||||||
|
hintStyle: const TextStyle(
|
||||||
|
color: Colors.grey,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.normal),
|
||||||
|
suffixIcon: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
InkResponse(
|
||||||
|
radius: 20,
|
||||||
|
onTap: () {
|
||||||
|
_scan(context);
|
||||||
|
},
|
||||||
|
child: const Icon(Icons.qr_code_scanner,
|
||||||
|
color: Colors.black87)),
|
||||||
|
IconButton(
|
||||||
|
splashRadius: 20,
|
||||||
|
onPressed: () {
|
||||||
|
setState(() {
|
||||||
|
_controller.clear();
|
||||||
|
_query = "";
|
||||||
|
});
|
||||||
|
_search();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.close, color: Colors.black87)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
contentPadding: const EdgeInsets.all(10),
|
||||||
|
filled: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(left: 10, right: 10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
userRow,
|
||||||
|
LocalTitle(textKey: "box.select.package", topPadding: 10),
|
||||||
|
const SizedBox(height: 10),
|
||||||
|
searchBox,
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: PackageSelectionResult(
|
||||||
|
controller: _scrollController,
|
||||||
|
isLoadingMore: _isLoadMore,
|
||||||
|
onLoadMore: _loadMoreData,
|
||||||
|
onRefresh: () async {
|
||||||
|
_init();
|
||||||
|
},
|
||||||
|
onTap: (a) async {
|
||||||
|
setState(() {
|
||||||
|
a.isChecked = !a.isChecked;
|
||||||
|
});
|
||||||
|
context.read<PackageSelectionModel>().selectPackage(a);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
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)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_scan(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
String? barcode = await scanBarcode();
|
||||||
|
if (barcode != null) {
|
||||||
|
setState(() {
|
||||||
|
_controller.text = barcode;
|
||||||
|
_query = barcode;
|
||||||
|
});
|
||||||
|
await _search();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, 'Error', e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_search({bool imm = false}) async {
|
||||||
|
try {
|
||||||
|
await context
|
||||||
|
.read<CartonSelectionModel>()
|
||||||
|
.search(_query, imm: imm, shipmentId: widget.shipment.id!);
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, 'Error', e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,10 +5,11 @@ import 'package:flutter/material.dart';
|
|||||||
class LocalTitle extends StatelessWidget {
|
class LocalTitle extends StatelessWidget {
|
||||||
final String? textKey;
|
final String? textKey;
|
||||||
final Widget? trailing;
|
final Widget? trailing;
|
||||||
|
final double topPadding;
|
||||||
final List<String>? translationVariables;
|
final List<String>? translationVariables;
|
||||||
|
|
||||||
const LocalTitle(
|
const LocalTitle(
|
||||||
{Key? key, this.textKey, this.trailing, this.translationVariables})
|
{Key? key, this.textKey, this.trailing, this.translationVariables,this.topPadding = 18})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -17,7 +18,7 @@ class LocalTitle extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(top: 18),
|
padding: EdgeInsets.only(top: topPadding),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
LocalText(context, textKey!,
|
LocalText(context, textKey!,
|
||||||
|
|||||||
Reference in New Issue
Block a user