update cargo type form from rate, update carton info and form

This commit is contained in:
tzw
2024-09-25 21:49:09 +06:30
parent 1be18c08a9
commit 02e079c514
51 changed files with 1407 additions and 643 deletions

View File

@@ -0,0 +1,114 @@
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../main/util.dart';
class CargoTypeAddition extends StatefulWidget {
final List<CargoType> cargoTypes;
const CargoTypeAddition({super.key, required this.cargoTypes});
@override
_CargoTypeAdditionState createState() => _CargoTypeAdditionState();
}
class _CargoTypeAdditionState extends State<CargoTypeAddition> {
bool _isLoading = false;
List<CargoType> cargoTypes = [];
@override
void initState() {
_init();
super.initState();
}
_init() {
var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false);
cargoTypes =
shipmentRateModel.rate.cargoTypes.map((e) => e.clone()).toList();
for (var p in cargoTypes) {
p.qty = 0;
if (widget.cargoTypes.any((e) => e.id == p.id)) {
p.isChecked = true;
} else {
p.isChecked = false;
}
widget.cargoTypes.forEach((vp) {
if (p.id == vp.id) {
p.qty = vp.qty;
}
});
}
if (mounted) {
setState(() {});
}
}
_onTap(CargoType cargo) {
if (cargo.isChecked) {
showMsgDialog(context, "Error", "Already exit!");
return;
}
Navigator.pop(context, cargo);
}
@override
Widget build(BuildContext context) {
List<Widget> getCargoRowList(List<CargoType> _c) {
return _c.map((c) {
return ListTile(
onTap: () {
_onTap(c);
},
title: new Text(c.name ?? '', style: textStyle),
trailing: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
minimumSize: Size(80, 35)),
onPressed: c.isChecked
? null
: () {
_onTap(c);
},
child: Text(
"Add",
style: TextStyle(color: Colors.white, fontSize: 14),
),
));
}).toList();
}
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: LocalAppBar(
labelKey: 'box.add.cargo_type',
backgroundColor: Colors.white,
labelColor: primaryColor,
arrowColor: primaryColor),
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
shrinkWrap: true,
children: <Widget>[
Column(
children: getCargoRowList(cargoTypes),
),
SizedBox(height: 30),
],
),
),
),
);
}
}

View File

@@ -12,7 +12,8 @@ import '../widgets/continue_button.dart';
import '../widgets/display_text.dart';
import '../widgets/local_title.dart';
import '../widgets/previous_button.dart';
import 'custom_duty_addition.dart';
import 'cargo_type_addition.dart';
import 'surcharge_item_addition.dart';
typedef OnPrevious = Function(
List<CargoType> cargoTypes, List<CargoType> customDuties);
@@ -56,28 +57,20 @@ class _CargoWidgetState extends State<CargoWidget> {
_init() {
// for cargo types
var model = context.read<ShipmentRateModel>();
_cargoTypes = model.rate.cargoTypes.map((e) => e.clone()).toList();
if (widget.cargoTypes.isNotEmpty) {
_cargoTypes.forEach((mp) {
mp.weight = 0;
widget.cargoTypes.forEach((vp) {
if (mp.id == vp.id) {
mp.weight = vp.weight;
}
});
});
_cargoTypes = List.from(widget.cargoTypes);
_cargoTypes.forEach((e) {
var editor = new TextEditingController();
editor.text = removeTrailingZeros(e.weight);
editor.addListener(inputChangeListener);
_cargoTypeControllers.add(editor);
});
double total = _cargoTypes.fold(0, (sum, value) => sum + value.weight);
_totalCtl.text = removeTrailingZeros(total);
_calculateTotalWeght();
} else {
var model = context.read<ShipmentRateModel>();
var cargoes = model.rate.cargoTypes.map((e) => e.clone()).toList();
_cargoTypes = cargoes.where((e) => e.isDefault).toList();
_cargoTypes.forEach((e) {
var editor = new TextEditingController();
editor.text = '';
@@ -103,6 +96,11 @@ class _CargoWidgetState extends State<CargoWidget> {
}
}
_calculateTotalWeght() {
double total = _cargoTypes.fold(0, (sum, value) => sum + value.weight);
_totalCtl.text = removeTrailingZeros(total);
}
bool isFieldEmpty(int index) {
return _cargoTypeControllers[index].text.isEmpty;
}
@@ -158,6 +156,39 @@ class _CargoWidgetState extends State<CargoWidget> {
],
);
final cargoTitle = LocalTitle(
textKey: "box.input_cargo_weight",
topPadding: 0,
trailing: IconButton(
icon: Icon(
Icons.add_circle,
color: primaryColor,
),
onPressed: () async {
CargoType? cargoType = await Navigator.push(
context,
CupertinoPageRoute(
builder: (context) =>
CargoTypeAddition(cargoTypes: _cargoTypes)));
if (cargoType == null) return;
_cargoTypes.add(cargoType);
_cargoTypeControllers.clear();
_cargoTypes.forEach((e) {
var editor = new TextEditingController();
editor.text = removeTrailingZeros(e.weight);
editor.addListener(inputChangeListener);
_cargoTypeControllers.add(editor);
});
_calculateTotalWeght();
if (mounted) {
setState(() {});
}
}),
);
final cargosBox = Wrap(
alignment: WrapAlignment.spaceBetween,
runSpacing: 15,
@@ -171,6 +202,8 @@ class _CargoWidgetState extends State<CargoWidget> {
InkResponse(
radius: 25,
onTap: () {
_cargoTypes.removeAt(key);
double totalWeight = double.tryParse(_totalCtl.text) ?? 0;
double removeWeight =
(double.tryParse(_cargoTypeControllers[key].text) ??
@@ -182,11 +215,12 @@ class _CargoWidgetState extends State<CargoWidget> {
}
_cargoTypeControllers[key].clear();
if (mounted) {
setState(() {});
}
},
child: Icon(MaterialIcons.clear, color: labelColor)),
child: Icon(Feather.minus_circle, color: labelColor)),
const SizedBox(width: 10),
Flexible(
child: inputTextFieldWidget(context,
@@ -254,14 +288,14 @@ class _CargoWidgetState extends State<CargoWidget> {
color: primaryColor,
),
onPressed: () async {
List<CargoType>? customList = await Navigator.push<List<CargoType>>(
CargoType? surchargeItem = await Navigator.push(
context,
CupertinoPageRoute(
builder: (context) =>
CustomDutyAddition(customDuties: _surchareItems)));
if (customList == null) return;
SurchargeItemAddition(items: _surchareItems)));
if (surchargeItem == null) return;
_surchareItems = List.from(customList);
_surchareItems.add(surchargeItem);
_surchargeControllers.clear();
_surchareItems.asMap().entries.forEach((e) {
@@ -315,10 +349,11 @@ class _CargoWidgetState extends State<CargoWidget> {
final continueBtn = ContinueButton(
onTap: () {
if (widget.onContinue != null) {
if(_surchareItems.isNotEmpty && _surchareItems.any((item)=> item.qty == 0)){
showMsgDialog(context, "Error", "Please insert surcharge item quantity");
return;
if (_surchareItems.isNotEmpty &&
_surchareItems.any((item) => item.qty == 0)) {
showMsgDialog(
context, "Error", "Please insert surcharge item quantity");
return;
}
widget.onContinue!(_cargoTypes, _surchareItems);
@@ -341,7 +376,7 @@ class _CargoWidgetState extends State<CargoWidget> {
children: [
const SizedBox(height: 8),
userRow,
LocalTitle(textKey: "box.input_cargo_weight", topPadding: 5),
cargoTitle,
cargosBox,
const SizedBox(height: 15),
Divider(),

View File

@@ -56,7 +56,9 @@ class _CartonEditorState extends State<CartonEditor> {
_isNew = false;
_consignee = User(
id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
id: _carton!.consigneeID,
fcsID: _carton!.consigneeFCSID,
name: _carton!.consigneeName);
_sender = User(
id: _carton!.senderID,
fcsID: _carton!.senderFCSID,
@@ -129,7 +131,7 @@ class _CartonEditorState extends State<CartonEditor> {
padding: const EdgeInsets.only(right: 5),
child: InkResponse(
radius: 30,
onTap: () {
onTap: () async {
//for packages
if (isFromPackages) {
if (_sender == null) {
@@ -149,20 +151,32 @@ class _CartonEditorState extends State<CartonEditor> {
return;
}
Navigator.push(
Carton? carton = await Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => CartonPackageForm(
sender: _sender!,
consignee: _consignee!,
)));
if (carton != null) {
setState(() {
_cartons.add(carton);
});
}
}
// for mix cartion
else {
Navigator.push(
Carton? carton = await Navigator.push(
context,
CupertinoPageRoute(
builder: (context) => const MixCartonForm()));
if (carton != null) {
setState(() {
_cartons.add(carton);
});
}
}
},
child: Icon(Icons.add_circle, color: primaryColor),

View File

@@ -18,6 +18,7 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
import '../../domain/entities/carton_size.dart';
import '../carton_size/model/carton_size_model.dart';
import '../widgets/local_button.dart';
import 'carton_package_editor.dart';
import 'mix_carton/mix_carton_editor.dart';
@@ -56,27 +57,41 @@ class _CartonInfoState extends State<CartonInfo> {
_init() async {
try {
_isLoading = true;
_carton.cartonType = carton_from_packages;
_carton.billTo = billToConsignee;
_carton.cartonSizeType = customCarton;
_multiImgController.setImageUrls = _carton.photoUrls;
_cargoTypes = _carton.cargoTypes.where((e) => !e.isCutomDuty).toList();
_surchareItems = _carton.cargoTypes.where((e) => e.isCutomDuty).toList();
_cargoTypes = _carton.cargoTypes;
_surchareItems = _carton.surchareItems;
// check carton size type
List<CartonSize> cartonSizes =
context.read<CartonSizeModel>().cartonSizes;
var sameLength = cartonSizes.any((size) => size.length == _carton.length);
var sameWidth = cartonSizes.any((size) => size.width == _carton.width);
var sameHeight = cartonSizes.any((size) => size.height == _carton.height);
bool isStandartSize = sameLength && sameWidth && sameHeight;
if (isStandartSize) {
_carton.cartonSizeType = standardCarton;
standardSize = cartonSizes.firstWhere((size) =>
size.length == _carton.length &&
size.width == _carton.width &&
size.height == _carton.height);
} else if (_carton.length == 0 &&
_carton.width == 0 &&
_carton.height == 0) {
_carton.cartonSizeType = packageCarton;
} else {
_carton.cartonSizeType = customCarton;
}
if (_carton.cartonType == carton_from_packages) {
_carton.deliveryType = delivery_caton;
_packages = await context
.read<PackageModel>()
.getPackagesByIds(_carton.packageIDs);
}
if (_carton.cartonType == carton_mix_carton) {
if (_carton.cartonType == mix_carton) {
_mixCartons = await context
.read<CartonModel>()
.getCartonsByIds(_carton.mixCartonIDs);
}
if (mounted) {
setState(() {});
.getCartonsByIds(_carton.cartonIDs);
}
totalWeight =
@@ -86,17 +101,23 @@ class _CartonInfoState extends State<CartonInfo> {
} finally {
_isLoading = false;
}
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
String? boxDimension = _carton.cartonSizeType == standardCarton
var fromPackage = _carton.cartonType == carton_from_packages;
String? boxDimension = _carton.cartonSizeType == standardCarton
? "${standardSize?.name} - ${standardSize?.length.toInt()}”x${standardSize?.width.toInt()}”x${standardSize?.height.toInt()}"
: _carton.cartonSizeType == customCarton
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}"
: null;
final cartonTypeBox = DisplayText(
final cartonNumberBox = DisplayText(
text: _carton.cartonNumber,
labelTextKey: "box.number",
);
@@ -111,10 +132,12 @@ class _CartonInfoState extends State<CartonInfo> {
},
icon: Icon(AntDesign.qrcode, color: Colors.black));
final cartonSubTypeBox = DisplayText(
final cartonTypeBox = DisplayText(
text: _carton.cartonType == carton_from_packages
? "For packages"
: "Mix carton",
: _carton.cartonType == mix_carton
? carton_mix_carton
: '',
labelTextKey: "box.carton.type",
);
@@ -132,13 +155,13 @@ class _CartonInfoState extends State<CartonInfo> {
labelTextKey: "box.fcs_shipment_num",
);
final deliveryBox = DisplayText(
text: _carton.deliveryType,
final lastMileBox = DisplayText(
text: _carton.lastMile == delivery_caton ? 'Delivery' : 'Pick-up',
labelTextKey: "box.delivery_type",
);
final cartonSizeBox = DisplayText(
subText: boxDimension == null ? null : Text("$boxDimension"),
subText: Text("${boxDimension ?? 'No defined size'}"),
labelTextKey: "box.carton_size",
);
@@ -149,8 +172,8 @@ class _CartonInfoState extends State<CartonInfo> {
);
final consigneeNameBox = DisplayText(
text: _carton.userName != null ? _carton.userName : "",
subText: Text(_carton.fcsID ?? "", style: textStyle),
text: _carton.consigneeName != null ? _carton.consigneeName : "",
subText: Text(_carton.consigneeFCSID ?? "", style: textStyle),
labelTextKey: "processing.consignee.name",
);
@@ -367,30 +390,29 @@ class _CartonInfoState extends State<CartonInfo> {
padding: const EdgeInsets.only(left: 20, right: 20),
child: ListView(children: <Widget>[
Row(children: [
Flexible(child: cartonTypeBox,flex: 1),
Flexible(child: cartonNumberBox, flex: 1),
Flexible(
child: cartonQrBox,
),
]),
Row(
children: [
Flexible(child: cartonSubTypeBox),
Flexible(child: cartonTypeBox),
],
),
_mixCartons.isEmpty ? userRowBox : const SizedBox(),
fromPackage ? userRowBox : const SizedBox(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(child: billInfoBox),
fromPackage ? Flexible(child: billInfoBox) : SizedBox(),
Flexible(child: shipmentBox),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
_mixCartons.isEmpty
? Flexible(child: deliveryBox)
fromPackage
? Flexible(child: lastMileBox)
: const SizedBox(),
Flexible(child: cartonSizeBox),
],
@@ -430,7 +452,9 @@ class _CartonInfoState extends State<CartonInfo> {
uploadImageBtn,
const SizedBox(height: 30),
img,
const SizedBox(height: 40),
_carton.photoUrls.isNotEmpty
? const SizedBox(height: 40)
: const SizedBox(),
deleteBtn,
const SizedBox(height: 20)
]))));
@@ -457,17 +481,22 @@ class _CartonInfoState extends State<CartonInfo> {
}
_gotoEditor() async {
bool? updated = _carton.cartonType == carton_mix_carton
? await Navigator.push<bool>(
context,
CupertinoPageRoute(
builder: (context) => MixCartonEditor(carton: _carton)),
)
: await Navigator.push<bool>(
context,
CupertinoPageRoute(
builder: (context) => CartonPackageEditor(carton: _carton)),
);
bool? updated = false;
if (_carton.cartonType == mix_carton) {
updated = await Navigator.push<bool>(
context,
CupertinoPageRoute(
builder: (context) => MixCartonEditor(carton: _carton)),
);
}
if (_carton.cartonType == carton_from_packages) {
updated = await Navigator.push<bool>(
context,
CupertinoPageRoute(
builder: (context) => CartonPackageEditor(carton: _carton)),
);
}
if (updated ?? false) {
Carton? c =
@@ -489,9 +518,8 @@ class _CartonInfoState extends State<CartonInfo> {
_isLoading = true;
});
try {
// var cartonModel = Provider.of<CartonModel>(context, listen: false);
// await cartonModel.deleteCarton(widget.carton);
// Navigator.pop(context, true);
await context.read<CartonModel>().deleteCarton(widget.carton);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {

View File

@@ -1,5 +1,6 @@
// ignore_for_file: deprecated_member_use
import 'package:fcs/pages/carton/model/carton_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
@@ -14,6 +15,7 @@ import '../../domain/entities/cargo_type.dart';
import '../../domain/entities/carton.dart';
import '../../domain/entities/package.dart';
import '../../domain/entities/user.dart';
import '../carton_size/model/carton_size_model.dart';
import '../fcs_shipment/model/fcs_shipment_model.dart';
import '../main/util.dart';
import '../package/model/package_model.dart';
@@ -53,7 +55,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
double _width = 0;
double _height = 0;
String _selectedDeliveryType = delivery_caton;
String _selectedLastMile = delivery_caton;
String _billToValue = billToSender;
FcsShipment? _shipment;
@@ -78,20 +80,14 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
id: widget.carton.senderID);
_consignee = User(
id: widget.carton.userID,
name: widget.carton.userName,
fcsID: widget.carton.fcsID);
id: widget.carton.consigneeID,
name: widget.carton.consigneeName,
fcsID: widget.carton.consigneeFCSID);
_billToValue = widget.carton.billTo ?? billToSender;
_selectedDeliveryType = widget.carton.deliveryType ?? delivery_caton;
_cartonSizeType = widget.carton.cartonSizeType ?? customCarton;
_length = widget.carton.length;
_width = widget.carton.width;
_height = widget.carton.height;
_cargoTypes =
widget.carton.cargoTypes.where((e) => !e.isCutomDuty).toList();
_surchareItems =
widget.carton.cargoTypes.where((e) => e.isCutomDuty).toList();
_selectedLastMile = widget.carton.lastMile ?? delivery_caton;
_cargoTypes = widget.carton.cargoTypes;
_surchareItems = widget.carton.surchareItems;
var s = await context
.read<FcsShipmentModel>()
@@ -102,6 +98,30 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
.read<PackageModel>()
.getPackagesByIds(widget.carton.packageIDs);
// check carton size type
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
var sameLength =
cartonSizes.any((size) => size.length == widget.carton.length);
var sameWidth =
cartonSizes.any((size) => size.width == widget.carton.width);
var sameHeight =
cartonSizes.any((size) => size.height == widget.carton.height);
bool isStandartSize = sameLength && sameWidth && sameHeight;
if (isStandartSize) {
_cartonSizeType = standardCarton;
_standardSize = cartonSizes.firstWhere((size) =>
size.length == widget.carton.length &&
size.width == widget.carton.width &&
size.height == widget.carton.height);
} else if (widget.carton.length == 0 &&
widget.carton.width == 0 &&
widget.carton.height == 0) {
_cartonSizeType = packageCarton;
} else {
_cartonSizeType = customCarton;
}
if (mounted) {
setState(() {});
}
@@ -143,8 +163,16 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
},
),
backgroundColor: Colors.white,
title: LocalText(context, 'box.update_title',
color: primaryColor, fontSize: 20),
title: Column(
children: [
LocalText(context, 'box.update_title',
color: primaryColor, fontSize: 20),
Text(
widget.carton.cartonNumber ?? '',
style: TextStyle(color: primaryColor, fontSize: 14),
)
],
),
),
body: Column(
children: [
@@ -172,7 +200,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
if (step.stepType == StepType.SIZE) {
return Expanded(
child: CartonSizeWidget(
deliveryType: _selectedDeliveryType,
lastMile: _selectedLastMile,
billType: _billToValue,
sender: _sender!,
consignee: _consignee!,
@@ -188,7 +216,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
onContinue: (deliveryType, billType, shipment, cartonSizeType,
{standardSize, length, width, height}) {
setState(() {
_selectedDeliveryType = deliveryType;
_selectedLastMile = deliveryType;
_billToValue = billType;
_shipment = shipment;
_cartonSizeType = cartonSizeType;
@@ -256,7 +284,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
length: _length,
width: _width,
height: _height,
deliveryType: _selectedDeliveryType,
lastMile: _selectedLastMile,
shipment: _shipment!,
packages: _packages,
cargoTypes: _cargoTypes,
@@ -279,6 +307,40 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
_isLoading = true;
});
try {
double length = 0;
double width = 0;
double height = 0;
if (_cartonSizeType == standardCarton) {
if (_standardSize != null) {
length = _standardSize!.length;
width = _standardSize!.width;
height = _standardSize!.height;
}
} else if (_cartonSizeType == customCarton) {
length = _length;
width = _width;
height = _height;
} else {
length = 0;
width = 0;
height = 0;
}
var carton = Carton(
cartonType: carton_from_packages,
billTo: _billToValue,
lastMile: _selectedLastMile,
fcsShipmentID: _shipment?.id,
length: length,
width: width,
height: height,
packages: _packages,
cargoTypes: _cargoTypes,
surchareItems: _surchareItems);
await context.read<CartonModel>().updateCarton(carton);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());

View File

@@ -1,5 +1,6 @@
// ignore_for_file: deprecated_member_use
import 'package:fcs/domain/entities/carton.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
@@ -20,6 +21,7 @@ import '../widgets/step_widget.dart';
import 'cargo_widget.dart';
import 'carton_size_widget.dart';
import 'carton_submit.dart';
import 'model/carton_model.dart';
import 'model/package_selection_model.dart';
import 'package_selection_widget.dart';
@@ -55,7 +57,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
double _width = 0;
double _height = 0;
String _selectedDeliveryType = delivery_caton;
String _selectedLastMile = delivery_caton;
String _billToValue = billToSender;
FcsShipment? _shipment;
@@ -134,7 +136,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
if (step.stepType == StepType.SIZE) {
return Expanded(
child: CartonSizeWidget(
deliveryType: _selectedDeliveryType,
lastMile: _selectedLastMile,
billType: _billToValue,
sender: widget.sender,
consignee: widget.consignee,
@@ -147,10 +149,10 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
onPrevious: () {
Navigator.pop(context);
},
onContinue: (deliveryType, billType, shipment, cartonSizeType,
onContinue: (lastMile, billType, shipment, cartonSizeType,
{standardSize, length, width, height}) {
setState(() {
_selectedDeliveryType = deliveryType;
_selectedLastMile = lastMile;
_billToValue = billType;
_shipment = shipment;
_cartonSizeType = cartonSizeType;
@@ -217,7 +219,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
length: _length,
width: _width,
height: _height,
deliveryType: _selectedDeliveryType,
lastMile: _selectedLastMile,
shipment: _shipment!,
packages: _packages,
cargoTypes: _cargoTypes,
@@ -240,7 +242,41 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
_isLoading = true;
});
try {
Navigator.pop(context, true);
double length = 0;
double width = 0;
double height = 0;
if (_cartonSizeType == standardCarton) {
if (_standardSize != null) {
length = _standardSize!.length;
width = _standardSize!.width;
height = _standardSize!.height;
}
} else if (_cartonSizeType == customCarton) {
length = _length;
width = _width;
height = _height;
} else {
length = 0;
width = 0;
height = 0;
}
var carton = Carton(
cartonType: carton_from_packages,
senderID: widget.sender.id,
consigneeID: widget.consignee.id,
billTo: _billToValue,
lastMile: _selectedLastMile,
fcsShipmentID: _shipment?.id,
length: length,
width: width,
height: height,
packages: _packages,
cargoTypes: _cargoTypes,
surchareItems: _surchareItems);
var c = await context.read<CartonModel>().createCarton(carton);
Navigator.pop(context, c);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {

View File

@@ -31,7 +31,7 @@ class CartonSizeWidget extends StatefulWidget {
final OnContinue? onContinue;
final User sender;
final User consignee;
final String deliveryType;
final String lastMile;
final String billType;
final FcsShipment? shipment;
final String cartonSizeType;
@@ -52,7 +52,7 @@ class CartonSizeWidget extends StatefulWidget {
this.height,
required this.sender,
required this.consignee,
required this.deliveryType,
required this.lastMile,
required this.billType})
: super(key: key);
@@ -68,7 +68,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
List<FcsShipment> _shipments = [];
CartonSize? _selectStandardSize;
late String _selectedDeliveryType;
late String _selectedLastmile;
late String _billToValue;
TextEditingController _widthController = new TextEditingController();
@@ -82,13 +82,10 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
}
_init() async {
_selectedDeliveryType = widget.deliveryType;
_selectedLastmile = widget.lastMile;
_billToValue = widget.billType;
_cartonSizeType = widget.cartonSizeType;
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
_lengthController.text =
widget.length == null ? "0" : removeTrailingZeros(widget.length ?? 0);
_widthController.text =
@@ -96,6 +93,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
_heightController.text =
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
_getStandardCartonSize();
_loadShipment();
if (mounted) {
@@ -103,11 +101,24 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
}
}
_getStandardCartonSize() {
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
if (mounted) {
setState(() {});
}
}
_loadShipment() async {
var fcsShipments =
await context.read<FcsShipmentModel>().getActiveFcsShipments();
_shipments = fcsShipments;
_shipment = widget.shipment;
if (_shipments.contains(widget.shipment)) {
_shipment = widget.shipment;
} else {
_shipment = null;
}
if (mounted) {
setState(() {});
}
@@ -116,6 +127,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
@override
void didUpdateWidget(covariant CartonSizeWidget oldWidget) {
_loadShipment();
_getStandardCartonSize();
super.didUpdateWidget(oldWidget);
}
@@ -125,7 +137,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
context.watch<CartonSizeModel>().getCartonSizes;
bool isStandardSize = _cartonSizeType == standardCarton;
bool isCustomSize = _cartonSizeType == customCarton;
bool isNoneDefinedSize = _cartonSizeType == packageCartion;
bool isNoneDefinedSize = _cartonSizeType == packageCarton;
final senderBox = DisplayText(
text: widget.sender.name,
@@ -139,7 +151,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
text: widget.consignee.name,
labelTextKey: "box.consignee.title",
iconData: MaterialCommunityIcons.account_arrow_left,
subText: Text(widget.consignee.fcsID!,
subText: Text(widget.consignee.fcsID ?? '',
style: TextStyle(fontSize: 13, color: labelColor)),
);
@@ -161,16 +173,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
child: InkWell(
onTap: () {
setState(() {
_selectedDeliveryType = delivery_caton;
_selectedLastmile = delivery_caton;
});
},
child: Row(children: <Widget>[
LocalRadio(
value: delivery_caton,
groupValue: _selectedDeliveryType,
groupValue: _selectedLastmile,
onChanged: (p0) {
setState(() {
_selectedDeliveryType = delivery_caton;
_selectedLastmile = delivery_caton;
});
},
),
@@ -179,7 +191,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
padding: const EdgeInsets.only(left: 10),
child: LocalText(context, 'box.delivery',
fontSize: 15,
color: _selectedDeliveryType == delivery_caton
color: _selectedLastmile == delivery_caton
? primaryColor
: Colors.black),
),
@@ -190,16 +202,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
child: InkWell(
onTap: () {
setState(() {
_selectedDeliveryType = pickup_carton;
_selectedLastmile = pickup_carton;
});
},
child: Row(children: <Widget>[
LocalRadio(
value: pickup_carton,
groupValue: _selectedDeliveryType,
groupValue: _selectedLastmile,
onChanged: (p0) {
setState(() {
_selectedDeliveryType = pickup_carton;
_selectedLastmile = pickup_carton;
});
},
),
@@ -208,7 +220,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
padding: const EdgeInsets.only(left: 10),
child: LocalText(context, 'box.pickup',
fontSize: 15,
color: _selectedDeliveryType == pickup_carton
color: _selectedLastmile == pickup_carton
? primaryColor
: Colors.black),
),
@@ -315,7 +327,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
if (widget.onContinue != null) {
widget.onContinue!(
_selectedDeliveryType, _billToValue, _shipment!, _cartonSizeType,
_selectedLastmile, _billToValue, _shipment!, _cartonSizeType,
standardSize: _selectStandardSize, length: l, width: w, height: h);
}
});
@@ -463,16 +475,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
InkWell(
onTap: () {
setState(() {
_cartonSizeType = packageCartion;
_cartonSizeType = packageCarton;
});
},
child: Row(children: <Widget>[
LocalRadio(
value: packageCartion,
value: packageCarton,
groupValue: _cartonSizeType,
onChanged: (p0) {
setState(() {
_cartonSizeType = packageCartion;
_cartonSizeType = packageCarton;
});
},
),

View File

@@ -30,7 +30,7 @@ class CartonSubmit extends StatelessWidget {
final double length;
final double width;
final double height;
final String deliveryType;
final String lastMile;
final List<CargoType> cargoTypes;
final List<CargoType> surchareItems;
final OnCreateCarton? onCreate;
@@ -47,7 +47,7 @@ class CartonSubmit extends StatelessWidget {
this.packages = const [],
this.standardSize,
required this.cartonSizeType,
required this.deliveryType,
required this.lastMile,
this.length = 0,
this.width = 0,
this.height = 0,
@@ -69,10 +69,7 @@ class CartonSubmit extends StatelessWidget {
final cartonType = Padding(
padding: const EdgeInsets.only(top: 10),
child: SubmitTextWidget(
labelKey: 'box.carton.type',
text: carton_from_packages,
// subText: boxDimension
),
labelKey: 'box.carton.type', text: carton_from_packages),
);
final shipmentBox = Padding(
@@ -187,7 +184,7 @@ class CartonSubmit extends StatelessWidget {
padding: const EdgeInsets.only(top: 10),
child: SubmitTextWidget(
labelKey: 'box.select.delivery',
text: deliveryType,
text: lastMile == delivery_caton ? 'Delivery' : 'Pick-up',
),
);
@@ -195,7 +192,7 @@ class CartonSubmit extends StatelessWidget {
padding: const EdgeInsets.only(top: 10),
child: SubmitTextWidget(
labelKey: 'box.carton_size',
text: boxDimension??'',
text: boxDimension ?? 'No defined size',
),
);

View File

@@ -1,131 +0,0 @@
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/local_button.dart';
class CustomDutyAddition extends StatefulWidget {
final List<CargoType> customDuties;
const CustomDutyAddition({super.key, required this.customDuties});
@override
_CustomDutyAdditionState createState() => _CustomDutyAdditionState();
}
class _CustomDutyAdditionState extends State<CustomDutyAddition> {
bool _isLoading = false;
List<CargoType> customDuties = [];
@override
void initState() {
_init();
super.initState();
}
_init() {
var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false);
customDuties =
shipmentRateModel.rate.customDuties.map((e) => e.clone()).toList();
for (var p in customDuties) {
p.qty = 0;
if (widget.customDuties.any((e) => e.id == p.id)) {
p.isChecked = true;
} else {
p.isChecked = false;
}
widget.customDuties.forEach((vp) {
if (p.id == vp.id) {
p.qty = vp.qty;
}
});
}
if (mounted) {
setState(() {});
}
}
@override
Widget build(BuildContext context) {
List<Widget> getCargoRowList(List<CargoType> _c) {
return _c.map((c) {
return Container(
child: Container(
padding:
EdgeInsets.only(left: 10.0, right: 5.0, top: 3.0, bottom: 3.0),
child: InkWell(
onTap: () {
setState(() {
c.isChecked = !c.isChecked;
});
},
child: Row(
children: <Widget>[
Checkbox(
value: c.isChecked,
activeColor: primaryColor,
onChanged: (bool? check) {
setState(() {
c.isChecked = check ?? false;
});
}),
new Text(c.name ?? '', style: textStyle),
],
),
),
),
);
}).toList();
}
final saveBtn = Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
child: LocalButton(
textKey: "box.cargo.select.btn",
callBack: () {
List<CargoType> _cargos =
customDuties.where((c) => c.isChecked).toList();
if (_cargos.isEmpty) {
showMsgDialog(context, 'Error', "Please select the cargo type");
return;
}
Navigator.pop(context, _cargos);
},
),
);
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: LocalAppBar(
labelKey: 'box.select.cargo_type',
backgroundColor: Colors.white,
labelColor: primaryColor,
arrowColor: primaryColor),
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
shrinkWrap: true,
children: <Widget>[
Column(
children: getCargoRowList(customDuties),
),
SizedBox(height: 30),
saveBtn,
SizedBox(height: 20),
],
),
),
),
);
}
}

View File

@@ -12,6 +12,7 @@ import '../../../domain/entities/carton_size.dart';
import '../../../domain/entities/fcs_shipment.dart';
import '../../../domain/vo/local_step.dart';
import '../../../helpers/theme.dart';
import '../../carton_size/model/carton_size_model.dart';
import '../../main/util.dart';
import '../../widgets/local_text.dart';
import '../../widgets/progress.dart';
@@ -58,10 +59,30 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
_init() async {
context.read<CartonSelectionModel>().clearSelection();
_cartonSizeType = customCarton;
_length = widget.carton.length;
_width = widget.carton.width;
_height = widget.carton.height;
// check carton size type
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
var sameLength =
cartonSizes.any((size) => size.length == widget.carton.length);
var sameWidth =
cartonSizes.any((size) => size.width == widget.carton.width);
var sameHeight =
cartonSizes.any((size) => size.height == widget.carton.height);
bool isStandartSize = sameLength && sameWidth && sameHeight;
if (isStandartSize) {
_cartonSizeType = standardCarton;
_standardSize = cartonSizes.firstWhere((size) =>
size.length == widget.carton.length &&
size.width == widget.carton.width &&
size.height == widget.carton.height);
} else if (widget.carton.length == 0 &&
widget.carton.width == 0 &&
widget.carton.height == 0) {
_cartonSizeType = packageCarton;
} else {
_cartonSizeType = customCarton;
}
var s = await context
.read<FcsShipmentModel>()
@@ -70,7 +91,7 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
_cartons = await context
.read<CartonModel>()
.getCartonsByIds(widget.carton.mixCartonIDs);
.getCartonsByIds(widget.carton.cartonIDs);
if (mounted) {
setState(() {});
@@ -113,8 +134,16 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
},
),
backgroundColor: Colors.white,
title: LocalText(context, 'box.update_title',
color: primaryColor, fontSize: 20),
title: Column(
children: [
LocalText(context, 'box.update_title',
color: primaryColor, fontSize: 20),
Text(
widget.carton.cartonNumber ?? '',
style: TextStyle(color: primaryColor, fontSize: 14),
)
],
),
),
body: Column(
children: [
@@ -212,6 +241,35 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
_isLoading = true;
});
try {
double length = 0;
double width = 0;
double height = 0;
if (_cartonSizeType == standardCarton) {
if (_standardSize != null) {
length = _standardSize!.length;
width = _standardSize!.width;
height = _standardSize!.height;
}
} else if (_cartonSizeType == customCarton) {
length = _length;
width = _width;
height = _height;
} else {
length = 0;
width = 0;
height = 0;
}
var carton = Carton(
id: widget.carton.id,
cartonType: mix_carton,
fcsShipmentID: _shipment?.id,
length: length,
width: width,
height: height,
cartons: _cartons);
await context.read<CartonModel>().updateCarton(carton);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());

View File

@@ -1,5 +1,6 @@
// ignore_for_file: deprecated_member_use
import 'package:fcs/pages/carton/model/carton_model.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
@@ -187,7 +188,35 @@ class _MixCartonFormState extends State<MixCartonForm> {
_isLoading = true;
});
try {
Navigator.pop(context, true);
double length = 0;
double width = 0;
double height = 0;
if (_cartonSizeType == standardCarton) {
if (_standardSize != null) {
length = _standardSize!.length;
width = _standardSize!.width;
height = _standardSize!.height;
}
} else if (_cartonSizeType == customCarton) {
length = _length;
width = _width;
height = _height;
} else {
length = 0;
width = 0;
height = 0;
}
var carton = Carton(
cartonType: mix_carton,
fcsShipmentID: _shipment?.id,
length: length,
width: width,
height: height,
cartons: _cartons);
var c = await context.read<CartonModel>().createMixCarton(carton);
Navigator.pop(context, c);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {

View File

@@ -110,17 +110,14 @@ class _MixCartonSubmitState extends State<MixCartonSubmit> {
final cartonType = Padding(
padding: const EdgeInsets.only(top: 10),
child: SubmitTextWidget(
labelKey: 'box.carton.type',
text: carton_mix_carton,
// subText: boxDimension,
),
labelKey: 'box.carton.type', text: carton_mix_carton),
);
final cartonSizeBox = Padding(
padding: const EdgeInsets.only(top: 10),
child: SubmitTextWidget(
labelKey: 'box.carton_size',
text: boxDimension ?? '',
text: boxDimension ?? 'No defined size',
),
);

View File

@@ -68,8 +68,6 @@ class _TypeWidgetState extends State<TypeWidget> {
}
_init() async {
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
_cartionSizeType = widget.cartonSizeType;
_lengthController.text =
@@ -79,6 +77,8 @@ class _TypeWidgetState extends State<TypeWidget> {
_heightController.text =
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
_getStandardCartonSize();
_loadShipment();
if (mounted) {
@@ -86,11 +86,24 @@ class _TypeWidgetState extends State<TypeWidget> {
}
}
_getStandardCartonSize() {
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
if (mounted) {
setState(() {});
}
}
_loadShipment() async {
var fcsShipments =
await context.read<FcsShipmentModel>().getActiveFcsShipments();
_shipments = fcsShipments;
_shipment = widget.shipment;
if (_shipments.contains(widget.shipment)) {
_shipment = widget.shipment;
} else {
_shipment = null;
}
if (mounted) {
setState(() {});
}
@@ -99,6 +112,7 @@ class _TypeWidgetState extends State<TypeWidget> {
@override
void didUpdateWidget(covariant TypeWidget oldWidget) {
_loadShipment();
_getStandardCartonSize();
super.didUpdateWidget(oldWidget);
}
@@ -109,7 +123,7 @@ class _TypeWidgetState extends State<TypeWidget> {
bool isStandardSize = _cartionSizeType == standardCarton;
bool isCustomSize = _cartionSizeType == customCarton;
bool isNoneDefinedSize = _cartionSizeType == packageCartion;
bool isNoneDefinedSize = _cartionSizeType == packageCarton;
final continueBtn = ContinueButton(onTap: () {
double l = double.tryParse(_lengthController.text) ?? 0;
@@ -287,16 +301,16 @@ class _TypeWidgetState extends State<TypeWidget> {
InkWell(
onTap: () {
setState(() {
_cartionSizeType = packageCartion;
_cartionSizeType = packageCarton;
});
},
child: Row(children: <Widget>[
LocalRadio(
value: packageCartion,
value: packageCarton,
groupValue: _cartionSizeType,
onChanged: (p0) {
setState(() {
_cartionSizeType = packageCartion;
_cartionSizeType = packageCarton;
});
},
),

View File

@@ -6,6 +6,7 @@ import 'package:fcs/data/services/services.dart';
import 'package:fcs/constants.dart';
import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/helpers/shared_pref.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:fcs/pagination/paginator_listener.dart';
import 'package:logging/logging.dart';
@@ -18,8 +19,6 @@ class CartonModel extends BaseModel {
final log = Logger('CartonModel');
var defaultShipment = FcsShipment(shipmentNumber: "All shipments", id: all);
PaginatorListener<Carton>? cartonsByFilter;
PaginatorListener<Carton>? getBoxes;
String? filterByStatus;
@@ -49,13 +48,10 @@ class CartonModel extends BaseModel {
@override
logout() async {
getBoxes?.close();
cartonsByFilter?.close();
}
Future<void> _initData() async {
logout();
_loadPaginationCartons();
}
filterCarton(FcsShipment? fcsShipment, User? consignee, User? sender,
@@ -140,7 +136,7 @@ class CartonModel extends BaseModel {
pageQuery = pageQuery.where("fcs_shipment_id", isEqualTo: shipment!.id);
}
pageQuery = pageQuery.orderBy("created_at", descending: true);
pageQuery = pageQuery.orderBy("update_time", descending: true);
getBoxes?.close();
getBoxes = PaginatorListener<Carton>(
@@ -148,30 +144,6 @@ class CartonModel extends BaseModel {
rowPerLoad: 30);
}
_loadPaginationCartons() {
if (user == null || !user!.hasCarton()) return null;
String path = "/$cartons_collection";
Query col = FirebaseFirestore.instance.collection(path);
// .where("carton_type",
// whereIn: [
// carton_from_packages,
// carton_from_cartons
// ]).where("status", isEqualTo: carton_packed_status)
// ;
Query pageQuery = FirebaseFirestore.instance
.collection(path)
// .where("carton_type",
// whereIn: [carton_from_packages, carton_from_cartons])
// .where("status", isEqualTo: carton_packed_status)
.orderBy("created_at", descending: true);
cartonsByFilter?.close();
cartonsByFilter = PaginatorListener<Carton>(
col, pageQuery, (data, id) => Carton.fromMap(data, id),
rowPerLoad: 30);
}
Future<List<Carton>> getCartons(String shipmentID) async {
String path = "/$cartons_collection";
var querySnap = await FirebaseFirestore.instance
@@ -235,8 +207,18 @@ class CartonModel extends BaseModel {
return Services.instance.cartonService.deleteCarton(carton);
}
Future<Carton> createMixCarton(Carton carton) {
return Services.instance.cartonService.createCarton(carton);
}
Future<void> updateMixCarton(Carton carton) {
return Services.instance.cartonService.updateMixCarton(carton);
}
Future<List<Carton>> searchCarton(String term) async {
if (term != '') {
await SharedPref.saveRecentSearch('carton_search', term);
}
return Services.instance.cartonService.searchCarton(term);
}
@@ -277,9 +259,11 @@ class CartonModel extends BaseModel {
uploadedURL.forEach((url) {
carton.photoUrls.add(url);
});
carton.photoUrls.removeWhere((e) => deletedUrls.contains(e));
}
try {
// await Services.instance.packageService.updateReceiving(package);
await Services.instance.cartonService.uploadCartonImages(carton);
} catch (e) {
// delete newly uploaded photos if fails
try {

View File

@@ -54,7 +54,7 @@ class CartonSelectionModel extends BaseModel {
query = query.where("carton_number", isEqualTo: term);
}
query = query.orderBy("created_at", descending: true);
query = query.orderBy("update_time", descending: true);
if (_lastDocument != null) {
query = query.startAfterDocument(_lastDocument!);

View File

@@ -35,8 +35,11 @@ class PrintQrCodePage extends StatelessWidget {
children: [
Text(carton.cartonNumber ?? "",
style: TextStyle(fontSize: 18, fontFamily: "Roboto")),
Text(carton.userName!,
style: TextStyle(fontSize: 16, fontFamily: "Roboto")),
carton.consigneeName == null || carton.consigneeName == ''
? const SizedBox()
: Text(carton.consigneeName!,
style:
TextStyle(fontSize: 16, fontFamily: "Roboto")),
Padding(
padding: const EdgeInsets.only(top: 3),
child: Text("${carton.actualWeight} lb",

View File

@@ -0,0 +1,114 @@
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../main/util.dart';
class SurchargeItemAddition extends StatefulWidget {
final List<CargoType> items;
const SurchargeItemAddition({super.key, required this.items});
@override
_SurchargeItemAdditionState createState() => _SurchargeItemAdditionState();
}
class _SurchargeItemAdditionState extends State<SurchargeItemAddition> {
bool _isLoading = false;
List<CargoType> surchargeItems = [];
@override
void initState() {
_init();
super.initState();
}
_init() {
var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false);
surchargeItems =
shipmentRateModel.rate.customDuties.map((e) => e.clone()).toList();
for (var p in surchargeItems) {
p.qty = 0;
if (widget.items.any((e) => e.id == p.id)) {
p.isChecked = true;
} else {
p.isChecked = false;
}
widget.items.forEach((vp) {
if (p.id == vp.id) {
p.qty = vp.qty;
}
});
}
if (mounted) {
setState(() {});
}
}
_onTap(CargoType cargo) {
if (cargo.isChecked) {
showMsgDialog(context, "Error", "Already exit!");
return;
}
Navigator.pop(context, cargo);
}
@override
Widget build(BuildContext context) {
List<Widget> getCargoRowList(List<CargoType> _c) {
return _c.map((c) {
return ListTile(
onTap: () {
_onTap(c);
},
title: new Text(c.name ?? '', style: textStyle),
trailing: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: primaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5),
),
minimumSize: Size(80, 35)),
onPressed: c.isChecked
? null
: () {
_onTap(c);
},
child: Text(
"Add",
style: TextStyle(color: Colors.white, fontSize: 14),
),
));
}).toList();
}
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: LocalAppBar(
labelKey: 'box.select.cargo_type',
backgroundColor: Colors.white,
labelColor: primaryColor,
arrowColor: primaryColor),
body: Container(
padding: EdgeInsets.all(10),
child: ListView(
shrinkWrap: true,
children: <Widget>[
Column(
children: getCargoRowList(surchargeItems),
),
SizedBox(height: 30),
],
),
),
),
);
}
}

View File

@@ -56,7 +56,7 @@ class CartonListRow extends StatelessWidget {
Padding(
padding: const EdgeInsets.only(top: 5),
child: new Text(
box.userName ?? "",
box.consigneeName ?? "",
style: new TextStyle(
fontSize: 15.0, color: Colors.grey),
),

View File

@@ -62,7 +62,7 @@ class CartonListRow extends StatelessWidget {
Padding(
padding: const EdgeInsets.only(top: 5),
child: new Text(
carton.userName ?? "",
carton.consigneeName ?? "",
style: new TextStyle(
fontSize: 15.0, color: Colors.grey),
),

View File

@@ -7,6 +7,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart';
import '../../helpers/shared_pref.dart';
import '../widgets/suggest_list.dart';
import 'carton_list_row.dart';
typedef CallbackCartonSelect(Carton carton);
@@ -32,7 +34,7 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
appBarTheme: AppBarTheme(color: primaryColor),
iconButtonTheme: IconButtonThemeData(
style: ButtonStyle(
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
@@ -120,13 +122,27 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
@override
Widget buildSuggestions(BuildContext context) {
return Container(
child: Center(
child: Opacity(
opacity: 0.2,
child: Icon(MaterialCommunityIcons.package,
size: 200, color: primaryColor)),
),
return FutureBuilder<List<String>?>(
future: SharedPref.getRecentSearch('carton_search', query),
builder: (context, snapshot) {
List<String> _oldFilters = snapshot.data ?? [];
if (_oldFilters.isEmpty) {
return const Center(
child: Opacity(
opacity: 0.2,
child: Icon(MaterialCommunityIcons.package,
color: primaryColor, size: 200),
),
);
}
return SuggestList(
recentSearchList: _oldFilters,
onTap: (String s) {
query = s;
showResults(context);
},
prefKey: 'carton_search');
},
);
}

View File

@@ -86,10 +86,10 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
_loadPackages() async {
if (!isFromPackages && !isSmallBag) return;
if (_box.cartonType == carton_from_packages && _box.userID == null) return;
if (_box.cartonType == carton_from_packages && _box.consigneeID == null) return;
PackageModel packageModel =
Provider.of<PackageModel>(context, listen: false);
List<Package> packages = await packageModel.getPackages(_box.userID!, [
List<Package> packages = await packageModel.getPackages(_box.consigneeID!, [
package_processed_status,
package_packed_status,
package_shipped_status,
@@ -137,13 +137,13 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
iconData: Ionicons.ios_airplane,
);
final fcsIDBox = DisplayText(
text: _box.fcsID,
text: _box.consigneeFCSID,
labelTextKey: "box.fcs.id",
icon: FcsIDIcon(),
);
final customerNameBox = DisplayText(
text: _box.userName,
text: _box.consigneeName,
labelTextKey: "box.name",
iconData: Icons.person,
);

View File

@@ -48,7 +48,7 @@ class DeliveryListRow extends StatelessWidget {
Padding(
padding: const EdgeInsets.only(top: 5),
child: new Text(
box.userName ?? "",
box.consigneeName ?? "",
style: new TextStyle(
fontSize: 15.0, color: Colors.grey),
),

View File

@@ -1,4 +1,6 @@
import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/domain/entities/shipment_consignee.dart';
import 'package:fcs/domain/entities/shipment_port.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.dart';
@@ -30,16 +32,16 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
var dateFormatter = new DateFormat('dd MMM yyyy');
TextEditingController _shipmentNumberController = new TextEditingController();
TextEditingController _cutoffDateController = new TextEditingController();
TextEditingController _arrivalDateController = new TextEditingController();
TextEditingController _departureDateControler = new TextEditingController();
TextEditingController _consigneeController = new TextEditingController();
TextEditingController _portController = new TextEditingController();
TextEditingController _destinationController = new TextEditingController();
TextEditingController _etaDateController = new TextEditingController();
TextEditingController _statusController = new TextEditingController();
FcsShipment _shipment = new FcsShipment();
bool _isLoading = false;
ShipmentType? _currentShipmentType;
ShipmentConsignee? _currentConsignee;
ShipmentPort? _currentLoadingPort;
ShipmentPort? _currentDestination;
bool _isNew = false;
@override
@@ -53,24 +55,38 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
if (_shipment.cutoffDate != null)
_cutoffDateController.text =
dateFormatter.format(_shipment.cutoffDate!);
if (_shipment.arrivalDate != null)
_arrivalDateController.text =
dateFormatter.format(_shipment.arrivalDate!);
if (_shipment.departureDate != null)
_departureDateControler.text =
dateFormatter.format(_shipment.departureDate!);
_statusController.text = _shipment.status ?? "";
_consigneeController.text = _shipment.consignee ?? "";
_portController.text = _shipment.port ?? "";
_destinationController.text = _shipment.destination ?? "";
if (_shipment.etaDate != null)
_etaDateController.text = dateFormatter.format(_shipment.etaDate!);
List<ShipmentType> list = model.shipmentTypes
_statusController.text = _shipment.status ?? "";
List<ShipmentType> shipmentTypes = model.shipmentTypes
.where((e) => e.id == _shipment.shipmentTypeId)
.toList();
_currentShipmentType =
shipmentTypes.isNotEmpty ? shipmentTypes.first : null;
_currentShipmentType = list.isNotEmpty ? list.first : null;
List<ShipmentConsignee> shipmentConsingees = model.shipmentConsingees
.where((e) => e.id == _shipment.consigneeId)
.toList();
_currentConsignee =
shipmentConsingees.isNotEmpty ? shipmentConsingees.first : null;
List<ShipmentPort> loadingPorts = model.shipmentPorts
.where((e) => e.id == _shipment.loadingPortId)
.toList();
_currentLoadingPort = loadingPorts.isNotEmpty ? loadingPorts.first : null;
List<ShipmentPort> loadingDestination = model.shipmentPorts
.where((e) => e.id == _shipment.destinationPortId)
.toList();
_currentDestination =
loadingDestination.isNotEmpty ? loadingDestination.first : null;
} else {
_currentShipmentType = model.shipmentTypes[0];
_currentShipmentType = model.shipmentTypes.first;
_currentConsignee = model.shipmentConsingees.first;
_currentLoadingPort = model.shipmentPorts.first;
_currentDestination = model.shipmentPorts.first;
}
}
@@ -82,8 +98,111 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
@override
Widget build(BuildContext context) {
var languageModel = Provider.of<LanguageModel>(context);
List<ShipmentType> shipmentTypes =
context.watch<FcsShipmentModel>().shipmentTypes;
var shipmentModel = context.watch<FcsShipmentModel>();
List<ShipmentType> shipmentTypes = shipmentModel.shipmentTypes;
List<ShipmentConsignee> shipmentConsingees =
shipmentModel.shipmentConsingees;
List<ShipmentPort> shipmentPorts = shipmentModel.shipmentPorts;
final shipmentTypeBox = DropdownButtonFormField(
value: _currentShipmentType == "" ? null : _currentShipmentType,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
enabledBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
focusedBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
fillColor: Colors.white,
labelStyle: languageModel.isEng
? newLabelStyle(color: Colors.black54, fontSize: 20)
: newLabelStyleMM(color: Colors.black54, fontSize: 20),
labelText:
AppTranslations.of(context)!.text('FCSshipment.shipment_type'),
icon: Icon(Ionicons.ios_airplane, color: primaryColor)),
items: shipmentTypes
.map((e) => DropdownMenuItem(child: Text(e.name), value: e))
.toList(),
onChanged: (selected) => {
setState(() {
_currentShipmentType = selected;
})
},
);
final consigneeBox = DropdownButtonFormField(
value: _currentConsignee == "" ? null : _currentConsignee,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
enabledBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
focusedBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
fillColor: Colors.white,
labelStyle: languageModel.isEng
? newLabelStyle(color: Colors.black54, fontSize: 20)
: newLabelStyleMM(color: Colors.black54, fontSize: 20),
labelText: AppTranslations.of(context)!.text('FCSshipment.consignee'),
icon: Icon(Icons.work, color: primaryColor)),
items: shipmentConsingees
.map((e) => DropdownMenuItem(child: Text(e.name), value: e))
.toList(),
onChanged: (selected) => {
setState(() {
_currentConsignee = selected;
})
},
);
final loadingPortBox = DropdownButtonFormField(
value: _currentLoadingPort == "" ? null : _currentLoadingPort,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
enabledBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
focusedBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
fillColor: Colors.white,
labelStyle: languageModel.isEng
? newLabelStyle(color: Colors.black54, fontSize: 20)
: newLabelStyleMM(color: Colors.black54, fontSize: 20),
labelText:
AppTranslations.of(context)!.text('FCSshipment.port_of_loading'),
icon: Icon(FontAwesomeIcons.ship, color: primaryColor)),
items: shipmentPorts
.map((e) => DropdownMenuItem(child: Text(e.name), value: e))
.toList(),
onChanged: (selected) => {
setState(() {
_currentLoadingPort = selected;
})
},
);
final destinationBox = DropdownButtonFormField(
value: _currentDestination == "" ? null : _currentDestination,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
enabledBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
focusedBorder:
UnderlineInputBorder(borderSide: BorderSide(color: primaryColor)),
fillColor: Colors.white,
labelStyle: languageModel.isEng
? newLabelStyle(color: Colors.black54, fontSize: 20)
: newLabelStyleMM(color: Colors.black54, fontSize: 20),
labelText: AppTranslations.of(context)!
.text('FCSshipment.final_destination'),
icon:
Icon(MaterialCommunityIcons.location_enter, color: primaryColor)),
items: shipmentPorts
.map((e) => DropdownMenuItem(child: Text(e.name), value: e))
.toList(),
onChanged: (selected) => {
setState(() {
_currentDestination = selected;
})
},
);
final createBtn = Padding(
padding: const EdgeInsets.symmetric(horizontal: 30),
@@ -150,7 +269,7 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
InputDate(
labelTextKey: "FCSshipment.ETA",
iconData: Icons.date_range,
controller: _arrivalDateController,
controller: _etaDateController,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value!.isEmpty) {
@@ -160,47 +279,14 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
},
),
const SizedBox(height: 20),
DropdownButtonFormField(
value:
_currentShipmentType == "" ? null : _currentShipmentType,
decoration: InputDecoration(
contentPadding: EdgeInsets.zero,
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: primaryColor)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: primaryColor)),
fillColor: Colors.white,
labelStyle: languageModel.isEng
? newLabelStyle(color: Colors.black54, fontSize: 20)
: newLabelStyleMM(
color: Colors.black54, fontSize: 20),
labelText: AppTranslations.of(context)!
.text('FCSshipment.shipment_type'),
icon: Icon(Ionicons.ios_airplane, color: primaryColor)),
items: shipmentTypes
.map((e) =>
DropdownMenuItem(child: Text(e.name), value: e))
.toList(),
onChanged: (selected) => {
setState(() {
_currentShipmentType = selected;
})
},
),
const SizedBox(height: 5),
InputText(
labelTextKey: 'FCSshipment.consignee',
iconData: Icons.work,
controller: _consigneeController),
InputText(
labelTextKey: 'FCSshipment.port_of_loading',
iconData: FontAwesomeIcons.ship,
controller: _portController),
InputText(
labelTextKey: 'FCSshipment.final_destination',
iconData: MaterialCommunityIcons.location_enter,
controller: _destinationController),
SizedBox(height: 20),
shipmentTypeBox,
const SizedBox(height: 25),
consigneeBox,
const SizedBox(height: 25),
loadingPortBox,
const SizedBox(height: 25),
destinationBox,
SizedBox(height: 30),
_isNew ? createBtn : updateBtn,
SizedBox(height: 15)
]),
@@ -214,16 +300,15 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
fcsShipment.id = _shipment.id;
fcsShipment.shipmentNumber = _shipmentNumberController.text;
fcsShipment.shipmentTypeId = _currentShipmentType?.id ?? "";
fcsShipment.consignee = _consigneeController.text;
fcsShipment.port = _portController.text;
fcsShipment.destination = _destinationController.text;
fcsShipment.consigneeId = _currentConsignee?.id ?? "";
fcsShipment.loadingPortId = _currentLoadingPort?.id ?? "";
fcsShipment.destinationPortId = _currentDestination?.id ?? "";
var cutoffDate = _cutoffDateController.text;
var arrivalDate = _arrivalDateController.text;
var etaDate = _etaDateController.text;
fcsShipment.cutoffDate =
(cutoffDate == "" ? null : dateFormatter.parse(cutoffDate))!;
fcsShipment.arrivalDate =
(arrivalDate == "" ? null : dateFormatter.parse(arrivalDate))!;
fcsShipment.etaDate = (etaDate == "" ? null : dateFormatter.parse(etaDate));
return fcsShipment;
}
@@ -271,11 +356,11 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
return _shipmentNumberController.text != "" ||
_cutoffDateController.text != "" ||
_arrivalDateController.text != "" ||
_consigneeController.text != "" ||
_portController.text != "" ||
_destinationController.text != "" ||
_currentShipmentType != shipmentModel.shipmentTypes[0];
_etaDateController.text != "" ||
_currentConsignee != shipmentModel.shipmentConsingees.first ||
_currentShipmentType != shipmentModel.shipmentTypes.first ||
_currentLoadingPort != shipmentModel.shipmentPorts.first ||
_currentDestination != shipmentModel.shipmentPorts.first;
} else {
FcsShipment fcsShipment = _getPayload();
return widget.shipment!.isChangedForEdit(fcsShipment);

View File

@@ -20,8 +20,8 @@ import 'package:provider/provider.dart';
import 'fcs_shipment_editor.dart';
class FcsShipmentInfo extends StatefulWidget {
final FcsShipment? fcsShipment;
FcsShipmentInfo({this.fcsShipment});
final FcsShipment fcsShipment;
FcsShipmentInfo({required this.fcsShipment});
@override
_FcsShipmentInfoState createState() => _FcsShipmentInfoState();
@@ -29,7 +29,7 @@ class FcsShipmentInfo extends StatefulWidget {
class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
var dateFormatter = new DateFormat('dd MMM yyyy');
FcsShipment? _fcsShipment;
late FcsShipment _fcsShipment;
bool _isLoading = false;
TextEditingController _shipmentNumberController = new TextEditingController();
TextEditingController _cutoffDateController = new TextEditingController();
@@ -49,21 +49,21 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
}
_load() {
_shipmentNumberController.text = _fcsShipment?.shipmentNumber ?? "";
if (_fcsShipment?.cutoffDate != null)
_shipmentNumberController.text = _fcsShipment.shipmentNumber ?? "";
if (_fcsShipment.cutoffDate != null)
_cutoffDateController.text =
dateFormatter.format(_fcsShipment!.cutoffDate!);
if (_fcsShipment?.arrivalDate != null)
_arrivalDateController.text =
dateFormatter.format(_fcsShipment!.arrivalDate!);
if (_fcsShipment?.departureDate != null)
dateFormatter.format(_fcsShipment.cutoffDate!);
if (_fcsShipment.etaDate != null)
_arrivalDateController.text = dateFormatter.format(_fcsShipment.etaDate!);
if (_fcsShipment.departureDate != null)
_departureDateControler.text =
dateFormatter.format(_fcsShipment!.departureDate!);
_shipmentTypeControler.text = _fcsShipment!.shipTypeName ?? "";
_consigneeController.text = _fcsShipment!.consignee ?? "";
_portController.text = _fcsShipment!.port ?? "";
_destinationController.text = _fcsShipment!.destination ?? "";
_statusController.text = _fcsShipment!.status ?? "";
dateFormatter.format(_fcsShipment.departureDate!);
_shipmentTypeControler.text = _fcsShipment.shipmentTypeName ?? "";
_consigneeController.text = _fcsShipment.consigneeName ?? '';
_portController.text = _fcsShipment.loadingPortName ?? '';
_destinationController.text = _fcsShipment.destinationPortName ?? '';
_statusController.text = _fcsShipment.status ?? "";
}
@override
@@ -176,7 +176,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
labelColor: primaryColor,
arrowColor: primaryColor,
actions: [
_fcsShipment?.status == fcs_shipment_pending_status
_fcsShipment.status == fcs_shipment_pending_status
? IconButton(
icon: Icon(Icons.edit, color: primaryColor),
onPressed: _edit,
@@ -212,20 +212,20 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
portBox,
destinationBox,
const SizedBox(height: 30),
_fcsShipment?.status == fcs_shipment_pending_status
_fcsShipment.status == fcs_shipment_pending_status
? processBtn
: Container(),
_fcsShipment?.status == fcs_shipment_pending_status
_fcsShipment.status == fcs_shipment_pending_status
? Container(
padding: EdgeInsets.only(top: 3), child: cancelBtn)
: Container(),
_fcsShipment?.status == fcs_shipment_processed_status
_fcsShipment.status == fcs_shipment_processed_status
? shipBtn
: Container(),
_fcsShipment?.status == fcs_shipment_shipped_status
_fcsShipment.status == fcs_shipment_shipped_status
? arriveBtn
: Container(),
_fcsShipment?.status == fcs_shipment_arrived_status
_fcsShipment.status == fcs_shipment_arrived_status
? invoiceBtn
: Container(),
SizedBox(height: 20)
@@ -244,8 +244,8 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
);
if (updated ?? false) {
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
if (_fcsShipment != null && _fcsShipment!.id != null) {
FcsShipment? f = await shipmentModel.getFcsShipment(_fcsShipment!.id!);
if (_fcsShipment.id != null) {
FcsShipment? f = await shipmentModel.getFcsShipment(_fcsShipment.id!);
if (f == null) return;
setState(() {
_fcsShipment = f;
@@ -294,7 +294,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
_isLoading = true;
});
try {
await context.read<FcsShipmentModel>().process(_fcsShipment!.id!);
await context.read<FcsShipmentModel>().process(_fcsShipment.id!);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
@@ -316,7 +316,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
_isLoading = true;
});
try {
await context.read<FcsShipmentModel>().ship(_fcsShipment!.id!);
await context.read<FcsShipmentModel>().ship(_fcsShipment.id!);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
@@ -338,7 +338,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
_isLoading = true;
});
try {
await context.read<FcsShipmentModel>().arrive(_fcsShipment!.id!);
await context.read<FcsShipmentModel>().arrive(_fcsShipment.id!);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
@@ -360,7 +360,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
_isLoading = true;
});
try {
await context.read<FcsShipmentModel>().invoice(_fcsShipment!.id!);
await context.read<FcsShipmentModel>().invoice(_fcsShipment.id!);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
@@ -376,7 +376,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
_isLoading = true;
});
try {
await context.read<FcsShipmentModel>().cancel(_fcsShipment!.id!);
await context.read<FcsShipmentModel>().cancel(_fcsShipment.id!);
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
@@ -402,11 +402,11 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
} else if (id == 4) {
reportName = "manifest";
}
_fcsShipment!.reportName = reportName;
_fcsShipment.reportName = reportName;
FcsShipmentModel fcsShipmentModel =
Provider.of<FcsShipmentModel>(context, listen: false);
String url = await fcsShipmentModel.report(_fcsShipment!);
String url = await fcsShipmentModel.report(_fcsShipment);
Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => PDFScreen(
title: "",

View File

@@ -43,21 +43,21 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: LocalAppBar(labelKey: "FCSshipment.list.title", actions: [
_menuFilteringWidget(context),
]),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
_newShipment();
},
icon: Icon(Icons.add),
label:
LocalText(context, "FCSshipment.add", color: Colors.white),
backgroundColor: primaryColor),
body: PaginatorListView<FcsShipment>(
paginatorListener: shipmentModel.fcsShipments!,
rowBuilder: (p) => FcsShipmentListRow(shipment: p),
color: primaryColor)));
appBar: LocalAppBar(labelKey: "FCSshipment.list.title", actions: [
_menuFilteringWidget(context),
]),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
_newShipment();
},
icon: Icon(Icons.add),
label: LocalText(context, "FCSshipment.add", color: Colors.white),
backgroundColor: primaryColor),
body: PaginatorListView<FcsShipment>(
paginatorListener: shipmentModel.fcsShipments!,
rowBuilder: (p) => FcsShipmentListRow(shipment: p),
color: primaryColor),
));
}
_newShipment() {
@@ -107,7 +107,9 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
value: choice,
child: Row(
children: <Widget>[
Flexible(child: Text("${choice.text}",style: TextStyle(color: Colors.black))),
Flexible(
child: Text("${choice.text}",
style: TextStyle(color: Colors.black))),
const SizedBox(
width: 10,
),

View File

@@ -4,9 +4,11 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/constants.dart';
import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:fcs/domain/entities/shipment_port.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:logging/logging.dart';
import '../../../domain/entities/shipment_consignee.dart';
import '../../../domain/entities/shipment_type.dart';
import '../../../pagination/paginator_listener.dart';
@@ -17,7 +19,26 @@ class FcsShipmentModel extends BaseModel {
int selectedIndex = 0;
List<ShipmentType> shipmentTypes = [];
List<ShipmentConsignee> shipmentConsingees = [];
List<ShipmentPort> shipmentPorts = [];
StreamSubscription<QuerySnapshot>? _shipmentTypeListener;
StreamSubscription<QuerySnapshot>? _shipmentConsigneeListener;
StreamSubscription<QuerySnapshot>? _shipmentPortListener;
ShipmentType? getShipmentType(id) {
var list = shipmentTypes.where((e) => e.id == id).toList();
return list.isNotEmpty ? list.first : null;
}
ShipmentConsignee? getShipmentConsignee(id) {
var list = shipmentConsingees.where((e) => e.id == id).toList();
return list.isNotEmpty ? list.first : null;
}
ShipmentPort? getShipmentPort(id) {
var list = shipmentPorts.where((e) => e.id == id).toList();
return list.isNotEmpty ? list.first : null;
}
onChanged(int index) {
selectedIndex = index;
@@ -39,7 +60,7 @@ class FcsShipmentModel extends BaseModel {
pageQuery.where("status", isEqualTo: fcs_shipment_pending_status);
}
// processing status
// processed status
if (index == 2) {
col = col.where("status", isEqualTo: fcs_shipment_processed_status);
pageQuery =
@@ -74,7 +95,7 @@ class FcsShipmentModel extends BaseModel {
pageQuery.where("status", isEqualTo: fcs_shipment_canceled_status);
}
pageQuery = pageQuery.orderBy("shipment_number", descending: true);
pageQuery = pageQuery.orderBy("update_time", descending: true);
fcsShipments?.close();
fcsShipments = PaginatorListener<FcsShipment>(
@@ -87,7 +108,7 @@ class FcsShipmentModel extends BaseModel {
try {
var snaps = await FirebaseFirestore.instance
.collection("/$fcs_shipment_collection")
// .where("status", isEqualTo: fcs_shipment_processed_status)
.where("status", isEqualTo: fcs_shipment_processed_status)
.get(const GetOptions(source: Source.server));
fcsShipments = snaps.docs.map((documentSnapshot) {
var fcs =
@@ -137,13 +158,19 @@ class FcsShipmentModel extends BaseModel {
void initUser(user) {
super.initUser(user);
_loadShipmentTypes();
_loadShipmentConsignees();
_loadShipmentPorts();
}
@override
logout() async {
fcsShipments?.close();
_shipmentTypeListener?.cancel();
_shipmentConsigneeListener?.cancel();
_shipmentPortListener?.cancel();
shipmentTypes.clear();
shipmentConsingees.clear();
shipmentPorts.clear();
}
Future<void> _loadShipmentTypes() async {
@@ -155,10 +182,52 @@ class FcsShipmentModel extends BaseModel {
.listen((QuerySnapshot snapshot) {
shipmentTypes.clear();
shipmentTypes = snapshot.docs.map((documentSnapshot) {
var privilege = ShipmentType.fromMap(
var type = ShipmentType.fromMap(
documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return privilege;
return type;
}).toList();
notifyListeners();
});
} catch (e) {
log.warning("Error!! $e");
}
}
Future<void> _loadShipmentConsignees() async {
try {
_shipmentConsigneeListener = FirebaseFirestore.instance
.collection(
"/$config_collection/$setting_doc_id/$shipment_consignee_collection")
.snapshots()
.listen((QuerySnapshot snapshot) {
shipmentConsingees.clear();
shipmentConsingees = snapshot.docs.map((documentSnapshot) {
var consignee = ShipmentConsignee.fromMap(
documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return consignee;
}).toList();
notifyListeners();
});
} catch (e) {
log.warning("Error!! $e");
}
}
Future<void> _loadShipmentPorts() async {
try {
_shipmentPortListener = FirebaseFirestore.instance
.collection(
"/$config_collection/$setting_doc_id/$shipment_port_collection")
.snapshots()
.listen((QuerySnapshot snapshot) {
shipmentPorts.clear();
shipmentPorts = snapshot.docs.map((documentSnapshot) {
var port = ShipmentPort.fromMap(
documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return port;
}).toList();
notifyListeners();
});
@@ -192,7 +261,7 @@ class FcsShipmentModel extends BaseModel {
Future<void> invoice(String id) {
return Services.instance.fcsShipmentService
.updateFcsShipmentStatus(id, fcs_shipment_shipped_status);
.updateFcsShipmentStatus(id, fcs_shipment_invoiced_status);
}
Future<void> cancel(String id) {

View File

@@ -224,6 +224,9 @@ class PackageModel extends BaseModel {
}
Future<List<Package>> searchPackage(String term) async {
if (term != '') {
await SharedPref.saveRecentSearch('package_search', term);
}
Future<List<Package>> packages =
Services.instance.packageService.searchPackage(term);

View File

@@ -8,6 +8,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart';
import '../../helpers/shared_pref.dart';
import '../widgets/suggest_list.dart';
Future<Package?> searchPackage(BuildContext context,
{CallbackPackageSelect? callbackPackageSelect}) async =>
await showSearch<Package>(
@@ -22,7 +25,7 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
PackageSearchDelegate({this.callbackPackageSelect});
@override
String get searchFieldLabel => 'Search by Tracking ID/Customer Name';
String get searchFieldLabel => 'Search by Tracking ID/Customer name';
@override
ThemeData appBarTheme(BuildContext context) {
@@ -31,7 +34,7 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
appBarTheme: AppBarTheme(color: primaryColor),
iconButtonTheme: IconButtonThemeData(
style: ButtonStyle(
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
@@ -123,12 +126,27 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
@override
Widget buildSuggestions(BuildContext context) {
return Container(
child: Center(
child: Opacity(
opacity: 0.2,
child: Icon(Octicons.package, size: 200, color: primaryColor)),
),
return FutureBuilder<List<String>?>(
future: SharedPref.getRecentSearch('package_search', query),
builder: (context, snapshot) {
List<String> _oldFilters = snapshot.data ?? [];
if (_oldFilters.isEmpty) {
return const Center(
child: Opacity(
opacity: 0.2,
child: Icon(Octicons.package,
color: primaryColor, size: 200),
),
);
}
return SuggestList(
recentSearchList: _oldFilters,
onTap: (String s) {
query = s;
showResults(context);
},
prefKey: 'package_search');
},
);
}

View File

@@ -11,6 +11,8 @@ import 'package:fcs/pagination/paginator_listener.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as Path;
import '../../../helpers/shared_pref.dart';
class PickupModel extends BaseModel {
final log = Logger('PickupModel');
PaginatorListener<Pickup>? pickups;
@@ -86,6 +88,9 @@ class PickupModel extends BaseModel {
}
Future<List<Pickup>> searchPickup(String term) async {
if (term != '') {
await SharedPref.saveRecentSearch('pickup_search', term);
}
Future<List<Pickup>> pickups =
Services.instance.pickupService.searchPickup(term);
return pickups;

View File

@@ -9,6 +9,9 @@ import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart';
import '../../helpers/shared_pref.dart';
import '../widgets/suggest_list.dart';
Future<Pickup?> searchPickup(BuildContext context,
{CallbackPickupSelect? callbackPickupSelect}) async =>
await showSearch<Pickup>(
@@ -32,7 +35,7 @@ class PackageSearchDelegate extends SearchDelegate<Pickup> {
appBarTheme: AppBarTheme(color: primaryColor),
iconButtonTheme: IconButtonThemeData(
style: ButtonStyle(
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
@@ -124,13 +127,27 @@ class PackageSearchDelegate extends SearchDelegate<Pickup> {
@override
Widget buildSuggestions(BuildContext context) {
return Container(
child: Center(
child: Opacity(
opacity: 0.2,
child: Icon(SimpleLineIcons.direction,
size: 200, color: primaryColor)),
),
return FutureBuilder<List<String>?>(
future: SharedPref.getRecentSearch('pickup_search', query),
builder: (context, snapshot) {
List<String> _oldFilters = snapshot.data ?? [];
if (_oldFilters.isEmpty) {
return const Center(
child: Opacity(
opacity: 0.2,
child: Icon(SimpleLineIcons.direction,
color: primaryColor, size: 200),
),
);
}
return SuggestList(
recentSearchList: _oldFilters,
onTap: (String s) {
query = s;
showResults(context);
},
prefKey: 'pickup_search');
},
);
}

View File

@@ -4,9 +4,11 @@ import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/local_app_bar.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../widgets/local_text.dart';
import 'model/shipment_rate_model.dart';
class CargoEditor extends StatefulWidget {
@@ -20,11 +22,13 @@ class CargoEditor extends StatefulWidget {
class _CargoEditorState extends State<CargoEditor> {
TextEditingController _descController = new TextEditingController();
TextEditingController _rateController = new TextEditingController();
TextEditingController _displayIndexController = new TextEditingController();
bool _isLoading = false;
late CargoType _cargo;
bool _isNew = false;
final _cargoFormKey = GlobalKey<FormState>();
bool _isDefault = false;
@override
void initState() {
@@ -33,6 +37,8 @@ class _CargoEditorState extends State<CargoEditor> {
_cargo = widget.cargo!;
_descController.text = _cargo.name ?? "";
_rateController.text = _cargo.rate.toStringAsFixed(2);
_displayIndexController.text = _cargo.displayIndex.toString();
_isDefault = _cargo.isDefault;
} else {
_isNew = true;
}
@@ -46,20 +52,23 @@ class _CargoEditorState extends State<CargoEditor> {
@override
Widget build(BuildContext context) {
final typeBox = InputText(
labelTextKey: 'cargo.type',
iconData: Icons.text_format,
controller: _descController,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value){
if(value==null || value.isEmpty){
return "Please insert cargo type";
}
return null;
},);
labelTextKey: 'cargo.type',
iconData: Icons.text_format,
controller: _descController,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.isEmpty) {
return "Please insert cargo type";
}
return null;
},
);
final rateBox = InputText(
labelTextKey: 'cargo.rate',
iconData: Icons.attach_money,
controller: _rateController,
textInputType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.isEmpty) {
@@ -68,6 +77,51 @@ class _CargoEditorState extends State<CargoEditor> {
return null;
},
);
final displayIndexBox = InputText(
labelTextKey: 'cargo.display_index',
iconData: Icons.numbers,
controller: _displayIndexController,
textInputType: TextInputType.number,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (value == null || value.isEmpty) {
return "Please insert display index";
}
return null;
},
);
final defaultBox = Padding(
padding: const EdgeInsets.symmetric(vertical: 20),
child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
LocalText(
context,
'cargo.is_default',
color: Colors.black54,
fontSize: 15,
),
],
),
),
Transform.scale(
scale: 0.7,
alignment: Alignment.centerRight,
child: CupertinoSwitch(
activeColor: primaryColor,
value: _isDefault,
onChanged: (v) {
setState(() {
_isDefault = v;
});
}))
]),
);
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
@@ -105,6 +159,8 @@ class _CargoEditorState extends State<CargoEditor> {
children: <Widget>[
typeBox,
rateBox,
displayIndexBox,
defaultBox,
SizedBox(height: 30),
],
),
@@ -131,7 +187,10 @@ class _CargoEditorState extends State<CargoEditor> {
var shipmentRateModel =
Provider.of<ShipmentRateModel>(context, listen: false);
CargoType _cargo = CargoType(
name: _descController.text, rate: double.parse(_rateController.text));
name: _descController.text,
rate: double.parse(_rateController.text),
displayIndex: int.parse(_displayIndexController.text),
isDefault: _isDefault);
if (_isNew) {
await shipmentRateModel.addCargoType(_cargo);
} else {

View File

@@ -37,7 +37,7 @@ class UserSearchDelegate extends SearchDelegate<User> {
appBarTheme: AppBarTheme(color: primaryColor),
iconButtonTheme: IconButtonThemeData(
style: ButtonStyle(
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
inputDecorationTheme: InputDecorationTheme(
border: InputBorder.none,
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),