Merge branch 'master' of tzw/fcs into master
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import 'package:fcs/pages/main/util.dart';
|
||||||
|
|
||||||
class CargoType {
|
class CargoType {
|
||||||
String? id;
|
String? id;
|
||||||
String? name;
|
String? name;
|
||||||
@@ -96,7 +98,7 @@ class CargoType {
|
|||||||
Map<String, dynamic> toMapForCarton() {
|
Map<String, dynamic> toMapForCarton() {
|
||||||
return {
|
return {
|
||||||
"id": id,
|
"id": id,
|
||||||
'weight': weight,
|
'weight': double.tryParse(twoDecimalFormatted(weight)) ?? 0.00,
|
||||||
"mix_cargo_type_ids": mixCargoes.map((e) => e.id).toList()
|
"mix_cargo_type_ids": mixCargoes.map((e) => e.id).toList()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -109,6 +111,22 @@ class CargoType {
|
|||||||
return CargoType.fromMap(toMap(), id!);
|
return CargoType.fromMap(toMap(), id!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CargoType cloneForCarton() {
|
||||||
|
return CargoType(
|
||||||
|
id: id,
|
||||||
|
name: name,
|
||||||
|
weight: weight,
|
||||||
|
isDefault: isDefault,
|
||||||
|
displayIndex: displayIndex,
|
||||||
|
isMixCargo: isMixCargo,
|
||||||
|
mixCargoIds: List.from(mixCargoIds),
|
||||||
|
mixCargoes: List.from(mixCargoes));
|
||||||
|
}
|
||||||
|
|
||||||
|
CargoType cloneForSurchage() {
|
||||||
|
return CargoType(id: id, name: name, qty: qty);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => other is CargoType && other.id == id;
|
bool operator ==(Object other) => other is CargoType && other.id == id;
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ class Carton {
|
|||||||
var _types = cargoTypes.where((t) => t.weight != 0).toList();
|
var _types = cargoTypes.where((t) => t.weight != 0).toList();
|
||||||
var _cargoTypes = _types.map((c) => c.toMapForCarton()).toList();
|
var _cargoTypes = _types.map((c) => c.toMapForCarton()).toList();
|
||||||
|
|
||||||
var _packagesIds = packages.map((c) => c.id).toList();
|
// var _packagesIds = packages.map((c) => c.id).toList();
|
||||||
|
|
||||||
var _surchareItems =
|
var _surchareItems =
|
||||||
surchareItems.map((c) => c.toMapForSurcharge()).toList();
|
surchareItems.map((c) => c.toMapForSurcharge()).toList();
|
||||||
@@ -184,7 +184,7 @@ class Carton {
|
|||||||
'length': length,
|
'length': length,
|
||||||
'width': width,
|
'width': width,
|
||||||
'height': height,
|
'height': height,
|
||||||
'package_ids': _packagesIds,
|
// 'package_ids': _packagesIds,
|
||||||
'cargo_types': _cargoTypes,
|
'cargo_types': _cargoTypes,
|
||||||
'surcharge_items': _surchareItems,
|
'surcharge_items': _surchareItems,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -47,14 +47,18 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
List<CargoType> _cargoTypes = [];
|
List<CargoType> _cargoTypes = [];
|
||||||
List<CargoType> _surchareItems = [];
|
List<CargoType> _surchareItems = [];
|
||||||
TextEditingController totalCtl = TextEditingController();
|
TextEditingController totalCtl = TextEditingController();
|
||||||
|
|
||||||
List<TextEditingController> cargoTypeControllers = [];
|
List<TextEditingController> cargoTypeControllers = [];
|
||||||
List<TextEditingController> surchargeControllers = [];
|
List<TextEditingController> surchargeControllers = [];
|
||||||
|
|
||||||
List<CargoType> _mixCargoTypes = [];
|
bool get hasValueTotalWeight =>
|
||||||
List<TextEditingController> mixCargoTypeControllers = [];
|
totalCtl.text.isNotEmpty && totalCtl.text != '0.00';
|
||||||
|
bool get hasValueCargoes =>
|
||||||
|
_cargoTypes.isNotEmpty && _cargoTypes.every((e) => e.weight != 0.00);
|
||||||
|
|
||||||
bool get isKnownTotalWeight =>
|
double get actualTotalWeight =>
|
||||||
totalCtl.text.isNotEmpty && totalCtl.text != '0';
|
_cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||||
|
String? error;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -63,25 +67,17 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
totalCtl.addListener(totalInputChangeListener);
|
|
||||||
// for cargo types
|
// for cargo types
|
||||||
if (widget.cargoTypes.isNotEmpty) {
|
if (widget.cargoTypes.isNotEmpty) {
|
||||||
List<CargoType> allCargoes = List.from(widget.cargoTypes);
|
_cargoTypes = List.from(widget.cargoTypes);
|
||||||
_cargoTypes = allCargoes.where((e) => !e.isMixCargo).toList();
|
|
||||||
for (var e in _cargoTypes) {
|
for (var e in _cargoTypes) {
|
||||||
var editor = TextEditingController();
|
var editor = TextEditingController();
|
||||||
editor.text = removeTrailingZeros(e.weight);
|
editor.text = twoDecimalFormatted(
|
||||||
|
double.tryParse(removeTrailingZeros(e.weight)) ?? 0);
|
||||||
editor.addListener(inputChangeListener);
|
editor.addListener(inputChangeListener);
|
||||||
cargoTypeControllers.add(editor);
|
cargoTypeControllers.add(editor);
|
||||||
}
|
}
|
||||||
_mixCargoTypes = allCargoes.where((e) => e.isMixCargo).toList();
|
_onPopulate();
|
||||||
for (var e in _mixCargoTypes) {
|
|
||||||
var editor = TextEditingController();
|
|
||||||
editor.text = removeTrailingZeros(e.weight);
|
|
||||||
editor.addListener(inputChangeListener);
|
|
||||||
mixCargoTypeControllers.add(editor);
|
|
||||||
}
|
|
||||||
_calculateTotalWeght();
|
|
||||||
} else {
|
} else {
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
_openCargoTypeSelection();
|
_openCargoTypeSelection();
|
||||||
@@ -94,7 +90,7 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
for (var e in _surchareItems) {
|
for (var e in _surchareItems) {
|
||||||
var editor = TextEditingController();
|
var editor = TextEditingController();
|
||||||
editor.text = e.qty.toString();
|
editor.text = e.qty.toString();
|
||||||
editor.addListener(inputChangeListenerForSurchage);
|
editor.addListener(inputChangeListener);
|
||||||
surchargeControllers.add(editor);
|
surchargeControllers.add(editor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,86 +100,90 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalInputChangeListener() {
|
|
||||||
print("Listen isKnownTotalWeight:$isKnownTotalWeight");
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
inputChangeListenerForSurchage() {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
_openCargoTypeSelection() async {
|
_openCargoTypeSelection() async {
|
||||||
List<CargoType>? cargoes = await showDialog(
|
List<CargoType>? cargoes = await showDialog(
|
||||||
context: context, builder: (_) => const CargoTypeAdditionDialog());
|
context: context, builder: (_) => const CargoTypeAdditionDialog());
|
||||||
if (cargoes == null) return;
|
if (cargoes == null) return;
|
||||||
_cargoTypes = cargoes.where((e) => !e.isMixCargo).toList();
|
_cargoTypes = cargoes;
|
||||||
_mixCargoTypes = cargoes.where((e) => e.isMixCargo).toList();
|
_cargoTypes.sort((a, b) => (a == b ? 0 : (a.isMixCargo ? 1 : -1)));
|
||||||
|
|
||||||
for (var e in _cargoTypes) {
|
for (var e in _cargoTypes) {
|
||||||
var editor = TextEditingController();
|
var editor = TextEditingController();
|
||||||
editor.text = '0';
|
editor.text = '0.00';
|
||||||
editor.addListener(inputChangeListener);
|
editor.addListener(inputChangeListener);
|
||||||
cargoTypeControllers.add(editor);
|
cargoTypeControllers.add(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var e in _mixCargoTypes) {
|
totalCtl.text = twoDecimalFormatted(
|
||||||
var editor = TextEditingController();
|
double.tryParse(removeTrailingZeros(actualTotalWeight)) ?? 0);
|
||||||
editor.text = '0';
|
|
||||||
editor.addListener(inputChangeListener);
|
|
||||||
mixCargoTypeControllers.add(editor);
|
|
||||||
}
|
|
||||||
_calculateTotalWeght();
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_calculateTotalWeght() {
|
|
||||||
print("_calculateTotalWeght isKnownTotalWeight:$isKnownTotalWeight");
|
|
||||||
double notMixTotal =
|
|
||||||
_cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
|
||||||
double mixTotal =
|
|
||||||
_mixCargoTypes.fold(0, (sum, value) => sum + value.weight);
|
|
||||||
double total = notMixTotal + mixTotal;
|
|
||||||
if (isKnownTotalWeight) {
|
|
||||||
} else {
|
|
||||||
totalCtl.text = removeTrailingZeros(total);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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() {
|
inputChangeListener() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> getEmptyFields() {
|
||||||
|
List<int> emptyFields = [];
|
||||||
|
for (int i = 0; i < cargoTypeControllers.length; i++) {
|
||||||
|
if (cargoTypeControllers[i].text.trim().isEmpty ||
|
||||||
|
cargoTypeControllers[i].text.trim() == "0") {
|
||||||
|
emptyFields.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return emptyFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onPopulate() {
|
||||||
|
if (!hasValueTotalWeight && hasValueCargoes) {
|
||||||
|
totalCtl.text = twoDecimalFormatted(
|
||||||
|
double.tryParse(removeTrailingZeros(actualTotalWeight)) ?? 0);
|
||||||
|
error = null;
|
||||||
|
} else {
|
||||||
|
// auto populate remaining value
|
||||||
|
double totalWeight = (double.tryParse(totalCtl.text) ?? 0);
|
||||||
|
|
||||||
|
if (actualTotalWeight > totalWeight) {
|
||||||
|
error = "Exceed total weight";
|
||||||
|
} else {
|
||||||
|
error = null;
|
||||||
|
double remainingWeight =
|
||||||
|
(totalWeight - actualTotalWeight).clamp(0, totalWeight);
|
||||||
|
|
||||||
|
List<int> emptyFieldIndexes = getEmptyFields();
|
||||||
|
|
||||||
|
if (emptyFieldIndexes.isNotEmpty) {
|
||||||
|
if (emptyFieldIndexes.length == 1) {
|
||||||
_cargoTypes.asMap().entries.forEach((e) {
|
_cargoTypes.asMap().entries.forEach((e) {
|
||||||
_cargoTypes[e.key].weight =
|
if (e.value.weight == 0) {
|
||||||
double.tryParse(cargoTypeControllers[e.key].text) ?? 0;
|
e.value.weight = remainingWeight;
|
||||||
});
|
cargoTypeControllers[e.key].text = twoDecimalFormatted(
|
||||||
_mixCargoTypes.asMap().entries.forEach((e) {
|
double.tryParse(removeTrailingZeros(e.value.weight)) ?? 0);
|
||||||
_mixCargoTypes[e.key].weight =
|
}
|
||||||
double.tryParse(mixCargoTypeControllers[e.key].text) ?? 0;
|
|
||||||
});
|
|
||||||
double notMixTotal =
|
|
||||||
_cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
|
||||||
double mixTotal =
|
|
||||||
_mixCargoTypes.fold(0, (sum, value) => sum + value.weight);
|
|
||||||
double total = notMixTotal + mixTotal;
|
|
||||||
setState(() {
|
|
||||||
totalCtl.text = removeTrailingZeros(total);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onCheckTotalWeight(String value) {
|
||||||
|
double totalWeight = double.tryParse(value) ?? 0;
|
||||||
|
if (totalWeight != actualTotalWeight) {
|
||||||
|
error = "Invalid total weight";
|
||||||
|
} else {
|
||||||
|
error = null;
|
||||||
|
}
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -218,191 +218,49 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
List<CargoType> allCargoTypes = _cargoTypes + _mixCargoTypes;
|
|
||||||
CargoType? cargoType = await Navigator.push(
|
CargoType? cargoType = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
CargoTypeAddition(cargoTypes: allCargoTypes)));
|
CargoTypeAddition(cargoTypes: _cargoTypes)));
|
||||||
if (cargoType == null) return;
|
if (cargoType == null) return;
|
||||||
if (cargoType.isMixCargo) {
|
|
||||||
_mixCargoTypes.add(cargoType);
|
|
||||||
mixCargoTypeControllers.clear();
|
|
||||||
|
|
||||||
for (var e in _mixCargoTypes) {
|
// add cargo type
|
||||||
var editor = TextEditingController();
|
if (cargoType.isMixCargo) {
|
||||||
editor.text = removeTrailingZeros(e.weight);
|
int lastTrueIndex =
|
||||||
editor.addListener(inputChangeListener);
|
_cargoTypes.lastIndexWhere((e) => e.isMixCargo);
|
||||||
mixCargoTypeControllers.add(editor);
|
if (lastTrueIndex != -1) {
|
||||||
}
|
_cargoTypes.insert(lastTrueIndex + 1, cargoType);
|
||||||
} else {
|
} else {
|
||||||
_cargoTypes.add(cargoType);
|
_cargoTypes.add(cargoType);
|
||||||
cargoTypeControllers.clear();
|
}
|
||||||
|
} 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) {
|
for (var e in _cargoTypes) {
|
||||||
var editor = TextEditingController();
|
var editor = TextEditingController();
|
||||||
editor.text = removeTrailingZeros(e.weight);
|
editor.text = twoDecimalFormatted(
|
||||||
|
double.tryParse(removeTrailingZeros(e.weight)) ?? 0);
|
||||||
editor.addListener(inputChangeListener);
|
editor.addListener(inputChangeListener);
|
||||||
cargoTypeControllers.add(editor);
|
cargoTypeControllers.add(editor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_calculateTotalWeght();
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
final cargosBox = Padding(
|
final totalWeightBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
|
||||||
child: 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: 23,
|
|
||||||
onTap: () {
|
|
||||||
_cargoTypes.removeAt(key);
|
|
||||||
|
|
||||||
double totalWeight =
|
|
||||||
double.tryParse(totalCtl.text) ?? 0;
|
|
||||||
double removeWeight =
|
|
||||||
(double.tryParse(cargoTypeControllers[key].text) ??
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (totalWeight >= removeWeight) {
|
|
||||||
double result = totalWeight - removeWeight;
|
|
||||||
totalCtl.text = removeTrailingZeros(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
cargoTypeControllers[key].clear();
|
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Icon(Feather.minus_circle, color: labelColor)),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Flexible(
|
|
||||||
child: inputTextFieldWidget(context,
|
|
||||||
lableText: c.name ?? "",
|
|
||||||
controller: cargoTypeControllers[key],
|
|
||||||
suffixIcon: InkResponse(
|
|
||||||
radius: 23,
|
|
||||||
onTap: () {},
|
|
||||||
child: Icon(Ionicons.md_refresh_circle,
|
|
||||||
color: labelColor))),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList()),
|
|
||||||
);
|
|
||||||
|
|
||||||
final mixCargosBox = Wrap(
|
|
||||||
alignment: WrapAlignment.spaceBetween,
|
|
||||||
runSpacing: 15,
|
|
||||||
children: _mixCargoTypes.asMap().entries.map((e) {
|
|
||||||
var key = e.key;
|
|
||||||
var c = e.value;
|
|
||||||
return SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width / 2.3,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
InkResponse(
|
|
||||||
radius: 23,
|
|
||||||
onTap: () {
|
|
||||||
_mixCargoTypes.removeAt(key);
|
|
||||||
|
|
||||||
double totalWeight =
|
|
||||||
double.tryParse(totalCtl.text) ?? 0;
|
|
||||||
double removeWeight = (double.tryParse(
|
|
||||||
mixCargoTypeControllers[key].text) ??
|
|
||||||
0);
|
|
||||||
|
|
||||||
if (totalWeight >= removeWeight) {
|
|
||||||
double result = totalWeight - removeWeight;
|
|
||||||
totalCtl.text = removeTrailingZeros(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
mixCargoTypeControllers[key].clear();
|
|
||||||
|
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Icon(Feather.minus_circle,
|
|
||||||
color: labelColor, size: 20)),
|
|
||||||
const SizedBox(width: 10),
|
|
||||||
Flexible(
|
|
||||||
child: inputTextFieldWidget(context,
|
|
||||||
lableText: c.name ?? "",
|
|
||||||
controller: mixCargoTypeControllers[key],
|
|
||||||
suffixIcon: InkResponse(
|
|
||||||
radius: 23,
|
|
||||||
onTap: () {},
|
|
||||||
child: Icon(Ionicons.md_refresh_circle,
|
|
||||||
color: labelColor, size: 22))),
|
|
||||||
),
|
|
||||||
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))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
c.mixCargoes.isEmpty
|
|
||||||
? const SizedBox()
|
|
||||||
: Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: Column(
|
|
||||||
children: c.mixCargoes.map((e) {
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 12),
|
|
||||||
child: Row(
|
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,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
@@ -415,43 +273,38 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
setState(() {
|
setState(() {
|
||||||
totalCtl.clear();
|
totalCtl.clear();
|
||||||
});
|
});
|
||||||
|
_onCheckTotalWeight(totalCtl.text);
|
||||||
},
|
},
|
||||||
child: Icon(MaterialIcons.clear, color: labelColor)),
|
child: Icon(MaterialIcons.clear, color: labelColor)),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: inputTextFieldWidget(context,
|
child: inputTextFieldWidget(context,
|
||||||
lableText: "Total",
|
lableText: "Total",
|
||||||
controller: totalCtl,
|
controller: totalCtl, onFieldSubmitted: (newValue) {
|
||||||
// onChanged: (neValue) {
|
if (hasValueCargoes) {
|
||||||
// List<int> emptyFields = getEmptyFields();
|
_onCheckTotalWeight(newValue);
|
||||||
// if (emptyFields.length == 1) {
|
} else {
|
||||||
// double totalWeight = double.tryParse(neValue) ?? 0;
|
_onPopulate();
|
||||||
|
}
|
||||||
// _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);
|
|
||||||
|
|
||||||
// if (totalWeight >= result) {
|
|
||||||
// double remaining = totalWeight - result;
|
|
||||||
// setState(() {
|
|
||||||
// cargoTypeControllers[emptyFields.first].text =
|
|
||||||
// removeTrailingZeros(remaining);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
suffixIcon: InkResponse(
|
suffixIcon: InkResponse(
|
||||||
radius: 23,
|
radius: 23,
|
||||||
|
onTap: () {
|
||||||
|
setState(() {
|
||||||
|
totalCtl.text = twoDecimalFormatted(
|
||||||
|
double.tryParse(removeTrailingZeros(
|
||||||
|
actualTotalWeight)) ??
|
||||||
|
0);
|
||||||
|
error = null;
|
||||||
|
});
|
||||||
|
},
|
||||||
child: Icon(Ionicons.md_refresh_circle,
|
child: Icon(Ionicons.md_refresh_circle,
|
||||||
color: labelColor))),
|
color: labelColor, size: 22))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final subchargeItemTitleBox = LocalTitle(
|
final subchargeItemTitleBox = LocalTitle(
|
||||||
@@ -485,10 +338,10 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final subChargeItemsBox = Padding(
|
final subChargeItemsBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
alignment: WrapAlignment.spaceBetween,
|
alignment: WrapAlignment.spaceBetween,
|
||||||
runSpacing: 15,
|
runSpacing: 25,
|
||||||
children: _surchareItems.asMap().entries.map((e) {
|
children: _surchareItems.asMap().entries.map((e) {
|
||||||
var key = e.key;
|
var key = e.key;
|
||||||
var c = e.value;
|
var c = e.value;
|
||||||
@@ -533,20 +386,160 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var allCargoes = _cargoTypes + _mixCargoTypes;
|
if (error != null) {
|
||||||
|
showMsgDialog(
|
||||||
widget.onContinue!(allCargoes, _surchareItems);
|
context, "Error", "Please add the right cargo type weight");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
widget.onContinue!(_cargoTypes, _surchareItems);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final previousBtn = PreviousButton(onTap: () {
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
|
if (error != null) {
|
||||||
|
showMsgDialog(
|
||||||
|
context, "Error", "Please add the right cargo type weight");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (widget.onPrevious != null) {
|
if (widget.onPrevious != null) {
|
||||||
var allCargoes = _cargoTypes + _mixCargoTypes;
|
widget.onPrevious!(_cargoTypes, _surchareItems);
|
||||||
widget.onPrevious!(allCargoes, _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(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -557,19 +550,20 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
userRow,
|
userRow,
|
||||||
cargoTitle,
|
cargoTitle,
|
||||||
cargosBox,
|
cargoesWidget(_cargoTypes),
|
||||||
_mixCargoTypes.isNotEmpty && _cargoTypes.isNotEmpty
|
const SizedBox(height: 15),
|
||||||
? Padding(
|
_cargoTypes.isNotEmpty
|
||||||
padding: const EdgeInsets.symmetric(
|
? Divider(
|
||||||
horizontal: 100, vertical: 25),
|
color: Colors.grey.shade300,
|
||||||
child: Divider(color: Colors.grey.shade300),
|
)
|
||||||
|
: const SizedBox(),
|
||||||
|
const SizedBox(height: 5),
|
||||||
|
error != null
|
||||||
|
? Text(
|
||||||
|
error!,
|
||||||
|
style: TextStyle(color: dangerColor),
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
mixCargosBox,
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 25),
|
|
||||||
child: Divider(color: Colors.grey.shade300),
|
|
||||||
),
|
|
||||||
totalWeightBox,
|
totalWeightBox,
|
||||||
subchargeItemTitleBox,
|
subchargeItemTitleBox,
|
||||||
subChargeItemsBox,
|
subChargeItemsBox,
|
||||||
@@ -599,6 +593,7 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
{required String lableText,
|
{required String lableText,
|
||||||
TextEditingController? controller,
|
TextEditingController? controller,
|
||||||
Function(String)? onChanged,
|
Function(String)? onChanged,
|
||||||
|
Function(String)? onFieldSubmitted,
|
||||||
bool readOnly = false,
|
bool readOnly = false,
|
||||||
Widget? suffixIcon}) {
|
Widget? suffixIcon}) {
|
||||||
return TextFormField(
|
return TextFormField(
|
||||||
@@ -607,9 +602,14 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
cursorColor: primaryColor,
|
cursorColor: primaryColor,
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged: onChanged,
|
onChanged: onChanged,
|
||||||
|
onFieldSubmitted: onFieldSubmitted,
|
||||||
readOnly: readOnly,
|
readOnly: readOnly,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
suffixIcon: suffixIcon,
|
suffixIcon: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8),
|
||||||
|
child: suffixIcon,
|
||||||
|
),
|
||||||
|
suffixIconConstraints: BoxConstraints(minWidth: 0, minHeight: 0),
|
||||||
contentPadding: EdgeInsets.all(0),
|
contentPadding: EdgeInsets.all(0),
|
||||||
labelText: lableText,
|
labelText: lableText,
|
||||||
labelStyle: newLabelStyle(color: Colors.black54, fontSize: 17),
|
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/helpers/theme.dart';
|
||||||
import 'package:fcs/pages/carton/carton_image_upload_editor.dart';
|
import 'package:fcs/pages/carton/carton_image_upload_editor.dart';
|
||||||
import 'package:fcs/pages/main/util.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/display_text.dart';
|
||||||
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.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/mix_carton_editor.dart';
|
||||||
import 'mix_carton_detail_list.dart';
|
import 'mix_carton_detail_list.dart';
|
||||||
import 'model/carton_model.dart';
|
import 'model/carton_model.dart';
|
||||||
|
import 'model/package_selection_model.dart';
|
||||||
import 'package_detail_list.dart';
|
import 'package_detail_list.dart';
|
||||||
import 'print_qr_code_page.dart';
|
import 'print_qr_code_page.dart';
|
||||||
|
|
||||||
@@ -48,10 +48,11 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
List<CargoType> _cargoTypes = [];
|
List<CargoType> _cargoTypes = [];
|
||||||
List<CargoType> _surchareItems = [];
|
List<CargoType> _surchareItems = [];
|
||||||
List<Carton> _mixCartons = [];
|
List<Carton> _mixCartons = [];
|
||||||
List<Package> _packages = [];
|
|
||||||
double totalWeight = 0.0;
|
double _totalWeight = 0.0;
|
||||||
double totalSurchargeCount = 0.0;
|
int _packageCount = 0;
|
||||||
CartonSize? standardSize;
|
|
||||||
|
CartonSize? _standardSize;
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -77,7 +78,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
bool isStandartSize = sameLength && sameWidth && sameHeight;
|
bool isStandartSize = sameLength && sameWidth && sameHeight;
|
||||||
if (isStandartSize) {
|
if (isStandartSize) {
|
||||||
_carton.cartonSizeType = standardCarton;
|
_carton.cartonSizeType = standardCarton;
|
||||||
standardSize = cartonSizes.firstWhere((size) =>
|
_standardSize = cartonSizes.firstWhere((size) =>
|
||||||
size.length == _carton.length &&
|
size.length == _carton.length &&
|
||||||
size.width == _carton.width &&
|
size.width == _carton.width &&
|
||||||
size.height == _carton.height);
|
size.height == _carton.height);
|
||||||
@@ -89,32 +90,11 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
_carton.cartonSizeType = customCarton;
|
_carton.cartonSizeType = customCarton;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.carton.fcsShipmentID != null &&
|
await Future.wait(
|
||||||
widget.carton.fcsShipmentID != '') {
|
[_loadFcsShipment(), _loadPackageCount(), _loadMixCargoes()]);
|
||||||
var s = await context
|
|
||||||
.read<FcsShipmentModel>()
|
|
||||||
.getFcsShipment(widget.carton.fcsShipmentID!);
|
|
||||||
_shipment = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_carton.cartonType == carton_from_packages) {
|
_totalWeight =
|
||||||
_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 =
|
|
||||||
_carton.cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
_carton.cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
||||||
totalSurchargeCount =
|
|
||||||
_surchareItems.fold(0, (sum, value) => sum + value.qty);
|
|
||||||
} finally {
|
} finally {
|
||||||
_isLoading = false;
|
_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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var fromPackage = _carton.cartonType == carton_from_packages;
|
var fromPackage = _carton.cartonType == carton_from_packages;
|
||||||
|
|
||||||
String? boxDimension = _carton.cartonSizeType == standardCarton
|
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.cartonSizeType == customCarton
|
||||||
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”"
|
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”"
|
||||||
: null;
|
: null;
|
||||||
@@ -178,7 +196,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
|
|
||||||
final packageLengthBox = DisplayText(
|
final packageLengthBox = DisplayText(
|
||||||
showLabelLink: true,
|
showLabelLink: true,
|
||||||
subText: Text(numberFormatter.format(_packages.length)),
|
subText: Text(numberFormatter.format(_packageCount)),
|
||||||
labelTextKey: "box.package",
|
labelTextKey: "box.package",
|
||||||
onTapLabel: () {
|
onTapLabel: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@@ -186,7 +204,11 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => PackageDetailList(
|
builder: (context) => PackageDetailList(
|
||||||
cartonNumber: _carton.cartonNumber ?? '',
|
cartonNumber: _carton.cartonNumber ?? '',
|
||||||
packages: _packages)));
|
packageCount: _packageCount,
|
||||||
|
senderID: _carton.senderID ?? "",
|
||||||
|
consingeeID: _carton.consigneeID ?? "",
|
||||||
|
fcsShipmentID: _carton.fcsShipmentID ?? "",
|
||||||
|
)));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -278,7 +300,8 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
_cargoTypes.isNotEmpty
|
_cargoTypes.isNotEmpty
|
||||||
? Padding(
|
? Padding(
|
||||||
padding: EdgeInsets.only(right: 0),
|
padding: EdgeInsets.only(right: 0),
|
||||||
child: Text("${removeTrailingZeros(totalWeight)} lb",
|
child: Text(
|
||||||
|
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(_totalWeight)) ?? 0)} lb",
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
||||||
: const SizedBox()
|
: const SizedBox()
|
||||||
@@ -294,7 +317,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: e.key.isEven ? Colors.grey.shade300 : oddColor,
|
color: e.key.isEven ? Colors.grey.shade200 : oddColor,
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -307,7 +330,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
color: Colors.black, fontSize: 15),
|
color: Colors.black, fontSize: 15),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${removeTrailingZeros(e.value.weight)} lb",
|
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(e.value.weight)) ?? 0)} lb",
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.black, fontSize: 15))
|
color: Colors.black, fontSize: 15))
|
||||||
@@ -325,7 +348,9 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
vertical: 2),
|
vertical: 2),
|
||||||
child: Text(
|
child: Text(
|
||||||
"- ${c.name}",
|
"- ${c.name}",
|
||||||
style: TextStyle(fontSize: 14),
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: labelColor),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList()),
|
}).toList()),
|
||||||
@@ -357,7 +382,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||||
child: Container(
|
child: Container(
|
||||||
color: e.key.isEven ? Colors.grey.shade300 : oddColor,
|
color: e.key.isEven ? Colors.grey.shade200 : oddColor,
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
@@ -526,7 +551,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: cartonSizeBox),
|
Flexible(child: cartonSizeBox),
|
||||||
_packages.isEmpty
|
_packageCount == 0
|
||||||
? const SizedBox()
|
? const SizedBox()
|
||||||
: Flexible(child: packageLengthBox),
|
: Flexible(child: packageLengthBox),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -13,12 +13,10 @@ import '../../../domain/vo/local_step.dart';
|
|||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.dart';
|
||||||
import '../../domain/entities/cargo_type.dart';
|
import '../../domain/entities/cargo_type.dart';
|
||||||
import '../../domain/entities/carton.dart';
|
import '../../domain/entities/carton.dart';
|
||||||
import '../../domain/entities/package.dart';
|
|
||||||
import '../../domain/entities/user.dart';
|
import '../../domain/entities/user.dart';
|
||||||
import '../carton_size/model/carton_size_model.dart';
|
import '../carton_size/model/carton_size_model.dart';
|
||||||
import '../fcs_shipment/model/fcs_shipment_model.dart';
|
import '../fcs_shipment/model/fcs_shipment_model.dart';
|
||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
import '../package/model/package_model.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';
|
||||||
@@ -26,7 +24,7 @@ import 'cargo_widget.dart';
|
|||||||
import 'carton_size_widget.dart';
|
import 'carton_size_widget.dart';
|
||||||
import 'carton_submit.dart';
|
import 'carton_submit.dart';
|
||||||
import 'model/package_selection_model.dart';
|
import 'model/package_selection_model.dart';
|
||||||
import 'packages_widget.dart';
|
import 'package_selection_widget.dart';
|
||||||
|
|
||||||
class CartonPackageEditor extends StatefulWidget {
|
class CartonPackageEditor extends StatefulWidget {
|
||||||
final Carton carton;
|
final Carton carton;
|
||||||
@@ -46,7 +44,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
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<Package> _packages = [];
|
|
||||||
List<CargoType> _cargoTypes = [];
|
List<CargoType> _cargoTypes = [];
|
||||||
List<CargoType> _surchareItems = [];
|
List<CargoType> _surchareItems = [];
|
||||||
|
|
||||||
@@ -86,8 +84,11 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
|
|
||||||
_billToValue = widget.carton.billTo ?? billToSender;
|
_billToValue = widget.carton.billTo ?? billToSender;
|
||||||
_selectedLastMile = widget.carton.lastMile ?? delivery_caton;
|
_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
|
// check carton size type
|
||||||
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
||||||
@@ -120,11 +121,6 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
.read<FcsShipmentModel>()
|
.read<FcsShipmentModel>()
|
||||||
.getFcsShipment(widget.carton.fcsShipmentID ?? "");
|
.getFcsShipment(widget.carton.fcsShipmentID ?? "");
|
||||||
_shipment = s;
|
_shipment = s;
|
||||||
|
|
||||||
_packages = await context
|
|
||||||
.read<PackageModel>()
|
|
||||||
.getPackagesByIds(widget.carton.packageIDs);
|
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -233,19 +229,17 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
));
|
));
|
||||||
} else if (step.stepType == StepType.PACKAGES) {
|
} else if (step.stepType == StepType.PACKAGES) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: PackagesWidget(
|
child: PackageSelectionWidget(
|
||||||
sender: _sender!,
|
sender: _sender!,
|
||||||
consignee: _consignee!,
|
consignee: _consignee!,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
onContinue: (packages) {
|
onContinue: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_packages = List.from(packages);
|
|
||||||
currentStep += 1;
|
currentStep += 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onPrevious: (packages) {
|
onPrevious: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_packages = List.from(packages);
|
|
||||||
currentStep -= 1;
|
currentStep -= 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -288,7 +282,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
height: _height,
|
height: _height,
|
||||||
lastMile: _selectedLastMile,
|
lastMile: _selectedLastMile,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
packages: _packages,
|
// packages: _packages,
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
surchareItems: _surchareItems,
|
surchareItems: _surchareItems,
|
||||||
onCreate: () {
|
onCreate: () {
|
||||||
@@ -340,7 +334,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
length: length,
|
length: length,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
packages: _packages,
|
// packages: _packages,
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
surchareItems: _surchareItems);
|
surchareItems: _surchareItems);
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ 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/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';
|
||||||
@@ -23,7 +22,7 @@ import 'carton_size_widget.dart';
|
|||||||
import 'carton_submit.dart';
|
import 'carton_submit.dart';
|
||||||
import 'model/carton_model.dart';
|
import 'model/carton_model.dart';
|
||||||
import 'model/package_selection_model.dart';
|
import 'model/package_selection_model.dart';
|
||||||
import 'packages_widget.dart';
|
import 'package_selection_widget.dart';
|
||||||
|
|
||||||
class CartonPackageForm extends StatefulWidget {
|
class CartonPackageForm extends StatefulWidget {
|
||||||
final User sender;
|
final User sender;
|
||||||
@@ -48,7 +47,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
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<Package> _packages = [];
|
|
||||||
List<CargoType> _cargoTypes = [];
|
List<CargoType> _cargoTypes = [];
|
||||||
List<CargoType> _surchareItems = [];
|
List<CargoType> _surchareItems = [];
|
||||||
|
|
||||||
@@ -166,19 +165,17 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
));
|
));
|
||||||
} else if (step.stepType == StepType.PACKAGES) {
|
} else if (step.stepType == StepType.PACKAGES) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: PackagesWidget(
|
child: PackageSelectionWidget(
|
||||||
sender: widget.sender,
|
sender: widget.sender,
|
||||||
consignee: widget.consignee,
|
consignee: widget.consignee,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
onContinue: (packages) {
|
onContinue: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_packages = List.from(packages);
|
|
||||||
currentStep += 1;
|
currentStep += 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onPrevious: (packages) {
|
onPrevious: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_packages = List.from(packages);
|
|
||||||
currentStep -= 1;
|
currentStep -= 1;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -220,7 +217,6 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
height: _height,
|
height: _height,
|
||||||
lastMile: _selectedLastMile,
|
lastMile: _selectedLastMile,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
packages: _packages,
|
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
surchareItems: _surchareItems,
|
surchareItems: _surchareItems,
|
||||||
onCreate: () {
|
onCreate: () {
|
||||||
@@ -236,7 +232,6 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
_create() async {
|
_create() async {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
@@ -272,7 +267,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
length: length,
|
length: length,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
packages: _packages,
|
// packages: _packages,
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
surchareItems: _surchareItems);
|
surchareItems: _surchareItems);
|
||||||
var c = await context.read<CartonModel>().createCarton(carton);
|
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/carton_size.dart';
|
||||||
import '../../../domain/entities/fcs_shipment.dart';
|
import '../../../domain/entities/fcs_shipment.dart';
|
||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.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';
|
||||||
@@ -24,7 +22,7 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
final User consingee;
|
final User consingee;
|
||||||
final String billToValue;
|
final String billToValue;
|
||||||
final FcsShipment shipment;
|
final FcsShipment shipment;
|
||||||
final List<Package> packages;
|
// final List<Package> packages;
|
||||||
final String cartonSizeType;
|
final String cartonSizeType;
|
||||||
final CartonSize? standardSize;
|
final CartonSize? standardSize;
|
||||||
final double length;
|
final double length;
|
||||||
@@ -44,7 +42,7 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
this.onCreate,
|
this.onCreate,
|
||||||
this.onPrevious,
|
this.onPrevious,
|
||||||
required this.shipment,
|
required this.shipment,
|
||||||
this.packages = const [],
|
// this.packages = const [],
|
||||||
this.standardSize,
|
this.standardSize,
|
||||||
required this.cartonSizeType,
|
required this.cartonSizeType,
|
||||||
required this.lastMile,
|
required this.lastMile,
|
||||||
@@ -196,42 +194,42 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final packagesBox = Padding(
|
// final packagesBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
// padding: const EdgeInsets.only(top: 10),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
// child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||||
Padding(
|
// Padding(
|
||||||
padding: const EdgeInsets.only(left: 5, bottom: 5),
|
// padding: const EdgeInsets.only(left: 5, bottom: 5),
|
||||||
child: LocalText(context, 'box.package.count',
|
// child: LocalText(context, 'box.package.count',
|
||||||
translationVariables: [packages.length.toString()],
|
// translationVariables: [packages.length.toString()],
|
||||||
color: primaryColor,
|
// color: primaryColor,
|
||||||
fontSize: 16,
|
// fontSize: 16,
|
||||||
fontWeight: FontWeight.normal),
|
// fontWeight: FontWeight.normal),
|
||||||
),
|
// ),
|
||||||
Container(
|
// Container(
|
||||||
decoration: BoxDecoration(
|
// decoration: BoxDecoration(
|
||||||
border: Border.all(color: primaryColor),
|
// border: Border.all(color: primaryColor),
|
||||||
borderRadius: BorderRadius.circular(5),
|
// borderRadius: BorderRadius.circular(5),
|
||||||
),
|
// ),
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
// padding: const EdgeInsets.all(8.0),
|
||||||
child: Wrap(
|
// child: Wrap(
|
||||||
spacing: 15,
|
// spacing: 15,
|
||||||
children: packages.map((e) {
|
// children: packages.map((e) {
|
||||||
return SizedBox(
|
// return SizedBox(
|
||||||
width: MediaQuery.of(context).size.width / 2.5,
|
// width: MediaQuery.of(context).size.width / 2.5,
|
||||||
child: Padding(
|
// child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
// padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Text(
|
// child: Text(
|
||||||
e.trackingID ?? "",
|
// e.trackingID ?? "",
|
||||||
style: TextStyle(color: Colors.black, fontSize: 15),
|
// style: TextStyle(color: Colors.black, fontSize: 15),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
);
|
// );
|
||||||
}).toList()),
|
// }).toList()),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
]),
|
// ]),
|
||||||
);
|
// );
|
||||||
|
|
||||||
final cargosBox = Padding(
|
final cargosBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
@@ -245,7 +243,8 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.normal),
|
fontWeight: FontWeight.normal),
|
||||||
Text("${removeTrailingZeros(totalWeight)} lb",
|
Text(
|
||||||
|
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(totalWeight)) ?? 0)} lb",
|
||||||
style: TextStyle(color: Colors.black, fontSize: 15))
|
style: TextStyle(color: Colors.black, fontSize: 15))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -264,37 +263,121 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
children: cargoTypes.map((e) {
|
children: cargoTypes.map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Row(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
e.name ?? "",
|
e.name ?? "",
|
||||||
style:
|
style: TextStyle(
|
||||||
TextStyle(color: Colors.black, fontSize: 15),
|
color: Colors.black, fontSize: 15),
|
||||||
),
|
),
|
||||||
Text("${removeTrailingZeros(e.weight)} lb",
|
Text(
|
||||||
|
"${twoDecimalFormatted(double.tryParse(removeTrailingZeros(e.weight)) ?? 0)} lb",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.black, fontSize: 15))
|
color: Colors.black, fontSize: 15))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
e.isMixCargo
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 20),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment:
|
||||||
|
CrossAxisAlignment.start,
|
||||||
|
children: e.mixCargoes.map((c) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 2),
|
||||||
|
child: Text(
|
||||||
|
"- ${c.name}",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: labelColor),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}).toList()),
|
}).toList()),
|
||||||
const SizedBox(height: 10),
|
)
|
||||||
|
: const SizedBox()
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList()),
|
||||||
|
// const SizedBox(height: 10),
|
||||||
|
// Column(
|
||||||
|
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
// children: surchareItems.map((e) {
|
||||||
|
// return Padding(
|
||||||
|
// padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
|
// child: Row(
|
||||||
|
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
// children: [
|
||||||
|
// Text(
|
||||||
|
// e.name ?? "",
|
||||||
|
// style: TextStyle(color: labelColor, fontSize: 15),
|
||||||
|
// ),
|
||||||
|
// Text("${numberFormatter.format(e.qty)} pc",
|
||||||
|
// style:
|
||||||
|
// TextStyle(color: labelColor, fontSize: 15))
|
||||||
|
// ],
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }).toList()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
|
||||||
|
final surChargeItemsBox = Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 10),
|
||||||
|
child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 5, bottom: 5, right: 8),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
LocalText(context, 'box.input_surcharge_item',
|
||||||
|
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: Column(
|
||||||
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: surchareItems.map((e) {
|
children: surchareItems.map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Row(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
e.name ?? "",
|
e.name ?? "",
|
||||||
style: TextStyle(color: labelColor, fontSize: 15),
|
style: TextStyle(
|
||||||
|
color: Colors.black, fontSize: 15),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"${removeTrailingZeros((e.qty).toDouble())} pc",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.black, fontSize: 15))
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Text("${numberFormatter.format(e.qty)} pc",
|
|
||||||
style:
|
|
||||||
TextStyle(color: labelColor, fontSize: 15))
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -365,9 +448,11 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
shipmentBox,
|
shipmentBox,
|
||||||
const SizedBox(height: 10),
|
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),
|
const SizedBox(height: 10),
|
||||||
cargosBox,
|
surchareItems.isNotEmpty ? surChargeItemsBox : const SizedBox(),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
|
import '../main/util.dart';
|
||||||
import '../widgets/local_text.dart';
|
import '../widgets/local_text.dart';
|
||||||
import 'carton_info.dart';
|
import 'carton_info.dart';
|
||||||
|
|
||||||
@@ -99,7 +100,7 @@ class MixCartonDetailList extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"${carton.cartonWeight.toStringAsFixed(2)} lb",
|
"${twoDecimalFormatted(carton.cartonWeight)} lb",
|
||||||
style: TextStyle(fontSize: 14.0, color: Colors.grey),
|
style: TextStyle(fontSize: 14.0, color: Colors.grey),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -5,43 +5,53 @@ import 'package:logging/logging.dart';
|
|||||||
|
|
||||||
import '../../../constants.dart';
|
import '../../../constants.dart';
|
||||||
import '../../../domain/entities/package.dart';
|
import '../../../domain/entities/package.dart';
|
||||||
|
import '../../../pagination/paginator_listener.dart';
|
||||||
import '../../main/model/base_model.dart';
|
import '../../main/model/base_model.dart';
|
||||||
|
|
||||||
class PackageSelectionModel extends BaseModel {
|
class PackageSelectionModel extends BaseModel {
|
||||||
final log = Logger("PackageSelectionModel");
|
final log = Logger("PackageSelectionModel");
|
||||||
String query = "";
|
PaginatorListener<Package>? getPackages;
|
||||||
List<Package> packages = [];
|
|
||||||
List<Package> selectedPackages = [];
|
|
||||||
|
|
||||||
|
List<Package> packages = [];
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
DocumentSnapshot? _lastDocument;
|
DocumentSnapshot? _lastDocument;
|
||||||
bool ended = false;
|
bool ended = false;
|
||||||
|
|
||||||
Timer? t;
|
@override
|
||||||
search(String term,
|
logout() async {
|
||||||
{bool imm = false,
|
|
||||||
required String shipmentId,
|
|
||||||
required String senderId,
|
|
||||||
required String consigneeId}) async {
|
|
||||||
query = term;
|
|
||||||
packages.clear();
|
packages.clear();
|
||||||
_lastDocument = null;
|
getPackages?.close();
|
||||||
ended = false;
|
}
|
||||||
t?.cancel();
|
|
||||||
t = Timer(Duration(milliseconds: imm ? 0 : 800), () async {
|
loadPackages(
|
||||||
await refresh(
|
{required String senderId,
|
||||||
term: term,
|
required String consigneeId,
|
||||||
shipmentId: shipmentId,
|
required String shipmentId}) {
|
||||||
consigneeId: consigneeId,
|
if (user == null) return;
|
||||||
senderId: senderId);
|
|
||||||
});
|
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(
|
Future<void> refresh(
|
||||||
{required String shipmentId,
|
{required String shipmentId,
|
||||||
required String senderId,
|
required String senderId,
|
||||||
required String consigneeId,
|
required String consigneeId}) async {
|
||||||
String term = ""}) async {
|
|
||||||
packages.clear();
|
packages.clear();
|
||||||
_lastDocument = null;
|
_lastDocument = null;
|
||||||
ended = false;
|
ended = false;
|
||||||
@@ -49,15 +59,14 @@ class PackageSelectionModel extends BaseModel {
|
|||||||
shipmentId: shipmentId,
|
shipmentId: shipmentId,
|
||||||
senderId: senderId,
|
senderId: senderId,
|
||||||
consigneeId: consigneeId,
|
consigneeId: consigneeId,
|
||||||
term: term);
|
);
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadMoreData(
|
Future<void> loadMoreData(
|
||||||
{required String shipmentId,
|
{required String shipmentId,
|
||||||
required String senderId,
|
required String senderId,
|
||||||
required String consigneeId,
|
required String consigneeId}) async {
|
||||||
String term = ""}) async {
|
|
||||||
int rowPerPage = 20;
|
int rowPerPage = 20;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -69,12 +78,9 @@ class PackageSelectionModel extends BaseModel {
|
|||||||
whereIn: [package_processed_status, package_packed_status])
|
whereIn: [package_processed_status, package_packed_status])
|
||||||
.where("sender_id", isEqualTo: senderId)
|
.where("sender_id", isEqualTo: senderId)
|
||||||
.where("user_id", isEqualTo: consigneeId)
|
.where("user_id", isEqualTo: consigneeId)
|
||||||
|
.where("fcs_shipment_id", isEqualTo: shipmentId)
|
||||||
.where("is_deleted", isEqualTo: false);
|
.where("is_deleted", isEqualTo: false);
|
||||||
|
|
||||||
if (term != "") {
|
|
||||||
query = query.where("tracking_id", isEqualTo: term);
|
|
||||||
}
|
|
||||||
|
|
||||||
query = query.orderBy("created_date", descending: true);
|
query = query.orderBy("created_date", descending: true);
|
||||||
|
|
||||||
if (_lastDocument != null) {
|
if (_lastDocument != null) {
|
||||||
@@ -92,10 +98,6 @@ class PackageSelectionModel extends BaseModel {
|
|||||||
return p;
|
return p;
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
for (var p in list) {
|
|
||||||
selectedPackages.contains(p) ? p.isChecked = true : p.isChecked = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
packages.addAll(list);
|
packages.addAll(list);
|
||||||
if (list.length < rowPerPage) ended = true;
|
if (list.length < rowPerPage) ended = true;
|
||||||
notifyListeners();
|
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() {
|
clearSelection() {
|
||||||
selectedPackages.clear();
|
|
||||||
packages.clear();
|
packages.clear();
|
||||||
query = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Package>> getPackagesBySenderAndConsigneeId(
|
Future<List<Package>> getPackagesBySenderAndConsigneeId(
|
||||||
@@ -174,4 +162,21 @@ class PackageSelectionModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
return list;
|
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/domain/entities/package.dart';
|
||||||
import 'package:fcs/helpers/theme.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/package/package_info.dart';
|
||||||
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../pagination/paginator_listview.dart';
|
||||||
import '../widgets/local_text.dart';
|
import '../widgets/local_text.dart';
|
||||||
|
|
||||||
class PackageDetailList extends StatelessWidget {
|
class PackageDetailList extends StatefulWidget {
|
||||||
final String cartonNumber;
|
final String cartonNumber;
|
||||||
final List<Package> packages;
|
final int packageCount;
|
||||||
PackageDetailList(
|
final String senderID;
|
||||||
{super.key, required this.cartonNumber, required this.packages});
|
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("#,###");
|
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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var packageModel = context.watch<PackageSelectionModel>();
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: LocalAppBar(
|
appBar: LocalAppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
@@ -31,19 +61,19 @@ class PackageDetailList extends StatelessWidget {
|
|||||||
"box.package.count",
|
"box.package.count",
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
translationVariables: [numberFormatter.format(packages.length)],
|
translationVariables: [
|
||||||
|
numberFormatter.format(widget.packageCount)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
Text(cartonNumber,
|
Text(widget.cartonNumber,
|
||||||
style: TextStyle(fontSize: 15, color: Colors.black))
|
style: TextStyle(fontSize: 15, color: Colors.black))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: ListView.separated(
|
body: PaginatorListView<Package>(
|
||||||
separatorBuilder: (context, index) =>
|
paginatorListener: packageModel.getPackages!,
|
||||||
Divider(height: 1, color: dividerColor),
|
rowBuilder: (p) {
|
||||||
itemCount: packages.length,
|
Package package = p;
|
||||||
itemBuilder: (BuildContext context, int index) {
|
|
||||||
var package = packages[index];
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
@@ -106,6 +136,6 @@ class PackageDetailList extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
));
|
color: primaryColor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,32 +74,38 @@ class PackageSelectionResult extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: new Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(
|
padding: const EdgeInsets.symmetric(
|
||||||
vertical: 8.0),
|
vertical: 8.0),
|
||||||
child: new Column(
|
child: Column(
|
||||||
crossAxisAlignment:
|
crossAxisAlignment:
|
||||||
CrossAxisAlignment.start,
|
CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new Text(package.trackingID ?? "",
|
Text(package.trackingID ?? "",
|
||||||
style: new TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 15.0,
|
fontSize: 15.0,
|
||||||
color: Colors.black)),
|
color: Colors.black)),
|
||||||
new Text(
|
Text(
|
||||||
package.cartonIds.isEmpty
|
package.market != null &&
|
||||||
? "-"
|
package.market != ""
|
||||||
: "${numberFormatter.format(package.cartonIds.length)} Boxes",
|
? "${package.market}"
|
||||||
style: new TextStyle(
|
: "-",
|
||||||
|
style: TextStyle(
|
||||||
fontSize: 15.0,
|
fontSize: 15.0,
|
||||||
color: Colors.grey),
|
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/domain/entities/fcs_shipment.dart';
|
||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.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/package.dart';
|
||||||
import '../../domain/entities/user.dart';
|
import '../../domain/entities/user.dart';
|
||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
import '../widgets/barcode_scanner.dart';
|
import '../package/package_info.dart';
|
||||||
import '../widgets/continue_button.dart';
|
import '../widgets/continue_button.dart';
|
||||||
import '../widgets/local_title.dart';
|
import '../widgets/local_title.dart';
|
||||||
import '../widgets/previous_button.dart';
|
import '../widgets/previous_button.dart';
|
||||||
import 'model/package_selection_model.dart';
|
import 'model/package_selection_model.dart';
|
||||||
import 'package_selection_result.dart';
|
import 'package_selection_result.dart';
|
||||||
|
|
||||||
typedef OnPrevious = Function(List<Package> packages);
|
typedef OnPrevious = Function();
|
||||||
typedef OnContinue = Function(List<Package> packages);
|
typedef OnContinue = Function();
|
||||||
|
|
||||||
class PackageSelectionWidget extends StatefulWidget {
|
class PackageSelectionWidget extends StatefulWidget {
|
||||||
final User sender;
|
final User sender;
|
||||||
final User consignee;
|
final User consignee;
|
||||||
final FcsShipment shipment;
|
final FcsShipment shipment;
|
||||||
final List<Package> packages;
|
|
||||||
final OnPrevious? onPrevious;
|
final OnPrevious? onPrevious;
|
||||||
final OnContinue? onContinue;
|
final OnContinue? onContinue;
|
||||||
|
|
||||||
const PackageSelectionWidget({
|
const PackageSelectionWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.packages,
|
|
||||||
this.onPrevious,
|
this.onPrevious,
|
||||||
this.onContinue,
|
this.onContinue,
|
||||||
required this.shipment,
|
required this.shipment,
|
||||||
@@ -41,8 +39,6 @@ class PackageSelectionWidget extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
||||||
final TextEditingController _controller = TextEditingController();
|
|
||||||
String _query = "";
|
|
||||||
bool _isLoadMore = false;
|
bool _isLoadMore = false;
|
||||||
final _scrollController = ScrollController();
|
final _scrollController = ScrollController();
|
||||||
bool _down = true;
|
bool _down = true;
|
||||||
@@ -60,29 +56,18 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
var searchModel = context.read<PackageSelectionModel>();
|
var packageModel = context.read<PackageSelectionModel>();
|
||||||
_controller.text = searchModel.query;
|
packageModel.refresh(
|
||||||
_query = searchModel.query;
|
|
||||||
|
|
||||||
searchModel.refresh(
|
|
||||||
shipmentId: widget.shipment.id!,
|
shipmentId: widget.shipment.id!,
|
||||||
consigneeId: widget.consignee.id!,
|
consigneeId: widget.consignee.id!,
|
||||||
senderId: widget.sender.id!,
|
senderId: widget.sender.id!,
|
||||||
term: _query);
|
);
|
||||||
|
|
||||||
searchModel.addSelectedPackage(widget.packages);
|
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @override
|
|
||||||
// void didUpdateWidget(covariant PackageSelectionWidget oldWidget) {
|
|
||||||
// _init();
|
|
||||||
// super.didUpdateWidget(oldWidget);
|
|
||||||
// }
|
|
||||||
|
|
||||||
Future<void> _loadMoreData() async {
|
Future<void> _loadMoreData() async {
|
||||||
if (_isLoadMore) return;
|
if (_isLoadMore) return;
|
||||||
var model = context.read<PackageSelectionModel>();
|
var model = context.read<PackageSelectionModel>();
|
||||||
@@ -95,7 +80,7 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
shipmentId: widget.shipment.id!,
|
shipmentId: widget.shipment.id!,
|
||||||
consigneeId: widget.consignee.id!,
|
consigneeId: widget.consignee.id!,
|
||||||
senderId: widget.sender.id!,
|
senderId: widget.sender.id!,
|
||||||
term: _query);
|
);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoadMore = false;
|
_isLoadMore = false;
|
||||||
@@ -105,8 +90,7 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var model = context.watch<PackageSelectionModel>();
|
var model = context.watch<PackageSelectionModel>();
|
||||||
List<Package> searchResults = model.packages;
|
List<Package> packages = model.packages;
|
||||||
List<Package> selectedPackageList = model.selectedPackages;
|
|
||||||
|
|
||||||
final senderBox = userDisplayBox(context,
|
final senderBox = userDisplayBox(context,
|
||||||
lableKey: "box.sender.title",
|
lableKey: "box.sender.title",
|
||||||
@@ -132,103 +116,23 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
|
|
||||||
final continueBtn = ContinueButton(
|
final continueBtn = ContinueButton(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (selectedPackageList.isEmpty || searchResults.isEmpty) {
|
if (packages.isEmpty) {
|
||||||
showMsgDialog(context, 'Error', "Please select the packages");
|
showMsgDialog(context, 'Error', "Please add the packages");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (widget.onContinue != null) {
|
if (widget.onContinue != null) {
|
||||||
widget.onContinue!(selectedPackageList);
|
widget.onContinue!();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final previousBtn = PreviousButton(onTap: () {
|
final previousBtn = PreviousButton(onTap: () {
|
||||||
if (widget.onPrevious != null) {
|
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(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -255,8 +159,6 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
LocalTitle(
|
LocalTitle(
|
||||||
textKey: "box.select.package", topPadding: 5),
|
textKey: "box.select.package", topPadding: 5),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
searchBox,
|
|
||||||
selectedPackageBox,
|
|
||||||
])
|
])
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
),
|
),
|
||||||
@@ -273,11 +175,12 @@ class _PackageSelectionWidgetState extends State<PackageSelectionWidget> {
|
|||||||
_down = true;
|
_down = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onTap: (a) async {
|
onTap: (a) {
|
||||||
setState(() {
|
Navigator.push(
|
||||||
a.isChecked = !a.isChecked;
|
context,
|
||||||
});
|
CupertinoPageRoute(
|
||||||
context.read<PackageSelectionModel>().selectPackage(a);
|
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/material.dart';
|
||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
import '../../main/util.dart';
|
||||||
import '../carton_info.dart';
|
import '../carton_info.dart';
|
||||||
import '../print_qr_code_page.dart';
|
import '../print_qr_code_page.dart';
|
||||||
|
|
||||||
class CartonListRow extends StatelessWidget {
|
class CartonListRow extends StatelessWidget {
|
||||||
final Carton box;
|
final Carton box;
|
||||||
CartonListRow({Key? key, required this.box}) : super(key: key);
|
CartonListRow({super.key, required this.box});
|
||||||
|
|
||||||
final double dotSize = 15.0;
|
final double dotSize = 15.0;
|
||||||
final DateFormat dateFormat = new DateFormat("dd MMM yyyy");
|
final DateFormat dateFormat = DateFormat("dd MMM yyyy");
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -28,9 +29,9 @@ class CartonListRow extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: new Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
padding: const EdgeInsets.symmetric(vertical: 10.0),
|
||||||
child: new Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.only(left: 0),
|
padding: EdgeInsets.only(left: 0),
|
||||||
@@ -40,24 +41,24 @@ class CartonListRow extends StatelessWidget {
|
|||||||
size: 30,
|
size: 30,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
new Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 15.0),
|
padding: const EdgeInsets.only(left: 15.0),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
new Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new Text(
|
Text(
|
||||||
box.cartonNumber ?? "",
|
box.cartonNumber ?? "",
|
||||||
style: new TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 15.0, color: Colors.black),
|
fontSize: 15.0, color: Colors.black),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: new Text(
|
child: Text(
|
||||||
box.consigneeName ?? "",
|
box.consigneeName ?? "",
|
||||||
style: new TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 15.0, color: Colors.grey),
|
fontSize: 15.0, color: Colors.grey),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -95,10 +96,9 @@ class CartonListRow extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
new Text(
|
Text(
|
||||||
"${box.cartonWeight.toStringAsFixed(2)} lb",
|
"${twoDecimalFormatted(box.cartonWeight)} lb",
|
||||||
style:
|
style: TextStyle(fontSize: 14.0, color: Colors.grey),
|
||||||
new TextStyle(fontSize: 14.0, color: Colors.grey),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -410,6 +410,11 @@ String removeTrailingZeros(double number) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String twoDecimalFormatted(double number) {
|
||||||
|
String formattedString = number.toStringAsFixed(2);
|
||||||
|
return formattedString;
|
||||||
|
}
|
||||||
|
|
||||||
bool isValidEmail(String email) {
|
bool isValidEmail(String email) {
|
||||||
// Define a regular expression for validating an email
|
// Define a regular expression for validating an email
|
||||||
final emailRegex = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$');
|
final emailRegex = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$');
|
||||||
@@ -561,4 +566,3 @@ Widget settingRow(BuildContext context,
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user