update package detal list and update cargo type input in carton section
This commit is contained in:
@@ -52,9 +52,9 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
List<TextEditingController> surchargeControllers = [];
|
||||
|
||||
bool get hasValueTotalWeight =>
|
||||
totalCtl.text.isNotEmpty && totalCtl.text != '0';
|
||||
totalCtl.text.isNotEmpty && totalCtl.text != '0.00';
|
||||
bool get hasValueCargoes =>
|
||||
_cargoTypes.isNotEmpty && _cargoTypes.every((e) => e.weight != 0);
|
||||
_cargoTypes.isNotEmpty && _cargoTypes.every((e) => e.weight != 0.00);
|
||||
|
||||
double get actualTotalWeight =>
|
||||
_cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||
@@ -72,11 +72,12 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
_cargoTypes = List.from(widget.cargoTypes);
|
||||
for (var e in _cargoTypes) {
|
||||
var editor = TextEditingController();
|
||||
editor.text = removeTrailingZeros(e.weight);
|
||||
editor.text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(e.weight)) ?? 0);
|
||||
editor.addListener(inputChangeListener);
|
||||
cargoTypeControllers.add(editor);
|
||||
}
|
||||
onUpdated();
|
||||
_onPopulate();
|
||||
} else {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_openCargoTypeSelection();
|
||||
@@ -108,11 +109,14 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
|
||||
for (var e in _cargoTypes) {
|
||||
var editor = TextEditingController();
|
||||
editor.text = '0';
|
||||
editor.text = '0.00';
|
||||
editor.addListener(inputChangeListener);
|
||||
cargoTypeControllers.add(editor);
|
||||
}
|
||||
|
||||
totalCtl.text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(actualTotalWeight)) ?? 0);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
@@ -133,9 +137,10 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
return emptyFields;
|
||||
}
|
||||
|
||||
void onUpdated() {
|
||||
void _onPopulate() {
|
||||
if (!hasValueTotalWeight && hasValueCargoes) {
|
||||
totalCtl.text = removeTrailingZeros(actualTotalWeight);
|
||||
totalCtl.text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(actualTotalWeight)) ?? 0);
|
||||
error = null;
|
||||
} else {
|
||||
// auto populate remaining value
|
||||
@@ -155,8 +160,8 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
_cargoTypes.asMap().entries.forEach((e) {
|
||||
if (e.value.weight == 0) {
|
||||
e.value.weight = remainingWeight;
|
||||
cargoTypeControllers[e.key].text =
|
||||
removeTrailingZeros(e.value.weight);
|
||||
cargoTypeControllers[e.key].text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(e.value.weight)) ?? 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -168,6 +173,18 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
}
|
||||
}
|
||||
|
||||
void _onCheckTotalWeight(String value) {
|
||||
double totalWeight = double.tryParse(value) ?? 0;
|
||||
if (totalWeight != actualTotalWeight) {
|
||||
error = "Invalid total weight";
|
||||
} else {
|
||||
error = null;
|
||||
}
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final senderBox = userDisplayBox(context,
|
||||
@@ -208,19 +225,30 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
CargoTypeAddition(cargoTypes: _cargoTypes)));
|
||||
if (cargoType == null) return;
|
||||
|
||||
if (!cargoType.isMixCargo) {
|
||||
_cargoTypes.add(cargoType);
|
||||
}
|
||||
_cargoTypes.sort((a, b) => (a == b ? 0 : (a.isMixCargo ? 1 : -1)));
|
||||
|
||||
// add cargo type
|
||||
if (cargoType.isMixCargo) {
|
||||
_cargoTypes.add(cargoType);
|
||||
int lastTrueIndex =
|
||||
_cargoTypes.lastIndexWhere((e) => e.isMixCargo);
|
||||
if (lastTrueIndex != -1) {
|
||||
_cargoTypes.insert(lastTrueIndex + 1, cargoType);
|
||||
} else {
|
||||
_cargoTypes.add(cargoType);
|
||||
}
|
||||
} else {
|
||||
int lastFalseIndex =
|
||||
_cargoTypes.lastIndexWhere((e) => !e.isMixCargo);
|
||||
if (lastFalseIndex != -1) {
|
||||
_cargoTypes.insert(lastFalseIndex + 1, cargoType);
|
||||
} else {
|
||||
_cargoTypes.insert(0, cargoType);
|
||||
}
|
||||
}
|
||||
|
||||
cargoTypeControllers.clear();
|
||||
for (var e in _cargoTypes) {
|
||||
var editor = TextEditingController();
|
||||
editor.text = removeTrailingZeros(e.weight);
|
||||
editor.text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(e.weight)) ?? 0);
|
||||
editor.addListener(inputChangeListener);
|
||||
cargoTypeControllers.add(editor);
|
||||
}
|
||||
@@ -230,177 +258,53 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
}),
|
||||
);
|
||||
|
||||
final cargosBox = Padding(
|
||||
final totalWeightBox = Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
runSpacing: 25,
|
||||
children: _cargoTypes.asMap().entries.map((e) {
|
||||
var key = e.key;
|
||||
var c = e.value;
|
||||
return SizedBox(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.3,
|
||||
child: Column(
|
||||
child: Row(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
InkResponse(
|
||||
radius: 25,
|
||||
onTap: () {
|
||||
double totalWeight =
|
||||
double.tryParse(totalCtl.text) ?? 0;
|
||||
|
||||
if (actualTotalWeight > totalWeight) {
|
||||
error = "Exceed total weight";
|
||||
} else {
|
||||
double result = totalWeight - c.weight;
|
||||
totalCtl.text = removeTrailingZeros(result);
|
||||
}
|
||||
|
||||
_cargoTypes.removeAt(key);
|
||||
cargoTypeControllers.removeAt(key);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
child: Icon(Feather.minus_circle, color: labelColor)),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: inputTextFieldWidget(context,
|
||||
lableText: c.name ?? "",
|
||||
controller: cargoTypeControllers[key],
|
||||
onFieldSubmitted: (value) {
|
||||
_cargoTypes[e.key].weight =
|
||||
double.tryParse(value) ?? 0;
|
||||
onUpdated();
|
||||
},
|
||||
suffixIcon: InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
double totalWeight =
|
||||
(double.tryParse(totalCtl.text) ?? 0);
|
||||
|
||||
var list = _cargoTypes
|
||||
.where((e) => e.id != c.id)
|
||||
.toList();
|
||||
double resetValue = totalWeight -
|
||||
(list.fold(0,
|
||||
(sum, value) => sum + value.weight));
|
||||
setState(() {
|
||||
e.value.weight = resetValue;
|
||||
cargoTypeControllers[e.key].text =
|
||||
removeTrailingZeros(resetValue);
|
||||
});
|
||||
|
||||
onUpdated();
|
||||
},
|
||||
child: Icon(Ionicons.md_refresh_circle,
|
||||
color: labelColor, size: 22))),
|
||||
),
|
||||
c.isMixCargo
|
||||
? InkResponse(
|
||||
radius: 23,
|
||||
onTap: () async {
|
||||
List<CargoType>? cargoes = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => MixCargoTypeAdditionDialog(
|
||||
cargoTypes: c.mixCargoes));
|
||||
if (cargoes == null) return;
|
||||
setState(() {
|
||||
c.mixCargoes = List.from(cargoes);
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.add_circle,
|
||||
color: labelColor, size: 22))
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
c.mixCargoes.isEmpty
|
||||
? const SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Column(
|
||||
children: c.mixCargoes.map((e) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(width: 25),
|
||||
InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
c.mixCargoes.remove(e);
|
||||
});
|
||||
},
|
||||
child: Icon(Feather.minus_circle,
|
||||
color: labelColor, size: 20)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Text(e.name ?? ""),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
);
|
||||
|
||||
final totalWeightBox = 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, color: labelColor)),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: inputTextFieldWidget(context,
|
||||
lableText: "Total",
|
||||
controller: totalCtl, onFieldSubmitted: (neValue) {
|
||||
if (hasValueCargoes) {
|
||||
double totalWeight = double.tryParse(neValue) ?? 0;
|
||||
if (totalWeight < actualTotalWeight) {
|
||||
InkResponse(
|
||||
radius: 25,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
error = "Invalid total weight";
|
||||
totalCtl.clear();
|
||||
});
|
||||
_onCheckTotalWeight(totalCtl.text);
|
||||
},
|
||||
child: Icon(MaterialIcons.clear, color: labelColor)),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: inputTextFieldWidget(context,
|
||||
lableText: "Total",
|
||||
controller: totalCtl, onFieldSubmitted: (newValue) {
|
||||
if (hasValueCargoes) {
|
||||
_onCheckTotalWeight(newValue);
|
||||
} else {
|
||||
setState(() {
|
||||
error = null;
|
||||
});
|
||||
_onPopulate();
|
||||
}
|
||||
} else {
|
||||
onUpdated();
|
||||
}
|
||||
},
|
||||
suffixIcon: InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
totalCtl.text =
|
||||
removeTrailingZeros(actualTotalWeight);
|
||||
error = null;
|
||||
});
|
||||
},
|
||||
child: Icon(Ionicons.md_refresh_circle,
|
||||
color: labelColor, size: 22))),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
},
|
||||
suffixIcon: InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
totalCtl.text = twoDecimalFormatted(
|
||||
double.tryParse(removeTrailingZeros(
|
||||
actualTotalWeight)) ??
|
||||
0);
|
||||
error = null;
|
||||
});
|
||||
},
|
||||
child: Icon(Ionicons.md_refresh_circle,
|
||||
color: labelColor, size: 22))),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
final subchargeItemTitleBox = LocalTitle(
|
||||
@@ -481,17 +385,161 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
context, "Error", "Please insert surcharge item quantity");
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != null) {
|
||||
showMsgDialog(
|
||||
context, "Error", "Please add the right cargo type weight");
|
||||
return;
|
||||
}
|
||||
widget.onContinue!(_cargoTypes, _surchareItems);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
final previousBtn = PreviousButton(onTap: () {
|
||||
if (error != null) {
|
||||
showMsgDialog(
|
||||
context, "Error", "Please add the right cargo type weight");
|
||||
return;
|
||||
}
|
||||
if (widget.onPrevious != null) {
|
||||
widget.onPrevious!(_cargoTypes, _surchareItems);
|
||||
}
|
||||
});
|
||||
|
||||
Widget cargoesWidget(List<CargoType> items) {
|
||||
List<Widget> widgets = [];
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
var key = i;
|
||||
var c = items[i];
|
||||
|
||||
if (i > 0 && (!items[i - 1].isMixCargo && items[i].isMixCargo)) {
|
||||
widgets.add(Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 70),
|
||||
child: Divider(color: Colors.grey.shade300)));
|
||||
}
|
||||
|
||||
widgets.add(SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.3,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
InkResponse(
|
||||
radius: 25,
|
||||
onTap: () {
|
||||
_cargoTypes.removeAt(key);
|
||||
cargoTypeControllers.removeAt(key);
|
||||
|
||||
_onCheckTotalWeight(totalCtl.text);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
},
|
||||
child: Icon(Feather.minus_circle, color: labelColor)),
|
||||
const SizedBox(width: 10),
|
||||
Flexible(
|
||||
child: inputTextFieldWidget(context,
|
||||
lableText: c.name ?? "",
|
||||
controller: cargoTypeControllers[key],
|
||||
onFieldSubmitted: (value) {
|
||||
_cargoTypes[key].weight = double.tryParse(value) ?? 0;
|
||||
_onPopulate();
|
||||
},
|
||||
suffixIcon: InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
double totalWeight =
|
||||
(double.tryParse(totalCtl.text) ?? 0);
|
||||
|
||||
var list = _cargoTypes
|
||||
.where((e) => e.id != c.id)
|
||||
.toList();
|
||||
double sum = (list.fold(
|
||||
0, (sum, value) => sum + value.weight));
|
||||
|
||||
if (sum > totalWeight) {
|
||||
error = "Exceed total weight";
|
||||
} else {
|
||||
error = null;
|
||||
double resetValue = totalWeight - sum;
|
||||
|
||||
setState(() {
|
||||
c.weight = resetValue;
|
||||
cargoTypeControllers[key].text =
|
||||
twoDecimalFormatted(double.tryParse(
|
||||
removeTrailingZeros(
|
||||
resetValue)) ??
|
||||
0);
|
||||
});
|
||||
_onPopulate();
|
||||
}
|
||||
},
|
||||
child: Icon(Ionicons.md_refresh_circle,
|
||||
color: labelColor, size: 22))),
|
||||
),
|
||||
c.isMixCargo
|
||||
? InkResponse(
|
||||
radius: 23,
|
||||
onTap: () async {
|
||||
List<CargoType>? cargoes = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => MixCargoTypeAdditionDialog(
|
||||
cargoTypes: c.mixCargoes));
|
||||
if (cargoes == null) return;
|
||||
setState(() {
|
||||
c.mixCargoes = List.from(cargoes);
|
||||
});
|
||||
},
|
||||
child: Icon(Icons.add_circle,
|
||||
color: labelColor, size: 22))
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
c.mixCargoes.isEmpty
|
||||
? const SizedBox()
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Column(
|
||||
children: c.mixCargoes.map((e) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
const SizedBox(width: 25),
|
||||
InkResponse(
|
||||
radius: 23,
|
||||
onTap: () {
|
||||
setState(() {
|
||||
c.mixCargoes.remove(e);
|
||||
});
|
||||
},
|
||||
child: Icon(Feather.minus_circle,
|
||||
color: labelColor, size: 20)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10),
|
||||
child: Text(e.name ?? ""),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
)
|
||||
],
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
runSpacing: 25,
|
||||
children: widgets),
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -502,9 +550,13 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
const SizedBox(height: 8),
|
||||
userRow,
|
||||
cargoTitle,
|
||||
cargosBox,
|
||||
cargoesWidget(_cargoTypes),
|
||||
const SizedBox(height: 15),
|
||||
Divider(),
|
||||
_cargoTypes.isNotEmpty
|
||||
? Divider(
|
||||
color: Colors.grey.shade300,
|
||||
)
|
||||
: const SizedBox(),
|
||||
const SizedBox(height: 5),
|
||||
error != null
|
||||
? Text(
|
||||
@@ -553,7 +605,11 @@ class _CargoWidgetState extends State<CargoWidget> {
|
||||
onFieldSubmitted: onFieldSubmitted,
|
||||
readOnly: readOnly,
|
||||
decoration: InputDecoration(
|
||||
suffixIcon: suffixIcon,
|
||||
suffixIcon: Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: suffixIcon,
|
||||
),
|
||||
suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0),
|
||||
contentPadding: EdgeInsets.all(0),
|
||||
labelText: lableText,
|
||||
labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17),
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:fcs/domain/entities/package.dart';
|
||||
import 'package:fcs/helpers/theme.dart';
|
||||
import 'package:fcs/pages/carton/carton_image_upload_editor.dart';
|
||||
import 'package:fcs/pages/main/util.dart';
|
||||
import 'package:fcs/pages/package/model/package_model.dart';
|
||||
import 'package:fcs/pages/widgets/display_text.dart';
|
||||
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||
import 'package:fcs/pages/widgets/local_text.dart';
|
||||
@@ -28,6 +27,7 @@ import 'carton_package_editor.dart';
|
||||
import 'mix_carton/mix_carton_editor.dart';
|
||||
import 'mix_carton_detail_list.dart';
|
||||
import 'model/carton_model.dart';
|
||||
import 'model/package_selection_model.dart';
|
||||
import 'package_detail_list.dart';
|
||||
import 'print_qr_code_page.dart';
|
||||
|
||||
@@ -48,10 +48,11 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
List<CargoType> _cargoTypes = [];
|
||||
List<CargoType> _surchareItems = [];
|
||||
List<Carton> _mixCartons = [];
|
||||
List<Package> _packages = [];
|
||||
double totalWeight = 0.0;
|
||||
double totalSurchargeCount = 0.0;
|
||||
CartonSize? standardSize;
|
||||
|
||||
double _totalWeight = 0.0;
|
||||
int _packageCount = 0;
|
||||
|
||||
CartonSize? _standardSize;
|
||||
FcsShipment? _shipment;
|
||||
|
||||
@override
|
||||
@@ -77,7 +78,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
bool isStandartSize = sameLength && sameWidth && sameHeight;
|
||||
if (isStandartSize) {
|
||||
_carton.cartonSizeType = standardCarton;
|
||||
standardSize = cartonSizes.firstWhere((size) =>
|
||||
_standardSize = cartonSizes.firstWhere((size) =>
|
||||
size.length == _carton.length &&
|
||||
size.width == _carton.width &&
|
||||
size.height == _carton.height);
|
||||
@@ -89,32 +90,11 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
_carton.cartonSizeType = customCarton;
|
||||
}
|
||||
|
||||
if (widget.carton.fcsShipmentID != null &&
|
||||
widget.carton.fcsShipmentID != '') {
|
||||
var s = await context
|
||||
.read<FcsShipmentModel>()
|
||||
.getFcsShipment(widget.carton.fcsShipmentID!);
|
||||
_shipment = s;
|
||||
}
|
||||
await Future.wait(
|
||||
[_loadFcsShipment(), _loadPackageCount(), _loadMixCargoes()]);
|
||||
|
||||
if (_carton.cartonType == carton_from_packages) {
|
||||
_packages = await context
|
||||
.read<PackageModel>()
|
||||
.getPackagesByIds(_carton.packageIDs);
|
||||
}
|
||||
|
||||
if (_carton.cartonType == mix_carton) {
|
||||
_mixCartons = await context
|
||||
.read<CartonModel>()
|
||||
.getCartonsByIds(_carton.cartonIDs);
|
||||
_cargoTypes.sort((a, b) => a.name!.compareTo(b.name!));
|
||||
_surchareItems.sort((a, b) => a.name!.compareTo(b.name!));
|
||||
}
|
||||
|
||||
totalWeight =
|
||||
_totalWeight =
|
||||
_carton.cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||
totalSurchargeCount =
|
||||
_surchareItems.fold(0, (sum, value) => sum + value.qty);
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
}
|
||||
@@ -124,12 +104,50 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadFcsShipment() async {
|
||||
if (widget.carton.fcsShipmentID != null &&
|
||||
widget.carton.fcsShipmentID != '') {
|
||||
var s = await context
|
||||
.read<FcsShipmentModel>()
|
||||
.getFcsShipment(widget.carton.fcsShipmentID!);
|
||||
_shipment = s;
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadPackageCount() async {
|
||||
if (_carton.cartonType == carton_from_packages) {
|
||||
int? count = await context.read<PackageSelectionModel>().getPackageCount(
|
||||
senderId: widget.carton.senderID ?? "",
|
||||
consigneeId: widget.carton.consigneeID ?? "",
|
||||
shipmentId: widget.carton.fcsShipmentID ?? "");
|
||||
_packageCount = count ?? 0;
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _loadMixCargoes() async {
|
||||
if (_carton.cartonType == mix_carton) {
|
||||
_mixCartons =
|
||||
await context.read<CartonModel>().getCartonsByIds(_carton.cartonIDs);
|
||||
_cargoTypes.sort((a, b) => a.name!.compareTo(b.name!));
|
||||
_surchareItems.sort((a, b) => a.name!.compareTo(b.name!));
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var fromPackage = _carton.cartonType == carton_from_packages;
|
||||
|
||||
String? boxDimension = _carton.cartonSizeType == standardCarton
|
||||
? "${standardSize?.name} - ${standardSize?.length.toInt()}”x${standardSize?.width.toInt()}”x${standardSize?.height.toInt()}”"
|
||||
? "${_standardSize?.name} - ${_standardSize?.length.toInt()}”x${_standardSize?.width.toInt()}”x${_standardSize?.height.toInt()}”"
|
||||
: _carton.cartonSizeType == customCarton
|
||||
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”"
|
||||
: null;
|
||||
@@ -178,15 +196,19 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
|
||||
final packageLengthBox = DisplayText(
|
||||
showLabelLink: true,
|
||||
subText: Text(numberFormatter.format(_packages.length)),
|
||||
subText: Text(numberFormatter.format(_packageCount)),
|
||||
labelTextKey: "box.package",
|
||||
onTapLabel: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => PackageDetailList(
|
||||
cartonNumber: _carton.cartonNumber ?? '',
|
||||
packages: _packages)));
|
||||
cartonNumber: _carton.cartonNumber ?? '',
|
||||
packageCount: _packageCount,
|
||||
senderID: _carton.senderID ?? "",
|
||||
consingeeID: _carton.consigneeID ?? "",
|
||||
fcsShipmentID: _carton.fcsShipmentID ?? "",
|
||||
)));
|
||||
},
|
||||
);
|
||||
|
||||
@@ -278,7 +300,8 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
_cargoTypes.isNotEmpty
|
||||
? Padding(
|
||||
padding: EdgeInsets.only(right: 0),
|
||||
child: Text("${removeTrailingZeros(totalWeight)} lb",
|
||||
child: Text(
|
||||
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(_totalWeight)) ?? 0)} lb",
|
||||
textAlign: TextAlign.end,
|
||||
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
||||
: const SizedBox()
|
||||
@@ -307,7 +330,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
color: Colors.black, fontSize: 15),
|
||||
),
|
||||
Text(
|
||||
"${removeTrailingZeros(e.value.weight)} lb",
|
||||
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(e.value.weight)) ?? 0)} lb",
|
||||
textAlign: TextAlign.end,
|
||||
style: TextStyle(
|
||||
color: Colors.black, fontSize: 15))
|
||||
@@ -528,7 +551,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Flexible(child: cartonSizeBox),
|
||||
_packages.isEmpty
|
||||
_packageCount == 0
|
||||
? const SizedBox()
|
||||
: Flexible(child: packageLengthBox),
|
||||
],
|
||||
|
||||
@@ -13,12 +13,10 @@ import '../../../domain/vo/local_step.dart';
|
||||
import '../../../helpers/theme.dart';
|
||||
import '../../domain/entities/cargo_type.dart';
|
||||
import '../../domain/entities/carton.dart';
|
||||
import '../../domain/entities/package.dart';
|
||||
import '../../domain/entities/user.dart';
|
||||
import '../carton_size/model/carton_size_model.dart';
|
||||
import '../fcs_shipment/model/fcs_shipment_model.dart';
|
||||
import '../main/util.dart';
|
||||
import '../package/model/package_model.dart';
|
||||
import '../widgets/local_text.dart';
|
||||
import '../widgets/progress.dart';
|
||||
import '../widgets/step_widget.dart';
|
||||
@@ -26,7 +24,7 @@ import 'cargo_widget.dart';
|
||||
import 'carton_size_widget.dart';
|
||||
import 'carton_submit.dart';
|
||||
import 'model/package_selection_model.dart';
|
||||
import 'packages_widget.dart';
|
||||
import 'package_selection_widget.dart';
|
||||
|
||||
class CartonPackageEditor extends StatefulWidget {
|
||||
final Carton carton;
|
||||
@@ -46,7 +44,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
LocalStep(lable: 'Cargos', stepType: StepType.CARGOS),
|
||||
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
||||
];
|
||||
List<Package> _packages = [];
|
||||
|
||||
List<CargoType> _cargoTypes = [];
|
||||
List<CargoType> _surchareItems = [];
|
||||
|
||||
@@ -86,8 +84,11 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
|
||||
_billToValue = widget.carton.billTo ?? billToSender;
|
||||
_selectedLastMile = widget.carton.lastMile ?? delivery_caton;
|
||||
_cargoTypes = widget.carton.cargoTypes;
|
||||
_surchareItems = widget.carton.surchareItems;
|
||||
|
||||
_cargoTypes =
|
||||
widget.carton.cargoTypes.map((e) => e.cloneForCarton()).toList();
|
||||
_surchareItems =
|
||||
widget.carton.surchareItems.map((e) => e.cloneForSurchage()).toList();
|
||||
|
||||
// check carton size type
|
||||
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
||||
@@ -120,11 +121,6 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
.read<FcsShipmentModel>()
|
||||
.getFcsShipment(widget.carton.fcsShipmentID ?? "");
|
||||
_shipment = s;
|
||||
|
||||
_packages = await context
|
||||
.read<PackageModel>()
|
||||
.getPackagesByIds(widget.carton.packageIDs);
|
||||
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
@@ -233,19 +229,17 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
));
|
||||
} else if (step.stepType == StepType.PACKAGES) {
|
||||
return Expanded(
|
||||
child: PackagesWidget(
|
||||
child: PackageSelectionWidget(
|
||||
sender: _sender!,
|
||||
consignee: _consignee!,
|
||||
shipment: _shipment!,
|
||||
onContinue: (packages) {
|
||||
onContinue: () {
|
||||
setState(() {
|
||||
_packages = List.from(packages);
|
||||
currentStep += 1;
|
||||
});
|
||||
},
|
||||
onPrevious: (packages) {
|
||||
onPrevious: () {
|
||||
setState(() {
|
||||
_packages = List.from(packages);
|
||||
currentStep -= 1;
|
||||
});
|
||||
},
|
||||
@@ -288,7 +282,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
height: _height,
|
||||
lastMile: _selectedLastMile,
|
||||
shipment: _shipment!,
|
||||
packages: _packages,
|
||||
// packages: _packages,
|
||||
cargoTypes: _cargoTypes,
|
||||
surchareItems: _surchareItems,
|
||||
onCreate: () {
|
||||
@@ -340,7 +334,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
||||
length: length,
|
||||
width: width,
|
||||
height: height,
|
||||
packages: _packages,
|
||||
// packages: _packages,
|
||||
cargoTypes: _cargoTypes,
|
||||
surchareItems: _surchareItems);
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import '../../../domain/entities/fcs_shipment.dart';
|
||||
import '../../../domain/vo/local_step.dart';
|
||||
import '../../../helpers/theme.dart';
|
||||
import '../../domain/entities/cargo_type.dart';
|
||||
import '../../domain/entities/package.dart';
|
||||
import '../../domain/entities/user.dart';
|
||||
import '../main/util.dart';
|
||||
import '../widgets/local_text.dart';
|
||||
@@ -23,7 +22,7 @@ import 'carton_size_widget.dart';
|
||||
import 'carton_submit.dart';
|
||||
import 'model/carton_model.dart';
|
||||
import 'model/package_selection_model.dart';
|
||||
import 'packages_widget.dart';
|
||||
import 'package_selection_widget.dart';
|
||||
|
||||
class CartonPackageForm extends StatefulWidget {
|
||||
final User sender;
|
||||
@@ -48,7 +47,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
||||
LocalStep(lable: 'Cargos', stepType: StepType.CARGOS),
|
||||
LocalStep(lable: 'Submit', stepType: StepType.SUBMIT)
|
||||
];
|
||||
List<Package> _packages = [];
|
||||
|
||||
List<CargoType> _cargoTypes = [];
|
||||
List<CargoType> _surchareItems = [];
|
||||
|
||||
@@ -166,19 +165,17 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
||||
));
|
||||
} else if (step.stepType == StepType.PACKAGES) {
|
||||
return Expanded(
|
||||
child: PackagesWidget(
|
||||
child: PackageSelectionWidget(
|
||||
sender: widget.sender,
|
||||
consignee: widget.consignee,
|
||||
shipment: _shipment!,
|
||||
onContinue: (packages) {
|
||||
onContinue: () {
|
||||
setState(() {
|
||||
_packages = List.from(packages);
|
||||
currentStep += 1;
|
||||
});
|
||||
},
|
||||
onPrevious: (packages) {
|
||||
onPrevious: () {
|
||||
setState(() {
|
||||
_packages = List.from(packages);
|
||||
currentStep -= 1;
|
||||
});
|
||||
},
|
||||
@@ -220,7 +217,6 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
||||
height: _height,
|
||||
lastMile: _selectedLastMile,
|
||||
shipment: _shipment!,
|
||||
packages: _packages,
|
||||
cargoTypes: _cargoTypes,
|
||||
surchareItems: _surchareItems,
|
||||
onCreate: () {
|
||||
@@ -236,7 +232,6 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_create() async {
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
@@ -272,7 +267,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
||||
length: length,
|
||||
width: width,
|
||||
height: height,
|
||||
packages: _packages,
|
||||
// packages: _packages,
|
||||
cargoTypes: _cargoTypes,
|
||||
surchareItems: _surchareItems);
|
||||
var c = await context.read<CartonModel>().createCarton(carton);
|
||||
|
||||
@@ -7,8 +7,6 @@ import '../../../domain/entities/cargo_type.dart';
|
||||
import '../../../domain/entities/carton_size.dart';
|
||||
import '../../../domain/entities/fcs_shipment.dart';
|
||||
import '../../../helpers/theme.dart';
|
||||
|
||||
import '../../domain/entities/package.dart';
|
||||
import '../../domain/entities/user.dart';
|
||||
import '../main/util.dart';
|
||||
import '../widgets/local_text.dart';
|
||||
@@ -24,7 +22,7 @@ class CartonSubmit extends StatelessWidget {
|
||||
final User consingee;
|
||||
final String billToValue;
|
||||
final FcsShipment shipment;
|
||||
final List<Package> packages;
|
||||
// final List<Package> packages;
|
||||
final String cartonSizeType;
|
||||
final CartonSize? standardSize;
|
||||
final double length;
|
||||
@@ -44,7 +42,7 @@ class CartonSubmit extends StatelessWidget {
|
||||
this.onCreate,
|
||||
this.onPrevious,
|
||||
required this.shipment,
|
||||
this.packages = const [],
|
||||
// this.packages = const [],
|
||||
this.standardSize,
|
||||
required this.cartonSizeType,
|
||||
required this.lastMile,
|
||||
@@ -196,42 +194,42 @@ class CartonSubmit extends StatelessWidget {
|
||||
),
|
||||
);
|
||||
|
||||
final packagesBox = Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 5, bottom: 5),
|
||||
child: LocalText(context, 'box.package.count',
|
||||
translationVariables: [packages.length.toString()],
|
||||
color: primaryColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: primaryColor),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Wrap(
|
||||
spacing: 15,
|
||||
children: packages.map((e) {
|
||||
return SizedBox(
|
||||
width: MediaQuery.of(context).size.width / 2.5,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||
child: Text(
|
||||
e.trackingID ?? "",
|
||||
style: TextStyle(color: Colors.black, fontSize: 15),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList()),
|
||||
),
|
||||
),
|
||||
]),
|
||||
);
|
||||
// final packagesBox = Padding(
|
||||
// padding: const EdgeInsets.only(top: 10),
|
||||
// child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(left: 5, bottom: 5),
|
||||
// child: LocalText(context, 'box.package.count',
|
||||
// translationVariables: [packages.length.toString()],
|
||||
// color: primaryColor,
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.normal),
|
||||
// ),
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// border: Border.all(color: primaryColor),
|
||||
// borderRadius: BorderRadius.circular(5),
|
||||
// ),
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Wrap(
|
||||
// spacing: 15,
|
||||
// children: packages.map((e) {
|
||||
// return SizedBox(
|
||||
// width: MediaQuery.of(context).size.width / 2.5,
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.symmetric(vertical: 3),
|
||||
// child: Text(
|
||||
// e.trackingID ?? "",
|
||||
// style: TextStyle(color: Colors.black, fontSize: 15),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }).toList()),
|
||||
// ),
|
||||
// ),
|
||||
// ]),
|
||||
// );
|
||||
|
||||
final cargosBox = Padding(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
@@ -245,7 +243,8 @@ class CartonSubmit extends StatelessWidget {
|
||||
color: primaryColor,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.normal),
|
||||
Text("${removeTrailingZeros(totalWeight)} lb",
|
||||
Text(
|
||||
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(totalWeight)) ?? 0)} lb",
|
||||
style: TextStyle(color: Colors.black, fontSize: 15))
|
||||
],
|
||||
),
|
||||
@@ -275,7 +274,8 @@ class CartonSubmit extends StatelessWidget {
|
||||
style: TextStyle(
|
||||
color: Colors.black, fontSize: 15),
|
||||
),
|
||||
Text("${removeTrailingZeros(e.weight)} lb",
|
||||
Text(
|
||||
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(e.weight)) ?? 0)} lb",
|
||||
style: TextStyle(
|
||||
color: Colors.black, fontSize: 15))
|
||||
],
|
||||
@@ -448,11 +448,11 @@ class CartonSubmit extends StatelessWidget {
|
||||
const SizedBox(height: 10),
|
||||
shipmentBox,
|
||||
const SizedBox(height: 10),
|
||||
packages.isNotEmpty ? packagesBox : const SizedBox(),
|
||||
// packages.isNotEmpty ? packagesBox : const SizedBox(),
|
||||
// const SizedBox(height: 10),
|
||||
cargoTypes.isNotEmpty ? cargosBox : const SizedBox(),
|
||||
const SizedBox(height: 10),
|
||||
cargosBox,
|
||||
const SizedBox(height: 10),
|
||||
surChargeItemsBox,
|
||||
surchareItems.isNotEmpty ? surChargeItemsBox : const SizedBox(),
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../main/util.dart';
|
||||
import '../widgets/local_text.dart';
|
||||
import 'carton_info.dart';
|
||||
|
||||
@@ -99,7 +100,7 @@ class MixCartonDetailList extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
"${carton.cartonWeight.toStringAsFixed(2)} lb",
|
||||
"${twoDecimalFormatted(carton.cartonWeight)} lb",
|
||||
style: TextStyle(fontSize: 14.0, color: Colors.grey),
|
||||
)
|
||||
],
|
||||
|
||||
@@ -5,59 +5,68 @@ import 'package:logging/logging.dart';
|
||||
|
||||
import '../../../constants.dart';
|
||||
import '../../../domain/entities/package.dart';
|
||||
import '../../../pagination/paginator_listener.dart';
|
||||
import '../../main/model/base_model.dart';
|
||||
|
||||
class PackageSelectionModel extends BaseModel {
|
||||
final log = Logger("PackageSelectionModel");
|
||||
String query = "";
|
||||
List<Package> packages = [];
|
||||
List<Package> selectedPackages = [];
|
||||
PaginatorListener<Package>? getPackages;
|
||||
|
||||
List<Package> packages = [];
|
||||
bool isLoading = false;
|
||||
DocumentSnapshot? _lastDocument;
|
||||
bool ended = false;
|
||||
|
||||
Timer? t;
|
||||
search(String term,
|
||||
{bool imm = false,
|
||||
required String shipmentId,
|
||||
required String senderId,
|
||||
required String consigneeId}) async {
|
||||
query = term;
|
||||
@override
|
||||
logout() async {
|
||||
packages.clear();
|
||||
_lastDocument = null;
|
||||
ended = false;
|
||||
t?.cancel();
|
||||
t = Timer(Duration(milliseconds: imm ? 0 : 800), () async {
|
||||
await refresh(
|
||||
term: term,
|
||||
shipmentId: shipmentId,
|
||||
consigneeId: consigneeId,
|
||||
senderId: senderId);
|
||||
});
|
||||
getPackages?.close();
|
||||
}
|
||||
|
||||
loadPackages(
|
||||
{required String senderId,
|
||||
required String consigneeId,
|
||||
required String shipmentId}) {
|
||||
if (user == null) return;
|
||||
|
||||
String path = "/$packages_collection";
|
||||
Query col = FirebaseFirestore.instance
|
||||
.collection(path)
|
||||
.where("sender_id", isEqualTo: senderId)
|
||||
.where("user_id", isEqualTo: consigneeId)
|
||||
.where("fcs_shipment_id", isEqualTo: shipmentId);
|
||||
Query pageQuery = FirebaseFirestore.instance
|
||||
.collection(path)
|
||||
.where("sender_id", isEqualTo: senderId)
|
||||
.where("user_id", isEqualTo: consigneeId)
|
||||
.where("fcs_shipment_id", isEqualTo: shipmentId);
|
||||
|
||||
pageQuery = pageQuery.orderBy("created_date", descending: true);
|
||||
getPackages?.close();
|
||||
getPackages = PaginatorListener<Package>(
|
||||
col, pageQuery, (data, id) => Package.fromMap(data, id),
|
||||
rowPerLoad: 30);
|
||||
}
|
||||
|
||||
Future<void> refresh(
|
||||
{required String shipmentId,
|
||||
required String senderId,
|
||||
required String consigneeId,
|
||||
String term = ""}) async {
|
||||
required String consigneeId}) async {
|
||||
packages.clear();
|
||||
_lastDocument = null;
|
||||
ended = false;
|
||||
await loadMoreData(
|
||||
shipmentId: shipmentId,
|
||||
senderId: senderId,
|
||||
consigneeId: consigneeId,
|
||||
term: term);
|
||||
shipmentId: shipmentId,
|
||||
senderId: senderId,
|
||||
consigneeId: consigneeId,
|
||||
);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Future<void> loadMoreData(
|
||||
{required String shipmentId,
|
||||
required String senderId,
|
||||
required String consigneeId,
|
||||
String term = ""}) async {
|
||||
required String consigneeId}) async {
|
||||
int rowPerPage = 20;
|
||||
|
||||
try {
|
||||
@@ -69,12 +78,9 @@ class PackageSelectionModel extends BaseModel {
|
||||
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);
|
||||
|
||||
if (term != "") {
|
||||
query = query.where("tracking_id", isEqualTo: term);
|
||||
}
|
||||
|
||||
query = query.orderBy("created_date", descending: true);
|
||||
|
||||
if (_lastDocument != null) {
|
||||
@@ -92,10 +98,6 @@ class PackageSelectionModel extends BaseModel {
|
||||
return p;
|
||||
}).toList();
|
||||
|
||||
for (var p in list) {
|
||||
selectedPackages.contains(p) ? p.isChecked = true : p.isChecked = false;
|
||||
}
|
||||
|
||||
packages.addAll(list);
|
||||
if (list.length < rowPerPage) ended = true;
|
||||
notifyListeners();
|
||||
@@ -106,22 +108,8 @@ class PackageSelectionModel extends BaseModel {
|
||||
}
|
||||
}
|
||||
|
||||
selectPackage(Package a) {
|
||||
if (a.isChecked) {
|
||||
selectedPackages.add(a);
|
||||
} else {
|
||||
selectedPackages.remove(a);
|
||||
}
|
||||
}
|
||||
|
||||
addSelectedPackage(List<Package> list) {
|
||||
selectedPackages = list;
|
||||
}
|
||||
|
||||
clearSelection() {
|
||||
selectedPackages.clear();
|
||||
packages.clear();
|
||||
query = "";
|
||||
}
|
||||
|
||||
Future<List<Package>> getPackagesBySenderAndConsigneeId(
|
||||
@@ -174,4 +162,21 @@ class PackageSelectionModel extends BaseModel {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
Future<int?> getPackageCount(
|
||||
{required String senderId,
|
||||
required String consigneeId,
|
||||
required String shipmentId}) async {
|
||||
String path = "/$packages_collection";
|
||||
|
||||
AggregateQuerySnapshot query = await FirebaseFirestore.instance
|
||||
.collection(path)
|
||||
.where("sender_id", isEqualTo: senderId)
|
||||
.where("user_id", isEqualTo: consigneeId)
|
||||
.where("fcs_shipment_id", isEqualTo: shipmentId)
|
||||
.count()
|
||||
.get();
|
||||
|
||||
return query.count;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,54 @@
|
||||
import 'package:fcs/domain/entities/package.dart';
|
||||
import 'package:fcs/helpers/theme.dart';
|
||||
import 'package:fcs/pages/carton/model/package_selection_model.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 'package:provider/provider.dart';
|
||||
|
||||
import '../../pagination/paginator_listview.dart';
|
||||
import '../widgets/local_text.dart';
|
||||
|
||||
class PackageDetailList extends StatelessWidget {
|
||||
class PackageDetailList extends StatefulWidget {
|
||||
final String cartonNumber;
|
||||
final List<Package> packages;
|
||||
PackageDetailList(
|
||||
{super.key, required this.cartonNumber, required this.packages});
|
||||
final int packageCount;
|
||||
final String senderID;
|
||||
final String consingeeID;
|
||||
final String fcsShipmentID;
|
||||
const PackageDetailList(
|
||||
{super.key,
|
||||
required this.cartonNumber,
|
||||
required this.packageCount,
|
||||
required this.senderID,
|
||||
required this.consingeeID,
|
||||
required this.fcsShipmentID});
|
||||
|
||||
@override
|
||||
State<PackageDetailList> createState() => _PackageDetailListState();
|
||||
}
|
||||
|
||||
class _PackageDetailListState extends State<PackageDetailList> {
|
||||
final NumberFormat numberFormatter = NumberFormat("#,###");
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
_init() {
|
||||
context.read<PackageSelectionModel>().loadPackages(
|
||||
senderId: widget.senderID,
|
||||
consigneeId: widget.consingeeID,
|
||||
shipmentId: widget.fcsShipmentID);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var packageModel = context.watch<PackageSelectionModel>();
|
||||
return Scaffold(
|
||||
appBar: LocalAppBar(
|
||||
backgroundColor: Colors.white,
|
||||
@@ -31,81 +61,81 @@ class PackageDetailList extends StatelessWidget {
|
||||
"box.package.count",
|
||||
fontSize: 20,
|
||||
color: primaryColor,
|
||||
translationVariables: [numberFormatter.format(packages.length)],
|
||||
translationVariables: [
|
||||
numberFormatter.format(widget.packageCount)
|
||||
],
|
||||
),
|
||||
Text(cartonNumber,
|
||||
Text(widget.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
|
||||
body: PaginatorListView<Package>(
|
||||
paginatorListener: packageModel.getPackages!,
|
||||
rowBuilder: (p) {
|
||||
Package package = p;
|
||||
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.market!,
|
||||
: package.trackingID!,
|
||||
style: TextStyle(
|
||||
fontSize: 15.0,
|
||||
color: Colors.grey),
|
||||
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),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
);
|
||||
},
|
||||
color: primaryColor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,32 +74,38 @@ class PackageSelectionResult extends StatelessWidget {
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 8.0),
|
||||
child: new Column(
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(package.trackingID ?? "",
|
||||
style: new TextStyle(
|
||||
Text(package.trackingID ?? "",
|
||||
style: TextStyle(
|
||||
fontSize: 15.0,
|
||||
color: Colors.black)),
|
||||
new Text(
|
||||
package.cartonIds.isEmpty
|
||||
? "-"
|
||||
: "${numberFormatter.format(package.cartonIds.length)} Boxes",
|
||||
style: new TextStyle(
|
||||
Text(
|
||||
package.market != null &&
|
||||
package.market != ""
|
||||
? "${package.market}"
|
||||
: "-",
|
||||
style: TextStyle(
|
||||
fontSize: 15.0,
|
||||
color: Colors.grey),
|
||||
),
|
||||
// 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()
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
||||
import 'package:fcs/helpers/theme.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
|
||||
@@ -8,27 +8,25 @@ 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 '../package/package_info.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);
|
||||
typedef OnPrevious = Function();
|
||||
typedef OnContinue = Function();
|
||||
|
||||
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({
|
||||
super.key,
|
||||
required this.packages,
|
||||
this.onPrevious,
|
||||
this.onContinue,
|
||||
required this.shipment,
|
||||
@@ -41,8 +39,6 @@ class PackageSelectionWidget extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
String _query = "";
|
||||
bool _isLoadMore = false;
|
||||
final _scrollController = ScrollController();
|
||||
bool _down = true;
|
||||
@@ -60,29 +56,18 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
}
|
||||
|
||||
_init() {
|
||||
var searchModel = context.read<PackageSelectionModel>();
|
||||
_controller.text = searchModel.query;
|
||||
_query = searchModel.query;
|
||||
|
||||
searchModel.refresh(
|
||||
shipmentId: widget.shipment.id!,
|
||||
consigneeId: widget.consignee.id!,
|
||||
senderId: widget.sender.id!,
|
||||
term: _query);
|
||||
|
||||
searchModel.addSelectedPackage(widget.packages);
|
||||
var packageModel = context.read<PackageSelectionModel>();
|
||||
packageModel.refresh(
|
||||
shipmentId: widget.shipment.id!,
|
||||
consigneeId: widget.consignee.id!,
|
||||
senderId: widget.sender.id!,
|
||||
);
|
||||
|
||||
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>();
|
||||
@@ -92,10 +77,10 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
});
|
||||
|
||||
await model.loadMoreData(
|
||||
shipmentId: widget.shipment.id!,
|
||||
consigneeId: widget.consignee.id!,
|
||||
senderId: widget.sender.id!,
|
||||
term: _query);
|
||||
shipmentId: widget.shipment.id!,
|
||||
consigneeId: widget.consignee.id!,
|
||||
senderId: widget.sender.id!,
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_isLoadMore = false;
|
||||
@@ -105,8 +90,7 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var model = context.watch<PackageSelectionModel>();
|
||||
List<Package> searchResults = model.packages;
|
||||
List<Package> selectedPackageList = model.selectedPackages;
|
||||
List<Package> packages = model.packages;
|
||||
|
||||
final senderBox = userDisplayBox(context,
|
||||
lableKey: "box.sender.title",
|
||||
@@ -132,103 +116,23 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
|
||||
final continueBtn = ContinueButton(
|
||||
onTap: () {
|
||||
if (selectedPackageList.isEmpty || searchResults.isEmpty) {
|
||||
showMsgDialog(context, 'Error', "Please select the packages");
|
||||
if (packages.isEmpty) {
|
||||
showMsgDialog(context, 'Error', "Please add the packages");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (widget.onContinue != null) {
|
||||
widget.onContinue!(selectedPackageList);
|
||||
widget.onContinue!();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
final previousBtn = PreviousButton(onTap: () {
|
||||
if (widget.onPrevious != null) {
|
||||
widget.onPrevious!(selectedPackageList);
|
||||
widget.onPrevious!();
|
||||
}
|
||||
});
|
||||
|
||||
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),
|
||||
),
|
||||
);
|
||||
|
||||
final selectedPackageBox = Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
physics: const BouncingScrollPhysics(),
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: selectedPackageList
|
||||
.map((e) => Padding(
|
||||
padding: const EdgeInsets.only(right: 20),
|
||||
child: Text(e.trackingID ?? "",
|
||||
style:
|
||||
TextStyle(color: Colors.black, fontSize: 15)),
|
||||
))
|
||||
.toList())),
|
||||
);
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -255,8 +159,6 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
LocalTitle(
|
||||
textKey: "box.select.package", topPadding: 5),
|
||||
const SizedBox(height: 10),
|
||||
searchBox,
|
||||
selectedPackageBox,
|
||||
])
|
||||
: const SizedBox(),
|
||||
),
|
||||
@@ -273,11 +175,12 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
_down = true;
|
||||
});
|
||||
},
|
||||
onTap: (a) async {
|
||||
setState(() {
|
||||
a.isChecked = !a.isChecked;
|
||||
});
|
||||
context.read<PackageSelectionModel>().selectPackage(a);
|
||||
onTap: (a) {
|
||||
Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => PackageInfo(package: a)),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -302,31 +205,4 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
_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<PackageSelectionModel>().search(_query,
|
||||
imm: imm,
|
||||
shipmentId: widget.shipment.id!,
|
||||
senderId: widget.sender.id!,
|
||||
consigneeId: widget.consignee.id!);
|
||||
} catch (e) {
|
||||
showMsgDialog(context, 'Error', e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,223 +0,0 @@
|
||||
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_text.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 = [];
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_init();
|
||||
super.initState();
|
||||
_scrollController.addListener(() {
|
||||
setState(() {
|
||||
_down = _scrollController.position.userScrollDirection ==
|
||||
ScrollDirection.forward;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
_init() async {
|
||||
_packages.clear();
|
||||
_isLoading = true;
|
||||
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);
|
||||
_isLoading = false;
|
||||
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 (_packages.isEmpty) {
|
||||
showMsgDialog(context, 'Error', "Please add the packages");
|
||||
return false;
|
||||
}
|
||||
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: _packages.isEmpty && !_isLoading
|
||||
? Center(
|
||||
child: LocalText(context, 'box.no_package',
|
||||
color: Colors.black, fontSize: 15))
|
||||
: 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()
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,15 +4,16 @@ 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 '../../main/util.dart';
|
||||
import '../carton_info.dart';
|
||||
import '../print_qr_code_page.dart';
|
||||
|
||||
class CartonListRow extends StatelessWidget {
|
||||
final Carton box;
|
||||
CartonListRow({Key? key, required this.box}) : super(key: key);
|
||||
CartonListRow({super.key, required this.box});
|
||||
|
||||
final double dotSize = 15.0;
|
||||
final DateFormat dateFormat = new DateFormat("dd MMM yyyy");
|
||||
final DateFormat dateFormat = DateFormat("dd MMM yyyy");
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -28,9 +29,9 @@ class CartonListRow extends StatelessWidget {
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: new Padding(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||
child: new Row(
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Container(
|
||||
padding: EdgeInsets.only(left: 0),
|
||||
@@ -40,24 +41,24 @@ class CartonListRow extends StatelessWidget {
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
new Expanded(
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(left: 15.0),
|
||||
child: Row(
|
||||
children: [
|
||||
new Column(
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
Text(
|
||||
box.cartonNumber ?? "",
|
||||
style: new TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 15.0, color: Colors.black),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: new Text(
|
||||
child: Text(
|
||||
box.consigneeName ?? "",
|
||||
style: new TextStyle(
|
||||
style: TextStyle(
|
||||
fontSize: 15.0, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
@@ -95,10 +96,9 @@ class CartonListRow extends StatelessWidget {
|
||||
padding: const EdgeInsets.only(top: 5),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
new Text(
|
||||
"${box.cartonWeight.toStringAsFixed(2)} lb",
|
||||
style:
|
||||
new TextStyle(fontSize: 14.0, color: Colors.grey),
|
||||
Text(
|
||||
"${twoDecimalFormatted(box.cartonWeight)} lb",
|
||||
style: TextStyle(fontSize: 14.0, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user