Merge branch 'master' of https://git.mokkon.com/sainw/fcs
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
"back.button_confirm":"Are you sure you want to continue without submitting changes?",
|
"back.button_confirm":"Are you sure you want to continue without submitting changes?",
|
||||||
"btn.clear":"Clear Filter",
|
"btn.clear":"Clear Filter",
|
||||||
"btn.filter":"Filter",
|
"btn.filter":"Filter",
|
||||||
|
"btn.exit_confirm":"Are you sure you want to exit?",
|
||||||
"Buttons End ================================================================":"",
|
"Buttons End ================================================================":"",
|
||||||
|
|
||||||
"Offline Start ================================================================":"",
|
"Offline Start ================================================================":"",
|
||||||
@@ -104,6 +105,7 @@
|
|||||||
"home.invitation.request.msg":"We are working on your invitation request!",
|
"home.invitation.request.msg":"We are working on your invitation request!",
|
||||||
"home.search":"Enter tracking number",
|
"home.search":"Enter tracking number",
|
||||||
"home.search.btn":"Search",
|
"home.search.btn":"Search",
|
||||||
|
"home.pin.logout.confirm":"Are you sure want to logout?",
|
||||||
"Home End ================================================================":"",
|
"Home End ================================================================":"",
|
||||||
|
|
||||||
"Invite Start ================================================================":"",
|
"Invite Start ================================================================":"",
|
||||||
@@ -351,7 +353,7 @@
|
|||||||
"box.no_package":"There is no packages.",
|
"box.no_package":"There is no packages.",
|
||||||
"box.input_cargo_weight":"Cargo type (lb)",
|
"box.input_cargo_weight":"Cargo type (lb)",
|
||||||
"box.input_surcharge_item":"Surcharge items",
|
"box.input_surcharge_item":"Surcharge items",
|
||||||
"box.select.cargo_type":"Select surcharge item",
|
"box.select.cargo_type":"Add surcharge item",
|
||||||
"box.surcharge.item":"Surcharge items",
|
"box.surcharge.item":"Surcharge items",
|
||||||
"box.package.count":"Packages ({0})",
|
"box.package.count":"Packages ({0})",
|
||||||
"box.bill_to":"Bill to",
|
"box.bill_to":"Bill to",
|
||||||
@@ -370,6 +372,7 @@
|
|||||||
"box.print.btn":"Print",
|
"box.print.btn":"Print",
|
||||||
"box.delivery":"Delivery",
|
"box.delivery":"Delivery",
|
||||||
"box.pickup":"Pick-up",
|
"box.pickup":"Pick-up",
|
||||||
|
"box.add.cargo_type":"Add cargo type",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
@@ -393,8 +396,8 @@
|
|||||||
"FCSshipment.departure_date":"Departure date",
|
"FCSshipment.departure_date":"Departure date",
|
||||||
"FCSshipment.shipment_type":"Shipment type",
|
"FCSshipment.shipment_type":"Shipment type",
|
||||||
"FCSshipment.consignee":"Consignee",
|
"FCSshipment.consignee":"Consignee",
|
||||||
"FCSshipment.port_of_loading":"Port of loading",
|
"FCSshipment.port_of_loading":"Loading port",
|
||||||
"FCSshipment.final_destination":"Final destination",
|
"FCSshipment.final_destination":"Destination port",
|
||||||
"FCSshipment.status":"Status",
|
"FCSshipment.status":"Status",
|
||||||
"FCSshipment.remark":"Remark",
|
"FCSshipment.remark":"Remark",
|
||||||
"FCSshipment.commercial_invoice":"Download commercial invoice",
|
"FCSshipment.commercial_invoice":"Download commercial invoice",
|
||||||
@@ -415,6 +418,7 @@
|
|||||||
"FCSshipment.process.confirm":"Process this shipment?",
|
"FCSshipment.process.confirm":"Process this shipment?",
|
||||||
"FCSshipment.arrive.confirm":"Arrive this shipment?",
|
"FCSshipment.arrive.confirm":"Arrive this shipment?",
|
||||||
"FCSshipment.invoice.confirm":"Invoice this shipment?",
|
"FCSshipment.invoice.confirm":"Invoice this shipment?",
|
||||||
|
"FCSshipment.delete.confirm":"Delete this shipment?",
|
||||||
"FCS Shipment End ================================================================":"",
|
"FCS Shipment End ================================================================":"",
|
||||||
|
|
||||||
"Shipment Start ================================================================":"",
|
"Shipment Start ================================================================":"",
|
||||||
@@ -509,6 +513,8 @@
|
|||||||
"cargo.qty":"Quantity",
|
"cargo.qty":"Quantity",
|
||||||
"cargo.amount":"Amount",
|
"cargo.amount":"Amount",
|
||||||
"cargo.edit.delete.confirm":"Delete this cargo type?",
|
"cargo.edit.delete.confirm":"Delete this cargo type?",
|
||||||
|
"cargo.display_index":"Display index",
|
||||||
|
"cargo.is_default":"Default Cargo",
|
||||||
"Cargo End ================================================================":"",
|
"Cargo End ================================================================":"",
|
||||||
|
|
||||||
"Invoices Start ================================================================":"",
|
"Invoices Start ================================================================":"",
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
"back.button_confirm":"Are you sure you want to continue without submitting changes?",
|
"back.button_confirm":"Are you sure you want to continue without submitting changes?",
|
||||||
"btn.clear":"Clear Filter",
|
"btn.clear":"Clear Filter",
|
||||||
"btn.filter":"Filter",
|
"btn.filter":"Filter",
|
||||||
|
"btn.exit_confirm":"Are you sure you want to exit?",
|
||||||
"Buttons End ================================================================":"",
|
"Buttons End ================================================================":"",
|
||||||
|
|
||||||
"Offline Start ================================================================":"",
|
"Offline Start ================================================================":"",
|
||||||
@@ -104,6 +105,7 @@
|
|||||||
"home.invitation.request.msg":"ဖိတ်ကြားမှု တောင်းဆိုသည်ကို လုပ်ဆောင်နေပါသည်!",
|
"home.invitation.request.msg":"ဖိတ်ကြားမှု တောင်းဆိုသည်ကို လုပ်ဆောင်နေပါသည်!",
|
||||||
"home.search":"Tracking number ရိုက်ထည့်ပါ",
|
"home.search":"Tracking number ရိုက်ထည့်ပါ",
|
||||||
"home.search.btn":"ရှာမည်",
|
"home.search.btn":"ရှာမည်",
|
||||||
|
"home.pin.logout.confirm":"အကောင့်ထွက်ရန်သေချာပြီလား?",
|
||||||
"Home End ================================================================":"",
|
"Home End ================================================================":"",
|
||||||
|
|
||||||
"Invite Start ================================================================":"",
|
"Invite Start ================================================================":"",
|
||||||
@@ -351,7 +353,7 @@
|
|||||||
"box.no_package":"There is no packages.",
|
"box.no_package":"There is no packages.",
|
||||||
"box.input_cargo_weight":"Cargo type (lb)",
|
"box.input_cargo_weight":"Cargo type (lb)",
|
||||||
"box.input_surcharge_item":"Surcharge items",
|
"box.input_surcharge_item":"Surcharge items",
|
||||||
"box.select.cargo_type":"Select surcharge item",
|
"box.select.cargo_type":"Add surcharge item",
|
||||||
"box.surcharge.item":"Surcharge items",
|
"box.surcharge.item":"Surcharge items",
|
||||||
"box.package.count":"Packages ({0})",
|
"box.package.count":"Packages ({0})",
|
||||||
"box.bill_to":"Bill to",
|
"box.bill_to":"Bill to",
|
||||||
@@ -370,6 +372,7 @@
|
|||||||
"box.print.btn":"ပရင့်ထုတ်မည်",
|
"box.print.btn":"ပရင့်ထုတ်မည်",
|
||||||
"box.delivery":"Delivery",
|
"box.delivery":"Delivery",
|
||||||
"box.pickup":"Pick-up",
|
"box.pickup":"Pick-up",
|
||||||
|
"box.add.cargo_type":"Add cargo type",
|
||||||
"Boxes End ================================================================":"",
|
"Boxes End ================================================================":"",
|
||||||
|
|
||||||
"Delivery Start ================================================================":"",
|
"Delivery Start ================================================================":"",
|
||||||
@@ -418,6 +421,7 @@
|
|||||||
"FCSshipment.process.confirm":"လုပ်ငန်းစဉ်ကို အတည်ပြုပါ ?",
|
"FCSshipment.process.confirm":"လုပ်ငန်းစဉ်ကို အတည်ပြုပါ ?",
|
||||||
"FCSshipment.arrive.confirm":"ရောက်ရှိကြောင်း အတည်ပြုပါ ?",
|
"FCSshipment.arrive.confirm":"ရောက်ရှိကြောင်း အတည်ပြုပါ ?",
|
||||||
"FCSshipment.invoice.confirm":"Invoice this shipment ?",
|
"FCSshipment.invoice.confirm":"Invoice this shipment ?",
|
||||||
|
"FCSshipment.delete.confirm":"တင်ပို့ခြင်းကို ဖျက်မလား?",
|
||||||
"FCS Shipment End ================================================================":"",
|
"FCS Shipment End ================================================================":"",
|
||||||
|
|
||||||
"Shipment Start ================================================================":"",
|
"Shipment Start ================================================================":"",
|
||||||
@@ -512,6 +516,8 @@
|
|||||||
"cargo.qty":"အရေအတွက်",
|
"cargo.qty":"အရေအတွက်",
|
||||||
"cargo.amount":"ပမာဏ",
|
"cargo.amount":"ပမာဏ",
|
||||||
"cargo.edit.delete.confirm":"ကုန်ပစ္စည်းကို ဖျက်မလား?",
|
"cargo.edit.delete.confirm":"ကုန်ပစ္စည်းကို ဖျက်မလား?",
|
||||||
|
"cargo.display_index":"Display index",
|
||||||
|
"cargo.is_default":"Default Cargo",
|
||||||
"Cargo End ================================================================":"",
|
"Cargo End ================================================================":"",
|
||||||
|
|
||||||
"Invoices Start ================================================================":"",
|
"Invoices Start ================================================================":"",
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import 'pages/carton/model/package_selection_model.dart';
|
|||||||
import 'pages/carton/model/sender_selection_model.dart';
|
import 'pages/carton/model/sender_selection_model.dart';
|
||||||
import 'pages/carton/model/shipment_selection_model.dart';
|
import 'pages/carton/model/shipment_selection_model.dart';
|
||||||
import 'pages/delivery/model/delivery_model.dart';
|
import 'pages/delivery/model/delivery_model.dart';
|
||||||
|
import 'pages/signin/pinlogin_page.dart';
|
||||||
|
|
||||||
class App extends StatefulWidget {
|
class App extends StatefulWidget {
|
||||||
final String title;
|
final String title;
|
||||||
@@ -121,6 +122,7 @@ class _AppState extends State<App> {
|
|||||||
'/welcome': (_) => WelcomePage(),
|
'/welcome': (_) => WelcomePage(),
|
||||||
'/home': (_) => HomePage(),
|
'/home': (_) => HomePage(),
|
||||||
'/language_selection': (context) => InitialLanguageSelectionPage(),
|
'/language_selection': (context) => InitialLanguageSelectionPage(),
|
||||||
|
'/pin_login': (_) => PinLoginPage()
|
||||||
};
|
};
|
||||||
return routes;
|
return routes;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,35 +2,25 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
enum Flavor { UNSET, DEV, STAGING, PRODUCTION, LOCAL }
|
enum Flavor { UNSET, DEV, STAGING, PRODUCTION, LOCAL }
|
||||||
|
|
||||||
const FlavorNames = ["Unset", "Development", "Staging", "Production", "Local"];
|
const FlavorNames = ["Unset", "Development", "Staging", "Production", "Local"];
|
||||||
|
|
||||||
class Config {
|
class Config {
|
||||||
static Config _instance = Config(
|
static Config _instance = Config(flavor: Flavor.UNSET, apiURL: "");
|
||||||
flavor: Flavor.UNSET,
|
|
||||||
apiURL: "",
|
|
||||||
bucketName: "",
|
|
||||||
reportProjectID: "",
|
|
||||||
reportURL: "");
|
|
||||||
|
|
||||||
final Flavor flavor;
|
final Flavor flavor;
|
||||||
final String name;
|
final String name;
|
||||||
final Color color;
|
final Color color;
|
||||||
final String apiURL;
|
final String apiURL;
|
||||||
final String reportURL;
|
|
||||||
final Level level;
|
final Level level;
|
||||||
final String reportProjectID;
|
|
||||||
final String bucketName;
|
|
||||||
|
|
||||||
factory Config(
|
factory Config(
|
||||||
{required Flavor flavor,
|
{required Flavor flavor,
|
||||||
required String apiURL,
|
required String apiURL,
|
||||||
required String reportURL,
|
Color color = Colors.blue,
|
||||||
required String reportProjectID,
|
Level level = Level.SEVERE}) {
|
||||||
required String bucketName,
|
_instance = Config._internal(
|
||||||
Color color= Colors.blue,
|
flavor, FlavorNames[flavor.index], color, apiURL, level);
|
||||||
Level level= Level.SEVERE}) {
|
|
||||||
_instance = Config._internal(flavor, FlavorNames[flavor.index], color,
|
|
||||||
apiURL, reportURL, level, reportProjectID, bucketName);
|
|
||||||
|
|
||||||
Logger.root.level = level;
|
Logger.root.level = level;
|
||||||
Logger.root.onRecord.listen((record) {
|
Logger.root.onRecord.listen((record) {
|
||||||
@@ -41,8 +31,7 @@ class Config {
|
|||||||
return _instance;
|
return _instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
Config._internal(this.flavor, this.name, this.color, this.apiURL,
|
Config._internal(this.flavor, this.name, this.color, this.apiURL, this.level);
|
||||||
this.reportURL, this.level, this.reportProjectID, this.bucketName);
|
|
||||||
|
|
||||||
static Config get instance {
|
static Config get instance {
|
||||||
return _instance;
|
return _instance;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ const privilege_collection = "privileges";
|
|||||||
const markets_collection = "markets";
|
const markets_collection = "markets";
|
||||||
const carton_sizes_collection = "carton_sizes";
|
const carton_sizes_collection = "carton_sizes";
|
||||||
const shipment_type_collection = "shipment_types";
|
const shipment_type_collection = "shipment_types";
|
||||||
|
const shipment_consignee_collection = "shipment_consignees";
|
||||||
|
const shipment_port_collection = "ports";
|
||||||
|
|
||||||
const packages_collection = "packages";
|
const packages_collection = "packages";
|
||||||
const messages_collection = "messages";
|
const messages_collection = "messages";
|
||||||
@@ -81,6 +83,7 @@ const privilege_receiving = "rc";
|
|||||||
const privilege_pickup = "pku";
|
const privilege_pickup = "pku";
|
||||||
const privilege_collect = "col";
|
const privilege_collect = "col";
|
||||||
const privilege_report = "rpt";
|
const privilege_report = "rpt";
|
||||||
|
const privilege_pin ="pin";
|
||||||
|
|
||||||
// Pickup types
|
// Pickup types
|
||||||
const shipment_local_pickup = "Local pickup";
|
const shipment_local_pickup = "Local pickup";
|
||||||
@@ -91,6 +94,7 @@ const shipment_courier_dropoff = "Courier drop off";
|
|||||||
//Carton types
|
//Carton types
|
||||||
const carton_from_packages = "For packages";
|
const carton_from_packages = "For packages";
|
||||||
const carton_mix_carton = "For cartons (Mix carton)";
|
const carton_mix_carton = "For cartons (Mix carton)";
|
||||||
|
const mix_carton = "Mix carton";
|
||||||
|
|
||||||
const carton_from_cartons = "From cartons";
|
const carton_from_cartons = "From cartons";
|
||||||
const carton_from_shipments = "From shipments";
|
const carton_from_shipments = "From shipments";
|
||||||
@@ -100,7 +104,7 @@ const carton_mix_box = "Mix box";
|
|||||||
// carton Size
|
// carton Size
|
||||||
const standardCarton = "Standard carton size";
|
const standardCarton = "Standard carton size";
|
||||||
const customCarton = "Custom size";
|
const customCarton = "Custom size";
|
||||||
const packageCartion = "Package";
|
const packageCarton = "Package";
|
||||||
|
|
||||||
//Mix types
|
//Mix types
|
||||||
const mix_delivery = "Mix Delivery";
|
const mix_delivery = "Mix Delivery";
|
||||||
@@ -140,9 +144,9 @@ const payment_confirmed_status = "confirmed";
|
|||||||
const payment_canceled_status = "canceled";
|
const payment_canceled_status = "canceled";
|
||||||
|
|
||||||
//Delivery types
|
//Delivery types
|
||||||
const delivery_caton = "Delivery";
|
const delivery_caton = "delivery";
|
||||||
const pickup_carton = "Pick-up";
|
const pickup_carton = "pickup";
|
||||||
|
|
||||||
// bill
|
// bill
|
||||||
const billToSender = "Bill to sender";
|
const billToSender = "sender";
|
||||||
const billToConsignee = "Bill to consignee";
|
const billToConsignee = "consignee";
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import 'package:fcs/helpers/firebase_helper.dart';
|
|||||||
import 'package:firebase_auth/firebase_auth.dart' as fb;
|
import 'package:firebase_auth/firebase_auth.dart' as fb;
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../../helpers/shared_pref.dart';
|
||||||
import '../services/services.dart';
|
import '../services/services.dart';
|
||||||
|
|
||||||
class AuthFb {
|
class AuthFb {
|
||||||
@@ -108,13 +109,15 @@ class AuthFb {
|
|||||||
Future<void> signoutStart() async {
|
Future<void> signoutStart() async {
|
||||||
await userListener?.cancel();
|
await userListener?.cancel();
|
||||||
await userAuthListener?.cancel();
|
await userAuthListener?.cancel();
|
||||||
|
await _pinUserListener?.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> signoutEnd() async {
|
Future<void> signoutEnd() async {
|
||||||
|
await SharedPref.setPinLockOn(false);
|
||||||
await _fb.signOut();
|
await _fb.signOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _addUserToStream({bool refreshIdToken = false}) async {
|
Future<User?> _addUserToStream({bool refreshIdToken = false}) async {
|
||||||
fb.User? firebaseUser = _fb.currentUser;
|
fb.User? firebaseUser = _fb.currentUser;
|
||||||
if (firebaseUser == null) return null;
|
if (firebaseUser == null) return null;
|
||||||
Map<dynamic, dynamic>? claims =
|
Map<dynamic, dynamic>? claims =
|
||||||
@@ -128,15 +131,20 @@ class AuthFb {
|
|||||||
user = await _getUserFromFirestore(cid);
|
user = await _getUserFromFirestore(cid);
|
||||||
}
|
}
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
controller.add(null);
|
_addUser(null);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadUserClaim(claims, user);
|
loadUserClaim(claims, user);
|
||||||
controller.add(user);
|
_addUser(user);
|
||||||
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
loadUserClaim(Map claims, User user) {
|
loadUserClaim(Map claims, User user) {
|
||||||
|
if (pinLoginUser != null) {
|
||||||
|
user.fcsID = pinLoginUser?.fcsID;
|
||||||
|
}
|
||||||
|
|
||||||
// add privileges
|
// add privileges
|
||||||
String? privileges = claims["pr"];
|
String? privileges = claims["pr"];
|
||||||
if (privileges != null && privileges != "") {
|
if (privileges != null && privileges != "") {
|
||||||
@@ -252,9 +260,9 @@ class AuthFb {
|
|||||||
// get privilege from claim
|
// get privilege from claim
|
||||||
Map<dynamic, dynamic> claims = await getClaims(refreshIdToken: true);
|
Map<dynamic, dynamic> claims = await getClaims(refreshIdToken: true);
|
||||||
loadUserClaim(claims, user);
|
loadUserClaim(claims, user);
|
||||||
controller.add(user);
|
_addUser(user);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
controller.add(null);
|
_addUser(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -286,12 +294,23 @@ class AuthFb {
|
|||||||
|
|
||||||
log.info("_startAuthListener: $user");
|
log.info("_startAuthListener: $user");
|
||||||
if (_logIn) {
|
if (_logIn) {
|
||||||
controller.add(user);
|
_addUser(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_addUser(User? user) {
|
||||||
|
if (user == null) {
|
||||||
|
pinLoginUser = null;
|
||||||
|
}
|
||||||
|
if (pinLoginUser != null) {
|
||||||
|
controller.add(pinLoginUser);
|
||||||
|
} else {
|
||||||
|
controller.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Stream<User?> user() {
|
Stream<User?> user() {
|
||||||
// ignore: close_sinks
|
// ignore: close_sinks
|
||||||
StreamSubscription<fb.User?>? authListener;
|
StreamSubscription<fb.User?>? authListener;
|
||||||
@@ -301,7 +320,7 @@ class AuthFb {
|
|||||||
authListener = _fb.authStateChanges().listen((firebaseUser) async {
|
authListener = _fb.authStateChanges().listen((firebaseUser) async {
|
||||||
_logIn = firebaseUser != null;
|
_logIn = firebaseUser != null;
|
||||||
if (firebaseUser == null) {
|
if (firebaseUser == null) {
|
||||||
controller.add(null);
|
_addUser(null);
|
||||||
} else {
|
} else {
|
||||||
_addUserToStream(refreshIdToken: true);
|
_addUserToStream(refreshIdToken: true);
|
||||||
_startUserListener();
|
_startUserListener();
|
||||||
@@ -319,4 +338,51 @@ class AuthFb {
|
|||||||
|
|
||||||
return controller.stream;
|
return controller.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
User? pinLoginUser;
|
||||||
|
|
||||||
|
StreamSubscription<DocumentSnapshot>? _pinUserListener;
|
||||||
|
|
||||||
|
Future<void> pinLogin(
|
||||||
|
{required String currentUserId,
|
||||||
|
required String fcsID,
|
||||||
|
required String pin}) async {
|
||||||
|
var data = await requestAPI("/pin/login", "POST",
|
||||||
|
token: await getToken(), payload: {'fcs_id': fcsID, 'pin': pin});
|
||||||
|
|
||||||
|
var userId = data['user_id'] ?? '';
|
||||||
|
if (userId == currentUserId) {
|
||||||
|
//logout
|
||||||
|
logoutPinAccount();
|
||||||
|
await SharedPref.setPinLockOn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
var pinToken = data['pin_token'] ?? '';
|
||||||
|
|
||||||
|
// Get user for pin login
|
||||||
|
_listenPinUser(userId: userId, pinToken: pinToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _listenPinUser(
|
||||||
|
{required String userId, required String pinToken}) async {
|
||||||
|
Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
|
||||||
|
.collection(user_collection)
|
||||||
|
.doc(userId)
|
||||||
|
.snapshots();
|
||||||
|
_pinUserListener?.cancel();
|
||||||
|
_pinUserListener = snapshot.listen((snap) async {
|
||||||
|
User user = User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
|
||||||
|
pinLoginUser = user;
|
||||||
|
if (pinLoginUser != null) {
|
||||||
|
pinLoginUser!.pinToken = pinToken;
|
||||||
|
}
|
||||||
|
await _addUserToStream(refreshIdToken: true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logoutPinAccount() async {
|
||||||
|
_pinUserListener?.cancel();
|
||||||
|
pinLoginUser = null;
|
||||||
|
await _addUserToStream(refreshIdToken: true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,24 @@ class CartonDataProvider {
|
|||||||
|
|
||||||
Future<void> deleteCarton(Carton carton) async {
|
Future<void> deleteCarton(Carton carton) async {
|
||||||
return await requestAPI("/cartons", "DELETE",
|
return await requestAPI("/cartons", "DELETE",
|
||||||
payload: carton.toMap(), token: await getToken());
|
payload: {'id': carton.id}, token: await getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Carton> createMixCarton(Carton carton) async {
|
||||||
|
var data = await requestAPI("/cartons", "POST",
|
||||||
|
payload: carton.toMapForMix(), token: await getToken());
|
||||||
|
return Carton.fromMap(data, data['id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateMixCarton(Carton carton) async {
|
||||||
|
return await requestAPI("/cartons", "PUT",
|
||||||
|
payload: carton.toMapForMix(), token: await getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> uploadCartonImages(Carton carton) async {
|
||||||
|
return await requestAPI("/cartons/upload_images", "PUT",
|
||||||
|
payload: {'id': carton.id, "photo_urls": carton.photoUrls},
|
||||||
|
token: await getToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deliver(Carton carton) async {
|
Future<void> deliver(Carton carton) async {
|
||||||
@@ -47,7 +64,7 @@ class CartonDataProvider {
|
|||||||
.collection(path)
|
.collection(path)
|
||||||
.where("carton_number", isEqualTo: term)
|
.where("carton_number", isEqualTo: term)
|
||||||
.where("is_deleted", isEqualTo: false)
|
.where("is_deleted", isEqualTo: false)
|
||||||
.orderBy("created_at", descending: true)
|
.orderBy("update_time", descending: true)
|
||||||
.get();
|
.get();
|
||||||
return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
|
return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:fcs/config.dart';
|
|
||||||
import 'package:fcs/constants.dart';
|
import 'package:fcs/constants.dart';
|
||||||
import 'package:fcs/domain/entities/package.dart';
|
import 'package:fcs/domain/entities/package.dart';
|
||||||
import 'package:fcs/helpers/api_helper.dart';
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
import 'package:fcs/helpers/firebase_helper.dart';
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../services/services.dart';
|
||||||
|
|
||||||
class PackageDataProvider {
|
class PackageDataProvider {
|
||||||
final log = Logger('PackageDataProvider');
|
final log = Logger('PackageDataProvider');
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ class PackageDataProvider {
|
|||||||
try {
|
try {
|
||||||
var data = await requestAPI(
|
var data = await requestAPI(
|
||||||
"/api/fts/$packages_collection/$escapePackage/$limit", "GET",
|
"/api/fts/$packages_collection/$escapePackage/$limit", "GET",
|
||||||
url: Config.instance.reportURL, token: await getToken());
|
url: Services.setting.reportURL, token: await getToken());
|
||||||
|
|
||||||
if (data == null) return [];
|
if (data == null) return [];
|
||||||
|
|
||||||
@@ -105,7 +106,7 @@ class PackageDataProvider {
|
|||||||
};
|
};
|
||||||
var result = await requestAPI("/api/data/packages", "POST",
|
var result = await requestAPI("/api/data/packages", "POST",
|
||||||
token: await getToken(),
|
token: await getToken(),
|
||||||
url: Config.instance.reportURL,
|
url: Services.setting.reportURL,
|
||||||
payload: jsonEncode(data));
|
payload: jsonEncode(data));
|
||||||
if (result == null) return packages;
|
if (result == null) return packages;
|
||||||
result.forEach((d) {
|
result.forEach((d) {
|
||||||
|
|||||||
@@ -4,8 +4,7 @@ import 'package:fcs/domain/entities/pickup.dart';
|
|||||||
import 'package:fcs/helpers/api_helper.dart';
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
import 'package:fcs/helpers/firebase_helper.dart';
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
import '../services/services.dart';
|
||||||
import '../../config.dart';
|
|
||||||
|
|
||||||
class PickupDataProvider {
|
class PickupDataProvider {
|
||||||
final log = Logger('PickupDataProvider');
|
final log = Logger('PickupDataProvider');
|
||||||
@@ -34,7 +33,7 @@ class PickupDataProvider {
|
|||||||
};
|
};
|
||||||
var result = await requestAPI("/api/data/pickups", "POST",
|
var result = await requestAPI("/api/data/pickups", "POST",
|
||||||
token: await getToken(),
|
token: await getToken(),
|
||||||
url: Config.instance.reportURL,
|
url: Services.setting.reportURL,
|
||||||
payload: jsonEncode(data));
|
payload: jsonEncode(data));
|
||||||
if (result == null) return pickups;
|
if (result == null) return pickups;
|
||||||
result.forEach((d) {
|
result.forEach((d) {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class RateDataProvider {
|
|||||||
.doc(rate_doc_id)
|
.doc(rate_doc_id)
|
||||||
.collection(cargo_types_collection)
|
.collection(cargo_types_collection)
|
||||||
.where("custom_duty", isEqualTo: false)
|
.where("custom_duty", isEqualTo: false)
|
||||||
|
.orderBy("display_index", descending: false)
|
||||||
.snapshots();
|
.snapshots();
|
||||||
|
|
||||||
await for (var snaps in snapshots) {
|
await for (var snaps in snapshots) {
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:fcs/config.dart';
|
|
||||||
import 'package:fcs/constants.dart';
|
import 'package:fcs/constants.dart';
|
||||||
import 'package:fcs/domain/entities/user.dart';
|
import 'package:fcs/domain/entities/user.dart';
|
||||||
import 'package:fcs/helpers/api_helper.dart';
|
import 'package:fcs/helpers/api_helper.dart';
|
||||||
import 'package:fcs/helpers/firebase_helper.dart';
|
import 'package:fcs/helpers/firebase_helper.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../services/services.dart';
|
||||||
|
|
||||||
class UserDataProvider {
|
class UserDataProvider {
|
||||||
final log = Logger('UserDataProvider');
|
final log = Logger('UserDataProvider');
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ class UserDataProvider {
|
|||||||
try {
|
try {
|
||||||
var data = await requestAPI(
|
var data = await requestAPI(
|
||||||
"/api/fts/$user_collection/$escapeBuyer/$limit", "GET",
|
"/api/fts/$user_collection/$escapeBuyer/$limit", "GET",
|
||||||
url: Config.instance.reportURL, token: await getToken());
|
url: Services.setting.reportURL, token: await getToken());
|
||||||
|
|
||||||
if (data == null) return [];
|
if (data == null) return [];
|
||||||
|
|
||||||
|
|||||||
@@ -74,4 +74,23 @@ class AuthServiceImp implements AuthService {
|
|||||||
Future<void> deleteAccount() {
|
Future<void> deleteAccount() {
|
||||||
return authFb.deleteAccount();
|
return authFb.deleteAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> pinLogin(
|
||||||
|
{required String currentUserId,
|
||||||
|
required String fcsID,
|
||||||
|
required String pin}) {
|
||||||
|
return authFb.pinLogin(
|
||||||
|
currentUserId: currentUserId, fcsID: fcsID, pin: pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
User? getPinLoginUser() {
|
||||||
|
return authFb.pinLoginUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> logoutPinAccount() {
|
||||||
|
return authFb.logoutPinAccount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,4 +15,10 @@ abstract class AuthService {
|
|||||||
Stream<User?> getUserStream();
|
Stream<User?> getUserStream();
|
||||||
Stream<Setting> getSetting();
|
Stream<Setting> getSetting();
|
||||||
Future<void> deleteAccount();
|
Future<void> deleteAccount();
|
||||||
|
Future<void> pinLogin(
|
||||||
|
{required String currentUserId,
|
||||||
|
required String fcsID,
|
||||||
|
required String pin});
|
||||||
|
User? getPinLoginUser();
|
||||||
|
Future<void> logoutPinAccount();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,4 +37,19 @@ class CartonServiceImp implements CartonService {
|
|||||||
Future<List<Carton>> searchCarton(String term) {
|
Future<List<Carton>> searchCarton(String term) {
|
||||||
return cartonDataProvider.searchCarton(term);
|
return cartonDataProvider.searchCarton(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Carton> createMixCarton(Carton carton) {
|
||||||
|
return cartonDataProvider.createMixCarton(carton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> updateMixCarton(Carton carton) {
|
||||||
|
return cartonDataProvider.updateMixCarton(carton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> uploadCartonImages(Carton carton) {
|
||||||
|
return cartonDataProvider.uploadCartonImages(carton);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,4 +6,7 @@ abstract class CartonService {
|
|||||||
Future<void> deleteCarton(Carton carton);
|
Future<void> deleteCarton(Carton carton);
|
||||||
Future<void> deliver(Carton carton);
|
Future<void> deliver(Carton carton);
|
||||||
Future<List<Carton>> searchCarton(String term);
|
Future<List<Carton>> searchCarton(String term);
|
||||||
|
Future<Carton> createMixCarton(Carton carton);
|
||||||
|
Future<void> updateMixCarton(Carton carton);
|
||||||
|
Future<void> uploadCartonImages(Carton carton);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import 'package:fcs/data/services/rate_service.dart';
|
|||||||
import 'package:fcs/data/services/shipment_imp.dart';
|
import 'package:fcs/data/services/shipment_imp.dart';
|
||||||
import 'package:fcs/data/services/shipment_service.dart';
|
import 'package:fcs/data/services/shipment_service.dart';
|
||||||
|
|
||||||
|
import '../../domain/entities/setting.dart';
|
||||||
import 'auth_imp.dart';
|
import 'auth_imp.dart';
|
||||||
import 'auth_service.dart';
|
import 'auth_service.dart';
|
||||||
import 'common_imp.dart';
|
import 'common_imp.dart';
|
||||||
@@ -37,6 +38,8 @@ import 'user_service.dart';
|
|||||||
|
|
||||||
class Services {
|
class Services {
|
||||||
static final Services instance = Services._();
|
static final Services instance = Services._();
|
||||||
|
static Setting setting = Setting();
|
||||||
|
|
||||||
|
|
||||||
late AuthService _authService;
|
late AuthService _authService;
|
||||||
late UserService _userService;
|
late UserService _userService;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ class CargoType {
|
|||||||
double customDutyFee;
|
double customDutyFee;
|
||||||
double calRate;
|
double calRate;
|
||||||
double calWeight;
|
double calWeight;
|
||||||
|
int displayIndex;
|
||||||
|
bool isDefault;
|
||||||
|
|
||||||
double get calAmount => calRate * calWeight;
|
double get calAmount => calRate * calWeight;
|
||||||
|
|
||||||
@@ -22,7 +24,9 @@ class CargoType {
|
|||||||
this.isChecked = false,
|
this.isChecked = false,
|
||||||
this.qty = 0,
|
this.qty = 0,
|
||||||
this.isCutomDuty = false,
|
this.isCutomDuty = false,
|
||||||
this.customDutyFee = 0});
|
this.customDutyFee = 0,
|
||||||
|
this.displayIndex = 0,
|
||||||
|
this.isDefault = false});
|
||||||
|
|
||||||
factory CargoType.fromMap(Map<String, dynamic> map, String id) {
|
factory CargoType.fromMap(Map<String, dynamic> map, String id) {
|
||||||
return CargoType(
|
return CargoType(
|
||||||
@@ -33,8 +37,24 @@ class CargoType {
|
|||||||
calWeight: map['cal_weight']?.toDouble() ?? 0,
|
calWeight: map['cal_weight']?.toDouble() ?? 0,
|
||||||
calRate: map['cal_rate']?.toDouble() ?? 0,
|
calRate: map['cal_rate']?.toDouble() ?? 0,
|
||||||
isCutomDuty: map['custom_duty'] ?? false,
|
isCutomDuty: map['custom_duty'] ?? false,
|
||||||
customDutyFee: (map['custom_duty_fee'] ?? 0).toDouble());
|
customDutyFee: (map['custom_duty_fee'] ?? 0).toDouble(),
|
||||||
//qty: (map['qty'] ?? 0).toInt());
|
displayIndex: map['display_index'] ?? 0,
|
||||||
|
isDefault: map['is_defalut'] ?? false);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory CargoType.fromMapForCargo(Map<String, dynamic> map, String id) {
|
||||||
|
return CargoType(
|
||||||
|
id: id,
|
||||||
|
name: map['name'],
|
||||||
|
weight: map['weight']?.toDouble() ?? 0,
|
||||||
|
displayIndex: map['display_index'] ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory CargoType.fromMapForsurcharge(Map<String, dynamic> map, String id) {
|
||||||
|
return CargoType(
|
||||||
|
id: id,
|
||||||
|
name: map['name'],
|
||||||
|
qty: map['qty'] == null ? 0 : int.tryParse(map['qty'].toString()) ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
@@ -47,10 +67,20 @@ class CargoType {
|
|||||||
'cal_rate': calRate,
|
'cal_rate': calRate,
|
||||||
'custom_duty': isCutomDuty,
|
'custom_duty': isCutomDuty,
|
||||||
'custom_duty_fee': customDutyFee,
|
'custom_duty_fee': customDutyFee,
|
||||||
'qty': qty
|
'qty': qty,
|
||||||
|
'is_defalut': isDefault,
|
||||||
|
'display_index': displayIndex
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMapForCargo() {
|
||||||
|
return {"id": id, 'weight': weight};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMapForSurcharge() {
|
||||||
|
return {"id": id, 'qty': qty};
|
||||||
|
}
|
||||||
|
|
||||||
CargoType clone() {
|
CargoType clone() {
|
||||||
return CargoType.fromMap(toMap(), this.id!);
|
return CargoType.fromMap(toMap(), this.id!);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,33 +10,34 @@ import 'package.dart';
|
|||||||
|
|
||||||
class Carton {
|
class Carton {
|
||||||
String? id;
|
String? id;
|
||||||
String? shipmentID;
|
String? cartonNumber;
|
||||||
String? shipmentNumber;
|
String? fcsShipmentID;
|
||||||
|
String? fcsShipmentNumber;
|
||||||
|
|
||||||
String? senderID;
|
String? senderID;
|
||||||
String? senderFCSID;
|
String? senderFCSID;
|
||||||
String? senderName;
|
String? senderName;
|
||||||
|
|
||||||
String? boxNumber;
|
String? consigneeFCSID;
|
||||||
String? status;
|
String? consigneeName;
|
||||||
String? cargoDesc;
|
String? consigneeID;
|
||||||
String? desc;
|
|
||||||
double width;
|
double width;
|
||||||
double height;
|
double height;
|
||||||
double length;
|
double length;
|
||||||
|
|
||||||
|
String? status;
|
||||||
|
String? cargoDesc;
|
||||||
|
String? desc;
|
||||||
|
|
||||||
int? shipmentWeight;
|
int? shipmentWeight;
|
||||||
bool? isChecked;
|
bool? isChecked;
|
||||||
bool? isShipmentCarton;
|
bool? isShipmentCarton;
|
||||||
String? cartonType;
|
String? cartonType;
|
||||||
String? fcsID;
|
|
||||||
String? userName;
|
|
||||||
String? userID;
|
|
||||||
String? fcsShipmentID;
|
|
||||||
String? fcsShipmentNumber;
|
|
||||||
String? mixCartonID;
|
|
||||||
String? mixCartonNumber;
|
String? mixCartonNumber;
|
||||||
String? cartonSizeID;
|
|
||||||
String? cartonSizeName;
|
String? lastMile;
|
||||||
String? deliveryType;
|
|
||||||
String? cartonSizeType;
|
String? cartonSizeType;
|
||||||
|
|
||||||
double cartonWeight;
|
double cartonWeight;
|
||||||
@@ -50,19 +51,18 @@ class Carton {
|
|||||||
List<String> photoUrls;
|
List<String> photoUrls;
|
||||||
String? remark;
|
String? remark;
|
||||||
DateTime? arrivedDate;
|
DateTime? arrivedDate;
|
||||||
String? cartonNumber;
|
|
||||||
|
|
||||||
List<String> packageIDs;
|
List<String> packageIDs;
|
||||||
List<Package> packages;
|
List<Package> packages;
|
||||||
List<CargoType> cargoTypes = [];
|
List<CargoType> cargoTypes = [];
|
||||||
|
List<CargoType> surchareItems = [];
|
||||||
|
|
||||||
DeliveryAddress? deliveryAddress;
|
DeliveryAddress? deliveryAddress;
|
||||||
Shipment? shipment;
|
Shipment? shipment;
|
||||||
|
|
||||||
//for mix box
|
//for mix carton
|
||||||
String? mixBoxType;
|
List<Carton> cartons;
|
||||||
List<Carton> mixCartons;
|
List<String> cartonIDs;
|
||||||
List<String> mixCartonIDs;
|
|
||||||
|
|
||||||
int get amount => (rate * weight);
|
int get amount => (rate * weight);
|
||||||
|
|
||||||
@@ -123,12 +123,9 @@ class Carton {
|
|||||||
|
|
||||||
Carton(
|
Carton(
|
||||||
{this.id,
|
{this.id,
|
||||||
this.shipmentID,
|
|
||||||
this.shipmentNumber,
|
|
||||||
this.senderID,
|
this.senderID,
|
||||||
this.senderFCSID,
|
this.senderFCSID,
|
||||||
this.senderName,
|
this.senderName,
|
||||||
this.boxNumber,
|
|
||||||
this.desc,
|
this.desc,
|
||||||
this.width = 0,
|
this.width = 0,
|
||||||
this.height = 0,
|
this.height = 0,
|
||||||
@@ -136,9 +133,9 @@ class Carton {
|
|||||||
this.shipmentWeight,
|
this.shipmentWeight,
|
||||||
this.isChecked = false,
|
this.isChecked = false,
|
||||||
this.cartonType,
|
this.cartonType,
|
||||||
this.fcsID,
|
this.consigneeFCSID,
|
||||||
this.userID,
|
this.consigneeID,
|
||||||
this.userName,
|
this.consigneeName,
|
||||||
this.rate = 0,
|
this.rate = 0,
|
||||||
this.weight = 0,
|
this.weight = 0,
|
||||||
this.packageType,
|
this.packageType,
|
||||||
@@ -150,47 +147,60 @@ class Carton {
|
|||||||
this.shipmentHistory = const [],
|
this.shipmentHistory = const [],
|
||||||
this.packages = const [],
|
this.packages = const [],
|
||||||
this.cargoTypes = const [],
|
this.cargoTypes = const [],
|
||||||
|
this.surchareItems = const [],
|
||||||
this.cartonNumber,
|
this.cartonNumber,
|
||||||
this.billTo,
|
this.billTo,
|
||||||
this.fcsShipmentID,
|
this.fcsShipmentID,
|
||||||
this.fcsShipmentNumber,
|
this.fcsShipmentNumber,
|
||||||
this.packageIDs = const [],
|
this.packageIDs = const [],
|
||||||
this.mixCartonID,
|
|
||||||
this.mixCartonNumber,
|
this.mixCartonNumber,
|
||||||
this.isShipmentCarton = false,
|
this.isShipmentCarton = false,
|
||||||
this.deliveryAddress,
|
this.deliveryAddress,
|
||||||
this.cartonSizeID,
|
|
||||||
this.cartonSizeName,
|
|
||||||
this.cartonSizeType,
|
this.cartonSizeType,
|
||||||
this.deliveryType,
|
this.lastMile,
|
||||||
this.mixBoxType,
|
this.cartons = const [],
|
||||||
this.mixCartons = const [],
|
this.cartonIDs = const [],
|
||||||
this.mixCartonIDs = const [],
|
|
||||||
this.cartonWeight = 0,
|
this.cartonWeight = 0,
|
||||||
this.photoUrls = const [],
|
this.photoUrls = const [],
|
||||||
this.isSelected = false});
|
this.isSelected = false});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
var _types = cargoTypes.where((t) => t.weight != 0).toList();
|
||||||
List _packages = packages.map((c) => c.toJson()).toList();
|
var _cargoTypes = _types.map((c) => c.toMapForCargo()).toList();
|
||||||
List _mixCartons = mixCartons.map((c) => c.toJson()).toList();
|
|
||||||
|
var _packagesIds = packages.map((c) => c.id).toList();
|
||||||
|
|
||||||
|
var _surchareItems =
|
||||||
|
surchareItems.map((c) => c.toMapForSurcharge()).toList();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'id': id,
|
'id': id,
|
||||||
|
'carton_type': cartonType,
|
||||||
'fcs_shipment_id': fcsShipmentID,
|
'fcs_shipment_id': fcsShipmentID,
|
||||||
'user_id': userID,
|
'sender_user_id': senderID,
|
||||||
'cargo_types': _cargoTypes,
|
'consignee_user_id': consigneeID,
|
||||||
'packages': _packages,
|
'bill_to': billTo,
|
||||||
|
'last_mile': lastMile,
|
||||||
'length': length,
|
'length': length,
|
||||||
'width': width,
|
'width': width,
|
||||||
'height': height,
|
'height': height,
|
||||||
'delivery_address': deliveryAddress?.toMap(),
|
'package_ids': _packagesIds,
|
||||||
|
'cargo_types': _cargoTypes,
|
||||||
|
'surcharge_items': _surchareItems,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMapForMix() {
|
||||||
|
var _cartonIds = cartons.map((c) => c.id).toList();
|
||||||
|
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
'carton_type': cartonType,
|
'carton_type': cartonType,
|
||||||
'mix_carton_id': mixCartonID,
|
'fcs_shipment_id': fcsShipmentID,
|
||||||
'mix_box_type': mixBoxType,
|
'length': length,
|
||||||
'mix_cartons': _mixCartons,
|
'width': width,
|
||||||
'sender_id': senderID,
|
'height': height,
|
||||||
'sender_fcs_id': senderFCSID,
|
'carton_ids': _cartonIds,
|
||||||
'sender_name': senderName
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,75 +209,48 @@ class Carton {
|
|||||||
map['arrived_date'] == null ? null : (map['arrived_date'] as Timestamp);
|
map['arrived_date'] == null ? null : (map['arrived_date'] as Timestamp);
|
||||||
var da = map['delivery_address'];
|
var da = map['delivery_address'];
|
||||||
var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null;
|
var _da = da != null ? DeliveryAddress.fromMap(da, da["id"]) : null;
|
||||||
|
|
||||||
var cargoTypesMaps =
|
var cargoTypesMaps =
|
||||||
List<Map<String, dynamic>>.from(map['cargo_types'] ?? []);
|
List<Map<String, dynamic>>.from(map['cargo_types'] ?? []);
|
||||||
var cargoTypes =
|
var cargoTypes = cargoTypesMaps
|
||||||
cargoTypesMaps.map((e) => CargoType.fromMap(e, e["id"])).toList();
|
.map((e) => CargoType.fromMapForCargo(e, e["id"]))
|
||||||
var mixCartonsMaps =
|
.toList();
|
||||||
List<Map<String, dynamic>>.from(map['mix_cartons'] ?? []);
|
|
||||||
var _mixCartons =
|
var surchargeItemMaps =
|
||||||
mixCartonsMaps.map((e) => Carton.fromMap(e, e["id"])).toList();
|
List<Map<String, dynamic>>.from(map['surcharge_items'] ?? []);
|
||||||
|
var surchageItems = surchargeItemMaps
|
||||||
|
.map((e) => CargoType.fromMapForsurcharge(e, e["id"]))
|
||||||
|
.toList();
|
||||||
|
|
||||||
List<String> _photoUrls =
|
List<String> _photoUrls =
|
||||||
map['photo_urls'] == null ? [] : List.from(map['photo_urls']);
|
map['photo_urls'] == null ? [] : List.from(map['photo_urls']);
|
||||||
|
|
||||||
return Carton(
|
return Carton(
|
||||||
id: docID,
|
id: docID,
|
||||||
arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null,
|
arrivedDate: _arrivedDate != null ? _arrivedDate.toDate() : null,
|
||||||
shipmentID: map['shipment_id'],
|
|
||||||
shipmentNumber: map['shipment_number'],
|
|
||||||
// receiverNumber: map['receiver_number'],
|
|
||||||
boxNumber: map['box_number'],
|
|
||||||
length: double.tryParse(map['length'].toString()) ?? 0,
|
length: double.tryParse(map['length'].toString()) ?? 0,
|
||||||
width: double.tryParse(map['width'].toString()) ?? 0,
|
width: double.tryParse(map['width'].toString()) ?? 0,
|
||||||
height: double.tryParse(map['height'].toString()) ?? 0,
|
height: double.tryParse(map['height'].toString()) ?? 0,
|
||||||
userName: map['user_name'],
|
|
||||||
fcsID: map['fcs_id'],
|
|
||||||
cartonType: map['carton_type'],
|
cartonType: map['carton_type'],
|
||||||
cartonNumber: map['carton_number'],
|
cartonNumber: map['carton_number'],
|
||||||
userID: map['user_id'],
|
|
||||||
fcsShipmentID: map['fcs_shipment_id'],
|
fcsShipmentID: map['fcs_shipment_id'],
|
||||||
fcsShipmentNumber: map['fcs_shipment_number'],
|
fcsShipmentNumber: map['fcs_shipment_number'],
|
||||||
isShipmentCarton: map['is_shipment_carton'],
|
|
||||||
mixCartonID: map['mix_carton_id'],
|
|
||||||
mixCartonNumber: map['mix_carton_number'],
|
|
||||||
status: map['status'],
|
status: map['status'],
|
||||||
packageIDs: List<String>.from(map['package_ids'] ?? []),
|
packageIDs: List<String>.from(map['package_ids'] ?? []),
|
||||||
deliveryAddress: _da,
|
deliveryAddress: _da,
|
||||||
cargoTypes: cargoTypes,
|
cargoTypes: cargoTypes,
|
||||||
mixBoxType: map['mix_box_type'],
|
surchareItems: surchageItems,
|
||||||
mixCartons: _mixCartons,
|
senderID: map['sender_user_id'],
|
||||||
senderID: map['sender_id'],
|
|
||||||
senderFCSID: map['sender_fcs_id'],
|
senderFCSID: map['sender_fcs_id'],
|
||||||
senderName: map['sender_name'],
|
senderName: map['sender_user_name'],
|
||||||
mixCartonIDs: List<String>.from(map['mix_carton_ids'] ?? []),
|
consigneeID: map['consignee_user_id'],
|
||||||
|
consigneeName: map['consignee_user_name'],
|
||||||
|
consigneeFCSID: map['consignee_fcs_id'],
|
||||||
|
cartonIDs: List<String>.from(map['carton_ids'] ?? []),
|
||||||
cartonWeight: (map['carton_weight'] ?? 0).toDouble(),
|
cartonWeight: (map['carton_weight'] ?? 0).toDouble(),
|
||||||
photoUrls: _photoUrls,
|
photoUrls: _photoUrls,
|
||||||
);
|
billTo: map['bill_to'] ?? '',
|
||||||
}
|
lastMile: map['last_mile'] ?? "");
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
|
|
||||||
List _packages = packages.map((c) => c.toJson()).toList();
|
|
||||||
List _mixCartons = mixCartons.map((c) => c.toJson()).toList();
|
|
||||||
return {
|
|
||||||
'id': id,
|
|
||||||
'fcs_shipment_id': fcsShipmentID,
|
|
||||||
'user_id': userID,
|
|
||||||
'cargo_types': _cargoTypes,
|
|
||||||
'packages': _packages,
|
|
||||||
'length': length,
|
|
||||||
'width': width,
|
|
||||||
'height': height,
|
|
||||||
'delivery_address': deliveryAddress?.toMap(),
|
|
||||||
'carton_type': cartonType,
|
|
||||||
'mix_carton_id': mixCartonID,
|
|
||||||
'mix_box_type': mixBoxType,
|
|
||||||
'mix_cartons': _mixCartons,
|
|
||||||
'sender_id': senderID,
|
|
||||||
'sender_fcs_id': senderFCSID,
|
|
||||||
'sender_name': senderName,
|
|
||||||
"photo_urls": photoUrls
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ class FcsShipment {
|
|||||||
String? id;
|
String? id;
|
||||||
String? shipmentNumber;
|
String? shipmentNumber;
|
||||||
DateTime? cutoffDate;
|
DateTime? cutoffDate;
|
||||||
|
DateTime? etaDate;
|
||||||
String? shipmentTypeId;
|
String? shipmentTypeId;
|
||||||
String? shipTypeName;
|
String? shipmentTypeName;
|
||||||
DateTime? arrivalDate;
|
|
||||||
DateTime? departureDate;
|
DateTime? departureDate;
|
||||||
String? consignee;
|
String? consigneeId;
|
||||||
String? port;
|
String? consigneeName;
|
||||||
String? destination;
|
String? loadingPortId;
|
||||||
|
String? loadingPortName;
|
||||||
|
String? destinationPortId;
|
||||||
|
String? destinationPortName;
|
||||||
String? status;
|
String? status;
|
||||||
String? reportName;
|
String? reportName;
|
||||||
|
|
||||||
@@ -19,13 +22,16 @@ class FcsShipment {
|
|||||||
this.shipmentNumber,
|
this.shipmentNumber,
|
||||||
this.cutoffDate,
|
this.cutoffDate,
|
||||||
this.shipmentTypeId,
|
this.shipmentTypeId,
|
||||||
this.shipTypeName,
|
this.shipmentTypeName,
|
||||||
this.status,
|
this.status,
|
||||||
this.arrivalDate,
|
this.etaDate,
|
||||||
this.departureDate,
|
this.departureDate,
|
||||||
this.consignee,
|
this.consigneeId,
|
||||||
this.port,
|
this.consigneeName,
|
||||||
this.destination,
|
this.loadingPortId,
|
||||||
|
this.loadingPortName,
|
||||||
|
this.destinationPortId,
|
||||||
|
this.destinationPortName,
|
||||||
this.reportName,
|
this.reportName,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -33,45 +39,45 @@ class FcsShipment {
|
|||||||
var _cutoffDate =
|
var _cutoffDate =
|
||||||
map['cutoff_date'] == null ? null : (map['cutoff_date'] as Timestamp);
|
map['cutoff_date'] == null ? null : (map['cutoff_date'] as Timestamp);
|
||||||
var _arrivalDate =
|
var _arrivalDate =
|
||||||
map['arrival_date'] == null ? null : (map['arrival_date'] as Timestamp);
|
map['eta_date'] == null ? null : (map['eta_date'] as Timestamp);
|
||||||
|
|
||||||
return FcsShipment(
|
return FcsShipment(
|
||||||
id: docID,
|
id: docID,
|
||||||
cutoffDate: _cutoffDate != null ? _cutoffDate.toDate() : null,
|
cutoffDate: _cutoffDate != null ? _cutoffDate.toDate() : null,
|
||||||
arrivalDate: _arrivalDate != null ? _arrivalDate.toDate() : null,
|
etaDate: _arrivalDate != null ? _arrivalDate.toDate() : null,
|
||||||
shipmentNumber: map['shipment_number'],
|
shipmentNumber: map['shipment_number'],
|
||||||
shipTypeName: map['shipment_type_name'],
|
|
||||||
shipmentTypeId: map['shipment_type_id'] ?? "",
|
shipmentTypeId: map['shipment_type_id'] ?? "",
|
||||||
|
shipmentTypeName: map['shipment_type_name'],
|
||||||
status: map['status'],
|
status: map['status'],
|
||||||
consignee: map['consignee'],
|
consigneeId: map['shipment_consignee_id'],
|
||||||
port: map['port'],
|
consigneeName: map['shipment_consignee_name'],
|
||||||
destination: map['destination'],
|
loadingPortId: map['loading_port_id'],
|
||||||
);
|
loadingPortName: map['loading_port_name'],
|
||||||
|
destinationPortId: map['destination_port_id'],
|
||||||
|
destinationPortName: map['destination_port_name']);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return {
|
return {
|
||||||
'id': id,
|
'id': id,
|
||||||
'shipment_number': shipmentNumber,
|
'shipment_number': shipmentNumber,
|
||||||
'shipment_type_id': shipmentTypeId,
|
|
||||||
'cutoff_date': cutoffDate?.toUtc().toIso8601String(),
|
'cutoff_date': cutoffDate?.toUtc().toIso8601String(),
|
||||||
'arrival_date': arrivalDate?.toUtc().toIso8601String(),
|
'eta_date': etaDate?.toUtc().toIso8601String(),
|
||||||
'consignee': consignee,
|
'shipment_type_id': shipmentTypeId,
|
||||||
'port': port,
|
'shipment_consignee_id': consigneeId,
|
||||||
'destination': destination,
|
'loading_port_id': loadingPortId,
|
||||||
// 'status': status,
|
'destination_port_id': destinationPortId
|
||||||
// 'report_name': reportName,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isChangedForEdit(FcsShipment fcsShipment) {
|
bool isChangedForEdit(FcsShipment fcsShipment) {
|
||||||
return fcsShipment.shipmentNumber != this.shipmentNumber ||
|
return fcsShipment.shipmentNumber != this.shipmentNumber ||
|
||||||
fcsShipment.cutoffDate != this.cutoffDate ||
|
fcsShipment.cutoffDate != this.cutoffDate ||
|
||||||
fcsShipment.arrivalDate != this.arrivalDate ||
|
fcsShipment.etaDate != this.etaDate ||
|
||||||
fcsShipment.shipmentTypeId != this.shipmentTypeId ||
|
fcsShipment.shipmentTypeId != this.shipmentTypeId ||
|
||||||
fcsShipment.consignee != this.consignee ||
|
fcsShipment.consigneeId != this.consigneeId ||
|
||||||
fcsShipment.port != this.port ||
|
fcsShipment.loadingPortId != this.loadingPortId ||
|
||||||
fcsShipment.destination != this.destination;
|
fcsShipment.destinationPortId != this.destinationPortId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ List<Day> dayLists = [
|
|||||||
|
|
||||||
class Setting {
|
class Setting {
|
||||||
final int supportBuildNum;
|
final int supportBuildNum;
|
||||||
|
final String reportURL;
|
||||||
|
final String reportProjectID;
|
||||||
|
final String bucketName;
|
||||||
// contact page
|
// contact page
|
||||||
String? usaAddress;
|
String? usaAddress;
|
||||||
String? mmAddress;
|
String? mmAddress;
|
||||||
@@ -44,7 +47,10 @@ class Setting {
|
|||||||
this.shipmentTypes = const [],
|
this.shipmentTypes = const [],
|
||||||
this.courierWebsite,
|
this.courierWebsite,
|
||||||
this.deactivateTextEn,
|
this.deactivateTextEn,
|
||||||
this.deactivateTextMm});
|
this.deactivateTextMm,
|
||||||
|
this.bucketName = '',
|
||||||
|
this.reportProjectID = '',
|
||||||
|
this.reportURL = ''});
|
||||||
|
|
||||||
factory Setting.fromMap(Map<String, dynamic> map) {
|
factory Setting.fromMap(Map<String, dynamic> map) {
|
||||||
return Setting(
|
return Setting(
|
||||||
@@ -62,9 +68,11 @@ class Setting {
|
|||||||
termsMm: map['terms_mm_markdown'],
|
termsMm: map['terms_mm_markdown'],
|
||||||
shipmentTypes: List.from(map['shipment_types']),
|
shipmentTypes: List.from(map['shipment_types']),
|
||||||
courierWebsite: map['courier_website'],
|
courierWebsite: map['courier_website'],
|
||||||
deactivateTextEn: map['deactivate_text_en']??"",
|
deactivateTextEn: map['deactivate_text_en'] ?? "",
|
||||||
deactivateTextMm: map['deactivate_text_mm']??""
|
deactivateTextMm: map['deactivate_text_mm'] ?? "",
|
||||||
);
|
reportProjectID: map['report_project_id'] ?? "",
|
||||||
|
reportURL: map['report_url'] ?? "",
|
||||||
|
bucketName: map['bucket_name'] ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
17
lib/domain/entities/shipment_consignee.dart
Normal file
17
lib/domain/entities/shipment_consignee.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
class ShipmentConsignee {
|
||||||
|
String id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
ShipmentConsignee({required this.id, required this.name});
|
||||||
|
|
||||||
|
factory ShipmentConsignee.fromMap(Map<String, dynamic> map, String id) {
|
||||||
|
return ShipmentConsignee(id: id, name: map['name'] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
other is ShipmentConsignee && other.id == id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
}
|
||||||
17
lib/domain/entities/shipment_port.dart
Normal file
17
lib/domain/entities/shipment_port.dart
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
class ShipmentPort {
|
||||||
|
String id;
|
||||||
|
String name;
|
||||||
|
|
||||||
|
ShipmentPort({required this.id, required this.name});
|
||||||
|
|
||||||
|
factory ShipmentPort.fromMap(Map<String, dynamic> map, String id) {
|
||||||
|
return ShipmentPort(id: id, name: map['name'] ?? "");
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) =>
|
||||||
|
other is ShipmentPort && other.id == id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
|
}
|
||||||
@@ -7,4 +7,10 @@ class ShipmentType {
|
|||||||
factory ShipmentType.fromMap(Map<String, dynamic> map, String id) {
|
factory ShipmentType.fromMap(Map<String, dynamic> map, String id) {
|
||||||
return ShipmentType(id: id, name: map['name'] ?? "");
|
return ShipmentType(id: id, name: map['name'] ?? "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) => other is ShipmentType && other.id == id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => id.hashCode;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ class User {
|
|||||||
String? preferCurrency;
|
String? preferCurrency;
|
||||||
bool enablePinLogin;
|
bool enablePinLogin;
|
||||||
String? pinDigit;
|
String? pinDigit;
|
||||||
|
List<String> privileges = [];
|
||||||
|
|
||||||
String get initial =>
|
String get initial =>
|
||||||
name != null && name != "" ? name!.substring(0, 1) : "?";
|
name != null && name != "" ? name!.substring(0, 1) : "?";
|
||||||
@@ -48,7 +49,9 @@ class User {
|
|||||||
String get getFcsUnseenCount =>
|
String get getFcsUnseenCount =>
|
||||||
fcsUnseenCount > 100 ? "99+" : fcsUnseenCount.toString();
|
fcsUnseenCount > 100 ? "99+" : fcsUnseenCount.toString();
|
||||||
|
|
||||||
List<String> privileges = [];
|
// for pin login
|
||||||
|
String? pinToken;
|
||||||
|
bool get isPinLogin => pinToken!=null;
|
||||||
|
|
||||||
String get phone => phoneNumber != null && phoneNumber!.startsWith("959")
|
String get phone => phoneNumber != null && phoneNumber!.startsWith("959")
|
||||||
? "0${phoneNumber!.substring(2)}"
|
? "0${phoneNumber!.substring(2)}"
|
||||||
@@ -117,7 +120,9 @@ class User {
|
|||||||
userUnseenCount: map['user_unseen_count'] ?? 0,
|
userUnseenCount: map['user_unseen_count'] ?? 0,
|
||||||
fcsUnseenCount: map['fcs_unseen_count'] ?? 0,
|
fcsUnseenCount: map['fcs_unseen_count'] ?? 0,
|
||||||
preferCurrency: map['preferred_currency'],
|
preferCurrency: map['preferred_currency'],
|
||||||
lastMessageTime: _date == null ? null : _date.toDate());
|
lastMessageTime: _date == null ? null : _date.toDate(),
|
||||||
|
enablePinLogin: map['enable_pin_login'] ?? false,
|
||||||
|
pinDigit: map['pin'] ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool diffPrivileges(User another) {
|
bool diffPrivileges(User another) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class LocalPopupMenu {
|
|||||||
List<LocalPopupMenu> shipFiteringMenu = <LocalPopupMenu>[
|
List<LocalPopupMenu> shipFiteringMenu = <LocalPopupMenu>[
|
||||||
LocalPopupMenu(id: 0, text :"All"),
|
LocalPopupMenu(id: 0, text :"All"),
|
||||||
LocalPopupMenu(id: 1, text: "Pending"),
|
LocalPopupMenu(id: 1, text: "Pending"),
|
||||||
LocalPopupMenu(id: 2, text: "Processing"),
|
LocalPopupMenu(id: 2, text: "Processed"),
|
||||||
LocalPopupMenu(id: 3, text: "Shipped"),
|
LocalPopupMenu(id: 3, text: "Shipped"),
|
||||||
LocalPopupMenu(id: 4, text: "Arrived"),
|
LocalPopupMenu(id: 4, text: "Arrived"),
|
||||||
LocalPopupMenu(id: 5, text: "Invoiced"),
|
LocalPopupMenu(id: 5, text: "Invoiced"),
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
|
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart' as vector;
|
||||||
|
|
||||||
class Privilege {
|
class Privilege {
|
||||||
String id;
|
String id;
|
||||||
@@ -49,6 +50,8 @@ class Privilege {
|
|||||||
iconData = MaterialCommunityIcons.layers;
|
iconData = MaterialCommunityIcons.layers;
|
||||||
} else if (this.id == privilege_report) {
|
} else if (this.id == privilege_report) {
|
||||||
iconData = Feather.file_text;
|
iconData = Feather.file_text;
|
||||||
|
} else if (this.id == privilege_pin) {
|
||||||
|
iconData = vector.MaterialCommunityIcons.account_lock_outline;
|
||||||
} else {
|
} else {
|
||||||
iconData = MaterialCommunityIcons.account_question;
|
iconData = MaterialCommunityIcons.account_question;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import 'dart:io';
|
|||||||
|
|
||||||
import 'package:device_info_plus/device_info_plus.dart';
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:fcs/data/services/services.dart';
|
||||||
|
import 'package:fcs/domain/entities/user.dart';
|
||||||
import 'package:fcs/domain/vo/status.dart';
|
import 'package:fcs/domain/vo/status.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
@@ -28,10 +30,14 @@ Future<dynamic> requestAPI(String path, method,
|
|||||||
if (token != null) {
|
if (token != null) {
|
||||||
headers["Token"] = token;
|
headers["Token"] = token;
|
||||||
}
|
}
|
||||||
|
User? pinLoginUser = Services.instance.authService.getPinLoginUser();
|
||||||
|
if (pinLoginUser != null) {
|
||||||
|
headers["pin_token"] = pinLoginUser.pinToken;
|
||||||
|
}
|
||||||
if (devInfo.deviceID != null) {
|
if (devInfo.deviceID != null) {
|
||||||
headers["Device"] = devInfo.deviceID ?? "" + ":" + deviceName;
|
headers["Device"] = devInfo.deviceID ?? "" + ":" + deviceName;
|
||||||
}
|
}
|
||||||
headers["Project-ID"] = Config.instance.reportProjectID;
|
headers["Project-ID"] = Services.setting.reportProjectID;
|
||||||
|
|
||||||
BaseOptions options = new BaseOptions(
|
BaseOptions options = new BaseOptions(
|
||||||
method: method,
|
method: method,
|
||||||
@@ -51,7 +57,7 @@ Future<dynamic> requestAPI(String path, method,
|
|||||||
});
|
});
|
||||||
|
|
||||||
String curlPath =
|
String curlPath =
|
||||||
"curl -X $method ${list.join("")}${payload != null ? '-d $payload ' : ''}${options.baseUrl}$path";
|
"curl -X $method ${list.join("")}${payload != null ? '-d \'${jsonEncode(payload)}\' ' : ''}${options.baseUrl}$path";
|
||||||
|
|
||||||
log.log(curlPath);
|
log.log(curlPath);
|
||||||
|
|
||||||
@@ -93,7 +99,7 @@ Future<dynamic> requestDownloadAPI(String path, method,
|
|||||||
var _downloadData = StringBuffer();
|
var _downloadData = StringBuffer();
|
||||||
var fileSave = new File(filePath!);
|
var fileSave = new File(filePath!);
|
||||||
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
||||||
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
request.headers.set("Project-ID", Services.setting.reportProjectID);
|
||||||
request.headers
|
request.headers
|
||||||
.set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8");
|
.set(HttpHeaders.contentTypeHeader, "application/json; charset=UTF-8");
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
@@ -134,7 +140,7 @@ Future<dynamic> requestDownloadPDFAPI(String path, method,
|
|||||||
// var _downloadData = StringBuffer();
|
// var _downloadData = StringBuffer();
|
||||||
var fileSave = new File(filePath!);
|
var fileSave = new File(filePath!);
|
||||||
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
var request = await client.getUrl(Uri.parse("$baseUrl$path"));
|
||||||
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
request.headers.set("Project-ID", Services.setting.reportProjectID);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
request.headers.set("Token", token);
|
request.headers.set("Token", token);
|
||||||
}
|
}
|
||||||
@@ -182,7 +188,7 @@ Future<dynamic> requestDownload(String path, method,
|
|||||||
HttpClient client = new HttpClient();
|
HttpClient client = new HttpClient();
|
||||||
// var _downloadData = StringBuffer();
|
// var _downloadData = StringBuffer();
|
||||||
var request = await client.postUrl(Uri.parse("$baseUrl$path"));
|
var request = await client.postUrl(Uri.parse("$baseUrl$path"));
|
||||||
request.headers.set("Project-ID", Config.instance.reportProjectID);
|
request.headers.set("Project-ID", Services.setting.reportProjectID);
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
request.headers.set("Token", token);
|
request.headers.set("Token", token);
|
||||||
}
|
}
|
||||||
@@ -238,7 +244,7 @@ Future<File> downloadPDF(
|
|||||||
|
|
||||||
await requestDownload("/api/pdf", "POST",
|
await requestDownload("/api/pdf", "POST",
|
||||||
filePath: path,
|
filePath: path,
|
||||||
url: Config.instance.reportURL,
|
url: Services.setting.reportURL,
|
||||||
token: await getToken(),
|
token: await getToken(),
|
||||||
payload: jsonEncode(data), onDownloadDone: (f) async {
|
payload: jsonEncode(data), onDownloadDone: (f) async {
|
||||||
completer.complete(f);
|
completer.complete(f);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Future<void> generateCartonPdf(Carton carton) async {
|
|||||||
style: pw.TextStyle(
|
style: pw.TextStyle(
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
)),
|
)),
|
||||||
pw.Text(carton.userName!,
|
pw.Text(carton.consigneeName!,
|
||||||
style: pw.TextStyle(
|
style: pw.TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
)),
|
)),
|
||||||
|
|||||||
@@ -108,4 +108,14 @@ class SharedPref {
|
|||||||
static Future<void> clearRecentSearch(String key) async {
|
static Future<void> clearRecentSearch(String key) async {
|
||||||
return await _remove(key);
|
return await _remove(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<bool?> getPinLockOn() async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getBool('pin_lock');
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> setPinLockOn(bool isLockOn) async {
|
||||||
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
prefs.setBool('pin_lock', isLockOn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,17 +12,18 @@ Future<void> main() async {
|
|||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
);
|
);
|
||||||
|
|
||||||
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
|
FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler);
|
||||||
|
|
||||||
Config(
|
Config(
|
||||||
flavor: Flavor.DEV,
|
flavor: Flavor.DEV,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
apiURL: "https://asia-northeast1-fcs-dev1.cloudfunctions.net/API13",
|
apiURL: "http://192.168.100.150:9090",
|
||||||
reportURL: "http://petrok.mokkon.com:7071",
|
// apiURL: "https://asia-northeast1-fcs-dev1.cloudfunctions.net/API13",
|
||||||
reportProjectID: "fcs-dev",
|
// reportURL: "http://petrok.mokkon.com:7071",
|
||||||
bucketName: "gs://fcs-dev1-us",
|
// reportProjectID: "fcs-dev",
|
||||||
|
// bucketName: "gs://fcs-dev1-us",
|
||||||
level: Level.ALL);
|
level: Level.ALL);
|
||||||
runApp(App(title: "FCS - Dev"));
|
runApp(App(title: "FCS - Dev"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,12 @@ void main() {
|
|||||||
Config(
|
Config(
|
||||||
flavor: Flavor.DEV,
|
flavor: Flavor.DEV,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
reportURL: "http://petrok.mokkon.com:8091",
|
|
||||||
reportProjectID: "fcs-dev",
|
|
||||||
apiURL: "http://192.168.1.155:7777",
|
apiURL: "http://192.168.1.155:7777",
|
||||||
bucketName: "gs://fcs-dev1-us",
|
// reportURL: "http://petrok.mokkon.com:8091",
|
||||||
|
// reportProjectID: "fcs-dev",
|
||||||
|
// bucketName: "gs://fcs-dev1-us",
|
||||||
level: Level.ALL);
|
level: Level.ALL);
|
||||||
runApp(App(title: "FCS - Dev local",));
|
runApp(App(
|
||||||
|
title: "FCS - Dev local",
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ Future<void> main() async {
|
|||||||
flavor: Flavor.PRODUCTION,
|
flavor: Flavor.PRODUCTION,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
apiURL: "https://asia-northeast1-fcs-prod1.cloudfunctions.net/API13",
|
apiURL: "https://asia-northeast1-fcs-prod1.cloudfunctions.net/API13",
|
||||||
reportURL: "http://petrok.mokkon.com:8092",
|
// reportURL: "http://petrok.mokkon.com:8092",
|
||||||
reportProjectID: "fcs-prod",
|
// reportProjectID: "fcs-prod",
|
||||||
bucketName: "gs://fcs-prod1",
|
// bucketName: "gs://fcs-prod1",
|
||||||
level: Level.ALL);
|
level: Level.ALL);
|
||||||
runApp(App(title: "FCS"));
|
runApp(App(title: "FCS"));
|
||||||
}
|
}
|
||||||
|
|||||||
114
lib/pages/carton/cargo_type_addition.dart
Normal file
114
lib/pages/carton/cargo_type_addition.dart
Normal 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),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,7 +12,8 @@ import '../widgets/continue_button.dart';
|
|||||||
import '../widgets/display_text.dart';
|
import '../widgets/display_text.dart';
|
||||||
import '../widgets/local_title.dart';
|
import '../widgets/local_title.dart';
|
||||||
import '../widgets/previous_button.dart';
|
import '../widgets/previous_button.dart';
|
||||||
import 'custom_duty_addition.dart';
|
import 'cargo_type_addition.dart';
|
||||||
|
import 'surcharge_item_addition.dart';
|
||||||
|
|
||||||
typedef OnPrevious = Function(
|
typedef OnPrevious = Function(
|
||||||
List<CargoType> cargoTypes, List<CargoType> customDuties);
|
List<CargoType> cargoTypes, List<CargoType> customDuties);
|
||||||
@@ -56,28 +57,20 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
// for cargo types
|
// for cargo types
|
||||||
var model = context.read<ShipmentRateModel>();
|
|
||||||
_cargoTypes = model.rate.cargoTypes.map((e) => e.clone()).toList();
|
|
||||||
|
|
||||||
if (widget.cargoTypes.isNotEmpty) {
|
if (widget.cargoTypes.isNotEmpty) {
|
||||||
_cargoTypes.forEach((mp) {
|
_cargoTypes = List.from(widget.cargoTypes);
|
||||||
mp.weight = 0;
|
|
||||||
widget.cargoTypes.forEach((vp) {
|
|
||||||
if (mp.id == vp.id) {
|
|
||||||
mp.weight = vp.weight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
_cargoTypes.forEach((e) {
|
_cargoTypes.forEach((e) {
|
||||||
var editor = new TextEditingController();
|
var editor = new TextEditingController();
|
||||||
editor.text = removeTrailingZeros(e.weight);
|
editor.text = removeTrailingZeros(e.weight);
|
||||||
editor.addListener(inputChangeListener);
|
editor.addListener(inputChangeListener);
|
||||||
_cargoTypeControllers.add(editor);
|
_cargoTypeControllers.add(editor);
|
||||||
});
|
});
|
||||||
|
_calculateTotalWeght();
|
||||||
double total = _cargoTypes.fold(0, (sum, value) => sum + value.weight);
|
|
||||||
_totalCtl.text = removeTrailingZeros(total);
|
|
||||||
} else {
|
} 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) {
|
_cargoTypes.forEach((e) {
|
||||||
var editor = new TextEditingController();
|
var editor = new TextEditingController();
|
||||||
editor.text = '';
|
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) {
|
bool isFieldEmpty(int index) {
|
||||||
return _cargoTypeControllers[index].text.isEmpty;
|
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(
|
final cargosBox = Wrap(
|
||||||
alignment: WrapAlignment.spaceBetween,
|
alignment: WrapAlignment.spaceBetween,
|
||||||
runSpacing: 15,
|
runSpacing: 15,
|
||||||
@@ -171,6 +202,8 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
InkResponse(
|
InkResponse(
|
||||||
radius: 25,
|
radius: 25,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
_cargoTypes.removeAt(key);
|
||||||
|
|
||||||
double totalWeight = double.tryParse(_totalCtl.text) ?? 0;
|
double totalWeight = double.tryParse(_totalCtl.text) ?? 0;
|
||||||
double removeWeight =
|
double removeWeight =
|
||||||
(double.tryParse(_cargoTypeControllers[key].text) ??
|
(double.tryParse(_cargoTypeControllers[key].text) ??
|
||||||
@@ -182,11 +215,12 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_cargoTypeControllers[key].clear();
|
_cargoTypeControllers[key].clear();
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Icon(MaterialIcons.clear, color: labelColor)),
|
child: Icon(Feather.minus_circle, color: labelColor)),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: inputTextFieldWidget(context,
|
child: inputTextFieldWidget(context,
|
||||||
@@ -254,14 +288,14 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
color: primaryColor,
|
color: primaryColor,
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
List<CargoType>? customList = await Navigator.push<List<CargoType>>(
|
CargoType? surchargeItem = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
CustomDutyAddition(customDuties: _surchareItems)));
|
SurchargeItemAddition(items: _surchareItems)));
|
||||||
if (customList == null) return;
|
if (surchargeItem == null) return;
|
||||||
|
|
||||||
_surchareItems = List.from(customList);
|
_surchareItems.add(surchargeItem);
|
||||||
|
|
||||||
_surchargeControllers.clear();
|
_surchargeControllers.clear();
|
||||||
_surchareItems.asMap().entries.forEach((e) {
|
_surchareItems.asMap().entries.forEach((e) {
|
||||||
@@ -315,9 +349,10 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
final continueBtn = ContinueButton(
|
final continueBtn = ContinueButton(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (widget.onContinue != null) {
|
if (widget.onContinue != null) {
|
||||||
|
if (_surchareItems.isNotEmpty &&
|
||||||
if(_surchareItems.isNotEmpty && _surchareItems.any((item)=> item.qty == 0)){
|
_surchareItems.any((item) => item.qty == 0)) {
|
||||||
showMsgDialog(context, "Error", "Please insert surcharge item quantity");
|
showMsgDialog(
|
||||||
|
context, "Error", "Please insert surcharge item quantity");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -341,7 +376,7 @@ class _CargoWidgetState extends State<CargoWidget> {
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
userRow,
|
userRow,
|
||||||
LocalTitle(textKey: "box.input_cargo_weight", topPadding: 5),
|
cargoTitle,
|
||||||
cargosBox,
|
cargosBox,
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
Divider(),
|
Divider(),
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
_isNew = false;
|
_isNew = false;
|
||||||
|
|
||||||
_consignee = User(
|
_consignee = User(
|
||||||
id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
|
id: _carton!.consigneeID,
|
||||||
|
fcsID: _carton!.consigneeFCSID,
|
||||||
|
name: _carton!.consigneeName);
|
||||||
_sender = User(
|
_sender = User(
|
||||||
id: _carton!.senderID,
|
id: _carton!.senderID,
|
||||||
fcsID: _carton!.senderFCSID,
|
fcsID: _carton!.senderFCSID,
|
||||||
@@ -129,7 +131,7 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
padding: const EdgeInsets.only(right: 5),
|
padding: const EdgeInsets.only(right: 5),
|
||||||
child: InkResponse(
|
child: InkResponse(
|
||||||
radius: 30,
|
radius: 30,
|
||||||
onTap: () {
|
onTap: () async {
|
||||||
//for packages
|
//for packages
|
||||||
if (isFromPackages) {
|
if (isFromPackages) {
|
||||||
if (_sender == null) {
|
if (_sender == null) {
|
||||||
@@ -149,20 +151,32 @@ class _CartonEditorState extends State<CartonEditor> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Navigator.push(
|
Carton? carton = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => CartonPackageForm(
|
builder: (context) => CartonPackageForm(
|
||||||
sender: _sender!,
|
sender: _sender!,
|
||||||
consignee: _consignee!,
|
consignee: _consignee!,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
if (carton != null) {
|
||||||
|
setState(() {
|
||||||
|
_cartons.add(carton);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// for mix cartion
|
// for mix cartion
|
||||||
else {
|
else {
|
||||||
Navigator.push(
|
Carton? carton = await Navigator.push(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => const MixCartonForm()));
|
builder: (context) => const MixCartonForm()));
|
||||||
|
|
||||||
|
if (carton != null) {
|
||||||
|
setState(() {
|
||||||
|
_cartons.add(carton);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Icon(Icons.add_circle, color: primaryColor),
|
child: Icon(Icons.add_circle, color: primaryColor),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import '../../domain/entities/carton_size.dart';
|
import '../../domain/entities/carton_size.dart';
|
||||||
|
import '../carton_size/model/carton_size_model.dart';
|
||||||
import '../widgets/local_button.dart';
|
import '../widgets/local_button.dart';
|
||||||
import 'carton_package_editor.dart';
|
import 'carton_package_editor.dart';
|
||||||
import 'mix_carton/mix_carton_editor.dart';
|
import 'mix_carton/mix_carton_editor.dart';
|
||||||
@@ -56,27 +57,43 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
_init() async {
|
_init() async {
|
||||||
try {
|
try {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
_carton.cartonType = carton_from_packages;
|
|
||||||
_carton.billTo = billToConsignee;
|
|
||||||
_carton.cartonSizeType = customCarton;
|
|
||||||
_multiImgController.setImageUrls = _carton.photoUrls;
|
_multiImgController.setImageUrls = _carton.photoUrls;
|
||||||
_cargoTypes = _carton.cargoTypes.where((e) => !e.isCutomDuty).toList();
|
_cargoTypes = _carton.cargoTypes;
|
||||||
_surchareItems = _carton.cargoTypes.where((e) => e.isCutomDuty).toList();
|
_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) {
|
if (_carton.cartonType == carton_from_packages) {
|
||||||
_carton.deliveryType = delivery_caton;
|
|
||||||
_packages = await context
|
_packages = await context
|
||||||
.read<PackageModel>()
|
.read<PackageModel>()
|
||||||
.getPackagesByIds(_carton.packageIDs);
|
.getPackagesByIds(_carton.packageIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_carton.cartonType == carton_mix_carton) {
|
if (_carton.cartonType == mix_carton) {
|
||||||
_mixCartons = await context
|
_mixCartons = await context
|
||||||
.read<CartonModel>()
|
.read<CartonModel>()
|
||||||
.getCartonsByIds(_carton.mixCartonIDs);
|
.getCartonsByIds(_carton.cartonIDs);
|
||||||
}
|
_cargoTypes.sort((a, b) => a.name!.compareTo(b.name!));
|
||||||
|
_surchareItems.sort((a, b) => a.name!.compareTo(b.name!));
|
||||||
if (mounted) {
|
|
||||||
setState(() {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
totalWeight =
|
totalWeight =
|
||||||
@@ -86,17 +103,23 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
} finally {
|
} finally {
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var fromPackage = _carton.cartonType == carton_from_packages;
|
||||||
|
|
||||||
String? boxDimension = _carton.cartonSizeType == standardCarton
|
String? boxDimension = _carton.cartonSizeType == standardCarton
|
||||||
? "${standardSize?.name} - ${standardSize?.length.toInt()}”x${standardSize?.width.toInt()}”x${standardSize?.height.toInt()}”"
|
? "${standardSize?.name} - ${standardSize?.length.toInt()}”x${standardSize?.width.toInt()}”x${standardSize?.height.toInt()}”"
|
||||||
: _carton.cartonSizeType == customCarton
|
: _carton.cartonSizeType == customCarton
|
||||||
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”"
|
? "${_carton.length.toInt()}”x${_carton.width.toInt()}”x${_carton.height.toInt()}”"
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
final cartonTypeBox = DisplayText(
|
final cartonNumberBox = DisplayText(
|
||||||
text: _carton.cartonNumber,
|
text: _carton.cartonNumber,
|
||||||
labelTextKey: "box.number",
|
labelTextKey: "box.number",
|
||||||
);
|
);
|
||||||
@@ -111,10 +134,12 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
},
|
},
|
||||||
icon: Icon(AntDesign.qrcode, color: Colors.black));
|
icon: Icon(AntDesign.qrcode, color: Colors.black));
|
||||||
|
|
||||||
final cartonSubTypeBox = DisplayText(
|
final cartonTypeBox = DisplayText(
|
||||||
text: _carton.cartonType == carton_from_packages
|
text: _carton.cartonType == carton_from_packages
|
||||||
? "For packages"
|
? "For packages"
|
||||||
: "Mix carton",
|
: _carton.cartonType == mix_carton
|
||||||
|
? carton_mix_carton
|
||||||
|
: '',
|
||||||
labelTextKey: "box.carton.type",
|
labelTextKey: "box.carton.type",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -132,14 +157,18 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
labelTextKey: "box.fcs_shipment_num",
|
labelTextKey: "box.fcs_shipment_num",
|
||||||
);
|
);
|
||||||
|
|
||||||
final deliveryBox = DisplayText(
|
final lastMileBox = DisplayText(
|
||||||
text: _carton.deliveryType,
|
text: _carton.lastMile == delivery_caton
|
||||||
|
? 'Delivery'
|
||||||
|
: _carton.lastMile == pickup_carton
|
||||||
|
? 'Pick-up'
|
||||||
|
: '',
|
||||||
labelTextKey: "box.delivery_type",
|
labelTextKey: "box.delivery_type",
|
||||||
);
|
);
|
||||||
|
|
||||||
final cartonSizeBox = DisplayText(
|
final cartonSizeBox = DisplayText(
|
||||||
subText: boxDimension == null ? null : Text("$boxDimension"),
|
subText: Text("${boxDimension ?? 'No defined size'}"),
|
||||||
labelTextKey: "box.carton_size",
|
labelTextKey: "box.select_carton_size",
|
||||||
);
|
);
|
||||||
|
|
||||||
final senderBox = DisplayText(
|
final senderBox = DisplayText(
|
||||||
@@ -149,8 +178,8 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final consigneeNameBox = DisplayText(
|
final consigneeNameBox = DisplayText(
|
||||||
text: _carton.userName != null ? _carton.userName : "",
|
text: _carton.consigneeName != null ? _carton.consigneeName : "",
|
||||||
subText: Text(_carton.fcsID ?? "", style: textStyle),
|
subText: Text(_carton.consigneeFCSID ?? "", style: textStyle),
|
||||||
labelTextKey: "processing.consignee.name",
|
labelTextKey: "processing.consignee.name",
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -169,6 +198,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
|
|
||||||
final userRowBox = Row(
|
final userRowBox = Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -205,7 +235,7 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final cargosBox = Padding(
|
final cargosBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 15),
|
padding: const EdgeInsets.only(top: 20),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
@@ -214,10 +244,13 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.normal),
|
fontWeight: FontWeight.normal),
|
||||||
Padding(
|
_cargoTypes.isNotEmpty
|
||||||
|
? Padding(
|
||||||
padding: EdgeInsets.only(right: 50),
|
padding: EdgeInsets.only(right: 50),
|
||||||
child: Text("${removeTrailingZeros(totalWeight)} lb",
|
child: Text("${removeTrailingZeros(totalWeight)} lb",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
||||||
|
: const SizedBox()
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Container(
|
Container(
|
||||||
@@ -239,38 +272,25 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
TextStyle(color: Colors.black, fontSize: 15),
|
TextStyle(color: Colors.black, fontSize: 15),
|
||||||
),
|
),
|
||||||
Text("${removeTrailingZeros(e.weight)} lb",
|
Text("${removeTrailingZeros(e.weight)} lb",
|
||||||
|
textAlign: TextAlign.end,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Colors.black, fontSize: 15))
|
color: Colors.black, fontSize: 15))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList()),
|
}).toList()),
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
final surchargeItemBox = Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 15),
|
final surchargeItemBox =
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
LocalText(context, 'box.surcharge.item',
|
|
||||||
color: Colors.black54,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.normal),
|
|
||||||
Padding(
|
|
||||||
padding: EdgeInsets.only(right: 50),
|
|
||||||
child: Text("${removeTrailingZeros(totalSurchargeCount)} pcs",
|
|
||||||
style: TextStyle(color: Colors.black54, fontSize: 15)))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Container(
|
Container(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(right: 60),
|
padding: const EdgeInsets.only(right: 50),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
@@ -283,24 +303,21 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
e.name ?? "",
|
e.name ?? "",
|
||||||
style:
|
style: TextStyle(color: Colors.black, fontSize: 15),
|
||||||
TextStyle(color: Colors.black, fontSize: 15),
|
|
||||||
),
|
),
|
||||||
Text(
|
Text("${removeTrailingZeros((e.qty).toDouble())} pc",
|
||||||
"${removeTrailingZeros((e.qty).toDouble())} pc",
|
textAlign: TextAlign.end,
|
||||||
style: TextStyle(
|
style:
|
||||||
color: Colors.black, fontSize: 15))
|
TextStyle(color: Colors.black, fontSize: 15))
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList()),
|
}).toList()),
|
||||||
const SizedBox(height: 10),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]),
|
]);
|
||||||
);
|
|
||||||
|
|
||||||
final img = MultiImageFile(
|
final img = MultiImageFile(
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@@ -367,30 +384,29 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
padding: const EdgeInsets.only(left: 20, right: 20),
|
padding: const EdgeInsets.only(left: 20, right: 20),
|
||||||
child: ListView(children: <Widget>[
|
child: ListView(children: <Widget>[
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Flexible(child: cartonTypeBox,flex: 1),
|
Flexible(child: cartonNumberBox, flex: 1),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: cartonQrBox,
|
child: cartonQrBox,
|
||||||
),
|
),
|
||||||
|
|
||||||
]),
|
]),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: cartonSubTypeBox),
|
Flexible(child: cartonTypeBox),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
_mixCartons.isEmpty ? userRowBox : const SizedBox(),
|
fromPackage ? userRowBox : const SizedBox(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: billInfoBox),
|
fromPackage ? Flexible(child: billInfoBox) : SizedBox(),
|
||||||
Flexible(child: shipmentBox),
|
Flexible(child: shipmentBox),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
_mixCartons.isEmpty
|
fromPackage
|
||||||
? Flexible(child: deliveryBox)
|
? Flexible(child: lastMileBox)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
Flexible(child: cartonSizeBox),
|
Flexible(child: cartonSizeBox),
|
||||||
],
|
],
|
||||||
@@ -425,12 +441,17 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_cargoTypes.isEmpty ? const SizedBox() : cargosBox,
|
cargosBox,
|
||||||
_surchareItems.isEmpty ? const SizedBox() : surchargeItemBox,
|
surchargeItemBox,
|
||||||
|
const SizedBox(height: 10),
|
||||||
uploadImageBtn,
|
uploadImageBtn,
|
||||||
const SizedBox(height: 30),
|
_carton.photoUrls.isNotEmpty
|
||||||
|
? const SizedBox(height: 10)
|
||||||
|
: const SizedBox(),
|
||||||
img,
|
img,
|
||||||
const SizedBox(height: 40),
|
_carton.photoUrls.isNotEmpty
|
||||||
|
? const SizedBox(height: 40)
|
||||||
|
: const SizedBox(),
|
||||||
deleteBtn,
|
deleteBtn,
|
||||||
const SizedBox(height: 20)
|
const SizedBox(height: 20)
|
||||||
]))));
|
]))));
|
||||||
@@ -457,17 +478,22 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_gotoEditor() async {
|
_gotoEditor() async {
|
||||||
bool? updated = _carton.cartonType == carton_mix_carton
|
bool? updated = false;
|
||||||
? await Navigator.push<bool>(
|
if (_carton.cartonType == mix_carton) {
|
||||||
|
updated = await Navigator.push<bool>(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => MixCartonEditor(carton: _carton)),
|
builder: (context) => MixCartonEditor(carton: _carton)),
|
||||||
)
|
);
|
||||||
: await Navigator.push<bool>(
|
}
|
||||||
|
|
||||||
|
if (_carton.cartonType == carton_from_packages) {
|
||||||
|
updated = await Navigator.push<bool>(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
builder: (context) => CartonPackageEditor(carton: _carton)),
|
builder: (context) => CartonPackageEditor(carton: _carton)),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (updated ?? false) {
|
if (updated ?? false) {
|
||||||
Carton? c =
|
Carton? c =
|
||||||
@@ -489,9 +515,8 @@ class _CartonInfoState extends State<CartonInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
// var cartonModel = Provider.of<CartonModel>(context, listen: false);
|
await context.read<CartonModel>().deleteCarton(widget.carton);
|
||||||
// await cartonModel.deleteCarton(widget.carton);
|
Navigator.pop(context, true);
|
||||||
// Navigator.pop(context, true);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// ignore_for_file: deprecated_member_use
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
|
import 'package:fcs/pages/carton/model/carton_model.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -14,6 +15,7 @@ import '../../domain/entities/cargo_type.dart';
|
|||||||
import '../../domain/entities/carton.dart';
|
import '../../domain/entities/carton.dart';
|
||||||
import '../../domain/entities/package.dart';
|
import '../../domain/entities/package.dart';
|
||||||
import '../../domain/entities/user.dart';
|
import '../../domain/entities/user.dart';
|
||||||
|
import '../carton_size/model/carton_size_model.dart';
|
||||||
import '../fcs_shipment/model/fcs_shipment_model.dart';
|
import '../fcs_shipment/model/fcs_shipment_model.dart';
|
||||||
import '../main/util.dart';
|
import '../main/util.dart';
|
||||||
import '../package/model/package_model.dart';
|
import '../package/model/package_model.dart';
|
||||||
@@ -53,7 +55,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
double _width = 0;
|
double _width = 0;
|
||||||
double _height = 0;
|
double _height = 0;
|
||||||
|
|
||||||
String _selectedDeliveryType = delivery_caton;
|
String _selectedLastMile = delivery_caton;
|
||||||
String _billToValue = billToSender;
|
String _billToValue = billToSender;
|
||||||
|
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
@@ -78,20 +80,41 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
id: widget.carton.senderID);
|
id: widget.carton.senderID);
|
||||||
|
|
||||||
_consignee = User(
|
_consignee = User(
|
||||||
id: widget.carton.userID,
|
id: widget.carton.consigneeID,
|
||||||
name: widget.carton.userName,
|
name: widget.carton.consigneeName,
|
||||||
fcsID: widget.carton.fcsID);
|
fcsID: widget.carton.consigneeFCSID);
|
||||||
|
|
||||||
_billToValue = widget.carton.billTo ?? billToSender;
|
_billToValue = widget.carton.billTo ?? billToSender;
|
||||||
_selectedDeliveryType = widget.carton.deliveryType ?? delivery_caton;
|
_selectedLastMile = widget.carton.lastMile ?? delivery_caton;
|
||||||
_cartonSizeType = widget.carton.cartonSizeType ?? customCarton;
|
_cargoTypes = widget.carton.cargoTypes;
|
||||||
_length = widget.carton.length;
|
_surchareItems = widget.carton.surchareItems;
|
||||||
_width = widget.carton.width;
|
|
||||||
_height = widget.carton.height;
|
// check carton size type
|
||||||
_cargoTypes =
|
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
||||||
widget.carton.cargoTypes.where((e) => !e.isCutomDuty).toList();
|
|
||||||
_surchareItems =
|
var sameLength =
|
||||||
widget.carton.cargoTypes.where((e) => e.isCutomDuty).toList();
|
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;
|
||||||
|
_length = widget.carton.length.toDouble();
|
||||||
|
_width = widget.carton.width.toDouble();
|
||||||
|
_height = widget.carton.height.toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
var s = await context
|
var s = await context
|
||||||
.read<FcsShipmentModel>()
|
.read<FcsShipmentModel>()
|
||||||
@@ -143,8 +166,16 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: LocalText(context, 'box.update_title',
|
title: Column(
|
||||||
|
children: [
|
||||||
|
LocalText(context, 'box.update_title',
|
||||||
color: primaryColor, fontSize: 20),
|
color: primaryColor, fontSize: 20),
|
||||||
|
Text(
|
||||||
|
widget.carton.cartonNumber ?? '',
|
||||||
|
style: TextStyle(color: primaryColor, fontSize: 14),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -172,7 +203,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
if (step.stepType == StepType.SIZE) {
|
if (step.stepType == StepType.SIZE) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: CartonSizeWidget(
|
child: CartonSizeWidget(
|
||||||
deliveryType: _selectedDeliveryType,
|
lastMile: _selectedLastMile,
|
||||||
billType: _billToValue,
|
billType: _billToValue,
|
||||||
sender: _sender!,
|
sender: _sender!,
|
||||||
consignee: _consignee!,
|
consignee: _consignee!,
|
||||||
@@ -188,7 +219,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
onContinue: (deliveryType, billType, shipment, cartonSizeType,
|
onContinue: (deliveryType, billType, shipment, cartonSizeType,
|
||||||
{standardSize, length, width, height}) {
|
{standardSize, length, width, height}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = deliveryType;
|
_selectedLastMile = deliveryType;
|
||||||
_billToValue = billType;
|
_billToValue = billType;
|
||||||
_shipment = shipment;
|
_shipment = shipment;
|
||||||
_cartonSizeType = cartonSizeType;
|
_cartonSizeType = cartonSizeType;
|
||||||
@@ -256,7 +287,7 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
length: _length,
|
length: _length,
|
||||||
width: _width,
|
width: _width,
|
||||||
height: _height,
|
height: _height,
|
||||||
deliveryType: _selectedDeliveryType,
|
lastMile: _selectedLastMile,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
packages: _packages,
|
packages: _packages,
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
@@ -279,6 +310,43 @@ class _CartonPackageEditorState extends State<CartonPackageEditor> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
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: carton_from_packages,
|
||||||
|
senderID: widget.carton.senderID,
|
||||||
|
consigneeID: widget.carton.consigneeID,
|
||||||
|
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);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// ignore_for_file: deprecated_member_use
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -20,6 +21,7 @@ import '../widgets/step_widget.dart';
|
|||||||
import 'cargo_widget.dart';
|
import 'cargo_widget.dart';
|
||||||
import 'carton_size_widget.dart';
|
import 'carton_size_widget.dart';
|
||||||
import 'carton_submit.dart';
|
import 'carton_submit.dart';
|
||||||
|
import 'model/carton_model.dart';
|
||||||
import 'model/package_selection_model.dart';
|
import 'model/package_selection_model.dart';
|
||||||
import 'package_selection_widget.dart';
|
import 'package_selection_widget.dart';
|
||||||
|
|
||||||
@@ -55,7 +57,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
double _width = 0;
|
double _width = 0;
|
||||||
double _height = 0;
|
double _height = 0;
|
||||||
|
|
||||||
String _selectedDeliveryType = delivery_caton;
|
String _selectedLastMile = delivery_caton;
|
||||||
String _billToValue = billToSender;
|
String _billToValue = billToSender;
|
||||||
|
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
@@ -134,7 +136,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
if (step.stepType == StepType.SIZE) {
|
if (step.stepType == StepType.SIZE) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: CartonSizeWidget(
|
child: CartonSizeWidget(
|
||||||
deliveryType: _selectedDeliveryType,
|
lastMile: _selectedLastMile,
|
||||||
billType: _billToValue,
|
billType: _billToValue,
|
||||||
sender: widget.sender,
|
sender: widget.sender,
|
||||||
consignee: widget.consignee,
|
consignee: widget.consignee,
|
||||||
@@ -147,10 +149,10 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
onPrevious: () {
|
onPrevious: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
},
|
},
|
||||||
onContinue: (deliveryType, billType, shipment, cartonSizeType,
|
onContinue: (lastMile, billType, shipment, cartonSizeType,
|
||||||
{standardSize, length, width, height}) {
|
{standardSize, length, width, height}) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = deliveryType;
|
_selectedLastMile = lastMile;
|
||||||
_billToValue = billType;
|
_billToValue = billType;
|
||||||
_shipment = shipment;
|
_shipment = shipment;
|
||||||
_cartonSizeType = cartonSizeType;
|
_cartonSizeType = cartonSizeType;
|
||||||
@@ -217,7 +219,7 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
length: _length,
|
length: _length,
|
||||||
width: _width,
|
width: _width,
|
||||||
height: _height,
|
height: _height,
|
||||||
deliveryType: _selectedDeliveryType,
|
lastMile: _selectedLastMile,
|
||||||
shipment: _shipment!,
|
shipment: _shipment!,
|
||||||
packages: _packages,
|
packages: _packages,
|
||||||
cargoTypes: _cargoTypes,
|
cargoTypes: _cargoTypes,
|
||||||
@@ -240,7 +242,41 @@ class _CartonPackageFormState extends State<CartonPackageForm> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
final OnContinue? onContinue;
|
final OnContinue? onContinue;
|
||||||
final User sender;
|
final User sender;
|
||||||
final User consignee;
|
final User consignee;
|
||||||
final String deliveryType;
|
final String lastMile;
|
||||||
final String billType;
|
final String billType;
|
||||||
final FcsShipment? shipment;
|
final FcsShipment? shipment;
|
||||||
final String cartonSizeType;
|
final String cartonSizeType;
|
||||||
@@ -52,7 +52,7 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
this.height,
|
this.height,
|
||||||
required this.sender,
|
required this.sender,
|
||||||
required this.consignee,
|
required this.consignee,
|
||||||
required this.deliveryType,
|
required this.lastMile,
|
||||||
required this.billType})
|
required this.billType})
|
||||||
: super(key: key);
|
: super(key: key);
|
||||||
|
|
||||||
@@ -61,14 +61,12 @@ class CartonSizeWidget extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
||||||
// List<String> _deliveryTypes = [delivery_caton, pickup_carton];
|
|
||||||
|
|
||||||
FcsShipment? _shipment;
|
FcsShipment? _shipment;
|
||||||
String _cartonSizeType = standardCarton;
|
String _cartonSizeType = standardCarton;
|
||||||
|
|
||||||
List<FcsShipment> _shipments = [];
|
List<FcsShipment> _shipments = [];
|
||||||
CartonSize? _selectStandardSize;
|
CartonSize? _selectStandardSize;
|
||||||
late String _selectedDeliveryType;
|
late String _selectedLastmile;
|
||||||
late String _billToValue;
|
late String _billToValue;
|
||||||
|
|
||||||
TextEditingController _widthController = new TextEditingController();
|
TextEditingController _widthController = new TextEditingController();
|
||||||
@@ -82,13 +80,9 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() async {
|
_init() async {
|
||||||
_selectedDeliveryType = widget.deliveryType;
|
_selectedLastmile = widget.lastMile;
|
||||||
_billToValue = widget.billType;
|
_billToValue = widget.billType;
|
||||||
_cartonSizeType = widget.cartonSizeType;
|
_cartonSizeType = widget.cartonSizeType;
|
||||||
|
|
||||||
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
|
||||||
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
|
|
||||||
|
|
||||||
_lengthController.text =
|
_lengthController.text =
|
||||||
widget.length == null ? "0" : removeTrailingZeros(widget.length ?? 0);
|
widget.length == null ? "0" : removeTrailingZeros(widget.length ?? 0);
|
||||||
_widthController.text =
|
_widthController.text =
|
||||||
@@ -96,8 +90,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
_heightController.text =
|
_heightController.text =
|
||||||
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
|
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
|
||||||
|
|
||||||
|
_getStandardCartonSize();
|
||||||
_loadShipment();
|
_loadShipment();
|
||||||
|
if (mounted) {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_getStandardCartonSize() {
|
||||||
|
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
||||||
|
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -107,7 +109,12 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
var fcsShipments =
|
var fcsShipments =
|
||||||
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
||||||
_shipments = fcsShipments;
|
_shipments = fcsShipments;
|
||||||
|
if (_shipments.contains(widget.shipment)) {
|
||||||
_shipment = widget.shipment;
|
_shipment = widget.shipment;
|
||||||
|
} else {
|
||||||
|
_shipment = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -116,6 +123,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant CartonSizeWidget oldWidget) {
|
void didUpdateWidget(covariant CartonSizeWidget oldWidget) {
|
||||||
_loadShipment();
|
_loadShipment();
|
||||||
|
_getStandardCartonSize();
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +133,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
context.watch<CartonSizeModel>().getCartonSizes;
|
context.watch<CartonSizeModel>().getCartonSizes;
|
||||||
bool isStandardSize = _cartonSizeType == standardCarton;
|
bool isStandardSize = _cartonSizeType == standardCarton;
|
||||||
bool isCustomSize = _cartonSizeType == customCarton;
|
bool isCustomSize = _cartonSizeType == customCarton;
|
||||||
bool isNoneDefinedSize = _cartonSizeType == packageCartion;
|
bool isNoneDefinedSize = _cartonSizeType == packageCarton;
|
||||||
|
|
||||||
final senderBox = DisplayText(
|
final senderBox = DisplayText(
|
||||||
text: widget.sender.name,
|
text: widget.sender.name,
|
||||||
@@ -139,7 +147,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
text: widget.consignee.name,
|
text: widget.consignee.name,
|
||||||
labelTextKey: "box.consignee.title",
|
labelTextKey: "box.consignee.title",
|
||||||
iconData: MaterialCommunityIcons.account_arrow_left,
|
iconData: MaterialCommunityIcons.account_arrow_left,
|
||||||
subText: Text(widget.consignee.fcsID!,
|
subText: Text(widget.consignee.fcsID ?? '',
|
||||||
style: TextStyle(fontSize: 13, color: labelColor)),
|
style: TextStyle(fontSize: 13, color: labelColor)),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -161,16 +169,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = delivery_caton;
|
_selectedLastmile = delivery_caton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
LocalRadio(
|
LocalRadio(
|
||||||
value: delivery_caton,
|
value: delivery_caton,
|
||||||
groupValue: _selectedDeliveryType,
|
groupValue: _selectedLastmile,
|
||||||
onChanged: (p0) {
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = delivery_caton;
|
_selectedLastmile = delivery_caton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -179,7 +187,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.delivery',
|
child: LocalText(context, 'box.delivery',
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: _selectedDeliveryType == delivery_caton
|
color: _selectedLastmile == delivery_caton
|
||||||
? primaryColor
|
? primaryColor
|
||||||
: Colors.black),
|
: Colors.black),
|
||||||
),
|
),
|
||||||
@@ -190,16 +198,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = pickup_carton;
|
_selectedLastmile = pickup_carton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
LocalRadio(
|
LocalRadio(
|
||||||
value: pickup_carton,
|
value: pickup_carton,
|
||||||
groupValue: _selectedDeliveryType,
|
groupValue: _selectedLastmile,
|
||||||
onChanged: (p0) {
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_selectedDeliveryType = pickup_carton;
|
_selectedLastmile = pickup_carton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -208,7 +216,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
padding: const EdgeInsets.only(left: 10),
|
padding: const EdgeInsets.only(left: 10),
|
||||||
child: LocalText(context, 'box.pickup',
|
child: LocalText(context, 'box.pickup',
|
||||||
fontSize: 15,
|
fontSize: 15,
|
||||||
color: _selectedDeliveryType == pickup_carton
|
color: _selectedLastmile == pickup_carton
|
||||||
? primaryColor
|
? primaryColor
|
||||||
: Colors.black),
|
: Colors.black),
|
||||||
),
|
),
|
||||||
@@ -315,7 +323,7 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
|
|
||||||
if (widget.onContinue != null) {
|
if (widget.onContinue != null) {
|
||||||
widget.onContinue!(
|
widget.onContinue!(
|
||||||
_selectedDeliveryType, _billToValue, _shipment!, _cartonSizeType,
|
_selectedLastmile, _billToValue, _shipment!, _cartonSizeType,
|
||||||
standardSize: _selectStandardSize, length: l, width: w, height: h);
|
standardSize: _selectStandardSize, length: l, width: w, height: h);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -463,16 +471,16 @@ class _CartonSizeWidgetState extends State<CartonSizeWidget> {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartonSizeType = packageCartion;
|
_cartonSizeType = packageCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
LocalRadio(
|
LocalRadio(
|
||||||
value: packageCartion,
|
value: packageCarton,
|
||||||
groupValue: _cartonSizeType,
|
groupValue: _cartonSizeType,
|
||||||
onChanged: (p0) {
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartonSizeType = packageCartion;
|
_cartonSizeType = packageCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
final double length;
|
final double length;
|
||||||
final double width;
|
final double width;
|
||||||
final double height;
|
final double height;
|
||||||
final String deliveryType;
|
final String lastMile;
|
||||||
final List<CargoType> cargoTypes;
|
final List<CargoType> cargoTypes;
|
||||||
final List<CargoType> surchareItems;
|
final List<CargoType> surchareItems;
|
||||||
final OnCreateCarton? onCreate;
|
final OnCreateCarton? onCreate;
|
||||||
@@ -47,7 +47,7 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
this.packages = const [],
|
this.packages = const [],
|
||||||
this.standardSize,
|
this.standardSize,
|
||||||
required this.cartonSizeType,
|
required this.cartonSizeType,
|
||||||
required this.deliveryType,
|
required this.lastMile,
|
||||||
this.length = 0,
|
this.length = 0,
|
||||||
this.width = 0,
|
this.width = 0,
|
||||||
this.height = 0,
|
this.height = 0,
|
||||||
@@ -69,10 +69,7 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
final cartonType = Padding(
|
final cartonType = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SubmitTextWidget(
|
child: SubmitTextWidget(
|
||||||
labelKey: 'box.carton.type',
|
labelKey: 'box.carton.type', text: carton_from_packages),
|
||||||
text: carton_from_packages,
|
|
||||||
// subText: boxDimension
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final shipmentBox = Padding(
|
final shipmentBox = Padding(
|
||||||
@@ -187,15 +184,15 @@ class CartonSubmit extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SubmitTextWidget(
|
child: SubmitTextWidget(
|
||||||
labelKey: 'box.select.delivery',
|
labelKey: 'box.select.delivery',
|
||||||
text: deliveryType,
|
text: lastMile == delivery_caton ? 'Delivery' : 'Pick-up',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
final cartonSizeBox = Padding(
|
final cartonSizeBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SubmitTextWidget(
|
child: SubmitTextWidget(
|
||||||
labelKey: 'box.carton_size',
|
labelKey: 'box.select_carton_size',
|
||||||
text: boxDimension??'',
|
text: boxDimension ?? 'No defined size',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,7 @@ import '../../../domain/entities/carton_size.dart';
|
|||||||
import '../../../domain/entities/fcs_shipment.dart';
|
import '../../../domain/entities/fcs_shipment.dart';
|
||||||
import '../../../domain/vo/local_step.dart';
|
import '../../../domain/vo/local_step.dart';
|
||||||
import '../../../helpers/theme.dart';
|
import '../../../helpers/theme.dart';
|
||||||
|
import '../../carton_size/model/carton_size_model.dart';
|
||||||
import '../../main/util.dart';
|
import '../../main/util.dart';
|
||||||
import '../../widgets/local_text.dart';
|
import '../../widgets/local_text.dart';
|
||||||
import '../../widgets/progress.dart';
|
import '../../widgets/progress.dart';
|
||||||
@@ -58,10 +59,33 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
|
|
||||||
_init() async {
|
_init() async {
|
||||||
context.read<CartonSelectionModel>().clearSelection();
|
context.read<CartonSelectionModel>().clearSelection();
|
||||||
|
|
||||||
|
// 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;
|
_cartonSizeType = customCarton;
|
||||||
_length = widget.carton.length;
|
_length = widget.carton.length.toDouble();
|
||||||
_width = widget.carton.width;
|
_width = widget.carton.width.toDouble();
|
||||||
_height = widget.carton.height;
|
_height = widget.carton.height.toDouble();
|
||||||
|
}
|
||||||
|
|
||||||
var s = await context
|
var s = await context
|
||||||
.read<FcsShipmentModel>()
|
.read<FcsShipmentModel>()
|
||||||
@@ -70,7 +94,7 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
|
|
||||||
_cartons = await context
|
_cartons = await context
|
||||||
.read<CartonModel>()
|
.read<CartonModel>()
|
||||||
.getCartonsByIds(widget.carton.mixCartonIDs);
|
.getCartonsByIds(widget.carton.cartonIDs);
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
@@ -113,8 +137,16 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
title: LocalText(context, 'box.update_title',
|
title: Column(
|
||||||
|
children: [
|
||||||
|
LocalText(context, 'box.update_title',
|
||||||
color: primaryColor, fontSize: 20),
|
color: primaryColor, fontSize: 20),
|
||||||
|
Text(
|
||||||
|
widget.carton.cartonNumber ?? '',
|
||||||
|
style: TextStyle(color: primaryColor, fontSize: 14),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -212,6 +244,35 @@ class _MixCartonEditorState extends State<MixCartonEditor> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
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>().updateMixCarton(carton);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// ignore_for_file: deprecated_member_use
|
// ignore_for_file: deprecated_member_use
|
||||||
|
|
||||||
|
import 'package:fcs/pages/carton/model/carton_model.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
@@ -187,7 +188,35 @@ class _MixCartonFormState extends State<MixCartonForm> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -48,8 +48,8 @@ class MixCartonSubmit extends StatefulWidget {
|
|||||||
|
|
||||||
class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
||||||
final NumberFormat numberFormatter = NumberFormat("#,###");
|
final NumberFormat numberFormatter = NumberFormat("#,###");
|
||||||
Map<String?, double> _mapCargosByWeight = {};
|
Map<String?, double> _mapCargos = {};
|
||||||
Map<String?, double> _mapCargosByCustomDutyFee = {};
|
Map<String?, double> _mapSurchargeItems = {};
|
||||||
double totalWeight = 0;
|
double totalWeight = 0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -59,30 +59,37 @@ class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() {
|
_init() {
|
||||||
|
// get cargos by weight
|
||||||
List<CargoType> _cargoTypes = [];
|
List<CargoType> _cargoTypes = [];
|
||||||
for (var c in widget.cartons) {
|
for (var c in widget.cartons) {
|
||||||
_cargoTypes.addAll(c.cargoTypes);
|
_cargoTypes.addAll(c.cargoTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get cargos by weight
|
_cargoTypes.sort((a, b) => a.name!.compareTo(b.name!));
|
||||||
Map<String?, List<CargoType>> _cargosByWeight =
|
|
||||||
groupCargos(_cargoTypes.where((e) => !e.isCutomDuty).toList());
|
|
||||||
|
|
||||||
|
Map<String?, List<CargoType>> _cargosByWeight = groupCargos(_cargoTypes);
|
||||||
_cargosByWeight.forEach((key, value) {
|
_cargosByWeight.forEach((key, value) {
|
||||||
double total = value.fold(0, (sum, item) => sum + item.weight);
|
double total = value.fold(0, (sum, item) => sum + item.weight);
|
||||||
_mapCargosByWeight[key] = total;
|
_mapCargos[key] = total;
|
||||||
});
|
});
|
||||||
|
|
||||||
totalWeight =
|
totalWeight = _mapCargos.entries.fold(0, (sum, value) => sum + value.value);
|
||||||
_mapCargosByWeight.entries.fold(0, (sum, value) => sum + value.value);
|
|
||||||
|
// get surcharge items
|
||||||
|
|
||||||
|
List<CargoType> _surchargeItems = [];
|
||||||
|
for (var c in widget.cartons) {
|
||||||
|
_surchargeItems.addAll(c.surchareItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
_surchargeItems.sort((a, b) => a.name!.compareTo(b.name!));
|
||||||
|
|
||||||
// get cargos by custom duty fee
|
|
||||||
Map<String?, List<CargoType>> _cargosByCustomDutyFee =
|
Map<String?, List<CargoType>> _cargosByCustomDutyFee =
|
||||||
groupCargos(_cargoTypes.where((e) => e.isCutomDuty).toList());
|
groupCargos(_surchargeItems);
|
||||||
|
|
||||||
_cargosByCustomDutyFee.forEach((key, value) {
|
_cargosByCustomDutyFee.forEach((key, value) {
|
||||||
double total = value.fold(0, (sum, item) => sum + item.qty);
|
double total = value.fold(0, (sum, item) => sum + item.qty);
|
||||||
_mapCargosByCustomDutyFee[key] = total;
|
_mapSurchargeItems[key] = total;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@@ -110,17 +117,14 @@ class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
|||||||
final cartonType = Padding(
|
final cartonType = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SubmitTextWidget(
|
child: SubmitTextWidget(
|
||||||
labelKey: 'box.carton.type',
|
labelKey: 'box.carton.type', text: carton_mix_carton),
|
||||||
text: carton_mix_carton,
|
|
||||||
// subText: boxDimension,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
final cartonSizeBox = Padding(
|
final cartonSizeBox = Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: SubmitTextWidget(
|
child: SubmitTextWidget(
|
||||||
labelKey: 'box.carton_size',
|
labelKey: 'box.select_carton_size',
|
||||||
text: boxDimension ?? '',
|
text: boxDimension ?? 'No defined size',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -198,7 +202,7 @@ class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
|||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _mapCargosByWeight.entries.map((e) {
|
children: _mapCargos.entries.map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -219,7 +223,7 @@ class _MixCartonSubmitState extends State<MixCartonSubmit> {
|
|||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: _mapCargosByCustomDutyFee.entries.map((e) {
|
children: _mapSurchargeItems.entries.map((e) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@@ -68,8 +68,6 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_init() async {
|
_init() async {
|
||||||
List<CartonSize> cartonSizes = context.read<CartonSizeModel>().cartonSizes;
|
|
||||||
_selectStandardSize = widget.standardSize ?? cartonSizes.first;
|
|
||||||
_cartionSizeType = widget.cartonSizeType;
|
_cartionSizeType = widget.cartonSizeType;
|
||||||
|
|
||||||
_lengthController.text =
|
_lengthController.text =
|
||||||
@@ -79,6 +77,8 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
_heightController.text =
|
_heightController.text =
|
||||||
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
|
widget.height == null ? "0" : removeTrailingZeros(widget.height ?? 0);
|
||||||
|
|
||||||
|
_getStandardCartonSize();
|
||||||
|
|
||||||
_loadShipment();
|
_loadShipment();
|
||||||
|
|
||||||
if (mounted) {
|
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 {
|
_loadShipment() async {
|
||||||
var fcsShipments =
|
var fcsShipments =
|
||||||
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
await context.read<FcsShipmentModel>().getActiveFcsShipments();
|
||||||
_shipments = fcsShipments;
|
_shipments = fcsShipments;
|
||||||
|
if (_shipments.contains(widget.shipment)) {
|
||||||
_shipment = widget.shipment;
|
_shipment = widget.shipment;
|
||||||
|
} else {
|
||||||
|
_shipment = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
@@ -99,6 +112,7 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
@override
|
@override
|
||||||
void didUpdateWidget(covariant TypeWidget oldWidget) {
|
void didUpdateWidget(covariant TypeWidget oldWidget) {
|
||||||
_loadShipment();
|
_loadShipment();
|
||||||
|
_getStandardCartonSize();
|
||||||
super.didUpdateWidget(oldWidget);
|
super.didUpdateWidget(oldWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +123,7 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
|
|
||||||
bool isStandardSize = _cartionSizeType == standardCarton;
|
bool isStandardSize = _cartionSizeType == standardCarton;
|
||||||
bool isCustomSize = _cartionSizeType == customCarton;
|
bool isCustomSize = _cartionSizeType == customCarton;
|
||||||
bool isNoneDefinedSize = _cartionSizeType == packageCartion;
|
bool isNoneDefinedSize = _cartionSizeType == packageCarton;
|
||||||
|
|
||||||
final continueBtn = ContinueButton(onTap: () {
|
final continueBtn = ContinueButton(onTap: () {
|
||||||
double l = double.tryParse(_lengthController.text) ?? 0;
|
double l = double.tryParse(_lengthController.text) ?? 0;
|
||||||
@@ -287,16 +301,16 @@ class _TypeWidgetState extends State<TypeWidget> {
|
|||||||
InkWell(
|
InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartionSizeType = packageCartion;
|
_cartionSizeType = packageCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
child: Row(children: <Widget>[
|
child: Row(children: <Widget>[
|
||||||
LocalRadio(
|
LocalRadio(
|
||||||
value: packageCartion,
|
value: packageCarton,
|
||||||
groupValue: _cartionSizeType,
|
groupValue: _cartionSizeType,
|
||||||
onChanged: (p0) {
|
onChanged: (p0) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_cartionSizeType = packageCartion;
|
_cartionSizeType = packageCarton;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:fcs/data/services/services.dart';
|
|||||||
import 'package:fcs/constants.dart';
|
import 'package:fcs/constants.dart';
|
||||||
import 'package:fcs/domain/entities/carton.dart';
|
import 'package:fcs/domain/entities/carton.dart';
|
||||||
import 'package:fcs/domain/entities/fcs_shipment.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/pages/main/model/base_model.dart';
|
||||||
import 'package:fcs/pagination/paginator_listener.dart';
|
import 'package:fcs/pagination/paginator_listener.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
@@ -18,8 +19,6 @@ class CartonModel extends BaseModel {
|
|||||||
final log = Logger('CartonModel');
|
final log = Logger('CartonModel');
|
||||||
|
|
||||||
var defaultShipment = FcsShipment(shipmentNumber: "All shipments", id: all);
|
var defaultShipment = FcsShipment(shipmentNumber: "All shipments", id: all);
|
||||||
|
|
||||||
PaginatorListener<Carton>? cartonsByFilter;
|
|
||||||
PaginatorListener<Carton>? getBoxes;
|
PaginatorListener<Carton>? getBoxes;
|
||||||
|
|
||||||
String? filterByStatus;
|
String? filterByStatus;
|
||||||
@@ -49,13 +48,10 @@ class CartonModel extends BaseModel {
|
|||||||
@override
|
@override
|
||||||
logout() async {
|
logout() async {
|
||||||
getBoxes?.close();
|
getBoxes?.close();
|
||||||
cartonsByFilter?.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initData() async {
|
Future<void> _initData() async {
|
||||||
logout();
|
logout();
|
||||||
|
|
||||||
_loadPaginationCartons();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filterCarton(FcsShipment? fcsShipment, User? consignee, User? sender,
|
filterCarton(FcsShipment? fcsShipment, User? consignee, User? sender,
|
||||||
@@ -121,13 +117,15 @@ class CartonModel extends BaseModel {
|
|||||||
Query pageQuery = FirebaseFirestore.instance.collection(path);
|
Query pageQuery = FirebaseFirestore.instance.collection(path);
|
||||||
|
|
||||||
if (filterByConsingee != null) {
|
if (filterByConsingee != null) {
|
||||||
col = col.where("user_id", isEqualTo: filterByConsingee!.id);
|
col = col.where("consignee_user_id", isEqualTo: filterByConsingee!.id);
|
||||||
pageQuery = pageQuery.where("user_id", isEqualTo: filterByConsingee!.id);
|
pageQuery = pageQuery.where("consignee_user_id",
|
||||||
|
isEqualTo: filterByConsingee!.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterBySender != null) {
|
if (filterBySender != null) {
|
||||||
col = col.where("sender_id", isEqualTo: filterBySender!.id);
|
col = col.where("sender_user_id", isEqualTo: filterBySender!.id);
|
||||||
pageQuery = pageQuery.where("sender_id", isEqualTo: filterBySender!.id);
|
pageQuery =
|
||||||
|
pageQuery.where("sender_user_id", isEqualTo: filterBySender!.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filterByStatus != null) {
|
if (filterByStatus != null) {
|
||||||
@@ -140,7 +138,7 @@ class CartonModel extends BaseModel {
|
|||||||
pageQuery = pageQuery.where("fcs_shipment_id", isEqualTo: shipment!.id);
|
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?.close();
|
||||||
getBoxes = PaginatorListener<Carton>(
|
getBoxes = PaginatorListener<Carton>(
|
||||||
@@ -148,30 +146,6 @@ class CartonModel extends BaseModel {
|
|||||||
rowPerLoad: 30);
|
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 {
|
Future<List<Carton>> getCartons(String shipmentID) async {
|
||||||
String path = "/$cartons_collection";
|
String path = "/$cartons_collection";
|
||||||
var querySnap = await FirebaseFirestore.instance
|
var querySnap = await FirebaseFirestore.instance
|
||||||
@@ -235,7 +209,18 @@ class CartonModel extends BaseModel {
|
|||||||
return Services.instance.cartonService.deleteCarton(carton);
|
return Services.instance.cartonService.deleteCarton(carton);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<Carton> createMixCarton(Carton carton) {
|
||||||
|
return Services.instance.cartonService.createMixCarton(carton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateMixCarton(Carton carton) {
|
||||||
|
return Services.instance.cartonService.updateMixCarton(carton);
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<Carton>> searchCarton(String term) async {
|
Future<List<Carton>> searchCarton(String term) async {
|
||||||
|
if (term != '') {
|
||||||
|
await SharedPref.saveRecentSearch('carton_search', term);
|
||||||
|
}
|
||||||
return Services.instance.cartonService.searchCarton(term);
|
return Services.instance.cartonService.searchCarton(term);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,9 +261,11 @@ class CartonModel extends BaseModel {
|
|||||||
uploadedURL.forEach((url) {
|
uploadedURL.forEach((url) {
|
||||||
carton.photoUrls.add(url);
|
carton.photoUrls.add(url);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
carton.photoUrls.removeWhere((e) => deletedUrls.contains(e));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// await Services.instance.packageService.updateReceiving(package);
|
await Services.instance.cartonService.uploadCartonImages(carton);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// delete newly uploaded photos if fails
|
// delete newly uploaded photos if fails
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class CartonSelectionModel extends BaseModel {
|
|||||||
query = query.where("carton_number", isEqualTo: term);
|
query = query.where("carton_number", isEqualTo: term);
|
||||||
}
|
}
|
||||||
|
|
||||||
query = query.orderBy("created_at", descending: true);
|
query = query.orderBy("update_time", descending: true);
|
||||||
|
|
||||||
if (_lastDocument != null) {
|
if (_lastDocument != null) {
|
||||||
query = query.startAfterDocument(_lastDocument!);
|
query = query.startAfterDocument(_lastDocument!);
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import 'dart:async';
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:fcs/config.dart';
|
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import '../../../constants.dart';
|
import '../../../constants.dart';
|
||||||
|
import '../../../data/services/services.dart';
|
||||||
import '../../../domain/entities/user.dart';
|
import '../../../domain/entities/user.dart';
|
||||||
import '../../../helpers/api_helper.dart';
|
import '../../../helpers/api_helper.dart';
|
||||||
import '../../../helpers/firebase_helper.dart';
|
import '../../../helpers/firebase_helper.dart';
|
||||||
@@ -56,7 +56,7 @@ class ConsigneeSelectionModel extends BaseModel {
|
|||||||
|
|
||||||
var result = await requestAPI(
|
var result = await requestAPI(
|
||||||
"/api/fts/$user_collection/$escapeSender/$rowPerPage", "GET",
|
"/api/fts/$user_collection/$escapeSender/$rowPerPage", "GET",
|
||||||
url: Config.instance.reportURL, token: await getToken());
|
url: Services.setting.reportURL, token: await getToken());
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
for (var row in result) {
|
for (var row in result) {
|
||||||
@@ -91,8 +91,8 @@ class ConsigneeSelectionModel extends BaseModel {
|
|||||||
Query query = FirebaseFirestore.instance
|
Query query = FirebaseFirestore.instance
|
||||||
.collection(path)
|
.collection(path)
|
||||||
.where("is_sys_admin", isEqualTo: false)
|
.where("is_sys_admin", isEqualTo: false)
|
||||||
.where("is_deleted", isEqualTo: false)
|
.where("delete_time", isEqualTo: 0)
|
||||||
.orderBy("message_time", descending: true);
|
.orderBy("update_time", descending: true);
|
||||||
|
|
||||||
if (_lastDocument != null) {
|
if (_lastDocument != null) {
|
||||||
query = query.startAfterDocument(_lastDocument!);
|
query = query.startAfterDocument(_lastDocument!);
|
||||||
|
|||||||
@@ -3,9 +3,8 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:cloud_firestore/cloud_firestore.dart';
|
import 'package:cloud_firestore/cloud_firestore.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
import '../../../config.dart';
|
|
||||||
import '../../../constants.dart';
|
import '../../../constants.dart';
|
||||||
|
import '../../../data/services/services.dart';
|
||||||
import '../../../domain/entities/user.dart';
|
import '../../../domain/entities/user.dart';
|
||||||
import '../../../helpers/api_helper.dart';
|
import '../../../helpers/api_helper.dart';
|
||||||
import '../../../helpers/firebase_helper.dart';
|
import '../../../helpers/firebase_helper.dart';
|
||||||
@@ -57,7 +56,7 @@ class SenderSelectionModel extends BaseModel {
|
|||||||
|
|
||||||
var result = await requestAPI(
|
var result = await requestAPI(
|
||||||
"/api/fts/$user_collection/$escapeSender/$rowPerPage", "GET",
|
"/api/fts/$user_collection/$escapeSender/$rowPerPage", "GET",
|
||||||
url: Config.instance.reportURL, token: await getToken());
|
url: Services.setting.reportURL, token: await getToken());
|
||||||
|
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
for (var row in result) {
|
for (var row in result) {
|
||||||
@@ -93,8 +92,8 @@ class SenderSelectionModel extends BaseModel {
|
|||||||
Query query = FirebaseFirestore.instance
|
Query query = FirebaseFirestore.instance
|
||||||
.collection(path)
|
.collection(path)
|
||||||
.where("is_sys_admin", isEqualTo: false)
|
.where("is_sys_admin", isEqualTo: false)
|
||||||
.where("is_deleted", isEqualTo: false)
|
.where("delete_time", isEqualTo: 0)
|
||||||
.orderBy("message_time", descending: true);
|
.orderBy("update_time", descending: true);
|
||||||
|
|
||||||
if (_lastDocument != null) {
|
if (_lastDocument != null) {
|
||||||
query = query.startAfterDocument(_lastDocument!);
|
query = query.startAfterDocument(_lastDocument!);
|
||||||
|
|||||||
@@ -35,8 +35,11 @@ class PrintQrCodePage extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Text(carton.cartonNumber ?? "",
|
Text(carton.cartonNumber ?? "",
|
||||||
style: TextStyle(fontSize: 18, fontFamily: "Roboto")),
|
style: TextStyle(fontSize: 18, fontFamily: "Roboto")),
|
||||||
Text(carton.userName!,
|
carton.consigneeName == null || carton.consigneeName == ''
|
||||||
style: TextStyle(fontSize: 16, fontFamily: "Roboto")),
|
? const SizedBox()
|
||||||
|
: Text(carton.consigneeName!,
|
||||||
|
style:
|
||||||
|
TextStyle(fontSize: 16, fontFamily: "Roboto")),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 3),
|
padding: const EdgeInsets.only(top: 3),
|
||||||
child: Text("${carton.actualWeight} lb",
|
child: Text("${carton.actualWeight} lb",
|
||||||
|
|||||||
114
lib/pages/carton/surcharge_item_addition.dart
Normal file
114
lib/pages/carton/surcharge_item_addition.dart
Normal 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),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ class CartonListRow extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: new Text(
|
child: new Text(
|
||||||
box.userName ?? "",
|
box.consigneeName ?? "",
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: 15.0, color: Colors.grey),
|
fontSize: 15.0, color: Colors.grey),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class CartonListRow extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: new Text(
|
child: new Text(
|
||||||
carton.userName ?? "",
|
carton.consigneeName ?? "",
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: 15.0, color: Colors.grey),
|
fontSize: 15.0, color: Colors.grey),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../helpers/shared_pref.dart';
|
||||||
|
import '../widgets/suggest_list.dart';
|
||||||
import 'carton_list_row.dart';
|
import 'carton_list_row.dart';
|
||||||
|
|
||||||
typedef CallbackCartonSelect(Carton carton);
|
typedef CallbackCartonSelect(Carton carton);
|
||||||
@@ -32,7 +34,7 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
|
|||||||
appBarTheme: AppBarTheme(color: primaryColor),
|
appBarTheme: AppBarTheme(color: primaryColor),
|
||||||
iconButtonTheme: IconButtonThemeData(
|
iconButtonTheme: IconButtonThemeData(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
|
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
||||||
@@ -120,15 +122,29 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildSuggestions(BuildContext context) {
|
Widget buildSuggestions(BuildContext context) {
|
||||||
return Container(
|
return FutureBuilder<List<String>?>(
|
||||||
child: Center(
|
future: SharedPref.getRecentSearch('carton_search', query),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
List<String> _oldFilters = snapshot.data ?? [];
|
||||||
|
if (_oldFilters.isEmpty) {
|
||||||
|
return const Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.2,
|
opacity: 0.2,
|
||||||
child: Icon(MaterialCommunityIcons.package,
|
child: Icon(MaterialCommunityIcons.package,
|
||||||
size: 200, color: primaryColor)),
|
color: primaryColor, size: 200),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return SuggestList(
|
||||||
|
recentSearchList: _oldFilters,
|
||||||
|
onTap: (String s) {
|
||||||
|
query = s;
|
||||||
|
showResults(context);
|
||||||
|
},
|
||||||
|
prefKey: 'carton_search');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_scan(BuildContext context) async {
|
_scan(BuildContext context) async {
|
||||||
// PermissionStatus permission =
|
// PermissionStatus permission =
|
||||||
|
|||||||
@@ -86,10 +86,10 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
|
|||||||
_loadPackages() async {
|
_loadPackages() async {
|
||||||
if (!isFromPackages && !isSmallBag) return;
|
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 =
|
PackageModel packageModel =
|
||||||
Provider.of<PackageModel>(context, listen: false);
|
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_processed_status,
|
||||||
package_packed_status,
|
package_packed_status,
|
||||||
package_shipped_status,
|
package_shipped_status,
|
||||||
@@ -137,13 +137,13 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
|
|||||||
iconData: Ionicons.ios_airplane,
|
iconData: Ionicons.ios_airplane,
|
||||||
);
|
);
|
||||||
final fcsIDBox = DisplayText(
|
final fcsIDBox = DisplayText(
|
||||||
text: _box.fcsID,
|
text: _box.consigneeFCSID,
|
||||||
labelTextKey: "box.fcs.id",
|
labelTextKey: "box.fcs.id",
|
||||||
icon: FcsIDIcon(),
|
icon: FcsIDIcon(),
|
||||||
);
|
);
|
||||||
|
|
||||||
final customerNameBox = DisplayText(
|
final customerNameBox = DisplayText(
|
||||||
text: _box.userName,
|
text: _box.consigneeName,
|
||||||
labelTextKey: "box.name",
|
labelTextKey: "box.name",
|
||||||
iconData: Icons.person,
|
iconData: Icons.person,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class DeliveryListRow extends StatelessWidget {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 5),
|
padding: const EdgeInsets.only(top: 5),
|
||||||
child: new Text(
|
child: new Text(
|
||||||
box.userName ?? "",
|
box.consigneeName ?? "",
|
||||||
style: new TextStyle(
|
style: new TextStyle(
|
||||||
fontSize: 15.0, color: Colors.grey),
|
fontSize: 15.0, color: Colors.grey),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:fcs/domain/entities/fcs_shipment.dart';
|
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/helpers/theme.dart';
|
||||||
import 'package:fcs/localization/app_translations.dart';
|
import 'package:fcs/localization/app_translations.dart';
|
||||||
import 'package:fcs/pages/fcs_shipment/model/fcs_shipment_model.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');
|
var dateFormatter = new DateFormat('dd MMM yyyy');
|
||||||
TextEditingController _shipmentNumberController = new TextEditingController();
|
TextEditingController _shipmentNumberController = new TextEditingController();
|
||||||
TextEditingController _cutoffDateController = new TextEditingController();
|
TextEditingController _cutoffDateController = new TextEditingController();
|
||||||
TextEditingController _arrivalDateController = new TextEditingController();
|
TextEditingController _etaDateController = new TextEditingController();
|
||||||
TextEditingController _departureDateControler = new TextEditingController();
|
|
||||||
TextEditingController _consigneeController = new TextEditingController();
|
|
||||||
TextEditingController _portController = new TextEditingController();
|
|
||||||
TextEditingController _destinationController = new TextEditingController();
|
|
||||||
TextEditingController _statusController = new TextEditingController();
|
TextEditingController _statusController = new TextEditingController();
|
||||||
|
|
||||||
FcsShipment _shipment = new FcsShipment();
|
FcsShipment _shipment = new FcsShipment();
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
ShipmentType? _currentShipmentType;
|
ShipmentType? _currentShipmentType;
|
||||||
|
ShipmentConsignee? _currentConsignee;
|
||||||
|
ShipmentPort? _currentLoadingPort;
|
||||||
|
ShipmentPort? _currentDestination;
|
||||||
bool _isNew = false;
|
bool _isNew = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -53,24 +55,38 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
|
|||||||
if (_shipment.cutoffDate != null)
|
if (_shipment.cutoffDate != null)
|
||||||
_cutoffDateController.text =
|
_cutoffDateController.text =
|
||||||
dateFormatter.format(_shipment.cutoffDate!);
|
dateFormatter.format(_shipment.cutoffDate!);
|
||||||
if (_shipment.arrivalDate != null)
|
if (_shipment.etaDate != null)
|
||||||
_arrivalDateController.text =
|
_etaDateController.text = dateFormatter.format(_shipment.etaDate!);
|
||||||
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 ?? "";
|
|
||||||
|
|
||||||
List<ShipmentType> list = model.shipmentTypes
|
_statusController.text = _shipment.status ?? "";
|
||||||
|
|
||||||
|
List<ShipmentType> shipmentTypes = model.shipmentTypes
|
||||||
.where((e) => e.id == _shipment.shipmentTypeId)
|
.where((e) => e.id == _shipment.shipmentTypeId)
|
||||||
.toList();
|
.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 {
|
} 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var languageModel = Provider.of<LanguageModel>(context);
|
var languageModel = Provider.of<LanguageModel>(context);
|
||||||
List<ShipmentType> shipmentTypes =
|
var shipmentModel = context.watch<FcsShipmentModel>();
|
||||||
context.watch<FcsShipmentModel>().shipmentTypes;
|
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(
|
final createBtn = Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 30),
|
padding: const EdgeInsets.symmetric(horizontal: 30),
|
||||||
@@ -150,7 +269,7 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
|
|||||||
InputDate(
|
InputDate(
|
||||||
labelTextKey: "FCSshipment.ETA",
|
labelTextKey: "FCSshipment.ETA",
|
||||||
iconData: Icons.date_range,
|
iconData: Icons.date_range,
|
||||||
controller: _arrivalDateController,
|
controller: _etaDateController,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value!.isEmpty) {
|
if (value!.isEmpty) {
|
||||||
@@ -160,47 +279,14 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
DropdownButtonFormField(
|
shipmentTypeBox,
|
||||||
value:
|
const SizedBox(height: 25),
|
||||||
_currentShipmentType == "" ? null : _currentShipmentType,
|
consigneeBox,
|
||||||
decoration: InputDecoration(
|
const SizedBox(height: 25),
|
||||||
contentPadding: EdgeInsets.zero,
|
loadingPortBox,
|
||||||
enabledBorder: UnderlineInputBorder(
|
const SizedBox(height: 25),
|
||||||
borderSide: BorderSide(color: primaryColor)),
|
destinationBox,
|
||||||
focusedBorder: UnderlineInputBorder(
|
SizedBox(height: 30),
|
||||||
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),
|
|
||||||
_isNew ? createBtn : updateBtn,
|
_isNew ? createBtn : updateBtn,
|
||||||
SizedBox(height: 15)
|
SizedBox(height: 15)
|
||||||
]),
|
]),
|
||||||
@@ -214,16 +300,15 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
|
|||||||
fcsShipment.id = _shipment.id;
|
fcsShipment.id = _shipment.id;
|
||||||
fcsShipment.shipmentNumber = _shipmentNumberController.text;
|
fcsShipment.shipmentNumber = _shipmentNumberController.text;
|
||||||
fcsShipment.shipmentTypeId = _currentShipmentType?.id ?? "";
|
fcsShipment.shipmentTypeId = _currentShipmentType?.id ?? "";
|
||||||
fcsShipment.consignee = _consigneeController.text;
|
fcsShipment.consigneeId = _currentConsignee?.id ?? "";
|
||||||
fcsShipment.port = _portController.text;
|
fcsShipment.loadingPortId = _currentLoadingPort?.id ?? "";
|
||||||
fcsShipment.destination = _destinationController.text;
|
fcsShipment.destinationPortId = _currentDestination?.id ?? "";
|
||||||
|
|
||||||
var cutoffDate = _cutoffDateController.text;
|
var cutoffDate = _cutoffDateController.text;
|
||||||
var arrivalDate = _arrivalDateController.text;
|
var etaDate = _etaDateController.text;
|
||||||
fcsShipment.cutoffDate =
|
fcsShipment.cutoffDate =
|
||||||
(cutoffDate == "" ? null : dateFormatter.parse(cutoffDate))!;
|
(cutoffDate == "" ? null : dateFormatter.parse(cutoffDate))!;
|
||||||
fcsShipment.arrivalDate =
|
fcsShipment.etaDate = (etaDate == "" ? null : dateFormatter.parse(etaDate));
|
||||||
(arrivalDate == "" ? null : dateFormatter.parse(arrivalDate))!;
|
|
||||||
return fcsShipment;
|
return fcsShipment;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +356,11 @@ class _FcsShipmentEditorState extends State<FcsShipmentEditor> {
|
|||||||
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
|
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
|
||||||
return _shipmentNumberController.text != "" ||
|
return _shipmentNumberController.text != "" ||
|
||||||
_cutoffDateController.text != "" ||
|
_cutoffDateController.text != "" ||
|
||||||
_arrivalDateController.text != "" ||
|
_etaDateController.text != "" ||
|
||||||
_consigneeController.text != "" ||
|
_currentConsignee != shipmentModel.shipmentConsingees.first ||
|
||||||
_portController.text != "" ||
|
_currentShipmentType != shipmentModel.shipmentTypes.first ||
|
||||||
_destinationController.text != "" ||
|
_currentLoadingPort != shipmentModel.shipmentPorts.first ||
|
||||||
_currentShipmentType != shipmentModel.shipmentTypes[0];
|
_currentDestination != shipmentModel.shipmentPorts.first;
|
||||||
} else {
|
} else {
|
||||||
FcsShipment fcsShipment = _getPayload();
|
FcsShipment fcsShipment = _getPayload();
|
||||||
return widget.shipment!.isChangedForEdit(fcsShipment);
|
return widget.shipment!.isChangedForEdit(fcsShipment);
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ import 'package:provider/provider.dart';
|
|||||||
import 'fcs_shipment_editor.dart';
|
import 'fcs_shipment_editor.dart';
|
||||||
|
|
||||||
class FcsShipmentInfo extends StatefulWidget {
|
class FcsShipmentInfo extends StatefulWidget {
|
||||||
final FcsShipment? fcsShipment;
|
final FcsShipment fcsShipment;
|
||||||
FcsShipmentInfo({this.fcsShipment});
|
FcsShipmentInfo({required this.fcsShipment});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_FcsShipmentInfoState createState() => _FcsShipmentInfoState();
|
_FcsShipmentInfoState createState() => _FcsShipmentInfoState();
|
||||||
@@ -29,7 +29,7 @@ class FcsShipmentInfo extends StatefulWidget {
|
|||||||
|
|
||||||
class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
||||||
var dateFormatter = new DateFormat('dd MMM yyyy');
|
var dateFormatter = new DateFormat('dd MMM yyyy');
|
||||||
FcsShipment? _fcsShipment;
|
late FcsShipment _fcsShipment;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
TextEditingController _shipmentNumberController = new TextEditingController();
|
TextEditingController _shipmentNumberController = new TextEditingController();
|
||||||
TextEditingController _cutoffDateController = new TextEditingController();
|
TextEditingController _cutoffDateController = new TextEditingController();
|
||||||
@@ -49,21 +49,21 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_load() {
|
_load() {
|
||||||
_shipmentNumberController.text = _fcsShipment?.shipmentNumber ?? "";
|
_shipmentNumberController.text = _fcsShipment.shipmentNumber ?? "";
|
||||||
if (_fcsShipment?.cutoffDate != null)
|
if (_fcsShipment.cutoffDate != null)
|
||||||
_cutoffDateController.text =
|
_cutoffDateController.text =
|
||||||
dateFormatter.format(_fcsShipment!.cutoffDate!);
|
dateFormatter.format(_fcsShipment.cutoffDate!);
|
||||||
if (_fcsShipment?.arrivalDate != null)
|
if (_fcsShipment.etaDate != null)
|
||||||
_arrivalDateController.text =
|
_arrivalDateController.text = dateFormatter.format(_fcsShipment.etaDate!);
|
||||||
dateFormatter.format(_fcsShipment!.arrivalDate!);
|
if (_fcsShipment.departureDate != null)
|
||||||
if (_fcsShipment?.departureDate != null)
|
|
||||||
_departureDateControler.text =
|
_departureDateControler.text =
|
||||||
dateFormatter.format(_fcsShipment!.departureDate!);
|
dateFormatter.format(_fcsShipment.departureDate!);
|
||||||
_shipmentTypeControler.text = _fcsShipment!.shipTypeName ?? "";
|
|
||||||
_consigneeController.text = _fcsShipment!.consignee ?? "";
|
_shipmentTypeControler.text = _fcsShipment.shipmentTypeName ?? "";
|
||||||
_portController.text = _fcsShipment!.port ?? "";
|
_consigneeController.text = _fcsShipment.consigneeName ?? '';
|
||||||
_destinationController.text = _fcsShipment!.destination ?? "";
|
_portController.text = _fcsShipment.loadingPortName ?? '';
|
||||||
_statusController.text = _fcsShipment!.status ?? "";
|
_destinationController.text = _fcsShipment.destinationPortName ?? '';
|
||||||
|
_statusController.text = _fcsShipment.status ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -176,7 +176,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
labelColor: primaryColor,
|
labelColor: primaryColor,
|
||||||
arrowColor: primaryColor,
|
arrowColor: primaryColor,
|
||||||
actions: [
|
actions: [
|
||||||
_fcsShipment?.status == fcs_shipment_pending_status
|
_fcsShipment.status == fcs_shipment_pending_status
|
||||||
? IconButton(
|
? IconButton(
|
||||||
icon: Icon(Icons.edit, color: primaryColor),
|
icon: Icon(Icons.edit, color: primaryColor),
|
||||||
onPressed: _edit,
|
onPressed: _edit,
|
||||||
@@ -212,20 +212,20 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
portBox,
|
portBox,
|
||||||
destinationBox,
|
destinationBox,
|
||||||
const SizedBox(height: 30),
|
const SizedBox(height: 30),
|
||||||
_fcsShipment?.status == fcs_shipment_pending_status
|
_fcsShipment.status == fcs_shipment_pending_status
|
||||||
? processBtn
|
? processBtn
|
||||||
: Container(),
|
: Container(),
|
||||||
_fcsShipment?.status == fcs_shipment_pending_status
|
_fcsShipment.status == fcs_shipment_pending_status
|
||||||
? Container(
|
? Container(
|
||||||
padding: EdgeInsets.only(top: 3), child: cancelBtn)
|
padding: EdgeInsets.only(top: 3), child: cancelBtn)
|
||||||
: Container(),
|
: Container(),
|
||||||
_fcsShipment?.status == fcs_shipment_processed_status
|
_fcsShipment.status == fcs_shipment_processed_status
|
||||||
? shipBtn
|
? shipBtn
|
||||||
: Container(),
|
: Container(),
|
||||||
_fcsShipment?.status == fcs_shipment_shipped_status
|
_fcsShipment.status == fcs_shipment_shipped_status
|
||||||
? arriveBtn
|
? arriveBtn
|
||||||
: Container(),
|
: Container(),
|
||||||
_fcsShipment?.status == fcs_shipment_arrived_status
|
_fcsShipment.status == fcs_shipment_arrived_status
|
||||||
? invoiceBtn
|
? invoiceBtn
|
||||||
: Container(),
|
: Container(),
|
||||||
SizedBox(height: 20)
|
SizedBox(height: 20)
|
||||||
@@ -244,8 +244,8 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
);
|
);
|
||||||
if (updated ?? false) {
|
if (updated ?? false) {
|
||||||
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
|
var shipmentModel = Provider.of<FcsShipmentModel>(context, listen: false);
|
||||||
if (_fcsShipment != null && _fcsShipment!.id != null) {
|
if (_fcsShipment.id != null) {
|
||||||
FcsShipment? f = await shipmentModel.getFcsShipment(_fcsShipment!.id!);
|
FcsShipment? f = await shipmentModel.getFcsShipment(_fcsShipment.id!);
|
||||||
if (f == null) return;
|
if (f == null) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
_fcsShipment = f;
|
_fcsShipment = f;
|
||||||
@@ -294,7 +294,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await context.read<FcsShipmentModel>().process(_fcsShipment!.id!);
|
await context.read<FcsShipmentModel>().process(_fcsShipment.id!);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
@@ -316,7 +316,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await context.read<FcsShipmentModel>().ship(_fcsShipment!.id!);
|
await context.read<FcsShipmentModel>().ship(_fcsShipment.id!);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
@@ -338,7 +338,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await context.read<FcsShipmentModel>().arrive(_fcsShipment!.id!);
|
await context.read<FcsShipmentModel>().arrive(_fcsShipment.id!);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
@@ -360,7 +360,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await context.read<FcsShipmentModel>().invoice(_fcsShipment!.id!);
|
await context.read<FcsShipmentModel>().invoice(_fcsShipment.id!);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
@@ -376,7 +376,7 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
await context.read<FcsShipmentModel>().cancel(_fcsShipment!.id!);
|
await context.read<FcsShipmentModel>().cancel(_fcsShipment.id!);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
@@ -402,11 +402,11 @@ class _FcsShipmentInfoState extends State<FcsShipmentInfo> {
|
|||||||
} else if (id == 4) {
|
} else if (id == 4) {
|
||||||
reportName = "manifest";
|
reportName = "manifest";
|
||||||
}
|
}
|
||||||
_fcsShipment!.reportName = reportName;
|
_fcsShipment.reportName = reportName;
|
||||||
|
|
||||||
FcsShipmentModel fcsShipmentModel =
|
FcsShipmentModel fcsShipmentModel =
|
||||||
Provider.of<FcsShipmentModel>(context, listen: false);
|
Provider.of<FcsShipmentModel>(context, listen: false);
|
||||||
String url = await fcsShipmentModel.report(_fcsShipment!);
|
String url = await fcsShipmentModel.report(_fcsShipment);
|
||||||
Navigator.of(context).push(CupertinoPageRoute(
|
Navigator.of(context).push(CupertinoPageRoute(
|
||||||
builder: (context) => PDFScreen(
|
builder: (context) => PDFScreen(
|
||||||
title: "",
|
title: "",
|
||||||
|
|||||||
@@ -51,13 +51,13 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
|
|||||||
_newShipment();
|
_newShipment();
|
||||||
},
|
},
|
||||||
icon: Icon(Icons.add),
|
icon: Icon(Icons.add),
|
||||||
label:
|
label: LocalText(context, "FCSshipment.add", color: Colors.white),
|
||||||
LocalText(context, "FCSshipment.add", color: Colors.white),
|
|
||||||
backgroundColor: primaryColor),
|
backgroundColor: primaryColor),
|
||||||
body: PaginatorListView<FcsShipment>(
|
body: PaginatorListView<FcsShipment>(
|
||||||
paginatorListener: shipmentModel.fcsShipments!,
|
paginatorListener: shipmentModel.fcsShipments!,
|
||||||
rowBuilder: (p) => FcsShipmentListRow(shipment: p),
|
rowBuilder: (p) => FcsShipmentListRow(shipment: p),
|
||||||
color: primaryColor)));
|
color: primaryColor),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
_newShipment() {
|
_newShipment() {
|
||||||
@@ -107,7 +107,9 @@ class _FcsShipmentListState extends State<FcsShipmentList> {
|
|||||||
value: choice,
|
value: choice,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Flexible(child: Text("${choice.text}",style: TextStyle(color: Colors.black))),
|
Flexible(
|
||||||
|
child: Text("${choice.text}",
|
||||||
|
style: TextStyle(color: Colors.black))),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
width: 10,
|
width: 10,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import 'package:cloud_firestore/cloud_firestore.dart';
|
|||||||
import 'package:fcs/data/services/services.dart';
|
import 'package:fcs/data/services/services.dart';
|
||||||
import 'package:fcs/constants.dart';
|
import 'package:fcs/constants.dart';
|
||||||
import 'package:fcs/domain/entities/fcs_shipment.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:fcs/pages/main/model/base_model.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
|
|
||||||
|
import '../../../domain/entities/shipment_consignee.dart';
|
||||||
import '../../../domain/entities/shipment_type.dart';
|
import '../../../domain/entities/shipment_type.dart';
|
||||||
import '../../../pagination/paginator_listener.dart';
|
import '../../../pagination/paginator_listener.dart';
|
||||||
|
|
||||||
@@ -17,7 +19,26 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
int selectedIndex = 0;
|
int selectedIndex = 0;
|
||||||
|
|
||||||
List<ShipmentType> shipmentTypes = [];
|
List<ShipmentType> shipmentTypes = [];
|
||||||
|
List<ShipmentConsignee> shipmentConsingees = [];
|
||||||
|
List<ShipmentPort> shipmentPorts = [];
|
||||||
StreamSubscription<QuerySnapshot>? _shipmentTypeListener;
|
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) {
|
onChanged(int index) {
|
||||||
selectedIndex = index;
|
selectedIndex = index;
|
||||||
@@ -39,7 +60,7 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
pageQuery.where("status", isEqualTo: fcs_shipment_pending_status);
|
pageQuery.where("status", isEqualTo: fcs_shipment_pending_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
// processing status
|
// processed status
|
||||||
if (index == 2) {
|
if (index == 2) {
|
||||||
col = col.where("status", isEqualTo: fcs_shipment_processed_status);
|
col = col.where("status", isEqualTo: fcs_shipment_processed_status);
|
||||||
pageQuery =
|
pageQuery =
|
||||||
@@ -74,7 +95,7 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
pageQuery.where("status", isEqualTo: fcs_shipment_canceled_status);
|
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?.close();
|
||||||
fcsShipments = PaginatorListener<FcsShipment>(
|
fcsShipments = PaginatorListener<FcsShipment>(
|
||||||
@@ -87,7 +108,7 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
try {
|
try {
|
||||||
var snaps = await FirebaseFirestore.instance
|
var snaps = await FirebaseFirestore.instance
|
||||||
.collection("/$fcs_shipment_collection")
|
.collection("/$fcs_shipment_collection")
|
||||||
// .where("status", isEqualTo: fcs_shipment_processed_status)
|
.where("status", isEqualTo: fcs_shipment_processed_status)
|
||||||
.get(const GetOptions(source: Source.server));
|
.get(const GetOptions(source: Source.server));
|
||||||
fcsShipments = snaps.docs.map((documentSnapshot) {
|
fcsShipments = snaps.docs.map((documentSnapshot) {
|
||||||
var fcs =
|
var fcs =
|
||||||
@@ -136,14 +157,23 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
|
|
||||||
void initUser(user) {
|
void initUser(user) {
|
||||||
super.initUser(user);
|
super.initUser(user);
|
||||||
|
|
||||||
|
if (user != null && user.hasFcsShipments()) {
|
||||||
_loadShipmentTypes();
|
_loadShipmentTypes();
|
||||||
|
_loadShipmentConsignees();
|
||||||
|
_loadShipmentPorts();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
logout() async {
|
logout() async {
|
||||||
fcsShipments?.close();
|
fcsShipments?.close();
|
||||||
_shipmentTypeListener?.cancel();
|
_shipmentTypeListener?.cancel();
|
||||||
|
_shipmentConsigneeListener?.cancel();
|
||||||
|
_shipmentPortListener?.cancel();
|
||||||
shipmentTypes.clear();
|
shipmentTypes.clear();
|
||||||
|
shipmentConsingees.clear();
|
||||||
|
shipmentPorts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadShipmentTypes() async {
|
Future<void> _loadShipmentTypes() async {
|
||||||
@@ -155,10 +185,52 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
.listen((QuerySnapshot snapshot) {
|
.listen((QuerySnapshot snapshot) {
|
||||||
shipmentTypes.clear();
|
shipmentTypes.clear();
|
||||||
shipmentTypes = snapshot.docs.map((documentSnapshot) {
|
shipmentTypes = snapshot.docs.map((documentSnapshot) {
|
||||||
var privilege = ShipmentType.fromMap(
|
var type = ShipmentType.fromMap(
|
||||||
documentSnapshot.data() as Map<String, dynamic>,
|
documentSnapshot.data() as Map<String, dynamic>,
|
||||||
documentSnapshot.id);
|
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();
|
}).toList();
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
@@ -192,7 +264,7 @@ class FcsShipmentModel extends BaseModel {
|
|||||||
|
|
||||||
Future<void> invoice(String id) {
|
Future<void> invoice(String id) {
|
||||||
return Services.instance.fcsShipmentService
|
return Services.instance.fcsShipmentService
|
||||||
.updateFcsShipmentStatus(id, fcs_shipment_shipped_status);
|
.updateFcsShipmentStatus(id, fcs_shipment_invoiced_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> cancel(String id) {
|
Future<void> cancel(String id) {
|
||||||
|
|||||||
@@ -203,9 +203,27 @@ class _HomePageState extends State<HomePage> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_logoutPinAccount() async {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await context.read<MainModel>().logoutPinAccount();
|
||||||
|
Navigator.pushNamedAndRemoveUntil(context, "/pin_login", (r) => false);
|
||||||
|
} catch (e) {
|
||||||
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
} finally {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
User? user = Provider.of<MainModel>(context).user;
|
var mainModel = context.watch<MainModel>();
|
||||||
|
User? user = mainModel.user;
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
Future.microtask(
|
Future.microtask(
|
||||||
@@ -213,7 +231,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
login = Provider.of<MainModel>(context).isLogin();
|
login = mainModel.isLogin();
|
||||||
LanguageModel languageModel = Provider.of<LanguageModel>(context);
|
LanguageModel languageModel = Provider.of<LanguageModel>(context);
|
||||||
|
|
||||||
final faqBtn = TaskButton("faq.btn",
|
final faqBtn = TaskButton("faq.btn",
|
||||||
@@ -357,7 +375,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
selectedColor: Colors.white,
|
selectedColor: Colors.white,
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Icon(MaterialCommunityIcons.account_tie,size: 25),
|
Icon(MaterialCommunityIcons.account_tie, size: 25),
|
||||||
],
|
],
|
||||||
onPressed: (i) => this.setState(() {
|
onPressed: (i) => this.setState(() {
|
||||||
isFcs[0] = !isFcs[0];
|
isFcs[0] = !isFcs[0];
|
||||||
@@ -390,8 +408,11 @@ class _HomePageState extends State<HomePage> {
|
|||||||
|
|
||||||
final pinLoginBtn = IconButton(
|
final pinLoginBtn = IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context)
|
Navigator.pushAndRemoveUntil(
|
||||||
.push(CupertinoPageRoute(builder: (context) => PinLoginPage()));
|
context,
|
||||||
|
CupertinoPageRoute(
|
||||||
|
builder: (BuildContext context) => PinLoginPage()),
|
||||||
|
(r) => false);
|
||||||
},
|
},
|
||||||
iconSize: 25,
|
iconSize: 25,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
@@ -400,6 +421,19 @@ class _HomePageState extends State<HomePage> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final pinLogoutBtn = IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showConfirmDialog(context, "home.pin.logout.confirm", () async {
|
||||||
|
await _logoutPinAccount();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
iconSize: 25,
|
||||||
|
icon: Icon(
|
||||||
|
MaterialCommunityIcons.lock_open_variant_outline,
|
||||||
|
color: buttonColor,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
var searchInput = Row(children: [
|
var searchInput = Row(children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
@@ -478,7 +512,7 @@ class _HomePageState extends State<HomePage> {
|
|||||||
profileBtn,
|
profileBtn,
|
||||||
]
|
]
|
||||||
: <Widget>[
|
: <Widget>[
|
||||||
pinLoginBtn,
|
mainModel.isPinLogin ? pinLogoutBtn : pinLoginBtn,
|
||||||
fcsToggle,
|
fcsToggle,
|
||||||
profileBtn,
|
profileBtn,
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
|
|
||||||
String? messagingToken;
|
String? messagingToken;
|
||||||
User? user;
|
User? user;
|
||||||
|
User? _fbUser;
|
||||||
PackageInfo? packageInfo;
|
PackageInfo? packageInfo;
|
||||||
|
|
||||||
set setMessaginToken(token) {
|
set setMessaginToken(token) {
|
||||||
@@ -29,6 +30,9 @@ class MainModel extends ChangeNotifier {
|
|||||||
bool isLoaded = false;
|
bool isLoaded = false;
|
||||||
bool isOnline = false;
|
bool isOnline = false;
|
||||||
bool isFirstLaunch = false;
|
bool isFirstLaunch = false;
|
||||||
|
bool isLockOn = false;
|
||||||
|
|
||||||
|
bool get isPinLogin => user?.isPinLogin ?? false;
|
||||||
|
|
||||||
MainModel() {
|
MainModel() {
|
||||||
NetworkConnectivity.instance.statusStream.listen((data) {
|
NetworkConnectivity.instance.statusStream.listen((data) {
|
||||||
@@ -83,6 +87,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
await _listenSetting();
|
await _listenSetting();
|
||||||
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
|
this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
|
||||||
this.packageInfo = await PackageInfo.fromPlatform();
|
this.packageInfo = await PackageInfo.fromPlatform();
|
||||||
|
this.isLockOn = await SharedPref.getPinLockOn() ?? false;
|
||||||
|
|
||||||
userListener?.cancel();
|
userListener?.cancel();
|
||||||
userListener =
|
userListener =
|
||||||
@@ -91,6 +96,17 @@ class MainModel extends ChangeNotifier {
|
|||||||
bool diffPrivilege =
|
bool diffPrivilege =
|
||||||
_user != null && (user == null || user!.diffPrivileges(_user));
|
_user != null && (user == null || user!.diffPrivileges(_user));
|
||||||
bool loggingOut = user != null && _user == null;
|
bool loggingOut = user != null && _user == null;
|
||||||
|
|
||||||
|
if (_user != null) {
|
||||||
|
if (!_user.isPinLogin) {
|
||||||
|
_fbUser = _user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((_fbUser?.id == _user?.id)) {
|
||||||
|
_user?.pinToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
user = _user;
|
user = _user;
|
||||||
|
|
||||||
if (_user != null) {
|
if (_user != null) {
|
||||||
@@ -101,6 +117,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loggingOut) {
|
if (loggingOut) {
|
||||||
for (final m in models) {
|
for (final m in models) {
|
||||||
m.logout();
|
m.logout();
|
||||||
@@ -124,6 +141,7 @@ class MainModel extends ChangeNotifier {
|
|||||||
try {
|
try {
|
||||||
Services.instance.authService.getSetting().listen((event) {
|
Services.instance.authService.getSetting().listen((event) {
|
||||||
this.setting = event;
|
this.setting = event;
|
||||||
|
Services.setting = event;
|
||||||
models.forEach((m) => m.initSetting(setting));
|
models.forEach((m) => m.initSetting(setting));
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
});
|
});
|
||||||
@@ -196,4 +214,13 @@ class MainModel extends ChangeNotifier {
|
|||||||
Future<void> deleteAccount() async {
|
Future<void> deleteAccount() async {
|
||||||
return await Services.instance.authService.deleteAccount();
|
return await Services.instance.authService.deleteAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> pinLogin({required String fcsID, required String pin}) async {
|
||||||
|
await Services.instance.authService
|
||||||
|
.pinLogin(fcsID: fcsID, pin: pin, currentUserId: _fbUser?.id ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> logoutPinAccount() async {
|
||||||
|
await Services.instance.authService.logoutPinAccount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ class _SplashScreenState extends State<SplashScreen> {
|
|||||||
if (mainModel.isFirstLaunch) {
|
if (mainModel.isFirstLaunch) {
|
||||||
page = "/language_selection";
|
page = "/language_selection";
|
||||||
} else if (mainModel.isLogin()) {
|
} else if (mainModel.isLogin()) {
|
||||||
|
if (mainModel.isLockOn) {
|
||||||
|
page = "/pin_login";
|
||||||
|
} else {
|
||||||
page = "/home";
|
page = "/home";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
page = "/welcome";
|
page = "/welcome";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,6 +224,9 @@ class PackageModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Package>> searchPackage(String term) async {
|
Future<List<Package>> searchPackage(String term) async {
|
||||||
|
if (term != '') {
|
||||||
|
await SharedPref.saveRecentSearch('package_search', term);
|
||||||
|
}
|
||||||
Future<List<Package>> packages =
|
Future<List<Package>> packages =
|
||||||
Services.instance.packageService.searchPackage(term);
|
Services.instance.packageService.searchPackage(term);
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ class _PackageInfoState extends State<PackageInfo> {
|
|||||||
if (d == null) return;
|
if (d == null) return;
|
||||||
_changeDeliverayAddress(d);
|
_changeDeliverayAddress(d);
|
||||||
}
|
}
|
||||||
: () {},
|
: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../helpers/shared_pref.dart';
|
||||||
|
import '../widgets/suggest_list.dart';
|
||||||
|
|
||||||
Future<Package?> searchPackage(BuildContext context,
|
Future<Package?> searchPackage(BuildContext context,
|
||||||
{CallbackPackageSelect? callbackPackageSelect}) async =>
|
{CallbackPackageSelect? callbackPackageSelect}) async =>
|
||||||
await showSearch<Package>(
|
await showSearch<Package>(
|
||||||
@@ -22,7 +25,7 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
|
|||||||
PackageSearchDelegate({this.callbackPackageSelect});
|
PackageSearchDelegate({this.callbackPackageSelect});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get searchFieldLabel => 'Search by Tracking ID/Customer Name';
|
String get searchFieldLabel => 'Search by Tracking ID/Customer name';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ThemeData appBarTheme(BuildContext context) {
|
ThemeData appBarTheme(BuildContext context) {
|
||||||
@@ -31,7 +34,7 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
|
|||||||
appBarTheme: AppBarTheme(color: primaryColor),
|
appBarTheme: AppBarTheme(color: primaryColor),
|
||||||
iconButtonTheme: IconButtonThemeData(
|
iconButtonTheme: IconButtonThemeData(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
|
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
||||||
@@ -123,14 +126,29 @@ class PackageSearchDelegate extends SearchDelegate<Package> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildSuggestions(BuildContext context) {
|
Widget buildSuggestions(BuildContext context) {
|
||||||
return Container(
|
return FutureBuilder<List<String>?>(
|
||||||
child: Center(
|
future: SharedPref.getRecentSearch('package_search', query),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
List<String> _oldFilters = snapshot.data ?? [];
|
||||||
|
if (_oldFilters.isEmpty) {
|
||||||
|
return const Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.2,
|
opacity: 0.2,
|
||||||
child: Icon(Octicons.package, size: 200, color: primaryColor)),
|
child: Icon(Octicons.package,
|
||||||
|
color: primaryColor, size: 200),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return SuggestList(
|
||||||
|
recentSearchList: _oldFilters,
|
||||||
|
onTap: (String s) {
|
||||||
|
query = s;
|
||||||
|
showResults(context);
|
||||||
|
},
|
||||||
|
prefKey: 'package_search');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_scan(BuildContext context) async {
|
_scan(BuildContext context) async {
|
||||||
// PermissionStatus permission =
|
// PermissionStatus permission =
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import 'package:fcs/pagination/paginator_listener.dart';
|
|||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:path/path.dart' as Path;
|
import 'package:path/path.dart' as Path;
|
||||||
|
|
||||||
|
import '../../../helpers/shared_pref.dart';
|
||||||
|
|
||||||
class PickupModel extends BaseModel {
|
class PickupModel extends BaseModel {
|
||||||
final log = Logger('PickupModel');
|
final log = Logger('PickupModel');
|
||||||
PaginatorListener<Pickup>? pickups;
|
PaginatorListener<Pickup>? pickups;
|
||||||
@@ -86,6 +88,9 @@ class PickupModel extends BaseModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Pickup>> searchPickup(String term) async {
|
Future<List<Pickup>> searchPickup(String term) async {
|
||||||
|
if (term != '') {
|
||||||
|
await SharedPref.saveRecentSearch('pickup_search', term);
|
||||||
|
}
|
||||||
Future<List<Pickup>> pickups =
|
Future<List<Pickup>> pickups =
|
||||||
Services.instance.pickupService.searchPickup(term);
|
Services.instance.pickupService.searchPickup(term);
|
||||||
return pickups;
|
return pickups;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../helpers/shared_pref.dart';
|
||||||
|
import '../widgets/suggest_list.dart';
|
||||||
|
|
||||||
Future<Pickup?> searchPickup(BuildContext context,
|
Future<Pickup?> searchPickup(BuildContext context,
|
||||||
{CallbackPickupSelect? callbackPickupSelect}) async =>
|
{CallbackPickupSelect? callbackPickupSelect}) async =>
|
||||||
await showSearch<Pickup>(
|
await showSearch<Pickup>(
|
||||||
@@ -32,7 +35,7 @@ class PackageSearchDelegate extends SearchDelegate<Pickup> {
|
|||||||
appBarTheme: AppBarTheme(color: primaryColor),
|
appBarTheme: AppBarTheme(color: primaryColor),
|
||||||
iconButtonTheme: IconButtonThemeData(
|
iconButtonTheme: IconButtonThemeData(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
|
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
||||||
@@ -124,15 +127,29 @@ class PackageSearchDelegate extends SearchDelegate<Pickup> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget buildSuggestions(BuildContext context) {
|
Widget buildSuggestions(BuildContext context) {
|
||||||
return Container(
|
return FutureBuilder<List<String>?>(
|
||||||
child: Center(
|
future: SharedPref.getRecentSearch('pickup_search', query),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
List<String> _oldFilters = snapshot.data ?? [];
|
||||||
|
if (_oldFilters.isEmpty) {
|
||||||
|
return const Center(
|
||||||
child: Opacity(
|
child: Opacity(
|
||||||
opacity: 0.2,
|
opacity: 0.2,
|
||||||
child: Icon(SimpleLineIcons.direction,
|
child: Icon(SimpleLineIcons.direction,
|
||||||
size: 200, color: primaryColor)),
|
color: primaryColor, size: 200),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return SuggestList(
|
||||||
|
recentSearchList: _oldFilters,
|
||||||
|
onTap: (String s) {
|
||||||
|
query = s;
|
||||||
|
showResults(context);
|
||||||
|
},
|
||||||
|
prefKey: 'pickup_search');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
_scan(BuildContext context) async {
|
_scan(BuildContext context) async {
|
||||||
// PermissionStatus permission =
|
// PermissionStatus permission =
|
||||||
|
|||||||
@@ -129,12 +129,17 @@ class _ProfileState extends State<Profile> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final logoutbutton = fcsButton(
|
final logoutbutton =
|
||||||
context, getLocalString(context, "profile.logout"), callack: () {
|
fcsButton(context, getLocalString(context, "profile.logout"),
|
||||||
showConfirmDialog(context, "profile.logout.confirm", () async {
|
callack: mainModel.isPinLogin
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
showConfirmDialog(context, "profile.logout.confirm",
|
||||||
|
() async {
|
||||||
await _logout();
|
await _logout();
|
||||||
});
|
});
|
||||||
}, iconData: Icons.exit_to_app);
|
},
|
||||||
|
iconData: Icons.exit_to_app);
|
||||||
|
|
||||||
return LocalProgress(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
@@ -355,8 +360,12 @@ class _ProfileState extends State<Profile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_showToast(String title) {
|
_showToast(String title) {
|
||||||
final ScaffoldMessengerState scaffold =
|
ScaffoldMessengerState? scaffold = key.currentState;
|
||||||
key.currentState as ScaffoldMessengerState;
|
|
||||||
|
if (scaffold == null) {
|
||||||
|
scaffold = ScaffoldMessenger.of(context);
|
||||||
|
}
|
||||||
|
|
||||||
scaffold.showSnackBar(
|
scaffold.showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('copied "$title" data to clipboard'),
|
content: Text('copied "$title" data to clipboard'),
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import 'package:fcs/pages/main/util.dart';
|
|||||||
import 'package:fcs/pages/widgets/input_text.dart';
|
import 'package:fcs/pages/widgets/input_text.dart';
|
||||||
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
import 'package:fcs/pages/widgets/local_app_bar.dart';
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../widgets/local_text.dart';
|
||||||
import 'model/shipment_rate_model.dart';
|
import 'model/shipment_rate_model.dart';
|
||||||
|
|
||||||
class CargoEditor extends StatefulWidget {
|
class CargoEditor extends StatefulWidget {
|
||||||
@@ -20,11 +22,13 @@ class CargoEditor extends StatefulWidget {
|
|||||||
class _CargoEditorState extends State<CargoEditor> {
|
class _CargoEditorState extends State<CargoEditor> {
|
||||||
TextEditingController _descController = new TextEditingController();
|
TextEditingController _descController = new TextEditingController();
|
||||||
TextEditingController _rateController = new TextEditingController();
|
TextEditingController _rateController = new TextEditingController();
|
||||||
|
TextEditingController _displayIndexController = new TextEditingController();
|
||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
late CargoType _cargo;
|
late CargoType _cargo;
|
||||||
bool _isNew = false;
|
bool _isNew = false;
|
||||||
final _cargoFormKey = GlobalKey<FormState>();
|
final _cargoFormKey = GlobalKey<FormState>();
|
||||||
|
bool _isDefault = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -33,6 +37,8 @@ class _CargoEditorState extends State<CargoEditor> {
|
|||||||
_cargo = widget.cargo!;
|
_cargo = widget.cargo!;
|
||||||
_descController.text = _cargo.name ?? "";
|
_descController.text = _cargo.name ?? "";
|
||||||
_rateController.text = _cargo.rate.toStringAsFixed(2);
|
_rateController.text = _cargo.rate.toStringAsFixed(2);
|
||||||
|
_displayIndexController.text = _cargo.displayIndex.toString();
|
||||||
|
_isDefault = _cargo.isDefault;
|
||||||
} else {
|
} else {
|
||||||
_isNew = true;
|
_isNew = true;
|
||||||
}
|
}
|
||||||
@@ -50,16 +56,19 @@ class _CargoEditorState extends State<CargoEditor> {
|
|||||||
iconData: Icons.text_format,
|
iconData: Icons.text_format,
|
||||||
controller: _descController,
|
controller: _descController,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: (value){
|
validator: (value) {
|
||||||
if(value==null || value.isEmpty){
|
if (value == null || value.isEmpty) {
|
||||||
return "Please insert cargo type";
|
return "Please insert cargo type";
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},);
|
},
|
||||||
|
);
|
||||||
|
|
||||||
final rateBox = InputText(
|
final rateBox = InputText(
|
||||||
labelTextKey: 'cargo.rate',
|
labelTextKey: 'cargo.rate',
|
||||||
iconData: Icons.attach_money,
|
iconData: Icons.attach_money,
|
||||||
controller: _rateController,
|
controller: _rateController,
|
||||||
|
textInputType: TextInputType.number,
|
||||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
@@ -68,6 +77,51 @@ class _CargoEditorState extends State<CargoEditor> {
|
|||||||
return null;
|
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(
|
return LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
@@ -105,6 +159,8 @@ class _CargoEditorState extends State<CargoEditor> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
typeBox,
|
typeBox,
|
||||||
rateBox,
|
rateBox,
|
||||||
|
displayIndexBox,
|
||||||
|
defaultBox,
|
||||||
SizedBox(height: 30),
|
SizedBox(height: 30),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -131,7 +187,12 @@ class _CargoEditorState extends State<CargoEditor> {
|
|||||||
var shipmentRateModel =
|
var shipmentRateModel =
|
||||||
Provider.of<ShipmentRateModel>(context, listen: false);
|
Provider.of<ShipmentRateModel>(context, listen: false);
|
||||||
CargoType _cargo = CargoType(
|
CargoType _cargo = CargoType(
|
||||||
name: _descController.text, rate: double.parse(_rateController.text));
|
name: _descController.text,
|
||||||
|
rate: double.parse(_rateController.text),
|
||||||
|
displayIndex: _displayIndexController.text == ''
|
||||||
|
? 0
|
||||||
|
: int.parse(_displayIndexController.text),
|
||||||
|
isDefault: _isDefault);
|
||||||
if (_isNew) {
|
if (_isNew) {
|
||||||
await shipmentRateModel.addCargoType(_cargo);
|
await shipmentRateModel.addCargoType(_cargo);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import 'package:fcs/helpers/theme.dart';
|
import 'package:fcs/helpers/theme.dart';
|
||||||
|
import 'package:fcs/pages/main/model/language_model.dart';
|
||||||
|
import 'package:fcs/pages/main/model/main_model.dart';
|
||||||
import 'package:fcs/pages/main/util.dart';
|
import 'package:fcs/pages/main/util.dart';
|
||||||
import 'package:fcs/pages/widgets/local_button.dart';
|
import 'package:fcs/pages/widgets/local_button.dart';
|
||||||
import 'package:fcs/pages/widgets/local_text.dart';
|
import 'package:fcs/pages/widgets/local_text.dart';
|
||||||
import 'package:fcs/pages/widgets/progress.dart';
|
import 'package:fcs/pages/widgets/progress.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
import 'package:pin_input_text_field/pin_input_text_field.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
import '../../helpers/shared_pref.dart';
|
||||||
|
import '../../localization/app_translations.dart';
|
||||||
|
|
||||||
class PinLoginPage extends StatefulWidget {
|
class PinLoginPage extends StatefulWidget {
|
||||||
//final User user;
|
|
||||||
const PinLoginPage({super.key});
|
const PinLoginPage({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -18,10 +23,77 @@ class _PinLoginPageState extends State<PinLoginPage> {
|
|||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
String pin = "";
|
String pin = "";
|
||||||
String prefixText = "FCS-";
|
String prefixText = "FCS-";
|
||||||
//late User _user;
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
TextEditingController _fcsIdCtl = new TextEditingController();
|
TextEditingController _fcsIdCtl = new TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_init();
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
_init() async {
|
||||||
|
await SharedPref.setPinLockOn(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> _onWillPop() async {
|
||||||
|
// Show the confirmation dialog
|
||||||
|
return (await showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: Center(
|
||||||
|
child:
|
||||||
|
LocalText(context, 'btn.exit_confirm', color: primaryColor),
|
||||||
|
),
|
||||||
|
content: Container(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: Colors.grey[300],
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5.0))),
|
||||||
|
child: Text(
|
||||||
|
AppTranslations.of(context)!.text('btn.cancel'),
|
||||||
|
style: Provider.of<LanguageModel>(context).isEng
|
||||||
|
? TextStyle(color: primaryColor)
|
||||||
|
: TextStyle(
|
||||||
|
fontFamily: 'Myanmar3', color: primaryColor),
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(false);
|
||||||
|
}),
|
||||||
|
SizedBox(
|
||||||
|
width: 0,
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
backgroundColor: primaryColor,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(5.0))),
|
||||||
|
child: Text(AppTranslations.of(context)!.text('btn.ok'),
|
||||||
|
style: Provider.of<LanguageModel>(context).isEng
|
||||||
|
? TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold)
|
||||||
|
: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
fontFamily: 'Myanmar3')),
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)) ??
|
||||||
|
false;
|
||||||
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final fcsIdBox = TextFormField(
|
final fcsIdBox = TextFormField(
|
||||||
controller: _fcsIdCtl,
|
controller: _fcsIdCtl,
|
||||||
@@ -121,7 +193,11 @@ class _PinLoginPageState extends State<PinLoginPage> {
|
|||||||
callBack: _login,
|
callBack: _login,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return LocalProgress(
|
|
||||||
|
// ignore: deprecated_member_use
|
||||||
|
return WillPopScope(
|
||||||
|
onWillPop: _onWillPop,
|
||||||
|
child: LocalProgress(
|
||||||
inAsyncCall: _isLoading,
|
inAsyncCall: _isLoading,
|
||||||
child: new Scaffold(
|
child: new Scaffold(
|
||||||
body: Form(
|
body: Form(
|
||||||
@@ -157,6 +233,7 @@ class _PinLoginPageState extends State<PinLoginPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,14 +248,14 @@ class _PinLoginPageState extends State<PinLoginPage> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String fcsId = "$prefixText${_fcsIdCtl.text}";
|
String fcsId = "$prefixText${_fcsIdCtl.text}";
|
||||||
print(fcsId);
|
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Navigator.pop(context, true);
|
await context.read<MainModel>().pinLogin(fcsID: fcsId, pin: pin);
|
||||||
|
Navigator.pushNamedAndRemoveUntil(context, "/home", (r) => false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class StaffModel extends BaseModel {
|
|||||||
Future<void> updatePin(
|
Future<void> updatePin(
|
||||||
{required String userID,
|
{required String userID,
|
||||||
required bool enablePin,
|
required bool enablePin,
|
||||||
required int? pin}) async {
|
required String? pin}) async {
|
||||||
await request("/employee/pin", "PUT",
|
await request("/employee/pin", "PUT",
|
||||||
payload: {"id": userID, "enable_pin_login": enablePin, "pin": pin},
|
payload: {"id": userID, "enable_pin_login": enablePin, "pin": pin},
|
||||||
token: await getToken());
|
token: await getToken());
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ class _StaffPinEditorState extends State<StaffPinEditor> {
|
|||||||
await context.read<StaffModel>().updatePin(
|
await context.read<StaffModel>().updatePin(
|
||||||
userID: _staff.id!,
|
userID: _staff.id!,
|
||||||
enablePin: _enablePinLogin,
|
enablePin: _enablePinLogin,
|
||||||
pin: _enablePinLogin ? int.parse(_confirmPin) : null);
|
pin: _enablePinLogin ? _confirmPin : null);
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showMsgDialog(context, "Error", e.toString());
|
showMsgDialog(context, "Error", e.toString());
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class UserSearchDelegate extends SearchDelegate<User> {
|
|||||||
appBarTheme: AppBarTheme(color: primaryColor),
|
appBarTheme: AppBarTheme(color: primaryColor),
|
||||||
iconButtonTheme: IconButtonThemeData(
|
iconButtonTheme: IconButtonThemeData(
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
iconColor: MaterialStateProperty.all<Color>(Colors.white))),
|
iconColor: WidgetStateProperty.all<Color>(Colors.white))),
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
hintStyle: TextStyle(color: Colors.grey, fontSize: 14)),
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
|
import 'package:flutter_slidable/flutter_slidable.dart';
|
||||||
|
|
||||||
import '../helpers/theme.dart';
|
import '../helpers/theme.dart';
|
||||||
import 'paginator_listener.dart';
|
import 'paginator_listener.dart';
|
||||||
@@ -99,7 +100,23 @@ class _PaginatorListViewState<T> extends State<PaginatorListView<T>> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
T t = _paginatorListener.data[index];
|
T t = _paginatorListener.data[index];
|
||||||
return widget.rowBuilder(t);
|
return Slidable(
|
||||||
|
enabled: widget.onRemove != null ? true : false,
|
||||||
|
endActionPane: ActionPane(
|
||||||
|
extentRatio: 0.25,
|
||||||
|
motion: const ScrollMotion(),
|
||||||
|
children: widget.onRemove != null
|
||||||
|
? [
|
||||||
|
SlidableAction(
|
||||||
|
onPressed: ((context) => widget.onRemove!(t)),
|
||||||
|
backgroundColor: Colors.red,
|
||||||
|
icon: Icons.delete,
|
||||||
|
label: 'Delete',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: [],
|
||||||
|
),
|
||||||
|
child: widget.rowBuilder(t));
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ dependencies:
|
|||||||
pdf: ^3.10.8
|
pdf: ^3.10.8
|
||||||
qr_flutter: ^4.1.0
|
qr_flutter: ^4.1.0
|
||||||
flutter_markdown: ^0.6.20+1
|
flutter_markdown: ^0.6.20+1
|
||||||
|
flutter_slidable: ^3.1.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user