Files
fcs/lib/pages/shipment/shipment_info.dart

568 lines
17 KiB
Dart
Raw Normal View History

2020-10-16 10:58:31 +06:30
import 'package:fcs/domain/constants.dart';
2020-10-18 02:38:46 +06:30
import 'package:fcs/domain/entities/carton.dart';
2020-10-16 10:58:31 +06:30
import 'package:fcs/domain/entities/shipment.dart';
import 'package:fcs/helpers/theme.dart';
2020-10-18 02:38:46 +06:30
import 'package:fcs/pages/carton/model/carton_model.dart';
2020-10-16 10:58:31 +06:30
import 'package:fcs/pages/main/model/main_model.dart';
2020-10-18 02:38:46 +06:30
import 'package:fcs/pages/main/util.dart';
2020-10-16 10:58:31 +06:30
import 'package:fcs/pages/shipment/model/shipment_model.dart';
2020-10-19 05:13:49 +06:30
import 'package:fcs/pages/shipment/shipment_pack.dart';
2020-10-16 10:58:31 +06:30
import 'package:fcs/pages/widgets/defalut_delivery_address.dart';
import 'package:fcs/pages/widgets/display_text.dart';
2020-10-18 02:38:46 +06:30
import 'package:fcs/pages/widgets/fcs_id_icon.dart';
import 'package:fcs/pages/widgets/local_button.dart';
import 'package:fcs/pages/widgets/local_popup_menu_button.dart';
import 'package:fcs/pages/widgets/local_popupmenu.dart';
2020-10-16 10:58:31 +06:30
import 'package:fcs/pages/widgets/local_radio_buttons.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/multi_img_controller.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
2021-09-10 16:48:21 +06:30
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
2020-10-16 10:58:31 +06:30
import 'package:intl/intl.dart';
import 'package:provider/provider.dart';
2020-10-18 02:38:46 +06:30
import 'package:url_launcher/url_launcher.dart';
2020-10-16 10:58:31 +06:30
import 'box_row.dart';
2020-10-19 05:13:49 +06:30
import 'shipment_assign.dart';
import 'shipment_confirm.dart';
2020-10-18 02:38:46 +06:30
import 'shipment_editor.dart';
import 'widgets.dart';
2020-10-16 10:58:31 +06:30
class ShipmentInfo extends StatefulWidget {
2021-09-10 16:48:21 +06:30
final bool? isCustomer;
final Shipment? shipment;
2020-10-19 05:13:49 +06:30
ShipmentInfo({this.shipment, this.isCustomer});
2020-10-16 10:58:31 +06:30
@override
_ShipmentInfoState createState() => _ShipmentInfoState();
}
class _ShipmentInfoState extends State<ShipmentInfo> {
var dateFormatter = new DateFormat('dd MMM yyyy');
final numberFormatter = new NumberFormat("#,###");
MultiImgController multiImgController = MultiImgController();
2020-10-18 02:38:46 +06:30
var timeFormatter = new DateFormat('jm');
2020-10-16 10:58:31 +06:30
TextEditingController _addressEditingController = new TextEditingController();
TextEditingController _fromTimeEditingController =
new TextEditingController();
TextEditingController _toTimeEditingController = new TextEditingController();
TextEditingController _noOfPackageEditingController =
new TextEditingController();
TextEditingController _weightEditingController = new TextEditingController();
TextEditingController _pickupDate = new TextEditingController();
2021-09-10 16:48:21 +06:30
Shipment? _shipment;
2020-10-16 10:58:31 +06:30
bool _isLoading = false;
2021-09-10 16:48:21 +06:30
late bool _isCustomer;
2020-10-16 10:58:31 +06:30
var now = new DateTime.now();
@override
void initState() {
super.initState();
_shipment = widget.shipment;
2021-09-10 16:48:21 +06:30
_isCustomer = widget.isCustomer!;
_loadCartons(_shipment!.id!);
_addressEditingController.text = _shipment!.address ?? "";
_fromTimeEditingController.text = _shipment!.pickupTimeStart ?? "";
_toTimeEditingController.text = _shipment!.pickupTimeEnd ?? "";
2024-01-23 16:28:08 +06:30
_noOfPackageEditingController.text = _shipment!.numberOfPackage.toString();
_weightEditingController.text = _shipment!.weight.toString();
2021-09-10 16:48:21 +06:30
_pickupDate.text = dateFormatter.format(_shipment!.pickupDate ?? now);
2020-10-16 10:58:31 +06:30
}
2020-10-18 02:38:46 +06:30
_loadCartons(String shipmentID) async {
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
var cartons = await cartonModel.getCartons(shipmentID);
setState(() {
2021-09-10 16:48:21 +06:30
_shipment!.boxes = cartons;
2020-10-18 02:38:46 +06:30
});
}
2020-10-19 05:13:49 +06:30
_loadShipment(String id) async {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
Shipment? s = await shipmentModel.getShipment(id);
s!.boxes = _shipment!.boxes;
2020-10-19 05:13:49 +06:30
setState(() {
_shipment = s;
});
}
2020-10-16 10:58:31 +06:30
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
MainModel mainModel = Provider.of<MainModel>(context);
ShipmentModel pickupModel = Provider.of<ShipmentModel>(context);
2021-09-10 16:48:21 +06:30
bool isLocalPickup = _shipment!.shipmentType == shipment_local_pickup;
bool isCourierPickup = _shipment!.shipmentType == shipment_courier_pickup;
bool isLocalDropoff = _shipment!.shipmentType == shipment_local_dropoff;
bool isCourierDropoff = _shipment!.shipmentType == shipment_courier_dropoff;
bool isEditable = widget.isCustomer!
? (_shipment!.isPending || _shipment!.isAssigned)
: (_shipment!.isPending ||
_shipment!.isAssigned ||
_shipment!.isPickuped);
2020-10-19 05:13:49 +06:30
bool canCancel =
2021-09-10 16:48:21 +06:30
_shipment!.isPending || _shipment!.isConfirmed || _shipment!.isAssigned;
2020-10-16 10:58:31 +06:30
2020-10-19 05:13:49 +06:30
final popupMenu = LocalPopupMenuButton(
popmenus: [
LocalPopupMenu(
2021-09-10 16:48:21 +06:30
enabled: _shipment!.isPending && isLocalPickup,
2020-10-19 05:13:49 +06:30
id: 1,
textKey: "shipment.assign.for.pickup",
),
LocalPopupMenu(
enabled:
2021-09-10 16:48:21 +06:30
(_shipment!.isPickuped && isLocalPickup) || _shipment!.isReceived,
2020-10-19 05:13:49 +06:30
id: 3,
textKey: "shipment.pack.menuitem",
),
LocalPopupMenu(
2021-09-10 16:48:21 +06:30
enabled:
_shipment!.isPending && (isCourierPickup || isCourierDropoff),
2020-10-19 05:13:49 +06:30
id: 4,
textKey: "shipment.confirm.menuitem",
),
LocalPopupMenu(
enabled: canCancel,
id: 2,
textKey: "btn.cancel",
),
],
selectable: false,
buttonIcon: Icons.more_vert,
popupMenuCallback: (p) => p.id == 1
? _gotoAssign()
: p.id == 2
? _cancel()
2021-09-10 16:48:21 +06:30
: p.id == 3
? _gotoPack()
: p.id == 4
? _gotoConfirm()
: null,
2020-10-19 05:13:49 +06:30
);
final popupMenuCustomer = LocalPopupMenuButton(
popmenus: [
LocalPopupMenu(
enabled: canCancel,
id: 2,
textKey: "btn.cancel",
),
],
selectable: false,
buttonIcon: Icons.more_vert,
popupMenuCallback: (p) => p.id == 2 ? _cancel() : null,
);
2021-09-10 16:48:21 +06:30
final shipmentNumberBox = getShipmentNumberStatus(context, _shipment!);
2020-10-16 10:58:31 +06:30
2020-10-18 02:38:46 +06:30
final fromTimeBox = DisplayText(
labelTextKey: 'shipment.from',
iconData: Icons.timer,
2021-09-10 16:48:21 +06:30
text: _shipment!.pickupTimeStart ?? "",
2020-10-18 02:38:46 +06:30
);
final toTimeBox = DisplayText(
labelTextKey: 'shipment.to',
iconData: Icons.timer_off,
2021-09-10 16:48:21 +06:30
text: _shipment!.pickupTimeEnd ?? "",
2020-10-18 02:38:46 +06:30
);
2020-10-16 10:58:31 +06:30
2020-10-18 02:38:46 +06:30
final pickupDateBox = DisplayText(
2020-10-16 10:58:31 +06:30
labelTextKey: "shipment.date",
iconData: Icons.date_range,
2021-09-10 16:48:21 +06:30
text: _shipment!.pickupDate != null
? dateFormatter.format(_shipment!.pickupDate!)
: '',
2020-10-16 10:58:31 +06:30
);
2020-10-18 02:38:46 +06:30
var localDropoffAddressBox = Row(children: [
FcsIDIcon(),
Expanded(
child: DisplayText(
2021-09-10 16:48:21 +06:30
text: mainModel.setting!.usaAddress ?? "",
2020-10-18 02:38:46 +06:30
),
)
]);
final curierDropoffAddress = Padding(
padding: EdgeInsets.all(8),
child: FloatingActionButton.extended(
onPressed: _openCourierWebsite,
icon: Icon(Icons.open_in_new, color: primaryColor),
label: Text(
2020-10-19 05:13:49 +06:30
'Visit courier website \nfor nearest drop-off',
2020-10-18 02:38:46 +06:30
style: TextStyle(fontSize: 16, color: primaryColor),
),
backgroundColor: Colors.white,
));
2020-10-16 10:58:31 +06:30
final pickupAddressBox = DefaultDeliveryAddress(
2021-09-10 16:48:21 +06:30
deliveryAddress: _shipment!.pickupAddress,
2020-10-16 10:58:31 +06:30
iconData: Icons.location_on,
labelKey: "shipment.location",
);
2020-10-19 05:13:49 +06:30
var usersBox = DisplayText(
labelTextKey: "shipment.staff",
2021-09-10 16:48:21 +06:30
text: _shipment!.pickupUserName ?? "",
2020-10-19 05:13:49 +06:30
iconData: MaterialCommunityIcons.worker);
2020-10-16 10:58:31 +06:30
var handlingFeeBox = DisplayText(
labelTextKey: "shipment.handling.fee",
2021-09-10 17:14:59 +06:30
text: (_shipment!.handlingFee).toString(),
2020-10-19 05:13:49 +06:30
iconData: FontAwesome.truck);
final assignCompleteBtn = LocalButton(
textKey: "shipment.assign.complete.btn",
callBack: _completeAssign,
);
final completePickupBtn = LocalButton(
textKey: "shipment.pickup.complete.btn",
callBack: _pickup,
);
final completePackBtn = LocalButton(
textKey: "shipment.pack.complete.btn",
callBack: _pack,
);
final confirmCompleteBtn = LocalButton(
textKey: "shipment.confirm.complete.btn",
callBack: _confirm,
);
final fcsShipmentNumberBox = DisplayText(
2021-09-10 16:48:21 +06:30
text: _shipment!.fcsShipmentNumber ?? "",
2020-10-19 05:13:49 +06:30
labelTextKey: "FCSshipment.number",
iconData: Ionicons.ios_airplane,
);
final completeReceiveBtn = LocalButton(
textKey: "shipment.receive.complete.btn",
callBack: _receive,
2020-10-16 10:58:31 +06:30
);
return LocalProgress(
inAsyncCall: _isLoading,
child: Scaffold(
appBar: AppBar(
centerTitle: true,
leading: new IconButton(
icon: new Icon(
CupertinoIcons.back,
color: primaryColor,
),
onPressed: () => Navigator.of(context).pop(),
),
shadowColor: Colors.transparent,
backgroundColor: Colors.white,
title: LocalText(
context,
"shipment.info",
fontSize: 20,
color: primaryColor,
),
actions: <Widget>[
IconButton(
2020-10-19 05:13:49 +06:30
icon: Icon(Icons.edit,
color: isEditable ? primaryColor : Colors.grey),
onPressed: isEditable ? _edit : null,
2020-10-18 02:38:46 +06:30
),
2021-09-10 16:48:21 +06:30
widget.isCustomer! ? popupMenuCustomer : popupMenu,
2020-10-16 10:58:31 +06:30
]),
body: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView(
children: <Widget>[
2020-10-18 02:38:46 +06:30
shipmentNumberBox,
2020-10-16 10:58:31 +06:30
LocalTitle(textKey: "shipment.type"),
LocalRadioButtons(
2020-10-18 02:38:46 +06:30
readOnly: true,
values: pickupModel.shipmentTypes,
2021-09-10 16:48:21 +06:30
selectedValue: _shipment!.shipmentType,
2020-10-18 02:38:46 +06:30
),
...(isLocalDropoff
? [
LocalTitle(textKey: "shipment.location.dropoff"),
localDropoffAddressBox
]
: []),
...(isCourierDropoff
? [
LocalTitle(textKey: "shipment.courier.dropoff"),
curierDropoffAddress
]
: []),
...(isCourierPickup || isLocalPickup
? [
LocalTitle(textKey: "shipment.location"),
pickupAddressBox,
LocalTitle(textKey: "shipment.date.time"),
pickupDateBox,
fromTimeBox,
toTimeBox,
]
: []),
2020-10-16 10:58:31 +06:30
LocalTitle(
textKey: "boxes.name",
2020-10-19 05:13:49 +06:30
trailing: Text(
2021-09-10 16:48:21 +06:30
"${_shipment!.totalCount} Cartons - ${_shipment!.totalWeight} lb"),
2020-10-16 10:58:31 +06:30
),
2020-10-18 02:38:46 +06:30
Column(
2021-09-10 16:48:21 +06:30
children: getBoxList(context, _shipment!.boxes),
2020-10-18 02:38:46 +06:30
),
2020-10-19 05:13:49 +06:30
!_isCustomer ? fcsShipmentNumberBox : Container(),
2021-09-10 16:48:21 +06:30
...(!_shipment!.isPending
2020-10-19 05:13:49 +06:30
? [
handlingFeeBox,
]
: []),
...(isLocalPickup
? [
LocalTitle(textKey: "shipment.assign.for.pickup"),
usersBox,
]
: []),
...(isLocalPickup && !_isCustomer
? [
2021-09-10 16:48:21 +06:30
_shipment!.isPending ? assignCompleteBtn : Container(),
_shipment!.isAssigned ? completePickupBtn : Container(),
_shipment!.isPickuped ? completePackBtn : Container(),
2020-10-19 05:13:49 +06:30
]
: []),
...((isCourierPickup || isCourierDropoff) && !_isCustomer
? [
2021-09-10 16:48:21 +06:30
_shipment!.isPending ? confirmCompleteBtn : Container(),
_shipment!.isConfirmed ? completeReceiveBtn : Container(),
_shipment!.isReceived ? completePackBtn : Container(),
2020-10-19 05:13:49 +06:30
]
: []),
...((isLocalDropoff) && !_isCustomer
? [
2021-09-10 16:48:21 +06:30
_shipment!.isPending ? completeReceiveBtn : Container(),
_shipment!.isReceived ? completePackBtn : Container(),
2020-10-19 05:13:49 +06:30
]
: []),
2020-10-16 10:58:31 +06:30
],
),
),
),
);
}
2020-10-18 02:38:46 +06:30
List<Widget> getBoxList(BuildContext context, List<Carton> boxes) {
2024-01-23 16:28:08 +06:30
if (boxes.isEmpty) return [];
2020-10-16 10:58:31 +06:30
return boxes.asMap().entries.map((_box) {
2020-10-18 02:38:46 +06:30
return Row(
children: [
Expanded(child: BoxRow(box: _box.value)),
],
2020-10-16 10:58:31 +06:30
);
}).toList();
}
2020-10-18 02:38:46 +06:30
_edit() async {
2021-09-10 16:48:21 +06:30
bool? updated = await Navigator.push<bool>(
2020-10-18 02:38:46 +06:30
context,
CupertinoPageRoute(
builder: (context) => ShipmentEditor(
shipment: _shipment,
)),
);
if (updated ?? false) {
2021-09-10 16:48:21 +06:30
await _loadShipment(_shipment!.id!);
await _loadCartons(_shipment!.id!);
2020-10-18 02:38:46 +06:30
}
}
_cancel() {
showConfirmDialog(context, "shipment.cancel.confirm", () {
_cancelShipment();
});
}
_cancelShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.cancelShipment(_shipment!);
2020-10-18 02:38:46 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
_openCourierWebsite() {
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
launch("${mainModel.setting!.courierWebsite}");
2020-10-18 02:38:46 +06:30
}
2020-10-19 05:13:49 +06:30
_gotoAssign() async {
2021-09-10 16:48:21 +06:30
bool? assigned = await Navigator.push<bool>(
2020-10-19 05:13:49 +06:30
context,
CupertinoPageRoute(
builder: (context) => ShipmentAssign(
shipment: _shipment,
)),
);
if (assigned ?? false) {
2021-09-10 16:48:21 +06:30
await _loadShipment(_shipment!.id!);
2020-10-19 05:13:49 +06:30
}
}
_completeAssign() {
showConfirmDialog(context, "shipment.assign.complete.confirm", () {
_completeAssignShipment();
});
}
_completeAssignShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.completeAssignShipment(_shipment!);
2020-10-19 05:13:49 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
_pickup() {
showConfirmDialog(context, "shipment.pickup.complete.confirm", () {
_pickupShipment();
});
}
_pickupShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.completePickupShipment(_shipment!);
2020-10-19 05:13:49 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
_gotoPack() async {
2021-09-10 16:48:21 +06:30
bool? assigned = await Navigator.push<bool>(
2020-10-19 05:13:49 +06:30
context,
CupertinoPageRoute(
builder: (context) => ShipmentPack(
2021-09-10 16:48:21 +06:30
shipment: _shipment!,
2020-10-19 05:13:49 +06:30
)),
);
if (assigned ?? false) {
2021-09-10 16:48:21 +06:30
await _loadShipment(_shipment!.id!);
await _loadCartons(_shipment!.id!);
2020-10-19 05:13:49 +06:30
}
}
_pack() {
showConfirmDialog(context, "shipment.pack.complete.confirm", () {
_packShipment();
});
}
_packShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.completePackShipment(_shipment!);
2020-10-19 05:13:49 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
_gotoConfirm() async {
2021-09-10 16:48:21 +06:30
bool? assigned = await Navigator.push<bool>(
2020-10-19 05:13:49 +06:30
context,
CupertinoPageRoute(
builder: (context) => ShipmentConfirm(
shipment: _shipment,
)),
);
if (assigned ?? false) {
2021-09-10 16:48:21 +06:30
await _loadShipment(_shipment!.id!);
2020-10-19 05:13:49 +06:30
}
}
_confirm() {
showConfirmDialog(context, "shipment.confirm.complete.confirm", () {
_confirmShipment();
});
}
_confirmShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.completeConfirmShipment(_shipment!);
2020-10-19 05:13:49 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
_receive() {
showConfirmDialog(context, "shipment.receive.complete.confirm", () {
_receiveShipment();
});
}
_receiveShipment() async {
setState(() {
_isLoading = true;
});
try {
ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false);
2021-09-10 16:48:21 +06:30
await shipmentModel.completeReceiveShipment(_shipment!);
2020-10-19 05:13:49 +06:30
Navigator.pop(context, true);
} catch (e) {
showMsgDialog(context, "Error", e.toString());
} finally {
setState(() {
_isLoading = false;
});
}
}
2020-10-16 10:58:31 +06:30
}