Merge branch 'master' of phyothandar/fcs.kl into master

This commit is contained in:
2021-09-10 16:59:30 +00:00
committed by Gogs
236 changed files with 3086 additions and 3036 deletions

View File

@@ -9,7 +9,7 @@ import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/domain/exceiptions/signin_exception.dart'; import 'package:fcs/domain/exceiptions/signin_exception.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:firebase_auth/firebase_auth.dart'; import 'package:firebase_auth/firebase_auth.dart' as fb;
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
class AuthFb { class AuthFb {
@@ -18,17 +18,17 @@ class AuthFb {
static final AuthFb instance = AuthFb._(); static final AuthFb instance = AuthFb._();
AuthFb._(); AuthFb._();
StreamController<User> controller; late StreamController<User?> controller;
static final FirebaseAuth _fb = FirebaseAuth.instance; static final fb.FirebaseAuth _fb = fb.FirebaseAuth.instance;
static String _verificationId; static String _verificationId = '';
Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) { Future<fcs.AuthResult> sendSmsCodeToPhoneNumber(String phoneNumber) {
Completer<fcs.AuthResult> completer = Completer(); Completer<fcs.AuthResult> completer = Completer();
bool codeSentCompleted = false; bool codeSentCompleted = false;
final PhoneVerificationCompleted verificationCompleted = final fb.PhoneVerificationCompleted verificationCompleted =
(AuthCredential credential) async { (fb.AuthCredential credential) async {
AuthResult _authResult; fb.UserCredential _authResult;
try { try {
_authResult = await _fb.signInWithCredential(credential); _authResult = await _fb.signInWithCredential(credential);
print("PhoneVerificationCompleted :$_authResult"); print("PhoneVerificationCompleted :$_authResult");
@@ -48,23 +48,23 @@ class AuthFb {
'Inside _sendCodeToPhoneNumber: signInWithPhoneNumber auto succeeded: ${_authResult.user}'); 'Inside _sendCodeToPhoneNumber: signInWithPhoneNumber auto succeeded: ${_authResult.user}');
}; };
final PhoneVerificationFailed verificationFailed = final fb.PhoneVerificationFailed verificationFailed =
(AuthException authException) async { (fb.FirebaseAuthException authException) async {
print( print(
'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}'); 'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}');
completer.completeError(SigninException( completer.completeError(SigninException(
"Phone number verification failed:${authException.message}")); "Phone number verification failed:${authException.message}"));
}; };
final PhoneCodeSent codeSent = final fb.PhoneCodeSent codeSent =
(String verificationId, [int forceResendingToken]) async { (String verificationId, [int? forceResendingToken]) async {
_verificationId = verificationId; _verificationId = verificationId;
print("codeSent " + phoneNumber); print("codeSent " + phoneNumber);
codeSentCompleted = true; codeSentCompleted = true;
completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT)); completer.complete(fcs.AuthResult(authStatus: AuthStatus.SMS_SENT));
}; };
final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout = final fb.PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
(String verificationId) { (String verificationId) {
print("codeAutoRetrievalTimeout $verificationId "); print("codeAutoRetrievalTimeout $verificationId ");
@@ -89,11 +89,11 @@ class AuthFb {
Future<fcs.AuthResult> signInWithPhoneNumber(String smsCode) async { Future<fcs.AuthResult> signInWithPhoneNumber(String smsCode) async {
try { try {
final AuthCredential credential = PhoneAuthProvider.getCredential( final fb.AuthCredential credential = fb.PhoneAuthProvider.credential(
verificationId: _verificationId, verificationId: _verificationId, smsCode: smsCode);
smsCode: smsCode,
); fb.UserCredential _authResult =
AuthResult _authResult = await _fb.signInWithCredential(credential); await _fb.signInWithCredential(credential);
if (_authResult == null) { if (_authResult == null) {
throw SigninException("Sigin error!"); throw SigninException("Sigin error!");
} }
@@ -105,19 +105,21 @@ class AuthFb {
} }
Future<void> signout() async { Future<void> signout() async {
if (userListener != null) await userListener.cancel(); if (userListener != null) await userListener!.cancel();
return _fb.signOut(); return _fb.signOut();
} }
Future<void> _addUserToStream({bool refreshIdToken = false}) async { Future<void> _addUserToStream({bool refreshIdToken = false}) async {
FirebaseUser firebaseUser = await _fb.currentUser(); fb.User? firebaseUser = _fb.currentUser;
if (firebaseUser == null) return null; if (firebaseUser == null) return null;
Map claims = await getClaims(refreshIdToken: refreshIdToken); Map<dynamic, dynamic>? claims =
await getClaims(refreshIdToken: refreshIdToken);
log.info("Claims:$claims"); log.info("Claims:$claims");
if (claims == null) return;
String cid = claims["cid"]; String cid = claims["cid"];
User user; User? user;
if (cid != null && cid != "") { if (cid != null && cid != "") {
user = await _getUserFromFirestore(cid); user = await _getUserFromFirestore(cid);
} }
@@ -136,20 +138,20 @@ class AuthFb {
controller.add(user); controller.add(user);
} }
Future<User> _getUserFromFirestore(String userID) async { Future<User?> _getUserFromFirestore(String userID) async {
DocumentSnapshot snap = await Firestore.instance DocumentSnapshot snap = await FirebaseFirestore.instance
.collection(user_collection) .collection(user_collection)
.document(userID) .doc(userID)
.get(); .get();
if (snap.exists) { if (snap.exists) {
User user = User.fromMap(snap.data, snap.documentID); User user = User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
return user; return user;
} }
return null; return null;
} }
Future<bool> isLogin() async { Future<bool> isLogin() async {
final FirebaseUser firebaseUser = await _fb.currentUser(); final fb.User? firebaseUser = _fb.currentUser;
return Future.value(firebaseUser != null); return Future.value(firebaseUser != null);
} }
@@ -193,48 +195,50 @@ class AuthFb {
} }
Stream<Setting> settings() async* { Stream<Setting> settings() async* {
Stream<DocumentSnapshot> snapshot = Firestore.instance Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.collection(config_collection) .collection(config_collection)
.document(setting_doc_id) .doc(setting_doc_id)
.snapshots(); .snapshots();
await for (var snap in snapshot) { await for (var snap in snapshot) {
Setting setting = Setting.fromMap(snap.data); Setting setting = Setting.fromMap(snap.data() as Map<String, dynamic>);
yield setting; yield setting;
} }
} }
Future<String> _getCurrentUserID() async { Future<String?> _getCurrentUserID() async {
FirebaseUser firebaseUser = await _fb.currentUser(); fb.User? firebaseUser = _fb.currentUser;
if (firebaseUser == null) return null; if (firebaseUser == null) return null;
Map claims = await getClaims(); Map? claims = await getClaims();
if (claims == null) return null;
String cid = claims["cid"]; String cid = claims["cid"];
return cid; return cid;
} }
Future<void> _startUserListener() async { Future<void> _startUserListener() async {
if (userListener != null) userListener.cancel(); if (userListener != null) userListener!.cancel();
String _userID = await _getCurrentUserID(); String? _userID = await _getCurrentUserID();
if (_userID == null) { if (_userID == null) {
return; return;
} }
Stream<DocumentSnapshot> snapshot = Firestore.instance Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.collection(user_collection) .collection(user_collection)
.document(_userID) .doc(_userID)
.snapshots(); .snapshots();
userListener = snapshot.listen((snap) async { userListener = snapshot.listen((snap) async {
User user = User.fromMap(snap.data, snap.documentID); User user = User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
FirebaseUser firebaseUser = await _fb.currentUser(); fb.User? firebaseUser = _fb.currentUser;
if (firebaseUser == null) { if (firebaseUser == null) {
userListener.cancel(); userListener?.cancel();
return; return;
} }
try { try {
// get privilege from claim // get privilege from claim
IdTokenResult idToken = await firebaseUser.getIdToken(refresh: true); fb.IdTokenResult idToken = await firebaseUser.getIdTokenResult(true);
String privileges = idToken.claims["pr"];
String privileges = idToken.claims?["pr"] ?? '';
if (privileges != null && privileges != "") { if (privileges != null && privileges != "") {
user.privileges = privileges.split(":").toList(); user.privileges = privileges.split(":").toList();
} }
@@ -245,13 +249,13 @@ class AuthFb {
}); });
} }
StreamSubscription<DocumentSnapshot> userListener; StreamSubscription<DocumentSnapshot>? userListener;
Stream<User> user() { Stream<User?> user() {
// ignore: close_sinks // ignore: close_sinks
StreamSubscription<FirebaseUser> authListener; StreamSubscription<fb.User?>? authListener;
Future<void> _start() async { Future<void> _start() async {
authListener = _fb.onAuthStateChanged.listen((firebaseUser) async { authListener = _fb.authStateChanges().listen((firebaseUser) {
if (firebaseUser == null) { if (firebaseUser == null) {
controller.add(null); controller.add(null);
} else { } else {
@@ -263,10 +267,10 @@ class AuthFb {
void _stop() { void _stop() {
if (userListener != null) { if (userListener != null) {
userListener.cancel(); userListener!.cancel();
} }
if (authListener != null) { if (authListener != null) {
authListener.cancel(); authListener!.cancel();
} }
} }

View File

@@ -1,5 +1,4 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/constants.dart';
@@ -36,7 +35,7 @@ class CartonDataProvider {
} }
Future<List<Carton>> searchCarton(String term) async { Future<List<Carton>> searchCarton(String term) async {
if (term == null || term == '') return List(); if (term == null || term == '') return [];
// var bytes = utf8.encode(term); // var bytes = utf8.encode(term);
// var base64Str = base64.encode(bytes); // var base64Str = base64.encode(bytes);
@@ -45,7 +44,7 @@ class CartonDataProvider {
try { try {
String path = "/$cartons_collection"; String path = "/$cartons_collection";
var querySnap = await Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection(path) .collection(path)
.where("carton_number", isEqualTo: term) .where("carton_number", isEqualTo: term)
.where("carton_type", .where("carton_type",
@@ -53,13 +52,11 @@ class CartonDataProvider {
.where("status", isEqualTo: carton_packed_status) .where("status", isEqualTo: carton_packed_status)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.orderBy("user_name") .orderBy("user_name")
.getDocuments(); .get();
return querySnap.documents return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
.map((e) => Carton.fromMap(e.data, e.documentID))
.toList();
} catch (e) { } catch (e) {
log.warning("carton error:" + e.toString()); log.warning("carton error:" + e.toString());
return null; return [];
} }
} }
} }

View File

@@ -56,8 +56,8 @@ class PackageDataProvider {
token: await getToken()); token: await getToken());
} }
Future<List<Package>> ftsSearchPackage(String term) async { Future<List<Package>?> ftsSearchPackage(String term) async {
if (term == null || term == '') return List(); if (term == null || term == '') return [];
var bytes = utf8.encode(term); var bytes = utf8.encode(term);
var base64Str = base64.encode(bytes); var base64Str = base64.encode(bytes);
@@ -72,7 +72,7 @@ class PackageDataProvider {
"/api/fts/$packages_collection/$escapePackage/$limit", "GET", "/api/fts/$packages_collection/$escapePackage/$limit", "GET",
url: Config.instance.reportURL, token: await getToken()); url: Config.instance.reportURL, token: await getToken());
if (data == null) return List(); if (data == null) return [];
data.forEach((p) { data.forEach((p) {
var package = Package.fromJson(p); var package = Package.fromJson(p);
@@ -86,7 +86,7 @@ class PackageDataProvider {
} }
Future<List<Package>> searchPackage(String term) async { Future<List<Package>> searchPackage(String term) async {
if (term == null || term == '') return List(); if (term == null || term == '') return [];
List<Package> packages = []; List<Package> packages = [];

View File

@@ -16,33 +16,33 @@ class RateDataProvider {
static final RateDataProvider instance = RateDataProvider._(); static final RateDataProvider instance = RateDataProvider._();
RateDataProvider._(); RateDataProvider._();
StreamController<Rate> controller; late StreamController<Rate> controller;
static Rate _rate = Rate(); static Rate _rate = Rate();
Stream<Rate> _rateStream() async* { Stream<Rate> _rateStream() async* {
Stream<DocumentSnapshot> snapshot = Firestore.instance Stream<DocumentSnapshot> snapshot = FirebaseFirestore.instance
.collection(config_collection) .collection(config_collection)
.document(rate_doc_id) .doc(rate_doc_id)
.snapshots(); .snapshots();
await for (var snap in snapshot) { await for (var snap in snapshot) {
Rate rate = Rate.fromMap(snap.data); Rate rate = Rate.fromMap(snap.data() as Map<String, dynamic>);
yield rate; yield rate;
} }
} }
Stream<List<CargoType>> _cargoTypeStream() async* { Stream<List<CargoType>> _cargoTypeStream() async* {
List<CargoType> cargoTypes = []; List<CargoType> cargoTypes = [];
Stream<QuerySnapshot> snapshots = Firestore.instance Stream<QuerySnapshot> snapshots = FirebaseFirestore.instance
.collection(config_collection) .collection(config_collection)
.document(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)
.snapshots(); .snapshots();
await for (var snaps in snapshots) { await for (var snaps in snapshots) {
cargoTypes = []; cargoTypes = [];
cargoTypes = snaps.documents.map((snap) { cargoTypes = snaps.docs.map((snap) {
return CargoType.fromMap(snap.data, snap.documentID); return CargoType.fromMap(snap.data() as Map<String, dynamic>, snap.id);
}).toList(); }).toList();
yield cargoTypes; yield cargoTypes;
@@ -51,17 +51,17 @@ class RateDataProvider {
Stream<List<CargoType>> _customDutiesStream() async* { Stream<List<CargoType>> _customDutiesStream() async* {
List<CargoType> customDuries = []; List<CargoType> customDuries = [];
Stream<QuerySnapshot> snapshots = Firestore.instance Stream<QuerySnapshot> snapshots = FirebaseFirestore.instance
.collection(config_collection) .collection(config_collection)
.document(rate_doc_id) .doc(rate_doc_id)
.collection(cargo_types_collection) .collection(cargo_types_collection)
.where("custom_duty", isEqualTo: true) .where("custom_duty", isEqualTo: true)
.snapshots(); .snapshots();
await for (var snaps in snapshots) { await for (var snaps in snapshots) {
customDuries = []; customDuries = [];
customDuries = snaps.documents.map((snap) { customDuries = snaps.docs.map((snap) {
return CargoType.fromMap(snap.data, snap.documentID); return CargoType.fromMap(snap.data() as Map<String, dynamic>, snap.id);
}).toList(); }).toList();
yield customDuries; yield customDuries;
} }
@@ -69,25 +69,26 @@ class RateDataProvider {
Stream<List<DiscountByWeight>> _discountByWeightStream() async* { Stream<List<DiscountByWeight>> _discountByWeightStream() async* {
List<DiscountByWeight> discountByWeight = []; List<DiscountByWeight> discountByWeight = [];
Stream<QuerySnapshot> snapshots = Firestore.instance Stream<QuerySnapshot> snapshots = FirebaseFirestore.instance
.collection(config_collection) .collection(config_collection)
.document(rate_doc_id) .doc(rate_doc_id)
.collection(discounts_by_weights_collection) .collection(discounts_by_weights_collection)
.snapshots(); .snapshots();
await for (var snaps in snapshots) { await for (var snaps in snapshots) {
discountByWeight = []; discountByWeight = [];
discountByWeight = snaps.documents.map((snap) { discountByWeight = snaps.docs.map((snap) {
return DiscountByWeight.fromMap(snap.data, snap.documentID); return DiscountByWeight.fromMap(
snap.data() as Map<String, dynamic>, snap.id);
}).toList(); }).toList();
yield discountByWeight; yield discountByWeight;
} }
} }
StreamSubscription<Rate> rateListener; late StreamSubscription<Rate> rateListener;
StreamSubscription<List<CargoType>> cargoListener; late StreamSubscription<List<CargoType>> cargoListener;
StreamSubscription<List<CargoType>> customListener; late StreamSubscription<List<CargoType>> customListener;
StreamSubscription<List<DiscountByWeight>> discountListener; late StreamSubscription<List<DiscountByWeight>> discountListener;
Stream<Rate> rate() { Stream<Rate> rate() {
Future<void> _start() async { Future<void> _start() async {
rateListener = _rateStream().listen((rate) { rateListener = _rateStream().listen((rate) {

View File

@@ -37,23 +37,23 @@ class UserDataProvider {
payload: {"token": token}, token: await getToken()); payload: {"token": token}, token: await getToken());
} }
Future<User> findUser(String phoneNumber) async { Future<User?> findUser(String phoneNumber) async {
QuerySnapshot querySnap = await Firestore.instance QuerySnapshot querySnap = await FirebaseFirestore.instance
.collection(user_collection) .collection(user_collection)
.where("phone_number", isEqualTo: phoneNumber) .where("phone_number", isEqualTo: phoneNumber)
.limit(1) .limit(1)
.getDocuments(); .get();
if (querySnap.documents.length > 0) { if (querySnap.docs.length > 0) {
var snap = querySnap.documents.first; var snap = querySnap.docs.first;
User user = User.fromMap(snap.data, snap.documentID); User user = User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
return user; return user;
} }
return null; return null;
} }
Future<List<User>> searchUser(String term) async { Future<List<User>> searchUser(String term) async {
if (term == null || term == '') return List(); if (term == null || term == '') return [];
var bytes = utf8.encode(term); var bytes = utf8.encode(term);
var base64Str = base64.encode(bytes); var base64Str = base64.encode(bytes);
@@ -68,7 +68,7 @@ class UserDataProvider {
"/api/fts/$user_collection/$escapeBuyer/$limit", "GET", "/api/fts/$user_collection/$escapeBuyer/$limit", "GET",
url: Config.instance.reportURL, token: await getToken()); url: Config.instance.reportURL, token: await getToken());
if (data == null) return List(); if (data == null) return [];
data.forEach((buyer) { data.forEach((buyer) {
var user = User.fromJson(buyer); var user = User.fromJson(buyer);
@@ -76,7 +76,7 @@ class UserDataProvider {
}); });
} catch (e) { } catch (e) {
log.warning("buyer error:" + e.toString()); log.warning("buyer error:" + e.toString());
return null; // return null;
} }
return users; return users;
} }

View File

@@ -3,17 +3,16 @@ import 'package:fcs/domain/entities/auth_result.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/setting.dart'; import 'package:fcs/domain/entities/setting.dart';
import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/domain/entities/user.dart';
import 'package:flutter/material.dart';
import 'auth_service.dart'; import 'auth_service.dart';
class AuthServiceImp implements AuthService { class AuthServiceImp implements AuthService {
AuthServiceImp({ AuthServiceImp({
@required this.authFb, required this.authFb,
@required this.connectivity, required this.connectivity,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final AuthFb authFb; final AuthFb authFb;
@override @override
@@ -32,7 +31,7 @@ class AuthServiceImp implements AuthService {
} }
@override @override
Stream<User> getUserStream() { Stream<User?> getUserStream() {
return authFb.user(); return authFb.user();
} }

View File

@@ -11,6 +11,6 @@ abstract class AuthService {
Future<void> updateProfileName(String newUserName); Future<void> updateProfileName(String newUserName);
Future<void> updatePreferredCurrency(String currency); Future<void> updatePreferredCurrency(String currency);
Future<bool> hasInvite(); Future<bool> hasInvite();
Stream<User> getUserStream(); Stream<User?> getUserStream();
Stream<Setting> getSetting(); Stream<Setting> getSetting();
} }

View File

@@ -1,17 +1,16 @@
import 'package:fcs/data/provider/carton_data_provider.dart'; import 'package:fcs/data/provider/carton_data_provider.dart';
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:flutter/material.dart';
import 'carton_service.dart'; import 'carton_service.dart';
class CartonServiceImp implements CartonService { class CartonServiceImp implements CartonService {
CartonServiceImp({ CartonServiceImp({
@required this.cartonDataProvider, required this.cartonDataProvider,
@required this.connectivity, required this.connectivity,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final CartonDataProvider cartonDataProvider; final CartonDataProvider cartonDataProvider;
@override @override

View File

@@ -2,13 +2,12 @@ import 'package:fcs/data/provider/common_data_provider.dart';
import 'package:fcs/domain/entities/discount.dart'; import 'package:fcs/domain/entities/discount.dart';
import 'package:fcs/domain/entities/payment_method.dart'; import 'package:fcs/domain/entities/payment_method.dart';
import 'package:fcs/domain/vo/message.dart'; import 'package:fcs/domain/vo/message.dart';
import 'package:flutter/material.dart';
import 'common_service.dart'; import 'common_service.dart';
class CommonServiceImp implements CommonService { class CommonServiceImp implements CommonService {
CommonServiceImp({ CommonServiceImp({
@required this.commonDataProvider, required this.commonDataProvider,
}); });
final CommonDataProvider commonDataProvider; final CommonDataProvider commonDataProvider;

View File

@@ -1,17 +1,16 @@
import 'package:fcs/data/provider/delivery_address_data_provider.dart'; import 'package:fcs/data/provider/delivery_address_data_provider.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/domain/vo/delivery_address.dart';
import 'package:flutter/material.dart';
import 'delivery_address_service.dart'; import 'delivery_address_service.dart';
class DeliveryAddressImp implements DeliveryAddressService { class DeliveryAddressImp implements DeliveryAddressService {
DeliveryAddressImp({ DeliveryAddressImp({
@required this.connectivity, required this.connectivity,
@required this.deliveryAddressDataProvider, required this.deliveryAddressDataProvider,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final DeliveryAddressDataProvider deliveryAddressDataProvider; final DeliveryAddressDataProvider deliveryAddressDataProvider;
@override @override

View File

@@ -1,17 +1,16 @@
import 'package:fcs/data/provider/fcs_shipment_data_provider.dart'; import 'package:fcs/data/provider/fcs_shipment_data_provider.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/fcs_shipment.dart'; import 'package:fcs/domain/entities/fcs_shipment.dart';
import 'package:flutter/material.dart';
import 'fcs_shipment_service.dart'; import 'fcs_shipment_service.dart';
class FcsShipmentServiceImp implements FcsShipmentService { class FcsShipmentServiceImp implements FcsShipmentService {
FcsShipmentServiceImp({ FcsShipmentServiceImp({
@required this.connectivity, required this.connectivity,
@required this.shipmentDataProvider, required this.shipmentDataProvider,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final FcsShipmentDataProvider shipmentDataProvider; final FcsShipmentDataProvider shipmentDataProvider;
@override @override

View File

@@ -1,21 +1,17 @@
import 'package:fcs/data/provider/invoice_data_provider.dart'; import 'package:fcs/data/provider/invoice_data_provider.dart';
import 'package:fcs/data/provider/shipment_data_provider.dart';
import 'package:fcs/data/services/shipment_service.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/invoice.dart'; import 'package:fcs/domain/entities/invoice.dart';
import 'package:fcs/domain/entities/payment.dart'; import 'package:fcs/domain/entities/payment.dart';
import 'package:fcs/domain/entities/shipment.dart';
import 'package:flutter/material.dart';
import 'invoice_service.dart'; import 'invoice_service.dart';
class InvoiceServiceImp implements InvoiceService { class InvoiceServiceImp implements InvoiceService {
InvoiceServiceImp({ InvoiceServiceImp({
@required this.invoiceDataProvider, required this.invoiceDataProvider,
@required this.connectivity, required this.connectivity,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final InvoiceDataProvider invoiceDataProvider; final InvoiceDataProvider invoiceDataProvider;
@override @override

View File

@@ -1,17 +1,16 @@
import 'package:fcs/data/provider/package_data_provider.dart'; import 'package:fcs/data/provider/package_data_provider.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/package.dart';
import 'package:flutter/material.dart';
import 'package_service.dart'; import 'package_service.dart';
class PackageServiceImp implements PackageService { class PackageServiceImp implements PackageService {
PackageServiceImp({ PackageServiceImp({
@required this.connectivity, required this.connectivity,
@required this.packageDataProvider, required this.packageDataProvider,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final PackageDataProvider packageDataProvider; final PackageDataProvider packageDataProvider;
@override @override
@@ -30,7 +29,7 @@ class PackageServiceImp implements PackageService {
} }
@override @override
Future<List<Package>> ftsSearchPackage(String term) { Future<List<Package>?> ftsSearchPackage(String term) {
return packageDataProvider.ftsSearchPackage(term); return packageDataProvider.ftsSearchPackage(term);
} }

View File

@@ -7,7 +7,7 @@ abstract class PackageService {
Future<void> deleteReceiving(Package package); Future<void> deleteReceiving(Package package);
Future<void> updateProcessing(Package package); Future<void> updateProcessing(Package package);
Future<void> deleteProcessing(Package package); Future<void> deleteProcessing(Package package);
Future<List<Package>> ftsSearchPackage(String term); Future<List<Package>?> ftsSearchPackage(String term);
Future<List<Package>> searchPackage(String term); Future<List<Package>> searchPackage(String term);
Future<void> changeDeliveryAddress(String packageID, String deliveryID); Future<void> changeDeliveryAddress(String packageID, String deliveryID);
Future<void> packageReturn(String packageID); Future<void> packageReturn(String packageID);

View File

@@ -4,17 +4,16 @@ import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'package:fcs/domain/entities/discount_by_weight.dart';
import 'package:fcs/domain/entities/custom_duty.dart'; import 'package:fcs/domain/entities/custom_duty.dart';
import 'package:fcs/domain/entities/rate.dart'; import 'package:fcs/domain/entities/rate.dart';
import 'package:flutter/material.dart';
import 'rate_service.dart'; import 'rate_service.dart';
class RateServiceImp implements RateService { class RateServiceImp implements RateService {
RateServiceImp({ RateServiceImp({
@required this.rateDataProvider, required this.rateDataProvider,
@required this.connectivity, required this.connectivity,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final RateDataProvider rateDataProvider; final RateDataProvider rateDataProvider;
@override @override

View File

@@ -35,17 +35,18 @@ import 'user_service.dart';
class Services { class Services {
static final Services instance = Services._(); static final Services instance = Services._();
AuthService _authService; late AuthService _authService;
UserService _userService; late UserService _userService;
PackageService _packageService; late PackageService _packageService;
MessagingService _messagingService; late MessagingService _messagingService;
CommonService _commonService; late CommonService _commonService;
FcsShipmentService _fcsShipmentService; late FcsShipmentService _fcsShipmentService;
DeliveryAddressService _deliveryAddressService; late DeliveryAddressService _deliveryAddressService;
RateService _rateService; late RateService _rateService;
ShipmentService _shipmentService; late ShipmentService _shipmentService;
CartonService _cartonService; late CartonService _cartonService;
InvoiceService _invoiceService; late InvoiceService _invoiceService;
Services._() { Services._() {
_authService = AuthServiceImp( _authService = AuthServiceImp(
authFb: AuthFb.instance, authFb: AuthFb.instance,

View File

@@ -2,15 +2,14 @@ import 'package:fcs/data/provider/shipment_data_provider.dart';
import 'package:fcs/data/services/shipment_service.dart'; import 'package:fcs/data/services/shipment_service.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/domain/entities/shipment.dart';
import 'package:flutter/material.dart';
class ShipmentServiceImp implements ShipmentService { class ShipmentServiceImp implements ShipmentService {
ShipmentServiceImp({ ShipmentServiceImp({
@required this.shipmentDataProvider, required this.shipmentDataProvider,
@required this.connectivity, required this.connectivity,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final ShipmentDataProvider shipmentDataProvider; final ShipmentDataProvider shipmentDataProvider;
@override @override

View File

@@ -1,17 +1,16 @@
import 'package:fcs/data/provider/user_data_provider.dart'; import 'package:fcs/data/provider/user_data_provider.dart';
import 'package:fcs/domain/entities/connectivity.dart'; import 'package:fcs/domain/entities/connectivity.dart';
import 'package:fcs/domain/entities/user.dart'; import 'package:fcs/domain/entities/user.dart';
import 'package:flutter/material.dart';
import 'user_service.dart'; import 'user_service.dart';
class UserServiceImp implements UserService { class UserServiceImp implements UserService {
UserServiceImp({ UserServiceImp({
@required this.connectivity, required this.connectivity,
@required this.userDataProvider, required this.userDataProvider,
}); });
final Connectivity connectivity; final Connectivity? connectivity;
final UserDataProvider userDataProvider; final UserDataProvider userDataProvider;
@override @override
@@ -30,7 +29,7 @@ class UserServiceImp implements UserService {
} }
@override @override
Future<User> findUser(String phoneNumber) { Future<User?> findUser(String phoneNumber) {
return userDataProvider.findUser(phoneNumber); return userDataProvider.findUser(phoneNumber);
} }

View File

@@ -4,7 +4,7 @@ abstract class UserService {
Future<void> inviteUser(String userName, String phoneNumber); Future<void> inviteUser(String userName, String phoneNumber);
Future<void> deleteInvite(String phoneNumber); Future<void> deleteInvite(String phoneNumber);
Future<void> acceptRequest(String userID); Future<void> acceptRequest(String userID);
Future<User> findUser(String phoneNumber); Future<User?> findUser(String phoneNumber);
Future<List<User>> searchUser(String term); Future<List<User>> searchUser(String term);
Future<void> uploadMsgToken(String token); Future<void> uploadMsgToken(String token);
Future<void> removeMsgToken(String token); Future<void> removeMsgToken(String token);

View File

@@ -1,9 +1,9 @@
import 'auth_status.dart'; import 'auth_status.dart';
class AuthResult { class AuthResult {
AuthStatus authStatus; AuthStatus? authStatus;
String authErrorCode; String? authErrorCode;
String authErrorMsg; String? authErrorMsg;
AuthResult({this.authStatus, this.authErrorCode, this.authErrorMsg}); AuthResult({this.authStatus, this.authErrorCode, this.authErrorMsg});
} }

View File

@@ -1,28 +1,28 @@
class CargoType { class CargoType {
String id; String? id;
String name; String? name;
double rate; double rate;
double weight; double weight;
bool isChecked; bool isChecked;
int qty; int qty;
bool isCutomDuty; bool? isCutomDuty;
double customDutyFee; double customDutyFee;
double get calAmount => (calRate ?? 0) * (calWeight ?? 0);
double calRate; double calRate;
double calWeight; double calWeight;
double get calAmount => calRate * calWeight;
CargoType( CargoType(
{this.id, {this.id,
this.name, this.name,
this.rate, this.rate = 0,
this.weight, this.weight = 0,
this.calWeight, this.calWeight = 0,
this.calRate, this.calRate = 0,
this.isChecked = false, this.isChecked = false,
this.qty = 0, this.qty = 0,
this.isCutomDuty, this.isCutomDuty,
this.customDutyFee}); this.customDutyFee = 0});
factory CargoType.fromMap(Map<String, dynamic> map, String id) { factory CargoType.fromMap(Map<String, dynamic> map, String id) {
return CargoType( return CargoType(
@@ -52,7 +52,7 @@ class CargoType {
} }
CargoType clone() { CargoType clone() {
return CargoType.fromMap(toMap(), this.id); return CargoType.fromMap(toMap(), this.id!);
} }
@override @override
@@ -63,7 +63,7 @@ class CargoType {
@override @override
String toString() { String toString() {
return name; return name ?? "";
} }
bool isChangedForEdit(CargoType cargoType) { bool isChangedForEdit(CargoType cargoType) {

View File

@@ -9,64 +9,64 @@ import 'cargo_type.dart';
import 'package.dart'; import 'package.dart';
class Carton { class Carton {
String id; String? id;
String shipmentID; String? shipmentID;
String shipmentNumber; String? shipmentNumber;
String senderID; String? senderID;
String senderFCSID; String? senderFCSID;
String senderName; String? senderName;
String boxNumber; String? boxNumber;
String status; String? status;
String cargoDesc; String? cargoDesc;
String desc; String? desc;
double width; double width;
double height; double height;
double length; double length;
int shipmentWeight; int? shipmentWeight;
bool isChecked; bool? isChecked;
bool isShipmentCarton; bool? isShipmentCarton;
String cartonType; String? cartonType;
String fcsID; String? fcsID;
String userName; String? userName;
String userID; String? userID;
String fcsShipmentID; String? fcsShipmentID;
String fcsShipmentNumber; String? fcsShipmentNumber;
String mixCartonID; String? mixCartonID;
String mixCartonNumber; String? mixCartonNumber;
String cartonSizeID; String? cartonSizeID;
String cartonSizeName; String? cartonSizeName;
double cartonWeight; double? cartonWeight;
int rate; int rate;
int weight; int weight;
String packageType; String? packageType;
String pickUpID; String? pickUpID;
List<String> photos; List<String> photos = [];
String remark; String? remark;
DateTime arrivedDate; DateTime? arrivedDate;
String cartonNumber; String? cartonNumber;
List<String> packageIDs; List<String> packageIDs;
List<Package> packages; List<Package> packages;
List<CargoType> cargoTypes; List<CargoType> cargoTypes = [];
DeliveryAddress deliveryAddress; DeliveryAddress? deliveryAddress;
Shipment shipment; Shipment? shipment;
//for mix box //for mix box
String mixBoxType; String? mixBoxType;
List<Carton> mixCartons; List<Carton> mixCartons;
List<String> mixCartonIDs; List<String> mixCartonIDs;
int get amount => rate != null && weight != null ? rate * weight : 0; int get amount => rate != null && weight != null ? (rate * weight) : 0;
// String get packageNumber => // String get packageNumber =>
// shipmentNumber + "-" + receiverNumber + " #" + boxNumber; // shipmentNumber + "-" + receiverNumber + " #" + boxNumber;
double get price => rate.toDouble() * weight;
double get actualWeight => double get actualWeight => cargoTypes == null
cargoTypes == null ? 0 : cargoTypes.fold(0, (p, e) => e.weight + p); ? 0
: cargoTypes.fold(0, (p, e) => e.weight + p);
int getShipmentWeight(double volumetricRatio) { int getShipmentWeight(double volumetricRatio) {
if (length == null || if (length == null ||
@@ -84,15 +84,15 @@ class Carton {
/// getCargoTypeForCalWeight returns carton with shipment weight /// getCargoTypeForCalWeight returns carton with shipment weight
List<CargoType> getCargoTypeForCalWeight(double volumetricRatio) { List<CargoType> getCargoTypeForCalWeight(double volumetricRatio) {
// get shipment weight // get shipment weight
double volume = (length ?? 0) * (width ?? 0) * (height ?? 0); double volume = length * width * height;
double sw = volume / volumetricRatio ?? 0; double sw = volume / volumetricRatio;
// get actual weight // get actual weight
double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight); double aw = cargoTypes.fold(0.0, (p, c) => p + c.weight);
if (aw == 0 || sw == 0) return []; if (aw == 0 || sw == 0) return [];
cargoTypes.forEach((e) { cargoTypes.forEach((e) {
double calWeight = aw > sw ? e.weight : e.weight / aw * sw; double calWeight = aw > sw ? e.weight : (e.weight / aw) * sw;
e.calWeight = calWeight; e.calWeight = calWeight;
}); });
return cargoTypes; return cargoTypes;
@@ -115,8 +115,8 @@ class Carton {
double total = 0; double total = 0;
cargoTypes.forEach((e) { cargoTypes.forEach((e) {
double r = double r = e.rate -
e.rate - (discountByWeight != null ? discountByWeight.discount : 0); (discountByWeight != null ? (discountByWeight.discount) : 0);
double amount = e.weight * r; double amount = e.weight * r;
total += amount; total += amount;
}); });
@@ -134,9 +134,9 @@ class Carton {
this.senderName, this.senderName,
this.boxNumber, this.boxNumber,
this.desc, this.desc,
this.width, this.width = 0,
this.height, this.height = 0,
this.length, this.length = 0,
this.shipmentWeight, this.shipmentWeight,
this.isChecked = false, this.isChecked = false,
this.cartonType, this.cartonType,
@@ -151,13 +151,13 @@ class Carton {
this.status, this.status,
this.arrivedDate, this.arrivedDate,
this.cargoDesc, this.cargoDesc,
this.shipmentHistory, this.shipmentHistory = const [],
this.packages, this.packages = const [],
this.cargoTypes, this.cargoTypes = const [],
this.cartonNumber, this.cartonNumber,
this.fcsShipmentID, this.fcsShipmentID,
this.fcsShipmentNumber, this.fcsShipmentNumber,
this.packageIDs, this.packageIDs = const [],
this.mixCartonID, this.mixCartonID,
this.mixCartonNumber, this.mixCartonNumber,
this.isShipmentCarton = false, this.isShipmentCarton = false,
@@ -165,14 +165,14 @@ class Carton {
this.cartonSizeID, this.cartonSizeID,
this.cartonSizeName, this.cartonSizeName,
this.mixBoxType, this.mixBoxType,
this.mixCartons, this.mixCartons = const [],
this.mixCartonIDs, this.mixCartonIDs = const [],
this.cartonWeight}); this.cartonWeight});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
List _cargoTypes = cargoTypes?.map((c) => c.toMap())?.toList() ?? []; List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
List _packages = packages?.map((c) => c.toJson())?.toList(); List _packages = packages.map((c) => c.toJson()).toList();
List _mixCartons = mixCartons?.map((c) => c.toJson())?.toList(); List _mixCartons = mixCartons.map((c) => c.toJson()).toList();
return { return {
'id': id, 'id': id,
'fcs_shipment_id': fcsShipmentID, 'fcs_shipment_id': fcsShipmentID,
@@ -213,9 +213,9 @@ class Carton {
shipmentNumber: map['shipment_number'], shipmentNumber: map['shipment_number'],
// receiverNumber: map['receiver_number'], // receiverNumber: map['receiver_number'],
boxNumber: map['box_number'], boxNumber: map['box_number'],
length: double.tryParse(map['length']?.toString()), length: double.tryParse(map['length'].toString()) ?? 0,
width: double.tryParse(map['width']?.toString()), width: double.tryParse(map['width'].toString()) ?? 0,
height: double.tryParse(map['height']?.toString()), height: double.tryParse(map['height'].toString()) ?? 0,
userName: map['user_name'], userName: map['user_name'],
fcsID: map['fcs_id'], fcsID: map['fcs_id'],
cartonType: map['carton_type'], cartonType: map['carton_type'],
@@ -242,8 +242,8 @@ class Carton {
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
List _packages = packages?.map((c) => c.toJson())?.toList(); List _packages = packages.map((c) => c.toJson()).toList();
List _mixCartons = mixCartons?.map((c) => c.toJson())?.toList(); List _mixCartons = mixCartons.map((c) => c.toJson()).toList();
return { return {
'id': id, 'id': id,
'fcs_shipment_id': fcsShipmentID, 'fcs_shipment_id': fcsShipmentID,

View File

@@ -1,10 +1,11 @@
class CartonSize { class CartonSize {
String id; String? id;
String name; String? name;
double length; double length;
double width; double width;
double height; double height;
CartonSize({this.id, this.name, this.length, this.width, this.height}); CartonSize(
{this.id, this.name, this.length = 0, this.width = 0, this.height = 0});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {
@@ -27,19 +28,10 @@ class CartonSize {
} }
@override @override
bool operator ==(other) { bool operator ==(Object other) => other is CartonSize && other.id == id;
if (identical(this, other)) {
return true;
}
return other.id == this.id;
}
@override @override
int get hashCode { int get hashCode => id.hashCode;
int result = 17;
result = 37 * result + id.hashCode;
return result;
}
bool isChangedForEdit(CartonSize cartonSize) { bool isChangedForEdit(CartonSize cartonSize) {
return cartonSize.name != this.name || return cartonSize.name != this.name ||

View File

@@ -1,11 +1,15 @@
class CustomDuty { class CustomDuty {
String id; String? id;
String productType; String? productType;
String desc; String? desc;
double fee; double fee;
double shipmentRate; double shipmentRate;
CustomDuty( CustomDuty(
{this.id, this.productType, this.desc, this.fee, this.shipmentRate}); {this.id,
this.productType,
this.desc,
this.fee = 0,
this.shipmentRate = 0});
factory CustomDuty.fromMap(Map<String, dynamic> map, String id) { factory CustomDuty.fromMap(Map<String, dynamic> map, String id) {
return CustomDuty( return CustomDuty(

View File

@@ -1,10 +1,8 @@
class Customer { class Customer {
String id; String? id;
String name; String? name;
String phoneNumber; String? phoneNumber;
String status; String? status;
Customer({ Customer({
this.id, this.id,

View File

@@ -1,9 +1,9 @@
class Discount { class Discount {
String id; String? id;
String code; String? code;
String customerId; String? customerId;
String customerName; String? customerName;
String status; String? status;
double amount; double amount;
Discount({ Discount({
@@ -11,7 +11,7 @@ class Discount {
this.code, this.code,
this.customerId, this.customerId,
this.customerName, this.customerName,
this.amount, this.amount = 0,
this.status, this.status,
}); });

View File

@@ -1,9 +1,9 @@
class DiscountByWeight { class DiscountByWeight {
String id; String? id;
double weight; double weight;
double discount; double discount;
DiscountByWeight({this.id, this.weight, this.discount}); DiscountByWeight({this.id, this.weight = 0, this.discount = 0});
factory DiscountByWeight.fromMap(Map<String, dynamic> map, String id) { factory DiscountByWeight.fromMap(Map<String, dynamic> map, String id) {
return DiscountByWeight( return DiscountByWeight(

View File

@@ -1,16 +1,17 @@
class FAQ { class FAQ {
String id; String? id;
int sn; int? sn;
String questionEng; String? questionEng;
String questionMm; String? questionMm;
String answerEng; String? answerEng;
String answerMm; String? answerMm;
String pageLinkLabelEng; String? pageLinkLabelEng;
String pageLinkLabelMm; String? pageLinkLabelMm;
String pageLink; String? pageLink;
String question(bool isEng) => isEng ? questionEng : questionMm; String question(bool isEng) =>
String answer(bool isEng) => isEng ? answerEng : answerMm; isEng ? (questionEng ?? "") : (questionMm ?? "");
String answer(bool isEng) => isEng ? (answerEng ?? "") : (answerMm ?? "");
FAQ( FAQ(
{this.id, {this.id,

View File

@@ -3,17 +3,18 @@ import 'package:cloud_firestore/cloud_firestore.dart';
import '../constants.dart'; import '../constants.dart';
class FcsShipment { class FcsShipment {
String id; String? id;
String shipmentNumber; String? shipmentNumber;
DateTime cutoffDate; DateTime? cutoffDate;
String shipType; String? shipType;
DateTime arrivalDate; DateTime? arrivalDate;
DateTime departureDate; DateTime? departureDate;
String consignee; String? consignee;
String port; String? port;
String destination; String? destination;
String status; String? status;
String reportName; String? reportName;
FcsShipment({ FcsShipment({
this.id, this.id,
this.shipmentNumber, this.shipmentNumber,
@@ -51,10 +52,10 @@ class FcsShipment {
return { return {
"id": id, "id": id,
'shipment_number': shipmentNumber, 'shipment_number': shipmentNumber,
'cutoff_date': cutoffDate?.toUtc()?.toIso8601String(), 'cutoff_date': cutoffDate?.toUtc().toIso8601String(),
'shipment_type': shipType, 'shipment_type': shipType,
'arrival_date': arrivalDate?.toUtc()?.toIso8601String(), 'arrival_date': arrivalDate?.toUtc().toIso8601String(),
'departure_date': departureDate?.toUtc()?.toIso8601String(), 'departure_date': departureDate?.toUtc().toIso8601String(),
'consignee': consignee, 'consignee': consignee,
'port': port, 'port': port,
'destination': destination, 'destination': destination,

View File

@@ -10,15 +10,15 @@ import 'package:fcs/domain/entities/rate.dart';
import 'package:fcs/domain/entities/shipment.dart'; import 'package:fcs/domain/entities/shipment.dart';
class Invoice { class Invoice {
String id; String? id;
String invoiceNumber; String? invoiceNumber;
DateTime invoiceDate; DateTime? invoiceDate;
String fcsShipmentID; String? fcsShipmentID;
String userID; String? userID;
String fcsID; String? fcsID;
String userName; String? userName;
String phoneNumber; String? phoneNumber;
String status; String? status;
double handlingFee; double handlingFee;
double deliveryFee; double deliveryFee;
@@ -28,11 +28,11 @@ class Invoice {
List<CustomDuty> customDuties; List<CustomDuty> customDuties;
List<Carton> cartons; List<Carton> cartons;
List<CargoType> cargoTypes; List<CargoType> cargoTypes;
List<Shipment> shipments; List<Shipment?>? shipments;
List<Payment> payments; List<Payment> payments;
Discount discount; Discount? discount;
PaymentMethod paymentMethod; PaymentMethod? paymentMethod;
String invoiceURL; String? invoiceURL;
List<CargoType> getCargoTypes(Rate rate) { List<CargoType> getCargoTypes(Rate rate) {
if (cargoTypes != null) return cargoTypes; if (cargoTypes != null) return cargoTypes;
@@ -40,7 +40,7 @@ class Invoice {
List<CargoType> _cargoTypes = []; List<CargoType> _cargoTypes = [];
double totalCalWeight = 0; double totalCalWeight = 0;
cartons.forEach((carton) { cartons.forEach((carton) {
if (carton.isChecked) { if (carton.isChecked ?? false) {
var _cartonsTypes = var _cartonsTypes =
carton.getCargoTypeForCalWeight(rate.volumetricRatio); carton.getCargoTypeForCalWeight(rate.volumetricRatio);
_cartonsTypes.forEach((ct) { _cartonsTypes.forEach((ct) {
@@ -68,15 +68,15 @@ class Invoice {
double getTotal(Rate rate) { double getTotal(Rate rate) {
List<CargoType> cargoTypes = getCargoTypes(rate); List<CargoType> cargoTypes = getCargoTypes(rate);
var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); double total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p);
return total; return total;
} }
double get balance => (amount ?? 0) - (paidAmount ?? 0); double get balance => amount - paidAmount;
double getNetAmount(Rate rate) { double getNetAmount(Rate rate) {
List<CargoType> cargoTypes = getCargoTypes(rate); List<CargoType> cargoTypes = getCargoTypes(rate);
var total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p); double total = cargoTypes.fold(0.0, (p, c) => c.calAmount + p);
total += getCustomFee(); total += getCustomFee();
total += getDeliveryFee(); total += getDeliveryFee();
total += getHandlingFee(); total += getHandlingFee();
@@ -85,13 +85,13 @@ class Invoice {
} }
double getHandlingFee() { double getHandlingFee() {
return shipments?.where((sh) => sh.isSelected ?? false)?.fold(0, (p, s) { return shipments!
return p + (s?.handlingFee ?? 0) - (s?.paidHandlingFee ?? 0); .where((sh) => sh!.isSelected)
}); .fold(0, (p, s) => p + (s!.handlingFee - s.paidHandlingFee));
} }
double getTotalBalance(Rate rate) { double getTotalBalance(Rate rate) {
return getNetAmount(rate) - (paidAmount ?? 0); return getNetAmount(rate) - paidAmount;
} }
double getCustomFee() { double getCustomFee() {
@@ -102,7 +102,7 @@ class Invoice {
return deliveryFee == null ? 0 : deliveryFee; return deliveryFee == null ? 0 : deliveryFee;
} }
double getDiscount() => discount == null ? 0 : discount.amount; double getDiscount() => discount == null ? 0 : discount!.amount;
Invoice( Invoice(
{this.id, {this.id,
@@ -111,19 +111,19 @@ class Invoice {
this.fcsID, this.fcsID,
this.userName, this.userName,
this.phoneNumber, this.phoneNumber,
this.amount, this.amount = 0,
this.paidAmount, this.paidAmount = 0,
this.discount, this.discount,
this.status, this.status,
this.customDuties, this.customDuties = const [],
this.cartons, this.cartons = const [],
this.cargoTypes, this.cargoTypes = const [],
this.handlingFee, this.handlingFee = 0,
this.deliveryFee, this.deliveryFee = 0,
this.fcsShipmentID, this.fcsShipmentID,
this.shipments, this.shipments = const [],
this.invoiceURL, this.invoiceURL,
this.payments, this.payments = const [],
this.paymentMethod}); this.paymentMethod});
factory Invoice.fromMap(Map<String, dynamic> map, String docID) { factory Invoice.fromMap(Map<String, dynamic> map, String docID) {
@@ -153,7 +153,7 @@ class Invoice {
return Invoice( return Invoice(
id: docID, id: docID,
invoiceNumber: map['invoice_number'], invoiceNumber: map['invoice_number'],
invoiceDate: invd?.toDate(), invoiceDate: invd.toDate(),
userName: map['user_name'], userName: map['user_name'],
fcsID: map['fcs_id'], fcsID: map['fcs_id'],
phoneNumber: map['phone_number'], phoneNumber: map['phone_number'],
@@ -174,12 +174,12 @@ class Invoice {
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList(); List _cargoTypes = cargoTypes.map((c) => c.toMap()).toList();
List _customDuties = customDuties?.map((c) => c.toMap())?.toList(); List _customDuties = customDuties.map((c) => c.toMap()).toList();
List _cartons = cartons?.map((c) => c.toMap())?.toList() ?? []; List _cartons = cartons.map((c) => c.toMap()).toList();
List _shipments = shipments?.map((s) => s.toMap())?.toList() ?? []; List _shipments = shipments!.map((s) => s!.toMap()).toList();
return { return {
"id": id, "id": id,
"invoice_date": invoiceDate?.toUtc()?.toIso8601String(), "invoice_date": invoiceDate?.toUtc().toIso8601String(),
"user_id": userID, "user_id": userID,
"user_name": userName, "user_name": userName,
"invoice_number": invoiceNumber, "invoice_number": invoiceNumber,

View File

@@ -1,11 +1,8 @@
class Market { class Market {
String id; String? id;
String name; String? name;
Market({ Market({this.id, this.name});
this.id,
this.name,
});
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
return { return {

View File

@@ -5,72 +5,71 @@ import 'package:fcs/domain/vo/delivery_address.dart';
import 'package:fcs/domain/vo/shipment_status.dart'; import 'package:fcs/domain/vo/shipment_status.dart';
class Package { class Package {
String id; String? id;
String trackingID; String? trackingID;
String userID; String? userID;
String fcsID; String? fcsID;
String userName; String? userName;
String phoneNumber; String? phoneNumber;
DateTime currentStatusDate; DateTime? currentStatusDate;
List<String> photoUrls; List<String> photoUrls;
List<ShipmentStatus> shipmentHistory; List<ShipmentStatus> shipmentHistory;
String desc; String? desc;
String status; String? status;
String shipmentNumber; String? shipmentNumber;
String senderFCSID; String? senderFCSID;
String senderName; String? senderName;
String senderPhoneNumber; String? senderPhoneNumber;
String boxNumber; String? boxNumber;
String cargoDesc; String? cargoDesc;
String market; String? market;
bool isChecked; bool isChecked;
int rate; int rate;
int weight; int weight;
String packageType; String? packageType;
String pickUpID; String? pickUpID;
List<String> photos; // List<String> photos;
String remark; String? remark;
DateTime arrivedDate; DateTime? arrivedDate;
DeliveryAddress deliveryAddress; DeliveryAddress? deliveryAddress;
//for packages in processing //for packages in processing
List<File> photoFiles; List<File?> photoFiles;
int get amount => rate != null && weight != null ? rate * weight : 0; int get amount => rate != null && weight != null ? rate * weight : 0;
double get price => rate.toDouble() * weight; double get price => rate.toDouble() * weight;
Package({ Package(
this.id, {this.id,
this.trackingID, this.trackingID,
this.userID, this.userID,
this.userName, this.userName,
this.fcsID, this.fcsID,
this.phoneNumber, this.phoneNumber,
this.shipmentNumber, this.shipmentNumber,
this.senderFCSID, this.senderFCSID,
this.senderName, this.senderName,
this.boxNumber, this.boxNumber,
this.rate, this.rate = 0,
this.weight, this.weight = 0,
this.packageType, this.packageType,
this.pickUpID, this.pickUpID,
this.remark, this.remark,
this.status, this.status,
this.arrivedDate, this.arrivedDate,
this.cargoDesc, this.cargoDesc,
this.market, this.market,
this.shipmentHistory, this.shipmentHistory = const [],
this.currentStatusDate, this.currentStatusDate,
this.photoUrls, this.photoUrls = const [],
this.desc, this.desc,
this.deliveryAddress, this.deliveryAddress,
this.isChecked = false, this.isChecked = false,
this.photoFiles, this.photoFiles = const [],
this.senderPhoneNumber this.senderPhoneNumber});
});
factory Package.fromMap(Map<String, dynamic> map, String docID) { factory Package.fromMap(Map<String, dynamic> map, String docID) {
var _currentStatusDate = (map['status_date'] as Timestamp); var _currentStatusDate = (map['status_date'] as Timestamp);
@@ -98,9 +97,7 @@ class Package {
senderName: map['sender_name'], senderName: map['sender_name'],
senderPhoneNumber: map['sender_phone_number'], senderPhoneNumber: map['sender_phone_number'],
deliveryAddress: _da, deliveryAddress: _da,
currentStatusDate: _currentStatusDate != null currentStatusDate: _currentStatusDate.toDate().toLocal(),
? _currentStatusDate.toDate().toLocal()
: null,
photoUrls: _photoUrls, photoUrls: _photoUrls,
shipmentHistory: _shipmentStatus); shipmentHistory: _shipmentStatus);
} }

View File

@@ -1,11 +1,11 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
class Payment { class Payment {
String id; String? id;
String invoiceID; String? invoiceID;
DateTime paymentDate; DateTime? paymentDate;
String paymentReceiptURL; String? paymentReceiptURL;
String status; String? status;
double amount; double amount;
Payment( Payment(
@@ -14,13 +14,13 @@ class Payment {
this.paymentDate, this.paymentDate,
this.paymentReceiptURL, this.paymentReceiptURL,
this.status, this.status,
this.amount}); this.amount = 0});
factory Payment.fromMap(Map<String, dynamic> map, String id) { factory Payment.fromMap(Map<String, dynamic> map, String id) {
var _paymentDate = (map['payment_date'] as Timestamp); var _paymentDate = (map['payment_date'] as Timestamp);
return Payment( return Payment(
id: id, id: id,
paymentDate: _paymentDate?.toDate(), paymentDate: _paymentDate.toDate(),
paymentReceiptURL: map['payment_receipt_url'], paymentReceiptURL: map['payment_receipt_url'],
status: map['status'], status: map['status'],
amount: map['amount']?.toDouble() ?? 0, amount: map['amount']?.toDouble() ?? 0,
@@ -31,7 +31,7 @@ class Payment {
return { return {
"id": id, "id": id,
"invoice_id": invoiceID, "invoice_id": invoiceID,
'payment_date': paymentDate?.toUtc()?.toIso8601String(), 'payment_date': paymentDate?.toUtc().toIso8601String(),
'payment_receipt_url': paymentReceiptURL, 'payment_receipt_url': paymentReceiptURL,
'status': status, 'status': status,
'amount': amount, 'amount': amount,
@@ -39,7 +39,7 @@ class Payment {
} }
Payment clone() { Payment clone() {
return Payment.fromMap(toMap(), this.id); return Payment.fromMap(toMap(), this.id!);
} }
@override @override

View File

@@ -1,11 +1,11 @@
class PaymentMethod { class PaymentMethod {
String id; String? id;
String name; String? name;
String accountName; String? accountName;
String account; String? account;
String phone; String? phone;
String email; String? email;
String link; String? link;
PaymentMethod( PaymentMethod(
{this.id, {this.id,

View File

@@ -1,15 +1,15 @@
import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/package.dart';
class Processing { class Processing {
String id; String? id;
//for consignee //for consignee
String userID; String? userID;
String userName; String? userName;
String userPhoneNumber; String? userPhoneNumber;
//for shipper //for shipper
String fcsID; String? fcsID;
String shipperName; String? shipperName;
String shipperPhoneNumber; String? shipperPhoneNumber;
List<Package> packages; List<Package> packages;
@@ -21,7 +21,7 @@ class Processing {
this.fcsID, this.fcsID,
this.shipperName, this.shipperName,
this.shipperPhoneNumber, this.shipperPhoneNumber,
this.packages}); this.packages = const []});
@override @override
bool operator ==(Object other) => other is Processing && other.id == id; bool operator ==(Object other) => other is Processing && other.id == id;

View File

@@ -1,4 +1,3 @@
import 'package:fcs/domain/entities/discount_by_weight.dart'; import 'package:fcs/domain/entities/discount_by_weight.dart';
import 'cargo_type.dart'; import 'cargo_type.dart';
@@ -11,26 +10,23 @@ class Rate {
double diffDiscountWeight; double diffDiscountWeight;
double diffWeightRate; double diffWeightRate;
List<CargoType> cargoTypes; List<CargoType> cargoTypes = [];
List<CargoType> customDuties; List<CargoType> customDuties = [];
List<DiscountByWeight> discountByWeights; List<DiscountByWeight> discountByWeights = [];
DiscountByWeight getDiscountByWeight(double weight) { DiscountByWeight getDiscountByWeight(double weight) {
discountByWeights.sort((d1, d2) => d2.weight.compareTo(d1.weight)); discountByWeights.sort((d1, d2) => d2.weight.compareTo(d1.weight));
return discountByWeights.firstWhere((e) => e.weight < weight, return discountByWeights.firstWhere((e) => e.weight < weight);
orElse: () => null);
} }
CargoType get defaultCargoType => cargoTypes == null CargoType get defaultCargoType => cargoTypes.firstWhere((e) => e.name == "General");
? null
: cargoTypes.firstWhere((e) => e.name == "General");
Rate( Rate(
{this.deliveryFee, {this.deliveryFee = 0,
this.freeDeliveryWeight, this.freeDeliveryWeight = 0,
this.volumetricRatio, this.volumetricRatio = 0,
this.diffDiscountWeight, this.diffDiscountWeight = 0,
this.diffWeightRate}); this.diffWeightRate = 0});
factory Rate.fromMap(Map<String, dynamic> map) { factory Rate.fromMap(Map<String, dynamic> map) {
return Rate( return Rate(

View File

@@ -1,9 +1,9 @@
class Receipt { class Receipt {
String id; String? id;
int amount; int? amount = 0;
String date; String? date;
String status; String? status;
String fileUrl; String? fileUrl;
Receipt({this.id, this.amount, this.date, this.status, this.fileUrl}); Receipt({this.id, this.amount, this.date, this.status, this.fileUrl});
} }

View File

@@ -10,25 +10,24 @@ List<Day> dayLists = [
class Setting { class Setting {
final int supportBuildNum; final int supportBuildNum;
// contact page // contact page
String usaAddress; String? usaAddress;
String mmAddress; String? mmAddress;
String usaContactNumber; String? usaContactNumber;
String mmContactNumber; String? mmContactNumber;
String emailAddress; String? emailAddress;
String facebookLink; String? facebookLink;
bool inviteRequired; bool? inviteRequired;
String appUrl; String? appUrl;
final String termsEng; final String? termsEng;
final String termsMm; final String? termsMm;
String about; String? about;
String courierWebsite; String? courierWebsite;
List<String> shipmentTypes; List<String> shipmentTypes;
Setting( Setting(
{this.supportBuildNum, {this.supportBuildNum = 1,
this.usaAddress, this.usaAddress,
this.mmAddress, this.mmAddress,
this.usaContactNumber, this.usaContactNumber,
@@ -40,7 +39,7 @@ class Setting {
this.termsEng, this.termsEng,
this.termsMm, this.termsMm,
this.about, this.about,
this.shipmentTypes, this.shipmentTypes = const [],
this.courierWebsite}); this.courierWebsite});
factory Setting.fromMap(Map<String, dynamic> map) { factory Setting.fromMap(Map<String, dynamic> map) {
@@ -76,9 +75,9 @@ class Setting {
} }
class Day { class Day {
int id; int? id;
String name; String? name;
bool isChecked = false; bool? isChecked = false;
Day({this.id, this.name, this.isChecked}); Day({this.id, this.name, this.isChecked});
@override @override

View File

@@ -4,35 +4,35 @@ import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/domain/vo/delivery_address.dart';
class Shipment { class Shipment {
String id; String? id;
String shipmentNumber; String? shipmentNumber;
String shipmentType; String? shipmentType;
DeliveryAddress pickupAddress; DeliveryAddress? pickupAddress;
DateTime pickupDate; DateTime? pickupDate;
String pickupTimeStart; String? pickupTimeStart;
String pickupTimeEnd; String? pickupTimeEnd;
String userName; String? userName;
String userID; String? userID;
String phoneNumber; String? phoneNumber;
int numberOfPackage; int numberOfPackage = 0;
int weight; int weight = 0;
double handlingFee; double handlingFee = 0;
double paidHandlingFee; double paidHandlingFee = 0;
String address; String? address;
String status; String? status;
bool isCourier; bool isCourier;
int radioIndex; int radioIndex;
List<Carton> boxes; List<Carton> boxes;
String pickupUserID; String? pickupUserID;
String pickupUserName; String? pickupUserName;
String pickupUserPhoneNumber; String? pickupUserPhoneNumber;
String fcsShipmentID; String? fcsShipmentID;
String fcsShipmentNumber; String? fcsShipmentNumber;
String shipmentLabelUrl; String? shipmentLabelUrl;
bool isSelected; bool isSelected = false;
Shipment( Shipment(
{this.id, {this.id,
@@ -43,28 +43,28 @@ class Shipment {
this.phoneNumber, this.phoneNumber,
this.pickupTimeStart, this.pickupTimeStart,
this.pickupTimeEnd, this.pickupTimeEnd,
this.numberOfPackage, this.numberOfPackage = 0,
this.weight, this.weight = 0,
this.handlingFee, this.handlingFee = 0,
this.paidHandlingFee, this.paidHandlingFee = 0,
this.address, this.address,
this.status, this.status,
this.pickupDate, this.pickupDate,
this.isCourier = false, this.isCourier = false,
this.radioIndex = 1, this.radioIndex = 1,
this.pickupAddress, required this.pickupAddress,
this.pickupUserID, this.pickupUserID,
this.pickupUserName, this.pickupUserName,
this.pickupUserPhoneNumber, this.pickupUserPhoneNumber,
this.fcsShipmentID, this.fcsShipmentID,
this.fcsShipmentNumber, this.fcsShipmentNumber,
this.shipmentLabelUrl, this.shipmentLabelUrl,
this.boxes}); this.boxes = const []});
int get last => DateTime.now().difference(pickupDate).inDays; // int get last => DateTime.now().difference(pickupDate).inDays;
double get totalWeight => boxes?.fold(0, (p, e) => p + e.actualWeight); double get totalWeight => boxes.fold(0, (p, e) => p + e.actualWeight);
int get totalCount => boxes?.length; int get totalCount => boxes.length;
bool get isPending => status == shipment_pending_status; bool get isPending => status == shipment_pending_status;
bool get isAssigned => status == shipment_assigned_status; bool get isAssigned => status == shipment_assigned_status;
@@ -100,15 +100,15 @@ class Shipment {
} }
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
List _boxes = boxes?.map((l) => l.toMap())?.toList() ?? []; List _boxes = boxes.map((l) => l.toMap()).toList();
return { return {
"id": id, "id": id,
'user_id': userID, 'user_id': userID,
'cartons': _boxes, 'cartons': _boxes,
'shipment_type': shipmentType, 'shipment_type': shipmentType,
'pickup_address': pickupAddress.toMap(), 'pickup_address': pickupAddress?.toMap(),
"pickup_date": pickupDate?.toUtc()?.toIso8601String(), "pickup_date": pickupDate?.toUtc().toIso8601String(),
'pickup_time_start': pickupTimeStart, 'pickup_time_start': pickupTimeStart,
'pickup_time_end': pickupTimeEnd, 'pickup_time_end': pickupTimeEnd,
'pickup_user_id': pickupUserID, 'pickup_user_id': pickupUserID,

View File

@@ -9,18 +9,19 @@ DateFormat timeFormat = DateFormat("HH:mm");
final DateFormat dateFormat = DateFormat("d MMM yyyy"); final DateFormat dateFormat = DateFormat("d MMM yyyy");
class User { class User {
String id; String? id;
String name; String? name;
String phoneNumber; String? phoneNumber;
String status; String? status;
String fcsID; String? fcsID;
DateTime lastMessageTime; DateTime? lastMessageTime;
String lastMessage; String? lastMessage;
int userUnseenCount; int userUnseenCount;
int fcsUnseenCount; int fcsUnseenCount;
String preferCurrency; String? preferCurrency;
String get initial => name != null && name != "" ? name.substring(0, 1) : "?"; String get initial =>
name != null && name != "" ? name!.substring(0, 1) : "?";
String get getLastMessage { String get getLastMessage {
var msg = lastMessage ?? "Say hi to $name"; var msg = lastMessage ?? "Say hi to $name";
@@ -31,27 +32,31 @@ class User {
String get getLastMessageTime { String get getLastMessageTime {
if (lastMessageTime == null) return ""; if (lastMessageTime == null) return "";
DateTime today = DateTime.now(); DateTime today = DateTime.now();
if (lastMessageTime.year == today.year && if (lastMessageTime!.year == today.year &&
lastMessageTime.month == today.month && lastMessageTime!.month == today.month &&
lastMessageTime.day == today.day) { lastMessageTime!.day == today.day) {
return timeFormat.format(lastMessageTime); return timeFormat.format(lastMessageTime!);
} else { } else {
return dateFormat.format(lastMessageTime); return dateFormat.format(lastMessageTime!);
} }
} }
String get getUserUnseenCount => userUnseenCount != null String get getUserUnseenCount => userUnseenCount != null
? userUnseenCount > 100 ? "99+" : userUnseenCount.toString() ? userUnseenCount > 100
? "99+"
: userUnseenCount.toString()
: "0"; : "0";
String get getFcsUnseenCount => fcsUnseenCount != null String get getFcsUnseenCount => fcsUnseenCount != null
? fcsUnseenCount > 100 ? "99+" : fcsUnseenCount.toString() ? fcsUnseenCount > 100
? "99+"
: fcsUnseenCount.toString()
: "0"; : "0";
List<String> privileges = []; List<String> privileges = [];
String get phone => phoneNumber != null && phoneNumber.startsWith("959") String get phone => phoneNumber != null && phoneNumber!.startsWith("959")
? "0${phoneNumber.substring(2)}" ? "0${phoneNumber!.substring(2)}"
: phoneNumber; : phoneNumber!;
bool get joined => status != null && status == user_joined_status; bool get joined => status != null && status == user_joined_status;
bool get invited => status != null && status == user_invited_status; bool get invited => status != null && status == user_invited_status;
bool get requested => status != null && status == user_requested_status; bool get requested => status != null && status == user_requested_status;
@@ -64,11 +69,11 @@ class User {
this.phoneNumber, this.phoneNumber,
this.fcsID, this.fcsID,
this.status, this.status,
this.privileges, this.privileges = const [],
this.lastMessage, this.lastMessage,
this.lastMessageTime, this.lastMessageTime,
this.userUnseenCount, this.userUnseenCount = 0,
this.fcsUnseenCount, this.fcsUnseenCount = 0,
this.preferCurrency}); this.preferCurrency});
factory User.fromJson(Map<String, dynamic> json) { factory User.fromJson(Map<String, dynamic> json) {

View File

@@ -1,12 +1,12 @@
class ServerException { class ServerException {
@override @override
List<Object> get props => null; List<Object>? get props => null;
call() { call() {
return null; return null;
} }
@override @override
bool get stringify => null; bool? get stringify => null;
} }

View File

@@ -1,12 +1,12 @@
import 'package:fcs/domain/entities/setting.dart'; import 'package:fcs/domain/entities/setting.dart';
class Contact { class Contact {
String usaAddress; String? usaAddress;
String mmAddress; String? mmAddress;
String usaContactNumber; String? usaContactNumber;
String mmContactNumber; String? mmContactNumber;
String emailAddress; String? emailAddress;
String facebookLink; String? facebookLink;
Contact({ Contact({
this.usaAddress, this.usaAddress,

View File

@@ -1,13 +1,14 @@
class DeliveryAddress { class DeliveryAddress {
String id; String? id;
String fullName; String? fullName;
String addressLine1; String? addressLine1;
String addressLine2; String? addressLine2;
String city; String? city;
String state; String? state;
String phoneNumber; String? phoneNumber;
bool isDefault; bool isDefault;
String userID; String? userID;
DeliveryAddress( DeliveryAddress(
{this.id, {this.id,
this.fullName, this.fullName,

View File

@@ -1,15 +1,15 @@
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
class Message { class Message {
String id; String? id;
String message; String? message;
DateTime date; DateTime? date;
String receiverID; String? receiverID;
String receiverName; String? receiverName;
String senderID; String? senderID;
String senderName; String? senderName;
String messageType; String? messageType;
String messageID; String? messageID;
Message( Message(
{this.id, {this.id,
@@ -21,11 +21,13 @@ class Message {
this.senderName, this.senderName,
this.messageType, this.messageType,
this.messageID}); this.messageID});
bool fromToday() { bool fromToday() {
if (date == null) return false;
var now = DateTime.now(); var now = DateTime.now();
return date.day == now.day && return date!.day == now.day &&
date.month == now.month && date!.month == now.month &&
date.year == now.year; date!.year == now.year;
} }
Map<String, dynamic> toMap() { Map<String, dynamic> toMap() {
@@ -36,9 +38,10 @@ class Message {
} }
bool sameDay(Message another) { bool sameDay(Message another) {
return date.year == another.date.year && if (date == null) return false;
date.month == another.date.month && return date!.year == another.date!.year &&
date.day == another.date.day; date!.month == another.date!.month &&
date!.day == another.date!.day;
} }
factory Message.fromMap(Map<String, dynamic> map, String id) { factory Message.fromMap(Map<String, dynamic> map, String id) {
@@ -52,7 +55,7 @@ class Message {
receiverName: map['receiver_name'], receiverName: map['receiver_name'],
messageType: map['msg_type'], messageType: map['msg_type'],
messageID: map['msg_id'], messageID: map['msg_id'],
date: date != null ? date.toDate() : null, date: date.toDate(),
); );
} }
} }

View File

@@ -1,20 +1,24 @@
import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/constants.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.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';
class Privilege { class Privilege {
String id; String id;
String name; String? name;
String desc; String? desc;
bool sysAdminOnly = true; bool? sysAdminOnly = true;
bool isChecked = false; bool? isChecked = false;
IconData iconData; IconData? iconData;
Privilege( Privilege(
{this.id, this.name, this.desc, this.isChecked, this.sysAdminOnly}) { {required this.id,
this.name,
this.desc,
this.isChecked,
this.sysAdminOnly}) {
if (this.id == privilege_admin) { if (this.id == privilege_admin) {
iconData = MaterialCommunityIcons.account_tie; iconData = MaterialCommunityIcons.account_tie;
} else if (this.id == privilege_support) { } else if (this.id == privilege_support) {

View File

@@ -1,5 +0,0 @@
class RadioGroup {
String text;
int index;
RadioGroup({this.text, this.index});
}

View File

@@ -3,17 +3,21 @@ import 'package:cloud_firestore/cloud_firestore.dart';
class ShipmentStatus { class ShipmentStatus {
String status; String status;
DateTime date; DateTime date;
bool done; bool? done;
String staffId; String? staffId;
String staffName; String? staffName;
ShipmentStatus( ShipmentStatus(
{this.status, this.date, this.done, this.staffId, this.staffName}); {required this.status,
required this.date,
this.done,
this.staffId,
this.staffName});
factory ShipmentStatus.fromMap(Map<String, dynamic> map) { factory ShipmentStatus.fromMap(Map<String, dynamic> map) {
var _date = (map['date'] as Timestamp); var _date = (map['date'] as Timestamp);
return ShipmentStatus( return ShipmentStatus(
status: map['status'], status: map['status'],
date: _date == null ? null : _date.toDate(), date: _date.toDate(),
done: map['done'], done: map['done'],
staffId: map['staff_id'], staffId: map['staff_id'],
staffName: map['staff_name']); staffName: map['staff_name']);

View File

@@ -1,8 +1,7 @@
class Status { class Status {
String status; String? status;
String message; String? message;
String errorCode; String? errorCode;
Status(this.status, this.message); Status(this.status, this.message);
Status.fromJson(Map<String, dynamic> json) { Status.fromJson(Map<String, dynamic> json) {

View File

@@ -1,8 +1,8 @@
import 'package:fcs/domain/entities/setting.dart'; import 'package:fcs/domain/entities/setting.dart';
class Term { class Term {
String termEng; String? termEng;
String termMm; String? termMm;
Term({this.termEng, this.termMm}); Term({this.termEng, this.termMm});

View File

@@ -20,8 +20,8 @@ Future<dynamic> requestAPI(
String path, String path,
method, { method, {
dynamic payload, dynamic payload,
String token, String? token,
String url, String? url,
}) async { }) async {
DevInfo devInfo = await DevInfo.getDevInfo(); DevInfo devInfo = await DevInfo.getDevInfo();
@@ -33,7 +33,7 @@ Future<dynamic> requestAPI(
headers["Token"] = token; headers["Token"] = token;
} }
if (devInfo != null && devInfo.deviceID != null && deviceName != null) { if (devInfo != null && devInfo.deviceID != null && deviceName != null) {
headers["Device"] = devInfo.deviceID + ":" + deviceName; headers["Device"] = devInfo.deviceID??"" + ":" + deviceName;
} }
headers["Project-ID"] = Config.instance.reportProjectID; headers["Project-ID"] = Config.instance.reportProjectID;
@@ -66,7 +66,7 @@ Future<dynamic> requestAPI(
// request makes http request // request makes http request
// if token is null // if token is null
Future<dynamic> requestDownloadAPI(String path, method, Future<dynamic> requestDownloadAPI(String path, method,
{dynamic payload, String token, String url, String filePath}) async { {dynamic payload, String? token, String? url, String? filePath}) async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
String deviceName = "${androidInfo.model}(${androidInfo.id})"; String deviceName = "${androidInfo.model}(${androidInfo.id})";
@@ -81,7 +81,7 @@ Future<dynamic> requestDownloadAPI(String path, method,
log.info("Path:$baseUrl$path"); log.info("Path:$baseUrl$path");
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
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", Config.instance.reportProjectID);
request.headers request.headers
@@ -108,7 +108,7 @@ Future<dynamic> requestDownloadAPI(String path, method,
// request makes http request // request makes http request
// if token is null // if token is null
Future<dynamic> requestDownloadPDFAPI(String path, method, Future<dynamic> requestDownloadPDFAPI(String path, method,
{dynamic payload, String token, String url, String filePath}) async { {dynamic payload, String? token, String? url, String? filePath}) async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
String deviceName = "${androidInfo.model}(${androidInfo.id})"; String deviceName = "${androidInfo.model}(${androidInfo.id})";
@@ -123,7 +123,7 @@ Future<dynamic> requestDownloadPDFAPI(String path, method,
log.info("Path:$baseUrl$path"); log.info("Path:$baseUrl$path");
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
// 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", Config.instance.reportProjectID);
if (token != null) { if (token != null) {
@@ -135,7 +135,7 @@ Future<dynamic> requestDownloadPDFAPI(String path, method,
request.headers.set("payload", escapePayload); request.headers.set("payload", escapePayload);
var response = await request.close(); var response = await request.close();
print("headers:${response.headers}"); print("headers:${response.headers}");
var _downloadData = List<int>(); List<int> _downloadData = [];
response.listen((d) => _downloadData.addAll(d), onDone: () { response.listen((d) => _downloadData.addAll(d), onDone: () {
fileSave.writeAsBytes(_downloadData); fileSave.writeAsBytes(_downloadData);
@@ -155,10 +155,10 @@ typedef OnDownloadDone(File file);
// if token is null // if token is null
Future<dynamic> requestDownload(String path, method, Future<dynamic> requestDownload(String path, method,
{dynamic payload, {dynamic payload,
String token, required String token,
String url, required String url,
String filePath, required String filePath,
OnDownloadDone onDownloadDone}) async { OnDownloadDone? onDownloadDone}) async {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin(); DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
String deviceName = "${androidInfo.model}(${androidInfo.id})"; String deviceName = "${androidInfo.model}(${androidInfo.id})";
@@ -188,7 +188,7 @@ Future<dynamic> requestDownload(String path, method,
// request.write(escapePayload); // request.write(escapePayload);
var response = await request.close(); var response = await request.close();
print("headers:${response.headers}"); print("headers:${response.headers}");
var _downloadData = List<int>(); List<int> _downloadData = [];
var cd = response.headers.value("content-disposition"); var cd = response.headers.value("content-disposition");
String fileName = "download.csv"; String fileName = "download.csv";
if (cd != null && cd.contains("filename=")) { if (cd != null && cd.contains("filename=")) {

View File

@@ -2,13 +2,13 @@ import 'package:device_info/device_info.dart';
import 'dart:io' show Platform; import 'dart:io' show Platform;
class DevInfo { class DevInfo {
bool isAndroid; bool? isAndroid;
bool isIOS; bool? isIOS;
String deviceID; String? deviceID;
String id; String? id;
String model; String? model;
static DevInfo _instance; static DevInfo? _instance;
static Future<DevInfo> getDevInfo() async { static Future<DevInfo> getDevInfo() async {
if (_instance != null) return Future.value(_instance); if (_instance != null) return Future.value(_instance);
@@ -18,14 +18,14 @@ class DevInfo {
if (Platform.isAndroid) { if (Platform.isAndroid) {
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo; AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
_instance.deviceID = androidInfo.androidId; _instance!.deviceID = androidInfo.androidId;
_instance.id = androidInfo.id; _instance!.id = androidInfo.id;
_instance.model = androidInfo.model; _instance!.model = androidInfo.model;
} else if (Platform.isIOS) { } else if (Platform.isIOS) {
IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo; IosDeviceInfo iosDeviceInfo = await deviceInfo.iosInfo;
_instance.deviceID = iosDeviceInfo.identifierForVendor; _instance!.deviceID = iosDeviceInfo.identifierForVendor;
_instance.id = iosDeviceInfo.utsname.release; _instance!.id = iosDeviceInfo.utsname.release;
_instance.model = iosDeviceInfo.model; _instance!.model = iosDeviceInfo.model;
} }
return Future.value(_instance); return Future.value(_instance);
} }

View File

@@ -1,71 +1,82 @@
import 'dart:io'; import 'dart:io';
import 'package:fcs/config.dart'; import 'package:firebase_auth/firebase_auth.dart' as fb;
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart'; import 'package:firebase_storage/firebase_storage.dart';
import 'package:logging/logging.dart'; import 'package:logging/logging.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
final log = Logger('firebaseHelper'); final log = Logger('firebaseHelper');
final FirebaseAuth auth = FirebaseAuth.instance; final fb.FirebaseAuth auth = fb.FirebaseAuth.instance;
Future<String> getToken() async { Future<String> getToken() async {
FirebaseUser firebaseUser = await auth.currentUser(); fb.User? firebaseUser = fb.FirebaseAuth.instance.currentUser;
IdTokenResult token = await firebaseUser.getIdToken(); String token = await firebaseUser?.getIdToken() ?? "";
return token.token; return token;
} }
Future<Map> getClaims({bool refreshIdToken = false}) async { Future<Map?> getClaims({bool refreshIdToken = false}) async {
FirebaseUser firebaseUser = await auth.currentUser(); fb.User? firebaseUser = auth.currentUser;
if (firebaseUser == null) return null; if (firebaseUser == null) return null;
IdTokenResult idToken = fb.IdTokenResult idToken =
await firebaseUser.getIdToken(refresh: refreshIdToken); await firebaseUser.getIdTokenResult(refreshIdToken);
return idToken.claims; return idToken.claims;
} }
// returns list of url // returns list of url
Future<List<String>> uploadFiles(String path, List<File> files, Future<List<String>> uploadFiles(String path, List<File?> files,
{String fileName}) async { {String? fileName}) async {
List<Future<String>> fu = []; List<Future<String>> fu = [];
for (File f in files) { for (File? f in files) {
Future<String> u = uploadStorage(path, f); Future<String> u = uploadStorage(path, f);
fu.add(u); fu.add(u);
} }
return Future.wait(fu); return Future.wait(fu);
} }
Future<String> uploadStorage(String path, File file, {String fileName}) async { Future<String> uploadStorage(String path, File? file,
{String? fileName}) async {
if (fileName == null) { if (fileName == null) {
fileName = Uuid().v4(); fileName = Uuid().v4();
} }
StorageReference storageReference = if (file == null) {
FirebaseStorage(storageBucket: Config.instance.bucketName) return Future.value('');
.ref() }
.child('$path/$fileName'); Reference ref = FirebaseStorage.instance.ref().child('$path/$fileName');
StorageUploadTask uploadTask = storageReference.putFile(file); UploadTask uploadTask = ref.putFile(file);
await uploadTask.onComplete; await uploadTask.resume();
String downloadUrl = await storageReference.getDownloadURL(); String downloadUrl = await ref.getDownloadURL();
print("name:${await storageReference.getName()}");
print("bucket:${await storageReference.getBucket()}");
print("path:${await storageReference.getPath()}");
print("meta:${await storageReference.getMetadata()}");
return downloadUrl; return downloadUrl;
// StorageReference storageReference =
// FirebaseStorage(storageBucket: Config.instance.bucketName)
// .ref()
// .child('$path/$fileName');
// StorageUploadTask uploadTask = storageReference.putFile(file);
// await uploadTask.onComplete;
// String downloadUrl = await storageReference.getDownloadURL();
// print("name:${await storageReference.getName()}");
// print("bucket:${await storageReference.getBucket()}");
// print("path:${await storageReference.getPath()}");
// print("meta:${await storageReference.getMetadata()}");
// return downloadUrl;
} }
Future<void> deleteStorageFromUrls(List<String> urls) async { Future<void> deleteStorageFromUrls(List<String?> urls) async {
if (urls == null) return; if (urls == null) return;
for (int i = 0; i < urls.length; i++) { for (int i = 0; i < urls.length; i++) {
await deleteStorageFromUrl(urls[i]); if (urls[i] == null) return;
await deleteStorageFromUrl(urls[i]!);
} }
} }
Future<void> deleteStorageFromUrl(String url) async { Future<void> deleteStorageFromUrl(String url) async {
try { try {
StorageReference storageReference = Reference ref = FirebaseStorage.instance.refFromURL(url);
await FirebaseStorage(storageBucket: Config.instance.bucketName) await ref.delete();
.getReferenceFromUrl(url); // StorageReference storageReference =
await storageReference.delete(); // await FirebaseStorage(storageBucket: Config.instance.bucketName)
// .getReferenceFromUrl(url);
// await storageReference.delete();
} catch (e) { } catch (e) {
log.warning("deleteStorage:$e"); log.warning("deleteStorage:$e");
} }

View File

@@ -11,7 +11,7 @@ class NetworkConnectivity {
final log = Logger('NetworkConnectivity'); final log = Logger('NetworkConnectivity');
static final NetworkConnectivity instance = NetworkConnectivity._internal(); static final NetworkConnectivity instance = NetworkConnectivity._internal();
static String hostName; static String? hostName;
NetworkConnectivity._internal() { NetworkConnectivity._internal() {
_initialise(); _initialise();
var uri = Uri.parse(Config.instance.apiURL); var uri = Uri.parse(Config.instance.apiURL);
@@ -38,7 +38,7 @@ class NetworkConnectivity {
// lookup if connectivity is not none // lookup if connectivity is not none
if (result != ConnectivityResult.none) { if (result != ConnectivityResult.none) {
try { try {
final hostNameLookup = await InternetAddress.lookup(hostName); final hostNameLookup = await InternetAddress.lookup(hostName ?? "");
if (hostNameLookup.isNotEmpty && if (hostNameLookup.isNotEmpty &&
hostNameLookup[0].rawAddress.isNotEmpty) { hostNameLookup[0].rawAddress.isNotEmpty) {
if (await checkHeartbeat()) { if (await checkHeartbeat()) {

View File

@@ -13,7 +13,7 @@ class Paginator<T> {
final log = Logger('Paginator'); final log = Logger('Paginator');
final int rowPerLoad; final int rowPerLoad;
DocumentSnapshot prev; DocumentSnapshot? prev;
bool ended = false; bool ended = false;
bool isLoading = false; bool isLoading = false;
List<T> values = []; List<T> values = [];
@@ -21,7 +21,7 @@ class Paginator<T> {
Query pageQuery; Query pageQuery;
Paginator(this.pageQuery, {this.rowPerLoad = 20, this.toObj}) { Paginator(this.pageQuery, {this.rowPerLoad = 20, required this.toObj}) {
_clearState(); _clearState();
} }
@@ -36,27 +36,27 @@ class Paginator<T> {
_clearState(); _clearState();
} }
Future<void> refresh({CallBack onFinished}) async { Future<void> refresh({CallBack? onFinished}) async {
_clearState(); _clearState();
await load(); await load();
if (onFinished != null) onFinished(); if (onFinished != null) onFinished();
} }
Future<bool> load({CallBack onFinished}) async { Future<bool?> load({CallBack? onFinished}) async {
if (ended) return null; if (ended) return null;
isLoading = true; isLoading = true;
Query _query = Query _query =
prev != null ? pageQuery.startAfterDocument(prev) : pageQuery; prev != null ? pageQuery.startAfterDocument(prev!) : pageQuery;
try { try {
await _query await _query
.limit(rowPerLoad) .limit(rowPerLoad)
.getDocuments(source: Source.server) .get(GetOptions(source: Source.server))
.then((QuerySnapshot snapshot) { .then((QuerySnapshot snapshot) {
int count = snapshot.documents.length; int count = snapshot.docs.length;
ended = count < rowPerLoad; ended = count < rowPerLoad;
prev = count > 0 ? snapshot.documents[count - 1] : prev; prev = count > 0 ? snapshot.docs[count - 1] : prev;
snapshot.documents.forEach((e) { snapshot.docs.forEach((e) {
values.add(toObj(e.data, e.documentID)); values.add(toObj(e.data() as Map<String, dynamic>, e.id));
}); });
}); });
} catch (e) { } catch (e) {

View File

@@ -7,17 +7,17 @@ class SharedPref {
static final SharedPref instance = SharedPref._(); static final SharedPref instance = SharedPref._();
SharedPref._(); SharedPref._();
static Future<bool> isFirstLaunch() async { static Future<bool?> isFirstLaunch() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool('first_launch'); return prefs.getBool('first_launch');
} }
static Future<void> finishFirstLaunch() async { static Future<void> finishFirstLaunch() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setBool('first_launch', false); prefs.setBool('first_launch', false);
} }
static Future<String> getLang() async { static Future<String?> getLang() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString('language'); return prefs.getString('language');
} }
@@ -27,7 +27,7 @@ class SharedPref {
prefs.setString('language', lang); prefs.setString('language', lang);
} }
static Future<bool> getStaffMode() async { static Future<bool?> getStaffMode() async {
SharedPreferences prefs = await SharedPreferences.getInstance(); SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool('staff_mode_on'); return prefs.getBool('staff_mode_on');
} }
@@ -41,7 +41,7 @@ class SharedPref {
await _save("user", user.toJson()); await _save("user", user.toJson());
} }
static Future<User> getUser() async { static Future<User?> getUser() async {
try { try {
return User.fromJson(await _read("user")); return User.fromJson(await _read("user"));
} catch (e) { } catch (e) {
@@ -57,7 +57,7 @@ class SharedPref {
await _save("skipped_recovery_email", skipped); await _save("skipped_recovery_email", skipped);
} }
static Future<bool> getSkippedRecoverEmail() async { static Future<bool?> getSkippedRecoverEmail() async {
try { try {
bool _skipped = await _read("skipped_recovery_email"); bool _skipped = await _read("skipped_recovery_email");
return _skipped; return _skipped;
@@ -69,7 +69,7 @@ class SharedPref {
static _read(String key) async { static _read(String key) async {
try { try {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
return json.decode(prefs.getString(key)); return json.decode(prefs.getString(key) ?? "");
} catch (e) { } catch (e) {
print("Error:$e"); print("Error:$e");
} }

View File

@@ -20,8 +20,10 @@ const TextStyle labelStyleMM = TextStyle(
fontFamily: "Myanmar3"); fontFamily: "Myanmar3");
const TextStyle subMenuStyle = const TextStyle subMenuStyle =
TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.w500); TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.w500);
const TextStyle subMenuStyleMM = const TextStyle subMenuStyleMM = TextStyle(
TextStyle(fontSize: 14, color: Colors.white, fontWeight: FontWeight.w500, fontSize: 14,
color: Colors.white,
fontWeight: FontWeight.w500,
fontFamily: "Myanmar3"); fontFamily: "Myanmar3");
const TextStyle welcomeLabelStyle = const TextStyle welcomeLabelStyle =
@@ -31,11 +33,10 @@ const TextStyle welcomeSubLabelStyle =
const TextStyle siginButtonStyle = const TextStyle siginButtonStyle =
TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500); TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w500);
TextStyle newLabelStyle( TextStyle newLabelStyle(
{Color color, {Color? color,
double fontSize, double? fontSize,
FontWeight fontWeight, FontWeight? fontWeight,
bool underline = false}) { bool underline = false}) {
return TextStyle( return TextStyle(
fontSize: fontSize == null ? 14 : fontSize, fontSize: fontSize == null ? 14 : fontSize,
@@ -45,9 +46,9 @@ TextStyle newLabelStyle(
} }
TextStyle newLabelStyleMM( TextStyle newLabelStyleMM(
{Color color, {Color? color,
double fontSize, double? fontSize,
FontWeight fontWeight, FontWeight? fontWeight,
bool underline = false}) { bool underline = false}) {
return TextStyle( return TextStyle(
fontSize: fontSize == null ? 13 : fontSize, fontSize: fontSize == null ? 13 : fontSize,
@@ -59,8 +60,8 @@ TextStyle newLabelStyleMM(
const TextStyle photoLabelStyle = const TextStyle photoLabelStyle =
TextStyle(color: Colors.black, fontSize: 13.0); TextStyle(color: Colors.black, fontSize: 13.0);
const TextStyle photoLabelStyleMM = TextStyle( const TextStyle photoLabelStyleMM =
color: Colors.black, fontSize: 13.0, fontFamily: "Myanmar3"); TextStyle(color: Colors.black, fontSize: 13.0, fontFamily: "Myanmar3");
const TextStyle textStyle = const TextStyle textStyle =
TextStyle(fontSize: 14, color: Colors.black87, fontWeight: FontWeight.w500); TextStyle(fontSize: 14, color: Colors.black87, fontWeight: FontWeight.w500);
const TextStyle textStyleOdd = TextStyle( const TextStyle textStyleOdd = TextStyle(

View File

@@ -6,14 +6,14 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show rootBundle; import 'package:flutter/services.dart' show rootBundle;
class AppTranslations { class AppTranslations {
Locale locale; late Locale locale;
static Map<dynamic, dynamic> _localisedValues; static late Map<dynamic, dynamic> _localisedValues;
AppTranslations(Locale locale) { AppTranslations(Locale locale) {
this.locale = locale; this.locale = locale;
} }
static AppTranslations of(BuildContext context) { static AppTranslations? of(BuildContext context) {
return Localizations.of<AppTranslations>(context, AppTranslations); return Localizations.of<AppTranslations>(context, AppTranslations);
} }
@@ -27,7 +27,7 @@ class AppTranslations {
get currentLanguage => locale.languageCode; get currentLanguage => locale.languageCode;
String text(String key, {List<String> translationVariables}) { String text(String key, {List<String>? translationVariables}) {
String value = _localisedValues[key]; String value = _localisedValues[key];
if (value == null) { if (value == null) {
return "$key not found"; return "$key not found";

View File

@@ -15,7 +15,7 @@ class AppTranslationsDelegate extends LocalizationsDelegate<AppTranslations> {
@override @override
Future<AppTranslations> load(Locale locale) { Future<AppTranslations> load(Locale locale) {
return AppTranslations.load(newLocale ?? locale); return AppTranslations.load(newLocale);
} }
@override @override

View File

@@ -23,5 +23,5 @@ class Translation {
supportedLanguagesCodes.map<Locale>((language) => Locale(language, "")); supportedLanguagesCodes.map<Locale>((language) => Locale(language, ""));
//function to be invoked when changing the language //function to be invoked when changing the language
LocaleChangeCallback? onLocaleChanged; late LocaleChangeCallback onLocaleChanged;
} }

View File

@@ -1,6 +1,5 @@
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/display_text.dart';
import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
@@ -15,7 +14,7 @@ class BuyingOnlinePage extends StatefulWidget {
class _BuyingOnlinePagetate extends State<BuyingOnlinePage> class _BuyingOnlinePagetate extends State<BuyingOnlinePage>
with SingleTickerProviderStateMixin { with SingleTickerProviderStateMixin {
TabController _tabController; late TabController _tabController;
@override @override
void initState() { void initState() {
@@ -28,22 +27,22 @@ class _BuyingOnlinePagetate extends State<BuyingOnlinePage>
MainModel mainModel = Provider.of<MainModel>(context); MainModel mainModel = Provider.of<MainModel>(context);
final phoneNumberBox = DisplayText( final phoneNumberBox = DisplayText(
text: mainModel.user.phone, text: mainModel.user?.phone,
labelTextKey: "contact.phone", labelTextKey: "contact.phone",
iconData: Icons.location_on, iconData: Icons.location_on,
); );
final nameBox = Center( final nameBox = Center(
child: Text( child: Text(
mainModel.user.name, mainModel.user?.name ?? "",
style: TextStyle(fontSize: 18, color: primaryColor), style: TextStyle(fontSize: 18, color: primaryColor),
)); ));
final fcsIdBox = DisplayText( final fcsIdBox = DisplayText(
text: mainModel.user.fcsID, text: mainModel.user?.fcsID,
labelTextKey: "customer.fcs.id", labelTextKey: "customer.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
); );
final shippingAddressBox = DisplayText( final shippingAddressBox = DisplayText(
text: mainModel.setting.usaAddress, text: mainModel.setting?.usaAddress,
labelTextKey: "profile.usa.shipping.address", labelTextKey: "profile.usa.shipping.address",
iconData: Icons.location_on, iconData: Icons.location_on,
); );

View File

@@ -6,10 +6,10 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class CargoTable extends StatefulWidget { class CargoTable extends StatefulWidget {
final List<CargoType> cargoTypes; final List<CargoType>? cargoTypes;
const CargoTable({ const CargoTable({
Key key, Key? key,
this.cargoTypes, this.cargoTypes,
}) : super(key: key); }) : super(key: key);
@@ -58,13 +58,13 @@ class _CargoTableState extends State<CargoTable> {
return []; return [];
} }
double total = 0; double total = 0;
var rows = widget.cargoTypes.map((c) { var rows = widget.cargoTypes!.map((c) {
total += c.weight; total += c.weight;
return MyDataRow( return MyDataRow(
onSelectChanged: (bool selected) async {}, onSelectChanged: (bool selected) async {},
cells: [ cells: [
MyDataCell(new Text( MyDataCell(new Text(
c.name == null ? "" : c.name, c.name ?? "",
style: textStyle, style: textStyle,
)), )),
MyDataCell(c.qty == null || c.qty == 0 MyDataCell(c.qty == null || c.qty == 0

View File

@@ -35,7 +35,7 @@ class _CargoTypeAdditionState extends State<CargoTypeAddition> {
p.isChecked = false; p.isChecked = false;
p.isCutomDuty = false; p.isCutomDuty = false;
p.weight = 0; p.weight = 0;
p.qty = null; p.qty = 0;
}); });
specialCargos.forEach((p) { specialCargos.forEach((p) {
p.isChecked = false; p.isChecked = false;
@@ -69,12 +69,12 @@ class _CargoTypeAdditionState extends State<CargoTypeAddition> {
Checkbox( Checkbox(
value: c.isChecked, value: c.isChecked,
activeColor: primaryColor, activeColor: primaryColor,
onChanged: (bool check) { onChanged: (bool? check) {
setState(() { setState(() {
c.isChecked = check; c.isChecked = check ?? false;
}); });
}), }),
new Text(c.name, style: textStyle), new Text(c.name ?? '', style: textStyle),
], ],
), ),
), ),

View File

@@ -12,7 +12,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class CargoTypeEditor extends StatefulWidget { class CargoTypeEditor extends StatefulWidget {
final CargoType cargo; final CargoType? cargo;
CargoTypeEditor({this.cargo}); CargoTypeEditor({this.cargo});
@override @override
@@ -23,14 +23,14 @@ class _CargoTypeEditorState extends State<CargoTypeEditor> {
TextEditingController _weightController = new TextEditingController(); TextEditingController _weightController = new TextEditingController();
bool _isLoading = false; bool _isLoading = false;
CargoType _cargo; CargoType? _cargo;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
if (widget.cargo != null) { if (widget.cargo != null) {
_cargo = widget.cargo; _cargo = widget.cargo;
_weightController.text = _cargo.weight.toStringAsFixed(2); _weightController.text = _cargo!.weight.toStringAsFixed(2);
} else { } else {
_loadDefalut(); _loadDefalut();
} }
@@ -67,7 +67,7 @@ class _CargoTypeEditorState extends State<CargoTypeEditor> {
}, },
labelKey: "cargo.type", labelKey: "cargo.type",
iconData: Icons.text_format, iconData: Icons.text_format,
selectedValue: _cargo, selectedValue: _cargo!,
values: cargos, values: cargos,
); );
@@ -75,7 +75,7 @@ class _CargoTypeEditorState extends State<CargoTypeEditor> {
context, context,
getLocalString(context, 'box.cargo.save.btn'), getLocalString(context, 'box.cargo.save.btn'),
callack: () { callack: () {
_cargo.weight = double.tryParse(_weightController.text) ?? 0; _cargo!.weight = double.tryParse(_weightController.text) ?? 0;
Navigator.pop(context, _cargo); Navigator.pop(context, _cargo);
}, },
); );

View File

@@ -11,13 +11,13 @@ typedef OnRemove(CargoType cargoType);
typedef OnUpdate(CargoType cargoType); typedef OnUpdate(CargoType cargoType);
class CargoTable extends StatefulWidget { class CargoTable extends StatefulWidget {
final List<CargoType> cargoTypes; final List<CargoType>? cargoTypes;
final bool isNew; final bool? isNew;
final OnRemove onRemove; final OnRemove? onRemove;
final OnUpdate onUpdate; final OnUpdate? onUpdate;
const CargoTable( const CargoTable(
{Key key, this.cargoTypes, this.isNew, this.onRemove, this.onUpdate}) {Key? key, this.cargoTypes, this.isNew, this.onRemove, this.onUpdate})
: super(key: key); : super(key: key);
@override @override
@@ -26,14 +26,14 @@ class CargoTable extends StatefulWidget {
class _CargoTableState extends State<CargoTable> { class _CargoTableState extends State<CargoTable> {
double totalWeight = 0; double totalWeight = 0;
List<CargoType> cargoTypes; List<CargoType>? cargoTypes;
@override @override
void initState() { void initState() {
cargoTypes = widget.cargoTypes; cargoTypes = widget.cargoTypes;
if (!widget.isNew) { if (!widget.isNew!) {
totalWeight = totalWeight =
cargoTypes.fold(0, (previous, current) => previous + current.weight); cargoTypes!.fold(0, (previous, current) => previous + current.weight);
} }
super.initState(); super.initState();
@@ -41,7 +41,7 @@ class _CargoTableState extends State<CargoTable> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
print("Cargotypes:${cargoTypes.length}"); print("Cargotypes:${cargoTypes!.length}");
return SingleChildScrollView( return SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
@@ -80,18 +80,18 @@ class _CargoTableState extends State<CargoTable> {
if (cargoTypes == null) { if (cargoTypes == null) {
return []; return [];
} }
var rows = cargoTypes.map((c) { var rows = cargoTypes!.map((c) {
return MyDataRow( return MyDataRow(
onSelectChanged: (bool selected) async {}, onSelectChanged: (bool selected) async {},
cells: [ cells: [
MyDataCell( MyDataCell(
new Text( new Text(
c.name == null ? "" : c.name, c.name ?? '',
style: textStyle, style: textStyle,
), ),
), ),
MyDataCell( MyDataCell(
c.isCutomDuty c.isCutomDuty!
? GestureDetector( ? GestureDetector(
onTap: () async { onTap: () async {
String _t = await showDialog( String _t = await showDialog(
@@ -103,7 +103,7 @@ class _CargoTableState extends State<CargoTable> {
setState(() { setState(() {
c.qty = int.tryParse(_t) ?? 0; c.qty = int.tryParse(_t) ?? 0;
}); });
if (widget.onUpdate != null) widget.onUpdate(c); if (widget.onUpdate != null) widget.onUpdate!(c);
}, },
child: Center( child: Center(
child: Container( child: Container(
@@ -153,7 +153,7 @@ class _CargoTableState extends State<CargoTable> {
if (c.weight != 0) { if (c.weight != 0) {
_cal(); _cal();
} }
if (widget.onUpdate != null) widget.onUpdate(c); if (widget.onUpdate != null) widget.onUpdate!(c);
}, },
child: Container( child: Container(
padding: const EdgeInsets.all(7.0), padding: const EdgeInsets.all(7.0),
@@ -176,7 +176,7 @@ class _CargoTableState extends State<CargoTable> {
color: primaryColor, color: primaryColor,
), ),
onPressed: () { onPressed: () {
if (widget.onRemove != null) widget.onRemove(c); if (widget.onRemove != null) widget.onRemove!(c);
}) })
], ],
), ),
@@ -237,26 +237,25 @@ class _CargoTableState extends State<CargoTable> {
} }
_cal() { _cal() {
var cargoType = autoCalWeight(cargoTypes, totalWeight); var cargoType = autoCalWeight(cargoTypes!, totalWeight);
if (cargoType == null) return; if (cargoType == null) return;
setState(() { setState(() {
cargoTypes.remove(cargoType); cargoTypes!.remove(cargoType);
cargoTypes.add(cargoType); cargoTypes!.add(cargoType);
}); });
if (widget.onUpdate != null) { if (widget.onUpdate != null) {
widget.onUpdate(cargoType); widget.onUpdate!(cargoType);
} }
} }
} }
CargoType autoCalWeight(List<CargoType> cargoTypes, double total) { CargoType? autoCalWeight(List<CargoType> cargoTypes, double total) {
if ((cargoTypes?.length ?? 0) == 0 || total == 0) return null;
List<CargoType> noWeight = cargoTypes.where((c) => c.weight == 0).toList(); List<CargoType> noWeight = cargoTypes.where((c) => c.weight == 0).toList();
if (noWeight.length != 1) return null; if (noWeight.length != 1) return null;
var _existing = double _existing =
cargoTypes.fold(0, (previous, current) => previous + current.weight); cargoTypes.fold(0, (previous, current) => previous + current.weight);
noWeight[0].weight = total - _existing; noWeight[0].weight = total - _existing;

View File

@@ -1,23 +1,21 @@
import 'package:fcs/domain/entities/cargo_type.dart'; import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/my_data_table.dart'; import 'package:fcs/pages/widgets/my_data_table.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'cargo_type_editor.dart';
import 'total_weight_edit.dart'; import 'total_weight_edit.dart';
typedef OnAdd(CargoType cargoType); typedef OnAdd(CargoType cargoType);
typedef OnRemove(CargoType cargoType); typedef OnRemove(CargoType cargoType);
class CargoTable extends StatefulWidget { class CargoTable extends StatefulWidget {
final List<CargoType> cargoTypes; final List<CargoType>? cargoTypes;
final OnAdd onAdd; final OnAdd? onAdd;
final OnRemove onRemove; final OnRemove? onRemove;
const CargoTable({Key key, this.cargoTypes, this.onAdd, this.onRemove}) const CargoTable({Key? key, this.cargoTypes, this.onAdd, this.onRemove})
: super(key: key); : super(key: key);
@override @override
@@ -67,7 +65,7 @@ class _CargoTableState extends State<CargoTable> {
List<String> _types = []; List<String> _types = [];
double _total = 0; double _total = 0;
var rows = widget.cargoTypes.map((c) { var rows = widget.cargoTypes!.map((c) {
_total += c.weight; _total += c.weight;
return MyDataRow( return MyDataRow(
onSelectChanged: (bool selected) async {}, onSelectChanged: (bool selected) async {},
@@ -75,7 +73,7 @@ class _CargoTableState extends State<CargoTable> {
MyDataCell(Row( MyDataCell(Row(
children: [ children: [
new Text( new Text(
c.name == null ? "" : c.name, c.name ?? "",
style: textStyle, style: textStyle,
), ),
new Text( new Text(
@@ -99,7 +97,7 @@ class _CargoTableState extends State<CargoTable> {
color: primaryColor, color: primaryColor,
), ),
onPressed: () { onPressed: () {
if (widget.onRemove != null) widget.onRemove(c); if (widget.onRemove != null) widget.onRemove!(c);
}) })
], ],
), ),
@@ -127,7 +125,7 @@ class _CargoTableState extends State<CargoTable> {
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
child: InkWell( child: InkWell(
onTap: () async { onTap: () async {
double _t = await Navigator.of(context).push<double>( double? _t = await Navigator.of(context).push<double>(
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => builder: (context) =>
TotalWeightEdit(totalWeight: totalWeight))); TotalWeightEdit(totalWeight: totalWeight)));
@@ -135,21 +133,21 @@ class _CargoTableState extends State<CargoTable> {
setState(() { setState(() {
totalWeight = _t; totalWeight = _t;
this.remainingWeight = this.totalWeight - _total; this.remainingWeight = this.totalWeight - _total;
widget.cargoTypes.forEach((c) { widget.cargoTypes!.forEach((c) {
if (c.qty == null) { if (c.qty == null) {
this._cargos.add(c); this._cargos.add(c);
} }
}); });
this._cargos.forEach((c) { this._cargos.forEach((c) {
_list.add(c.name); _list.add(c.name!);
}); });
widget.cargoTypes.forEach((c) { widget.cargoTypes!.forEach((c) {
_types.add(c.name); _types.add(c.name!);
}); });
if (this._cargos.length == widget.cargoTypes.length - 1) { if (this._cargos.length == widget.cargoTypes!.length - 1) {
_types.forEach((t) { _types.forEach((t) {
if (!_list.contains(t)) { if (!_list.contains(t)) {
widget.cargoTypes.forEach((c) { widget.cargoTypes!.forEach((c) {
if (c.name == t) { if (c.name == t) {
c.weight = this.remainingWeight; c.weight = this.remainingWeight;
} }

View File

@@ -29,7 +29,7 @@ import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'cargo_type_addtion.dart'; import 'cargo_type_addtion.dart';
import 'carton_cargo_table.dart'; import 'carton_cargo_table.dart';
@@ -40,7 +40,7 @@ import 'package_carton_editor.dart';
import 'widgets.dart'; import 'widgets.dart';
class CartonEditor extends StatefulWidget { class CartonEditor extends StatefulWidget {
final Carton box; final Carton? box;
CartonEditor({this.box}); CartonEditor({this.box});
@override @override
@@ -51,32 +51,32 @@ class _CartonEditorState extends State<CartonEditor> {
TextEditingController _widthController = new TextEditingController(); TextEditingController _widthController = new TextEditingController();
TextEditingController _heightController = new TextEditingController(); TextEditingController _heightController = new TextEditingController();
TextEditingController _lengthController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController();
DeliveryAddress _deliveryAddress = new DeliveryAddress(); DeliveryAddress? _deliveryAddress = new DeliveryAddress();
List<CargoType> _cargoTypes = []; List<CargoType> _cargoTypes = [];
Carton _carton; Carton? _carton;
bool _isLoading = false; bool _isLoading = false;
bool _isNew; bool _isNew = false;
User _user; User? _user;
String _selectedCartonType; String? _selectedCartonType;
double volumetricRatio = 0; double volumetricRatio = 0;
double shipmentWeight = 0; double shipmentWeight = 0;
FcsShipment _fcsShipment; FcsShipment? _fcsShipment;
List<FcsShipment> _fcsShipments; List<FcsShipment>? _fcsShipments;
List<Carton> _cartons = []; List<Carton> _cartons = [];
CartonSize selectedCatonSize; CartonSize? selectedCatonSize;
//for mix carton //for mix carton
List<Carton> _mixCartons = []; List<Carton> _mixCartons = [];
String _selectedMixBoxType; String? _selectedMixBoxType;
//for carton from cargos //for carton from cargos
User consignee; User? consignee;
User sender; User? sender;
List<Carton> _cartonsFromCartons = []; List<Carton> _cartonsFromCartons = [];
double totalWeight; double? totalWeight;
@override @override
void initState() { void initState() {
@@ -92,28 +92,28 @@ class _CartonEditorState extends State<CartonEditor> {
if (widget.box != null) { if (widget.box != null) {
_carton = widget.box; _carton = widget.box;
_deliveryAddress = _carton.deliveryAddress; _deliveryAddress = _carton!.deliveryAddress;
_widthController.text = _carton.width.toString(); _widthController.text = _carton!.width.toString();
_heightController.text = _carton.height.toString(); _heightController.text = _carton!.height.toString();
_lengthController.text = _carton.length.toString(); _lengthController.text = _carton!.length.toString();
_selectedCartonType = _carton.cartonType; _selectedCartonType = _carton!.cartonType;
_cargoTypes = _carton.cargoTypes.map((e) => e.clone()).toList(); _cargoTypes = _carton!.cargoTypes.map((e) => e.clone()).toList();
_isNew = false; _isNew = false;
_user = User( _user = User(
id: _carton.userID, fcsID: _carton.fcsID, name: _carton.userName); id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
consignee = User( consignee = User(
id: _carton.userID, fcsID: _carton.fcsID, name: _carton.userName); id: _carton!.userID, fcsID: _carton!.fcsID, name: _carton!.userName);
sender = User( sender = User(
id: _carton.senderID, id: _carton!.senderID,
fcsID: _carton.senderFCSID, fcsID: _carton!.senderFCSID,
name: _carton.senderName); name: _carton!.senderName);
_selectedMixBoxType = _carton.mixBoxType ?? ""; _selectedMixBoxType = _carton!.mixBoxType;
this._mixCartons = this._mixCartons =
_carton.mixCartons == null ? [] : List.from(_carton.mixCartons); _carton!.mixCartons == null ? [] : List.from(_carton!.mixCartons);
bool isMixBox = _carton.cartonType == carton_mix_box; bool isMixBox = _carton!.cartonType == carton_mix_box;
bool isFromPackages = _carton.cartonType == carton_from_packages; bool isFromPackages = _carton!.cartonType == carton_from_packages;
if (isFromPackages) _loadPackages(); if (isFromPackages) _loadPackages();
if (!isMixBox) { if (!isMixBox) {
@@ -138,8 +138,8 @@ class _CartonEditorState extends State<CartonEditor> {
FcsShipmentModel fcsShipmentModel = FcsShipmentModel fcsShipmentModel =
Provider.of<FcsShipmentModel>(context, listen: false); Provider.of<FcsShipmentModel>(context, listen: false);
var fcsShipments = await fcsShipmentModel.getActiveFcsShipments(); var fcsShipments = await fcsShipmentModel.getActiveFcsShipments();
var fcsShipment = fcsShipments var fcsShipment =
.firstWhere((e) => e.id == _carton.fcsShipmentID, orElse: () => null); fcsShipments.firstWhere((e) => e.id == _carton!.fcsShipmentID);
setState(() { setState(() {
_fcsShipments = fcsShipments; _fcsShipments = fcsShipments;
_fcsShipment = fcsShipment; _fcsShipment = fcsShipment;
@@ -151,9 +151,9 @@ class _CartonEditorState extends State<CartonEditor> {
PackageModel packageModel = PackageModel packageModel =
Provider.of<PackageModel>(context, listen: false); Provider.of<PackageModel>(context, listen: false);
List<Package> packages = await packageModel.getPackages( List<Package> packages = await packageModel.getPackages(
_user.id, [package_processed_status, package_packed_status]); _user!.id!, [package_processed_status, package_packed_status]);
if (_isNew) { if (_isNew) {
String prevCompare; String? prevCompare;
packages.forEach((p) { packages.forEach((p) {
String compare = (p.deliveryAddress?.fullName ?? "") + String compare = (p.deliveryAddress?.fullName ?? "") +
(p.deliveryAddress?.phoneNumber ?? ""); (p.deliveryAddress?.phoneNumber ?? "");
@@ -169,8 +169,8 @@ class _CartonEditorState extends State<CartonEditor> {
}); });
} else { } else {
packages.forEach((p) { packages.forEach((p) {
if (_carton.packages.contains(p)) { if (_carton!.packages.contains(p)) {
p.isChecked = _carton.packages.firstWhere((cp) => cp == p).isChecked; p.isChecked = _carton!.packages.firstWhere((cp) => cp == p).isChecked;
} else { } else {
p.isChecked = false; p.isChecked = false;
} }
@@ -178,7 +178,7 @@ class _CartonEditorState extends State<CartonEditor> {
} }
setState(() { setState(() {
_carton.packages = packages; _carton!.packages = packages;
}); });
// _populateDeliveryAddress(); // _populateDeliveryAddress();
} }
@@ -195,9 +195,9 @@ class _CartonEditorState extends State<CartonEditor> {
// } // }
_calShipmentWeight() { _calShipmentWeight() {
double l = double.parse(_lengthController.text, (s) => 0); double l = double.parse(_lengthController.text);
double w = double.parse(_widthController.text, (s) => 0); double w = double.parse(_widthController.text);
double h = double.parse(_heightController.text, (s) => 0); double h = double.parse(_heightController.text);
setState(() { setState(() {
shipmentWeight = l * w * h / volumetricRatio; shipmentWeight = l * w * h / volumetricRatio;
}); });
@@ -206,9 +206,9 @@ class _CartonEditorState extends State<CartonEditor> {
_getCartonSize() { _getCartonSize() {
var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false); var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false);
cartonSizeModel.cartonSizes.forEach((c) { cartonSizeModel.cartonSizes.forEach((c) {
if (c.length == _carton.length && if (c.length == _carton!.length &&
c.width == _carton.width && c.width == _carton!.width &&
c.height == _carton.height) { c.height == _carton!.height) {
selectedCatonSize = CartonSize( selectedCatonSize = CartonSize(
id: c.id, id: c.id,
name: c.name, name: c.name,
@@ -232,7 +232,7 @@ class _CartonEditorState extends State<CartonEditor> {
bool isMixBox = _selectedCartonType == carton_mix_box; bool isMixBox = _selectedCartonType == carton_mix_box;
final shipmentBox = DisplayText( final shipmentBox = DisplayText(
text: _carton.fcsShipmentNumber, text: _carton!.fcsShipmentNumber,
labelTextKey: "box.fcs_shipment_num", labelTextKey: "box.fcs_shipment_num",
iconData: Ionicons.ios_airplane, iconData: Ionicons.ios_airplane,
); );
@@ -248,8 +248,8 @@ class _CartonEditorState extends State<CartonEditor> {
labelKey: "shipment.pack.fcs.shipment", labelKey: "shipment.pack.fcs.shipment",
iconData: Ionicons.ios_airplane, iconData: Ionicons.ios_airplane,
display: (u) => u.shipmentNumber, display: (u) => u.shipmentNumber,
selectedValue: _fcsShipment, selectedValue: _fcsShipment!,
values: _fcsShipments, values: _fcsShipments!,
)); ));
final fcsIDBox = Container( final fcsIDBox = Container(
@@ -297,7 +297,7 @@ class _CartonEditorState extends State<CartonEditor> {
readOnly: !_isNew, readOnly: !_isNew,
values: boxModel.cartonTypes, values: boxModel.cartonTypes,
selectedValue: _selectedCartonType, selectedValue: _selectedCartonType,
callback: (v) { callback: (String? v) {
setState(() { setState(() {
_selectedCartonType = v; _selectedCartonType = v;
}); });
@@ -337,7 +337,7 @@ class _CartonEditorState extends State<CartonEditor> {
value: e, value: e,
groupValue: _selectedMixBoxType, groupValue: _selectedMixBoxType,
activeColor: primaryColor, activeColor: primaryColor,
onChanged: (v) { onChanged: (String? v) {
setState(() { setState(() {
_selectedMixBoxType = v; _selectedMixBoxType = v;
}); });
@@ -407,7 +407,7 @@ class _CartonEditorState extends State<CartonEditor> {
color: primaryColor, color: primaryColor,
), ),
onPressed: () async { onPressed: () async {
List<CargoType> cargos = await Navigator.push<List<CargoType>>( List<CargoType>? cargos = await Navigator.push<List<CargoType>>(
context, context,
CupertinoPageRoute(builder: (context) => CargoTypeAddition())); CupertinoPageRoute(builder: (context) => CargoTypeAddition()));
if (cargos == null) return; if (cargos == null) return;
@@ -462,7 +462,7 @@ class _CartonEditorState extends State<CartonEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: consignee != null ? consignee.fcsID : "", text: consignee != null ? consignee!.fcsID : "",
labelTextKey: "processing.fcs.id", labelTextKey: "processing.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
)), )),
@@ -477,7 +477,7 @@ class _CartonEditorState extends State<CartonEditor> {
); );
final consigneeNameBox = DisplayText( final consigneeNameBox = DisplayText(
text: consignee != null ? consignee.name : "", text: consignee != null ? consignee!.name : "",
labelTextKey: "processing.consignee.name", labelTextKey: "processing.consignee.name",
maxLines: 2, maxLines: 2,
iconData: Icons.person, iconData: Icons.person,
@@ -496,7 +496,7 @@ class _CartonEditorState extends State<CartonEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: sender != null ? sender.fcsID : "", text: sender != null ? sender!.fcsID : "",
labelTextKey: "processing.fcs.id", labelTextKey: "processing.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
)), )),
@@ -511,7 +511,7 @@ class _CartonEditorState extends State<CartonEditor> {
); );
final shipperNamebox = DisplayText( final shipperNamebox = DisplayText(
text: sender != null ? sender.name : "", text: sender != null ? sender!.name : "",
labelTextKey: "processing.shipper.name", labelTextKey: "processing.shipper.name",
maxLines: 2, maxLines: 2,
iconData: Icons.person, iconData: Icons.person,
@@ -551,7 +551,7 @@ class _CartonEditorState extends State<CartonEditor> {
children: [ children: [
_isNew _isNew
? Container() ? Container()
: Center(child: getCartonNumberStatus(context, _carton)), : Center(child: getCartonNumberStatus(context, _carton!)),
LocalTitle(textKey: "box.type.title"), LocalTitle(textKey: "box.type.title"),
cartonTypeBox, cartonTypeBox,
LocalTitle(textKey: "box.shipment_info"), LocalTitle(textKey: "box.shipment_info"),
@@ -572,7 +572,7 @@ class _CartonEditorState extends State<CartonEditor> {
isFromPackages ? namebox : Container(), isFromPackages ? namebox : Container(),
isFromPackages isFromPackages
? CartonPackageTable( ? CartonPackageTable(
packages: _carton.packages, packages: _carton!.packages,
onSelect: (p, checked) { onSelect: (p, checked) {
// if (checked && // if (checked &&
// _deliveryAddress != null && // _deliveryAddress != null &&
@@ -623,7 +623,7 @@ class _CartonEditorState extends State<CartonEditor> {
deliveryAddress: _deliveryAddress, deliveryAddress: _deliveryAddress,
labelKey: "box.delivery_address", labelKey: "box.delivery_address",
onTap: () async { onTap: () async {
DeliveryAddress d = DeliveryAddress? d =
await Navigator.push<DeliveryAddress>( await Navigator.push<DeliveryAddress>(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
@@ -631,8 +631,8 @@ class _CartonEditorState extends State<CartonEditor> {
DeliveryAddressSelection( DeliveryAddressSelection(
deliveryAddress: _deliveryAddress, deliveryAddress: _deliveryAddress,
user: User( user: User(
id: _carton.userID, id: _carton!.userID,
name: _carton.userName))), name: _carton!.userName))),
); );
if (d == null) return; if (d == null) return;
setState(() { setState(() {
@@ -667,7 +667,7 @@ class _CartonEditorState extends State<CartonEditor> {
bool isFromCartons = _selectedCartonType == carton_from_cartons; bool isFromCartons = _selectedCartonType == carton_from_cartons;
if (isFromPackages) { if (isFromPackages) {
_loadPackages(); _loadPackages();
c.value.packages = _carton.packages; c.value.packages = _carton!.packages;
Carton _c = await Navigator.push( Carton _c = await Navigator.push(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
@@ -736,20 +736,20 @@ class _CartonEditorState extends State<CartonEditor> {
height: 1, height: 1,
color: Colors.grey, color: Colors.grey,
), ),
onChanged: (CartonSize newValue) { onChanged: (CartonSize? newValue) {
setState(() { setState(() {
if (newValue.name == MANAGE_CARTONSIZE) { if (newValue!.name == MANAGE_CARTONSIZE) {
selectedCatonSize = null; selectedCatonSize = null;
_manageCartonSize(); _manageCartonSize();
return; return;
} }
selectedCatonSize = newValue; selectedCatonSize = newValue;
_widthController.text = _widthController.text =
selectedCatonSize.width.toString(); selectedCatonSize!.width.toString();
_heightController.text = _heightController.text =
selectedCatonSize.height.toString(); selectedCatonSize!.height.toString();
_lengthController.text = _lengthController.text =
selectedCatonSize.length.toString(); selectedCatonSize!.length.toString();
}); });
}, },
isExpanded: true, isExpanded: true,
@@ -789,8 +789,7 @@ class _CartonEditorState extends State<CartonEditor> {
_updateCargo(CargoType cargo) { _updateCargo(CargoType cargo) {
setState(() { setState(() {
var _c = var _c = _cargoTypes.firstWhere((e) => e.id == cargo.id);
_cargoTypes.firstWhere((e) => e.id == cargo.id, orElse: () => null);
if (_c != null) { if (_c != null) {
_c.weight = cargo.weight; _c.weight = cargo.weight;
_c.qty = cargo.qty; _c.qty = cargo.qty;
@@ -827,30 +826,30 @@ class _CartonEditorState extends State<CartonEditor> {
double h = double.parse(_heightController.text, (s) => 0); double h = double.parse(_heightController.text, (s) => 0);
Carton carton = Carton(); Carton carton = Carton();
carton.id = _carton.id; carton.id = _carton!.id;
carton.cartonType = _selectedCartonType; carton.cartonType = _selectedCartonType!;
carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
if (isFromPackages) { if (isFromPackages) {
carton.userID = _user?.id; carton.userID = _user?.id ?? '';
carton.fcsID = _user?.fcsID; carton.fcsID = _user?.fcsID ?? '';
carton.userName = _user?.name; carton.userName = _user?.name ?? '';
carton.packages = _carton.packages.where((e) => e.isChecked).toList(); carton.packages = _carton!.packages.where((e) => e.isChecked).toList();
} }
if (isFromCartons) { if (isFromCartons) {
carton.userID = consignee?.id; carton.userID = consignee?.id ?? "";
carton.fcsID = consignee?.fcsID; carton.fcsID = consignee?.fcsID ?? "";
carton.userName = consignee?.name; carton.userName = consignee?.name ?? "";
carton.senderID = sender?.id; carton.senderID = sender?.id ?? "";
carton.senderFCSID = sender?.fcsID; carton.senderFCSID = sender?.fcsID ?? "";
carton.senderName = sender?.name; carton.senderName = sender?.name ?? "";
} }
carton.cargoTypes = _carton.cargoTypes; carton.cargoTypes = _carton!.cargoTypes;
carton.length = l; carton.length = l;
carton.width = w; carton.width = w;
carton.height = h; carton.height = h;
carton.deliveryAddress = _carton.deliveryAddress; carton.deliveryAddress = _carton!.deliveryAddress;
try { try {
Carton _c = await Navigator.push( Carton _c = await Navigator.push(
@@ -864,7 +863,7 @@ class _CartonEditorState extends State<CartonEditor> {
); );
if (_c == null) return; if (_c == null) return;
var cartonModel = Provider.of<CartonModel>(context, listen: false); var cartonModel = Provider.of<CartonModel>(context, listen: false);
Carton _carton = await cartonModel.getCarton(_c.id); Carton _carton = await cartonModel.getCarton(_c.id ?? "");
if (isFromPackages) { if (isFromPackages) {
_cartons.add(_carton); _cartons.add(_carton);
} }
@@ -898,15 +897,15 @@ class _CartonEditorState extends State<CartonEditor> {
showMsgDialog(context, "Error", "Please select FCS shipment"); showMsgDialog(context, "Error", "Please select FCS shipment");
return; return;
} }
if ((this._mixCartons?.length ?? 0) == 0) { if (this._mixCartons.length == 0) {
showMsgDialog(context, "Error", "Expect at least one carton"); showMsgDialog(context, "Error", "Expect at least one carton");
return; return;
} }
Carton carton = Carton(); Carton carton = Carton();
carton.id = _carton.id; carton.id = _carton!.id;
carton.cartonType = _selectedCartonType; carton.cartonType = _selectedCartonType!;
carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
carton.mixBoxType = _selectedMixBoxType; carton.mixBoxType = _selectedMixBoxType!;
carton.mixCartons = this._mixCartons; carton.mixCartons = this._mixCartons;
setState(() { setState(() {
_isLoading = true; _isLoading = true;
@@ -932,7 +931,7 @@ class _CartonEditorState extends State<CartonEditor> {
_save() async { _save() async {
bool isFromPackages = _selectedCartonType == carton_from_packages; bool isFromPackages = _selectedCartonType == carton_from_packages;
bool isFromCartons = _selectedCartonType == carton_from_cartons; bool isFromCartons = _selectedCartonType == carton_from_cartons;
if ((_cargoTypes?.length ?? 0) == 0 && (isFromPackages || isFromCartons)) { if (_cargoTypes.length == 0 && (isFromPackages || isFromCartons)) {
showMsgDialog(context, "Error", "Expect at least one cargo type"); showMsgDialog(context, "Error", "Expect at least one cargo type");
return; return;
} }
@@ -940,9 +939,9 @@ class _CartonEditorState extends State<CartonEditor> {
showMsgDialog(context, "Error", "Invalid cargo weight"); showMsgDialog(context, "Error", "Invalid cargo weight");
return; return;
} }
double l = double.parse(_lengthController.text, (s) => 0); double l = double.parse(_lengthController.text);
double w = double.parse(_widthController.text, (s) => 0); double w = double.parse(_widthController.text);
double h = double.parse(_heightController.text, (s) => 0); double h = double.parse(_heightController.text);
if ((l <= 0 || w <= 0 || h <= 0) && (isFromPackages || isFromCartons)) { if ((l <= 0 || w <= 0 || h <= 0) && (isFromPackages || isFromCartons)) {
showMsgDialog(context, "Error", "Invalid dimension"); showMsgDialog(context, "Error", "Invalid dimension");
return; return;
@@ -953,16 +952,16 @@ class _CartonEditorState extends State<CartonEditor> {
} }
Carton carton = Carton(); Carton carton = Carton();
carton.id = _carton.id; carton.id = _carton!.id;
carton.cartonType = _selectedCartonType; carton.cartonType = _selectedCartonType!;
carton.fcsShipmentID = _isNew ? _fcsShipment.id : _carton.fcsShipmentID; carton.fcsShipmentID = _isNew ? _fcsShipment!.id : _carton!.fcsShipmentID;
if (isFromPackages) { if (isFromPackages) {
carton.userID = _user?.id; carton.userID = _user?.id ?? "";
carton.packages = _carton.packages.where((e) => e.isChecked).toList(); carton.packages = _carton!.packages.where((e) => e.isChecked).toList();
} }
if (isFromCartons) { if (isFromCartons) {
carton.userID = consignee?.id; carton.userID = consignee?.id ?? "";
carton.senderID = sender?.id; carton.senderID = sender?.id ?? "";
} }
carton.cargoTypes = _cargoTypes; carton.cargoTypes = _cargoTypes;

View File

@@ -1,7 +1,5 @@
import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/entities/carton_size.dart';
import 'package:fcs/domain/entities/package.dart'; import 'package:fcs/domain/entities/package.dart';
import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/domain/vo/delivery_address.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
@@ -19,7 +17,7 @@ import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -33,7 +31,7 @@ import 'widgets.dart';
final DateFormat dateFormat = DateFormat("d MMM yyyy"); final DateFormat dateFormat = DateFormat("d MMM yyyy");
class CartonInfo extends StatefulWidget { class CartonInfo extends StatefulWidget {
final Carton box; final Carton? box;
CartonInfo({this.box}); CartonInfo({this.box});
@override @override
@@ -42,22 +40,22 @@ class CartonInfo extends StatefulWidget {
class _CartonInfoState extends State<CartonInfo> { class _CartonInfoState extends State<CartonInfo> {
bool _isLoading = false; bool _isLoading = false;
Carton _box; Carton? _box;
DeliveryAddress _deliveryAddress = new DeliveryAddress(); DeliveryAddress? _deliveryAddress = new DeliveryAddress();
TextEditingController _widthController = new TextEditingController(); TextEditingController _widthController = new TextEditingController();
TextEditingController _heightController = new TextEditingController(); TextEditingController _heightController = new TextEditingController();
TextEditingController _lengthController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController();
TextEditingController _cartonSizeController = new TextEditingController(); TextEditingController _cartonSizeController = new TextEditingController();
double volumetricRatio = 0; double volumetricRatio = 0;
double shipmentWeight = 0; double shipmentWeight = 0;
String selectMixBoxType; String? selectMixBoxType;
bool isMixBox; bool isMixBox = false;
bool isFromShipments; bool isFromShipments = false;
bool isFromPackages; bool isFromPackages = false;
bool isSmallBag; bool isSmallBag = false;
bool isFromCartons; bool isFromCartons = false;
bool isEdiable; bool isEdiable = false;
@override @override
void initState() { void initState() {
@@ -77,31 +75,31 @@ class _CartonInfoState extends State<CartonInfo> {
} }
_updateBoxData() { _updateBoxData() {
_widthController.text = _box.width.toString(); _widthController.text = _box!.width.toString();
_heightController.text = _box.height.toString(); _heightController.text = _box!.height.toString();
_lengthController.text = _box.length.toString(); _lengthController.text = _box!.length.toString();
_cartonSizeController.text = _box.cartonSizeName ?? ""; _cartonSizeController.text = _box!.cartonSizeName ?? "";
_deliveryAddress = _box.deliveryAddress; _deliveryAddress = _box!.deliveryAddress;
isMixBox = _box.cartonType == carton_mix_box; isMixBox = _box!.cartonType == carton_mix_box;
isFromShipments = _box.cartonType == carton_from_shipments; isFromShipments = _box!.cartonType == carton_from_shipments;
isFromPackages = _box.cartonType == carton_from_packages; isFromPackages = _box!.cartonType == carton_from_packages;
isSmallBag = _box.cartonType == carton_small_bag; isSmallBag = _box!.cartonType == carton_small_bag;
isFromCartons = _box.cartonType == carton_from_cartons; isFromCartons = _box!.cartonType == carton_from_cartons;
isEdiable = (isFromPackages || isMixBox || isFromCartons) && isEdiable = (isFromPackages || isMixBox || isFromCartons) &&
_box.status == carton_packed_status; _box!.status == carton_packed_status;
selectMixBoxType = _box.mixBoxType ?? ""; selectMixBoxType = _box!.mixBoxType;
getCartonSize(); getCartonSize();
} }
getCartonSize() { getCartonSize() {
var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false); var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false);
cartonSizeModel.cartonSizes.forEach((c) { cartonSizeModel.cartonSizes.forEach((c) {
if (c.length == _box.length && if (c.length == _box!.length &&
c.width == _box.width && c.width == _box!.width &&
c.height == _box.height) { c.height == _box!.height) {
setState(() { setState(() {
_cartonSizeController.text = c.name; _cartonSizeController.text = c.name ?? "";
}); });
} }
}); });
@@ -110,43 +108,45 @@ class _CartonInfoState extends State<CartonInfo> {
_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!.userID == 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!.userID ?? "", [
package_processed_status, package_processed_status,
package_packed_status, package_packed_status,
package_shipped_status, package_shipped_status,
package_delivered_status package_delivered_status
]); ]);
packages = packages.where((p) => _box.packageIDs.contains(p.id)).toList(); packages = packages.where((p) => _box!.packageIDs.contains(p.id)).toList();
packages.forEach((p) { packages.forEach((p) {
p.isChecked = true; p.isChecked = true;
}); });
setState(() { setState(() {
_box.packages = packages; _box!.packages = packages;
}); });
} }
_loadMixCartons() async { _loadMixCartons() async {
if (_box.cartonType != carton_mix_box) return; if (_box!.cartonType != carton_mix_box) return;
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false); CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
List<Carton> catons = []; List<Carton> catons = [];
for (var id in _box.mixCartonIDs) { for (var id in _box!.mixCartonIDs) {
Carton c = await cartonModel.getCarton(id); Carton c = await cartonModel.getCarton(id);
catons.add(c); catons.add(c);
} }
setState(() { setState(() {
_box.mixCartons = catons; _box!.mixCartons = catons;
}); });
} }
_calShipmentWeight() { _calShipmentWeight() {
double l = double.parse(_lengthController.text, (s) => 0); double l = double.parse(_lengthController.text);
double w = double.parse(_widthController.text, (s) => 0); double w = double.parse(_widthController.text);
double h = double.parse(_heightController.text, (s) => 0); double h = double.parse(_heightController.text);
setState(() { setState(() {
shipmentWeight = l * w * h / volumetricRatio; shipmentWeight = l * w * h / volumetricRatio;
}); });
@@ -166,33 +166,34 @@ class _CartonInfoState extends State<CartonInfo> {
final cartonTypeBox = LocalRadioButtons( final cartonTypeBox = LocalRadioButtons(
readOnly: true, readOnly: true,
values: cartonModel.cartonTypesInfo, values: cartonModel.cartonTypesInfo,
selectedValue: selectedValue: (_box!.isShipmentCarton ?? false)
_box.isShipmentCarton ? carton_from_shipments : _box.cartonType); ? carton_from_shipments
: _box!.cartonType);
final shipmentBox = DisplayText( final shipmentBox = DisplayText(
text: _box.fcsShipmentNumber, text: _box!.fcsShipmentNumber,
labelTextKey: "box.fcs_shipment_num", labelTextKey: "box.fcs_shipment_num",
iconData: Ionicons.ios_airplane, iconData: Ionicons.ios_airplane,
); );
final fcsIDBox = DisplayText( final fcsIDBox = DisplayText(
text: _box.fcsID == null ? "" : _box.fcsID, text: _box!.fcsID == null ? "" : _box!.fcsID,
labelTextKey: "box.fcs.id", labelTextKey: "box.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
); );
final customerNameBox = DisplayText( final customerNameBox = DisplayText(
text: _box.userName == null ? "" : _box.userName, text: _box!.userName == null ? "" : _box!.userName,
labelTextKey: "box.name", labelTextKey: "box.name",
iconData: Icons.person, iconData: Icons.person,
); );
final consigneefcsIDBox = DisplayText( final consigneefcsIDBox = DisplayText(
text: _box.fcsID != null ? _box.fcsID : "", text: _box!.fcsID != null ? _box!.fcsID : "",
labelTextKey: "processing.fcs.id", labelTextKey: "processing.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
); );
final consigneeNameBox = DisplayText( final consigneeNameBox = DisplayText(
text: _box.userName != null ? _box.userName : "", text: _box!.userName != null ? _box!.userName : "",
labelTextKey: "processing.consignee.name", labelTextKey: "processing.consignee.name",
maxLines: 2, maxLines: 2,
iconData: Icons.person, iconData: Icons.person,
@@ -211,7 +212,7 @@ class _CartonInfoState extends State<CartonInfo> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: _box.senderFCSID != null ? _box.senderFCSID : "", text: _box!.senderFCSID,
labelTextKey: "processing.fcs.id", labelTextKey: "processing.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
)), )),
@@ -219,7 +220,7 @@ class _CartonInfoState extends State<CartonInfo> {
); );
final shipperNamebox = DisplayText( final shipperNamebox = DisplayText(
text: _box.senderName != null ? _box.senderName : "", text: _box!.senderName,
labelTextKey: "processing.shipper.name", labelTextKey: "processing.shipper.name",
maxLines: 2, maxLines: 2,
iconData: Icons.person, iconData: Icons.person,
@@ -269,10 +270,10 @@ class _CartonInfoState extends State<CartonInfo> {
iconData: AntDesign.CodeSandbox, iconData: AntDesign.CodeSandbox,
); );
final cargoTableBox = CargoTable( final cargoTableBox = CargoTable(
cargoTypes: _box.cargoTypes, cargoTypes: _box!.cargoTypes,
); );
final mixCartonNumberBox = DisplayText( final mixCartonNumberBox = DisplayText(
text: _box.mixCartonNumber, text: _box!.mixCartonNumber,
labelTextKey: "box.mix.carton", labelTextKey: "box.mix.carton",
iconData: MaterialCommunityIcons.package, iconData: MaterialCommunityIcons.package,
); );
@@ -300,7 +301,7 @@ class _CartonInfoState extends State<CartonInfo> {
color: primaryColor, color: primaryColor,
), ),
), ),
Text(selectMixBoxType) Text(selectMixBoxType ?? "")
], ],
) )
], ],
@@ -340,7 +341,7 @@ class _CartonInfoState extends State<CartonInfo> {
body: Padding( body: Padding(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
child: ListView(shrinkWrap: true, children: <Widget>[ child: ListView(shrinkWrap: true, children: <Widget>[
Center(child: getCartonNumberStatus(context, _box)), Center(child: getCartonNumberStatus(context, _box!)),
LocalTitle(textKey: "box.type.title"), LocalTitle(textKey: "box.type.title"),
cartonTypeBox, cartonTypeBox,
LocalTitle(textKey: "box.shipment_info"), LocalTitle(textKey: "box.shipment_info"),
@@ -367,11 +368,11 @@ class _CartonInfoState extends State<CartonInfo> {
isMixBox ? mixTypeBox : Container(), isMixBox ? mixTypeBox : Container(),
isMixBox ? LocalTitle(textKey: "box.mix_caton_title") : Container(), isMixBox ? LocalTitle(textKey: "box.mix_caton_title") : Container(),
isMixBox isMixBox
? Column(children: _getCartons(context, _box.mixCartons)) ? Column(children: _getCartons(context, _box!.mixCartons))
: Container(), : Container(),
isFromPackages || isSmallBag isFromPackages || isSmallBag
? CartonPackageTable( ? CartonPackageTable(
packages: _box.packages, packages: _box!.packages,
) )
: Container(), : Container(),
isMixBox ? Container() : LocalTitle(textKey: "box.cargo.type"), isMixBox ? Container() : LocalTitle(textKey: "box.cargo.type"),
@@ -408,14 +409,14 @@ class _CartonInfoState extends State<CartonInfo> {
} }
_gotoEditor() async { _gotoEditor() async {
_box.mixCartons = _box.mixCartons; _box!.mixCartons = _box!.mixCartons;
bool updated = await Navigator.push<bool>( bool? updated = await Navigator.push<bool>(
context, context,
CupertinoPageRoute(builder: (context) => CartonEditor(box: _box)), CupertinoPageRoute(builder: (context) => CartonEditor(box: _box)),
); );
if (updated ?? false) { if (updated ?? false) {
var cartonModel = Provider.of<CartonModel>(context, listen: false); var cartonModel = Provider.of<CartonModel>(context, listen: false);
var c = await cartonModel.getCarton(widget.box.id); var c = await cartonModel.getCarton(widget.box!.id ?? "");
setState(() { setState(() {
_box = c; _box = c;
_loadPackages(); _loadPackages();
@@ -437,7 +438,7 @@ class _CartonInfoState extends State<CartonInfo> {
}); });
try { try {
var cartonModel = Provider.of<CartonModel>(context, listen: false); var cartonModel = Provider.of<CartonModel>(context, listen: false);
await cartonModel.deleteCarton(widget.box); await cartonModel.deleteCarton(widget.box!);
Navigator.pop(context, true); Navigator.pop(context, true);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());

View File

@@ -3,13 +3,13 @@ import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'carton_info.dart'; import 'carton_info.dart';
class CartonListRow extends StatelessWidget { class CartonListRow extends StatelessWidget {
final Carton box; final Carton box;
CartonListRow({Key key, this.box}) : super(key: key); CartonListRow({Key? key, required this.box}) : super(key: key);
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = new DateFormat("dd MMM yyyy");
@@ -71,14 +71,14 @@ class CartonListRow extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: getStatus(box.status == null ? "" : box.status), child: getStatus(box.status ?? ""),
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5),
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
new Text( new Text(
"${box.cartonWeight?.toStringAsFixed(2) ?? ''} lb", "${box.cartonWeight?.toStringAsFixed(2)} lb",
style: style:
new TextStyle(fontSize: 15.0, color: Colors.grey), new TextStyle(fontSize: 15.0, color: Colors.grey),
), ),

View File

@@ -8,10 +8,10 @@ import 'package:flutter/material.dart';
typedef OnSelect = Function(Carton carton, bool checked); typedef OnSelect = Function(Carton carton, bool checked);
class CartonMixTable extends StatelessWidget { class CartonMixTable extends StatelessWidget {
final List<Carton> cartons; final List<Carton>? cartons;
final OnSelect onSelect; final OnSelect? onSelect;
const CartonMixTable({Key key, this.cartons, this.onSelect}) const CartonMixTable({Key? key, this.cartons, this.onSelect})
: super(key: key); : super(key: key);
@override @override
@@ -32,21 +32,21 @@ class CartonMixTable extends StatelessWidget {
); );
final rows = cartons == null final rows = cartons == null
? [] ? [Container()]
: cartons.asMap().entries.map((p) { : cartons!.asMap().entries.map((p) {
return Container( return Container(
color: p.value.isChecked color: (p.value.isChecked ?? false)
? Colors.grey.withOpacity(0.2) ? Colors.grey.withOpacity(0.2)
: Colors.grey[50].withOpacity(0.2), : Colors.grey.shade50.withOpacity(0.2),
child: Container( child: Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), left: 0.0, right: 10.0, top: 3.0, bottom: 3.0),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
color: p.key == cartons.length - 1 color: p.key == cartons!.length - 1
? Colors.white ? Colors.white
: Colors.grey[350], : Colors.grey.shade300,
width: 1), width: 1),
), ),
), ),
@@ -55,8 +55,8 @@ class CartonMixTable extends StatelessWidget {
Checkbox( Checkbox(
value: p.value.isChecked, value: p.value.isChecked,
activeColor: primaryColor, activeColor: primaryColor,
onChanged: (bool check) { onChanged: (bool? check) {
if (onSelect != null) onSelect(p.value, check); if (onSelect != null) onSelect!(p.value, check!);
}), }),
Expanded( Expanded(
child: new Text( child: new Text(
@@ -64,7 +64,7 @@ class CartonMixTable extends StatelessWidget {
style: textStyle, style: textStyle,
)), )),
new Text( new Text(
p.value?.actualWeight?.toString() ?? "", p.value.actualWeight.toString(),
style: textStyle, style: textStyle,
), ),
], ],

View File

@@ -8,10 +8,10 @@ import 'package:flutter/material.dart';
typedef OnSelect = Function(Package package, bool checked); typedef OnSelect = Function(Package package, bool checked);
class CartonPackageTable extends StatelessWidget { class CartonPackageTable extends StatelessWidget {
final List<Package> packages; final List<Package>? packages;
final OnSelect onSelect; final OnSelect? onSelect;
const CartonPackageTable({Key key, this.packages, this.onSelect}) const CartonPackageTable({Key? key, this.packages, this.onSelect})
: super(key: key); : super(key: key);
@override @override
@@ -34,20 +34,20 @@ class CartonPackageTable extends StatelessWidget {
final rows = packages == null final rows = packages == null
? [Container()] ? [Container()]
: packages.asMap().entries.map((p) { : packages!.asMap().entries.map((p) {
return Container( return Container(
color: p.value.isChecked color: p.value.isChecked
? Colors.grey.withOpacity(0.2) ? Colors.grey.withOpacity(0.2)
: Colors.grey[50].withOpacity(0.2), : Colors.grey.shade50.withOpacity(0.2),
child: Container( child: Container(
padding: EdgeInsets.only( padding: EdgeInsets.only(
left: 0.0, right: 10.0, top: 3.0, bottom: 3.0), left: 0.0, right: 10.0, top: 3.0, bottom: 3.0),
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
bottom: BorderSide( bottom: BorderSide(
color: p.key == packages.length - 1 color: p.key == packages!.length - 1
? Colors.white ? Colors.white
: Colors.grey[350], : Colors.grey.shade300,
width: 1), width: 1),
), ),
), ),
@@ -62,15 +62,15 @@ class CartonPackageTable extends StatelessWidget {
: Checkbox( : Checkbox(
value: p.value.isChecked, value: p.value.isChecked,
activeColor: primaryColor, activeColor: primaryColor,
onChanged: (bool check) { onChanged: (bool? check) {
if (onSelect != null) onSelect(p.value, check); if (onSelect != null) onSelect!(p.value, check!);
}), }),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
p.value.trackingID, p.value.trackingID ?? "",
style: textStyle, style: textStyle,
), ),
Text( Text(
@@ -88,11 +88,11 @@ class CartonPackageTable extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
new Text( new Text(
p.value?.desc ?? "", p.value.desc ?? "",
style: textStyle, style: textStyle,
), ),
new Text( new Text(
"(${p.value?.market ?? ""})", "(${p.value.market})",
style: textStyle, style: textStyle,
) )
], ],

View File

@@ -2,15 +2,15 @@ import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
typedef OnRemove(Carton carton); typedef OnRemove(Carton carton);
class CartonRow extends StatelessWidget { class CartonRow extends StatelessWidget {
final Carton box; final Carton box;
final OnRemove onRemove; final OnRemove? onRemove;
CartonRow({Key key, this.box, this.onRemove}) : super(key: key); CartonRow({Key? key, required this.box, this.onRemove}) : super(key: key);
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = new DateFormat("dd MMM yyyy");
@@ -20,7 +20,7 @@ class CartonRow extends StatelessWidget {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
bottom: BorderSide(color: Colors.grey[300]), bottom: BorderSide(color: Colors.grey.shade300),
), ),
), ),
child: Row( child: Row(
@@ -75,7 +75,7 @@ class CartonRow extends StatelessWidget {
color: primaryColor, color: primaryColor,
), ),
onPressed: () { onPressed: () {
if (onRemove != null) onRemove(box); if (onRemove != null) onRemove!(box);
}), }),
box.actualWeight == 0 box.actualWeight == 0
? Container() ? Container()
@@ -84,7 +84,7 @@ class CartonRow extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
new Text( new Text(
"${box.actualWeight?.toStringAsFixed(2) ?? ''} lb", "${box.actualWeight.toStringAsFixed(2)} lb",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),

View File

@@ -3,10 +3,10 @@ import 'package:flutter/material.dart';
typedef OnAdd(String value); typedef OnAdd(String value);
class InputTextBorder extends StatelessWidget { class InputTextBorder extends StatelessWidget {
final OnAdd onAdd; final OnAdd? onAdd;
final TextEditingController controller; final TextEditingController? controller;
const InputTextBorder({Key key, this.onAdd, this.controller}) const InputTextBorder({Key? key, this.onAdd, this.controller})
: super(key: key); : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -14,7 +14,7 @@ class InputTextBorder extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
controller: controller, controller: controller,
onChanged: (v) { onChanged: (v) {
if (onAdd != null) onAdd(v); if (onAdd != null) onAdd!(v);
}, },
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
decoration: new InputDecoration( decoration: new InputDecoration(

View File

@@ -3,9 +3,7 @@ import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart'; import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/constants.dart'; import 'package:fcs/domain/constants.dart';
import 'package:fcs/domain/entities/cargo_type.dart';
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/domain/vo/message.dart';
import 'package:fcs/domain/vo/shipment_status.dart'; import 'package:fcs/domain/vo/shipment_status.dart';
import 'package:fcs/helpers/paginator.dart'; import 'package:fcs/helpers/paginator.dart';
import 'package:fcs/pages/main/model/base_model.dart'; import 'package:fcs/pages/main/model/base_model.dart';
@@ -14,19 +12,20 @@ import 'package:logging/logging.dart';
class CartonModel extends BaseModel { class CartonModel extends BaseModel {
List<Carton> _boxes = []; List<Carton> _boxes = [];
PaginatorListener cartonsByFilter; late PaginatorListener<Carton> cartonsByFilter;
final log = Logger('CartonModel'); final log = Logger('CartonModel');
List<Carton> get boxes => List<Carton> get boxes => _selectedIndex == 1
_selectedIndex == 1 ? _boxes : List<Carton>.from(_delivered.values); ? _boxes
: List<Carton>.from(_delivered?.values ?? []);
Paginator _delivered; Paginator? _delivered;
int _selectedIndex = 1; int _selectedIndex = 1;
int _selectedIndexFilter = 1; int _selectedIndexFilter = 1;
bool isLoading = false; bool isLoading = false;
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot>? listener;
StreamSubscription<QuerySnapshot> cartonListener; StreamSubscription<QuerySnapshot>? cartonListener;
static List<ShipmentStatus> statusHistory = [ static List<ShipmentStatus> statusHistory = [
ShipmentStatus(status: "Packed", date: DateTime(2020, 6, 1), done: true), ShipmentStatus(status: "Packed", date: DateTime(2020, 6, 1), done: true),
ShipmentStatus(status: "Shipped", date: DateTime(2020, 6, 5), done: false), ShipmentStatus(status: "Shipped", date: DateTime(2020, 6, 5), done: false),
@@ -87,22 +86,22 @@ class CartonModel extends BaseModel {
notifyListeners(); notifyListeners();
} }
get selectedIndex => _selectedIndex; int get selectedIndex => _selectedIndex;
get selectedIndexFilter => _selectedIndexFilter; int get selectedIndexFilter => _selectedIndexFilter;
initData() async { initData() async {
_selectedIndex = 1; _selectedIndex = 1;
_selectedIndexFilter = 1; _selectedIndexFilter = 1;
_loadBoxes(); _loadBoxes();
if (_delivered != null) _delivered.close(); if (_delivered != null) _delivered!.close();
_delivered = _getDelivered(); _delivered = _getDelivered();
_delivered.load(); _delivered!.load();
} }
@override @override
void privilegeChanged() { void privilegeChanged() {
if (user != null || !user.hasCarton()) { if (user != null || !user!.hasCarton()) {
_initData(); _initData();
} }
} }
@@ -120,12 +119,12 @@ class CartonModel extends BaseModel {
} }
Future<void> _loadBoxes() async { Future<void> _loadBoxes() async {
if (user == null || !user.hasCarton()) return; if (user == null || !user!.hasCarton()) return;
String path = "/$cartons_collection/"; String path = "/$cartons_collection/";
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
_boxes = []; _boxes = [];
try { try {
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("status", .where("status",
whereIn: [carton_packed_status, carton_shipped_status]) whereIn: [carton_packed_status, carton_shipped_status])
@@ -134,9 +133,10 @@ class CartonModel extends BaseModel {
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
_boxes.clear(); _boxes.clear();
_boxes = snapshot.documents.map((documentSnapshot) { _boxes = snapshot.docs.map((documentSnapshot) {
var s = Carton.fromMap( var s = Carton.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return s; return s;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -147,18 +147,18 @@ class CartonModel extends BaseModel {
} }
Future<void> _loadCartonsByFilter(String orderName) async { Future<void> _loadCartonsByFilter(String orderName) async {
if (user == null || !user.hasCarton()) return null; if (user == null || !user!.hasCarton()) return null;
String path = "/$cartons_collection"; String path = "/$cartons_collection";
try { try {
Query listenerQuery = Firestore.instance Query listenerQuery = FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("carton_type", whereIn: [ .where("carton_type", whereIn: [
carton_from_packages, carton_from_packages,
carton_from_cartons carton_from_cartons
]).where("status", isEqualTo: carton_packed_status); ]).where("status", isEqualTo: carton_packed_status);
Query pageQuery = Firestore.instance Query pageQuery = FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("carton_type", .where("carton_type",
whereIn: [carton_from_packages, carton_from_cartons]) whereIn: [carton_from_packages, carton_from_cartons])
@@ -172,10 +172,10 @@ class CartonModel extends BaseModel {
} }
} }
Paginator _getDelivered() { Paginator? _getDelivered() {
if (user == null || !user.hasCarton()) return null; if (user == null || !user!.hasCarton()) return null;
var pageQuery = Firestore.instance var pageQuery = FirebaseFirestore.instance
.collection("/$cartons_collection") .collection("/$cartons_collection")
.where("is_delivered", isEqualTo: true) .where("is_delivered", isEqualTo: true)
.where("is_deleted", isEqualTo: false); .where("is_deleted", isEqualTo: false);
@@ -186,10 +186,10 @@ class CartonModel extends BaseModel {
} }
Future<void> loadMore() async { Future<void> loadMore() async {
if (_delivered.ended || selectedIndex == 1) return; if (_delivered == null && _delivered!.ended || selectedIndex == 1) return;
isLoading = true; isLoading = true;
notifyListeners(); notifyListeners();
await _delivered.load(onFinished: () { await _delivered!.load(onFinished: () {
isLoading = false; isLoading = false;
notifyListeners(); notifyListeners();
}); });
@@ -197,7 +197,7 @@ class CartonModel extends BaseModel {
Future<void> refresh() async { Future<void> refresh() async {
if (selectedIndex == 1) return; if (selectedIndex == 1) return;
await _delivered.refresh(onFinished: () { await _delivered?.refresh(onFinished: () {
notifyListeners(); notifyListeners();
}); });
} }
@@ -208,69 +208,62 @@ class CartonModel extends BaseModel {
@override @override
logout() async { logout() async {
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
if (cartonListener != null) await cartonListener.cancel(); if (cartonListener != null) await cartonListener!.cancel();
if (_delivered != null) _delivered.close(); if (_delivered != null) _delivered!.close();
if (cartonsByFilter != null) cartonsByFilter.close(); if (cartonsByFilter != null) cartonsByFilter.close();
_boxes = []; _boxes = [];
} }
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 Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection(path) .collection(path)
.where("shipment_id", isEqualTo: shipmentID) .where("shipment_id", isEqualTo: shipmentID)
.getDocuments(); .get();
return querySnap.documents return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
.map((e) => Carton.fromMap(e.data, e.documentID))
.toList();
} }
Future<List<Carton>> getCartonsByFcsShipment(String fcsShipmentID) async { Future<List<Carton>> getCartonsByFcsShipment(String fcsShipmentID) async {
String path = "/$cartons_collection"; String path = "/$cartons_collection";
var querySnap = await Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection(path) .collection(path)
.where("fcs_shipment_id", isEqualTo: fcsShipmentID) .where("fcs_shipment_id", isEqualTo: fcsShipmentID)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(); .get();
return querySnap.documents return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
.map((e) => Carton.fromMap(e.data, e.documentID))
.toList();
} }
Future<List<Carton>> getCartonsForInvoice( Future<List<Carton>> getCartonsForInvoice(
String fcsShipmentID, String userID) async { String fcsShipmentID, String userID) async {
String path = "/$cartons_collection"; String path = "/$cartons_collection";
var querySnap = await Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection(path) .collection(path)
.where("fcs_shipment_id", isEqualTo: fcsShipmentID) .where("fcs_shipment_id", isEqualTo: fcsShipmentID)
.where("user_id", isEqualTo: userID) .where("user_id", isEqualTo: userID)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.where("is_invoiced", isEqualTo: false) .where("is_invoiced", isEqualTo: false)
.getDocuments(); .get();
List<Carton> cartons = querySnap.documents List<Carton> cartons =
.map((e) => Carton.fromMap(e.data, e.documentID)) querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
.toList();
return cartons; return cartons;
} }
Future<List<Carton>> getMixCartonsByFcsShipment(String fcsShipmentID) async { Future<List<Carton>> getMixCartonsByFcsShipment(String fcsShipmentID) async {
String path = "/$cartons_collection"; String path = "/$cartons_collection";
var querySnap = await Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection(path) .collection(path)
.where("fcs_shipment_id", isEqualTo: fcsShipmentID) .where("fcs_shipment_id", isEqualTo: fcsShipmentID)
.where("carton_type", isEqualTo: carton_mix_box) .where("carton_type", isEqualTo: carton_mix_box)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(); .get();
return querySnap.documents return querySnap.docs.map((e) => Carton.fromMap(e.data(), e.id)).toList();
.map((e) => Carton.fromMap(e.data, e.documentID))
.toList();
} }
Future<Carton> getCarton(String id) async { Future<Carton> getCarton(String id) async {
String path = "/$cartons_collection"; String path = "/$cartons_collection";
var snap = await Firestore.instance.collection(path).document(id).get(); var snap = await FirebaseFirestore.instance.collection(path).doc(id).get();
return Carton.fromMap(snap.data, snap.documentID); return Carton.fromMap(snap.data() as Map<String, dynamic>, snap.id);
} }
Future<Carton> createCarton(Carton carton) { Future<Carton> createCarton(Carton carton) {

View File

@@ -8,12 +8,9 @@ import 'package:fcs/domain/vo/delivery_address.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/carton_size/carton_size_list.dart'; import 'package:fcs/pages/carton_size/carton_size_list.dart';
import 'package:fcs/pages/carton_size/model/carton_size_model.dart'; import 'package:fcs/pages/carton_size/model/carton_size_model.dart';
import 'package:fcs/pages/delivery_address/model/delivery_address_model.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/widgets/defalut_delivery_address.dart'; import 'package:fcs/pages/widgets/defalut_delivery_address.dart';
import 'package:fcs/pages/widgets/delivery_address_selection.dart'; import 'package:fcs/pages/widgets/delivery_address_selection.dart';
import 'package:fcs/pages/widgets/display_text.dart';
import 'package:fcs/pages/widgets/length_picker.dart'; import 'package:fcs/pages/widgets/length_picker.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';
@@ -21,7 +18,7 @@ import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'cargo_type_addtion.dart'; import 'cargo_type_addtion.dart';
@@ -29,9 +26,9 @@ import 'carton_cargo_table.dart';
import 'model/carton_model.dart'; import 'model/carton_model.dart';
class PackageCartonEditor extends StatefulWidget { class PackageCartonEditor extends StatefulWidget {
final Carton carton; final Carton? carton;
final bool isNew; final bool? isNew;
final User consignee; final User? consignee;
PackageCartonEditor({this.carton, this.isNew, this.consignee}); PackageCartonEditor({this.carton, this.isNew, this.consignee});
@override @override
@@ -43,13 +40,13 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
TextEditingController _widthCtl = new TextEditingController(); TextEditingController _widthCtl = new TextEditingController();
TextEditingController _heightCtl = new TextEditingController(); TextEditingController _heightCtl = new TextEditingController();
Carton _carton; Carton? _carton;
bool _isLoading = false; bool _isLoading = false;
DeliveryAddress _deliveryAddress = new DeliveryAddress(); DeliveryAddress? _deliveryAddress = new DeliveryAddress();
List<CargoType> _cargoTypes = []; List<CargoType> _cargoTypes = [];
CartonSize selectedCatonSize; CartonSize? selectedCatonSize;
bool isFromPackages; bool isFromPackages = false;
bool isFromCartons; bool isFromCartons = false;
@override @override
void initState() { void initState() {
@@ -59,19 +56,19 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
_load() { _load() {
_carton = widget.carton; _carton = widget.carton;
isFromPackages = _carton.cartonType == carton_from_packages; isFromPackages = _carton!.cartonType == carton_from_packages;
isFromCartons = _carton.cartonType == carton_from_cartons; isFromCartons = _carton!.cartonType == carton_from_cartons;
if (widget.isNew) { if (widget.isNew!) {
_lengthCtl.text = "0"; _lengthCtl.text = "0";
_widthCtl.text = "0"; _widthCtl.text = "0";
_heightCtl.text = "0"; _heightCtl.text = "0";
} else { } else {
_cargoTypes = widget.carton.cargoTypes.map((e) => e.clone()).toList(); _cargoTypes = widget.carton!.cargoTypes.map((e) => e.clone()).toList();
_lengthCtl.text = _carton.length.toString(); _lengthCtl.text = _carton!.length.toString();
_widthCtl.text = _carton.width.toString(); _widthCtl.text = _carton!.width.toString();
_heightCtl.text = _carton.height.toString(); _heightCtl.text = _carton!.height.toString();
_deliveryAddress = _carton.deliveryAddress; _deliveryAddress = _carton!.deliveryAddress;
_getCartonSize(); _getCartonSize();
} }
} }
@@ -79,9 +76,9 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
_getCartonSize() { _getCartonSize() {
var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false); var cartonSizeModel = Provider.of<CartonSizeModel>(context, listen: false);
cartonSizeModel.cartonSizes.forEach((c) { cartonSizeModel.cartonSizes.forEach((c) {
if (c.length == _carton.length && if (c.length == _carton!.length &&
c.width == _carton.width && c.width == _carton!.width &&
c.height == _carton.height) { c.height == _carton!.height) {
selectedCatonSize = CartonSize( selectedCatonSize = CartonSize(
id: c.id, id: c.id,
name: c.name, name: c.name,
@@ -122,7 +119,7 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
], ],
); );
final createBtn = LocalButton( final createBtn = LocalButton(
textKey: widget.isNew ? "box.new_carton_btn" : "box.cargo.save.btn", textKey: widget.isNew! ? "box.new_carton_btn" : "box.cargo.save.btn",
callBack: _creatCarton, callBack: _creatCarton,
); );
@@ -134,11 +131,10 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
color: primaryColor, color: primaryColor,
), ),
onPressed: () async { onPressed: () async {
List<CargoType> cargos = await Navigator.push<List<CargoType>>( List<CargoType>? cargos = await Navigator.push<List<CargoType>>(
context, context,
CupertinoPageRoute(builder: (context) => CargoTypeAddition())); CupertinoPageRoute(builder: (context) => CargoTypeAddition()));
if (cargos == null) return; if (cargos == null) return;
if (cargos == null) return;
setState(() { setState(() {
_cargoTypes.addAll( _cargoTypes.addAll(
cargos.where((e) => !_cargoTypes.contains(e)).toList()); cargos.where((e) => !_cargoTypes.contains(e)).toList());
@@ -168,7 +164,7 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
backgroundColor: Colors.white, backgroundColor: Colors.white,
title: LocalText( title: LocalText(
context, context,
widget.isNew ? "boxes.create.title" : "box.edit.title", widget.isNew! ? "boxes.create.title" : "box.edit.title",
fontSize: 20, fontSize: 20,
color: primaryColor, color: primaryColor,
), ),
@@ -187,13 +183,14 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
deliveryAddress: _deliveryAddress, deliveryAddress: _deliveryAddress,
labelKey: "box.delivery_address", labelKey: "box.delivery_address",
onTap: () async { onTap: () async {
DeliveryAddress d = await Navigator.push<DeliveryAddress>( DeliveryAddress? d = await Navigator.push<DeliveryAddress>(
context, context,
CupertinoPageRoute( CupertinoPageRoute(
builder: (context) => DeliveryAddressSelection( builder: (context) => DeliveryAddressSelection(
deliveryAddress: _deliveryAddress, deliveryAddress: _deliveryAddress,
user: User( user: User(
id: _carton.userID, name: _carton.userName), id: _carton!.userID,
name: _carton!.userName),
)), )),
); );
if (d == null) return; if (d == null) return;
@@ -245,17 +242,17 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
height: 1, height: 1,
color: Colors.grey, color: Colors.grey,
), ),
onChanged: (CartonSize newValue) { onChanged: (CartonSize? newValue) {
setState(() { setState(() {
if (newValue.name == MANAGE_CARTONSIZE) { if (newValue!.name == MANAGE_CARTONSIZE) {
selectedCatonSize = null; selectedCatonSize = null;
_manageCartonSize(); _manageCartonSize();
return; return;
} }
selectedCatonSize = newValue; selectedCatonSize = newValue;
_widthCtl.text = selectedCatonSize.width.toString(); _widthCtl.text = selectedCatonSize!.width.toString();
_heightCtl.text = selectedCatonSize.height.toString(); _heightCtl.text = selectedCatonSize!.height.toString();
_lengthCtl.text = selectedCatonSize.length.toString(); _lengthCtl.text = selectedCatonSize!.length.toString();
}); });
}, },
isExpanded: true, isExpanded: true,
@@ -295,8 +292,7 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
_updateCargo(CargoType cargo) { _updateCargo(CargoType cargo) {
setState(() { setState(() {
var _c = var _c = _cargoTypes.firstWhere((e) => e.id == cargo.id);
_cargoTypes.firstWhere((e) => e.id == cargo.id, orElse: () => null);
if (_c != null) { if (_c != null) {
_c.weight = cargo.weight; _c.weight = cargo.weight;
_c.qty = cargo.qty; _c.qty = cargo.qty;
@@ -305,13 +301,13 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
} }
_creatCarton() async { _creatCarton() async {
if ((_cargoTypes?.length ?? 0) == 0) { if (_cargoTypes.length == 0) {
showMsgDialog(context, "Error", "Expect at least one cargo type"); showMsgDialog(context, "Error", "Expect at least one cargo type");
return; return;
} }
double l = double.parse(_lengthCtl.text, (s) => 0); double l = double.parse(_lengthCtl.text);
double w = double.parse(_widthCtl.text, (s) => 0); double w = double.parse(_widthCtl.text);
double h = double.parse(_heightCtl.text, (s) => 0); double h = double.parse(_heightCtl.text);
if ((l <= 0 || w <= 0 || h <= 0)) { if ((l <= 0 || w <= 0 || h <= 0)) {
showMsgDialog(context, "Error", "Invalid dimension"); showMsgDialog(context, "Error", "Invalid dimension");
return; return;
@@ -322,22 +318,22 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
} }
Carton carton = Carton(); Carton carton = Carton();
carton.id = _carton.id; carton.id = _carton!.id;
carton.cartonType = _carton.cartonType; carton.cartonType = _carton!.cartonType;
carton.fcsShipmentID = _carton.fcsShipmentID; carton.fcsShipmentID = _carton!.fcsShipmentID;
carton.cargoTypes = _cargoTypes; carton.cargoTypes = _cargoTypes;
if (isFromPackages) { if (isFromPackages) {
carton.userID = _carton.userID; carton.userID = _carton!.userID;
carton.packages = _carton.packages.where((e) => e.isChecked).toList(); carton.packages = _carton!.packages.where((e) => e.isChecked).toList();
} }
if (isFromCartons) { if (isFromCartons) {
carton.userID = _carton.userID; carton.userID = _carton!.userID;
carton.fcsID = _carton.fcsID; carton.fcsID = _carton!.fcsID;
carton.userName = _carton.userName; carton.userName = _carton!.userName;
carton.senderID = _carton.senderID; carton.senderID = _carton!.senderID;
carton.senderFCSID = _carton.senderFCSID; carton.senderFCSID = _carton!.senderFCSID;
carton.senderName = _carton.senderName; carton.senderName = _carton!.senderName;
} }
carton.length = l; carton.length = l;
@@ -350,12 +346,12 @@ class _PackageCartonEditorState extends State<PackageCartonEditor> {
try { try {
CartonModel cartonModel = CartonModel cartonModel =
Provider.of<CartonModel>(context, listen: false); Provider.of<CartonModel>(context, listen: false);
if (widget.isNew) { if (widget.isNew!) {
Carton _c = await cartonModel.createCarton(carton); Carton _c = await cartonModel.createCarton(carton);
Navigator.pop(context, _c); Navigator.pop(context, _c);
} else { } else {
await cartonModel.updateCarton(carton); await cartonModel.updateCarton(carton);
Carton _c = await cartonModel.getCarton(_carton.id); Carton _c = await cartonModel.getCarton(_carton!.id!);
Navigator.pop(context, _c); Navigator.pop(context, _c);
} }
} catch (e) { } catch (e) {

View File

@@ -10,9 +10,9 @@ import 'package:fcs/pages/main/util.dart';
typedef void ProfileCallback(); typedef void ProfileCallback();
class TotalWeightEdit extends StatefulWidget { class TotalWeightEdit extends StatefulWidget {
final double totalWeight; final double? totalWeight;
const TotalWeightEdit({Key key, this.totalWeight}) : super(key: key); const TotalWeightEdit({Key? key, this.totalWeight}) : super(key: key);
@override @override
_TotalWeightEditState createState() => _TotalWeightEditState(); _TotalWeightEditState createState() => _TotalWeightEditState();
} }
@@ -24,7 +24,7 @@ class _TotalWeightEditState extends State<TotalWeightEdit> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
totalController.text = widget.totalWeight.toStringAsFixed(2); totalController.text = widget.totalWeight!.toStringAsFixed(2);
} }
@override @override

View File

@@ -10,14 +10,14 @@ Widget getCartonNumberStatus(BuildContext context, Carton carton) {
LocalText( LocalText(
context, context,
'', '',
text: carton.cartonNumber ?? "", text: carton.cartonNumber ,
color: primaryColor, color: primaryColor,
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Chip(label: Text(carton.status ?? "")), child: Chip(label: Text(carton.status??"")),
), ),
], ],
); );

View File

@@ -1,45 +1,32 @@
import 'package:fcs/domain/entities/carton.dart'; import 'package:fcs/domain/entities/carton.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'carton_search.dart'; import 'carton_search.dart';
class CartonListRow extends StatefulWidget { class CartonListRow extends StatelessWidget {
final CallbackCartonSelect callbackCartonSelect; final CallbackCartonSelect? callbackCartonSelect;
final Carton carton; final Carton carton;
// const CartonListRow({this.carton, this.callbackCartonSelect}); // const CartonListRow({this.carton, this.callbackCartonSelect});
CartonListRow( CartonListRow({Key? key, required this.carton, this.callbackCartonSelect})
{Key key, this.carton, this.callbackCartonSelect})
: super(key: key); : super(key: key);
@override
_CartonListRowState createState() => _CartonListRowState();
}
class _CartonListRowState extends State<CartonListRow> {
final double dotSize = 15.0; final double dotSize = 15.0;
Carton _carton;
@override
void initState() {
super.initState();
this._carton = widget.carton;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border( border: Border(
bottom: BorderSide(color: Colors.grey[300]), bottom: BorderSide(color: Colors.grey.shade300),
), ),
), ),
child: InkWell( child: InkWell(
onTap: () { onTap: () {
Navigator.pop(context); Navigator.pop(context);
if (widget.callbackCartonSelect != null) if (callbackCartonSelect != null) callbackCartonSelect!(carton);
widget.callbackCartonSelect(widget.carton);
}, },
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
@@ -64,7 +51,7 @@ class _CartonListRowState extends State<CartonListRow> {
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: new Text( child: new Text(
_carton.cartonNumber ?? "", carton.cartonNumber ?? "",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
@@ -72,7 +59,7 @@ class _CartonListRowState extends State<CartonListRow> {
Padding( Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10), padding: const EdgeInsets.only(left: 10.0, top: 10),
child: new Text( child: new Text(
_carton.userName ?? "", carton.userName ?? "",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),
@@ -86,7 +73,7 @@ class _CartonListRowState extends State<CartonListRow> {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
new Text( new Text(
"${_carton.cartonWeight?.toStringAsFixed(2) ?? ''} lb", "${carton.cartonWeight?.toStringAsFixed(2)} lb",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),

View File

@@ -10,7 +10,7 @@ import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/popupmenu.dart'; import 'package:fcs/pages/widgets/popupmenu.dart';
import 'package:fcs/pagination/paginator_listview.dart'; import 'package:fcs/pagination/paginator_listview.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@@ -18,15 +18,15 @@ import 'carton_list_row.dart';
typedef CallbackCartonSelect(Carton carton); typedef CallbackCartonSelect(Carton carton);
Future<Carton> searchCarton(BuildContext context, Future<Carton?> searchCarton(BuildContext context,
{CallbackCartonSelect callbackCartonSelect}) async => {CallbackCartonSelect? callbackCartonSelect}) async =>
await showSearch<Carton>( await showSearch<Carton>(
context: context, context: context,
delegate: PartSearchDelegate(callbackCartonSelect: callbackCartonSelect), delegate: PartSearchDelegate(callbackCartonSelect: callbackCartonSelect),
); );
class PartSearchDelegate extends SearchDelegate<Carton> { class PartSearchDelegate extends SearchDelegate<Carton> {
final CallbackCartonSelect callbackCartonSelect; final CallbackCartonSelect? callbackCartonSelect;
PartSearchDelegate({this.callbackCartonSelect}); PartSearchDelegate({this.callbackCartonSelect});
@override @override
@@ -38,10 +38,10 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
return theme.copyWith( return theme.copyWith(
inputDecorationTheme: InputDecorationTheme( inputDecorationTheme: InputDecorationTheme(
hintStyle: TextStyle( hintStyle: TextStyle(
color: theme.primaryTextTheme.caption.color, fontSize: 14)), color: theme.primaryTextTheme.caption!.color, fontSize: 14)),
textTheme: theme.textTheme.copyWith( textTheme: theme.textTheme.copyWith(
title: theme.textTheme.title.copyWith( title: theme.textTheme.title!.copyWith(
color: theme.primaryTextTheme.title.color, fontSize: 16)), color: theme.primaryTextTheme.title!.color, fontSize: 16)),
primaryColor: primaryColor, primaryColor: primaryColor,
); );
} }
@@ -85,7 +85,7 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
Widget buildLeading(BuildContext context) { Widget buildLeading(BuildContext context) {
return IconButton( return IconButton(
icon: Icon(Icons.arrow_back), icon: Icon(Icons.arrow_back),
onPressed: () => close(context, null), onPressed: () => close(context, new Carton()),
); );
} }
@@ -96,7 +96,7 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
future: cartonModel.searchCarton(query), future: cartonModel.searchCarton(query),
builder: (context, AsyncSnapshot<List<Carton>> snapshot) { builder: (context, AsyncSnapshot<List<Carton>> snapshot) {
if (snapshot.hasData) { if (snapshot.hasData) {
if (snapshot.data.length == 0) { if (snapshot.data!.length == 0) {
return Container( return Container(
child: Center( child: Center(
child: Text( child: Text(
@@ -109,7 +109,7 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
return Container( return Container(
padding: EdgeInsets.only(top: 15), padding: EdgeInsets.only(top: 15),
child: ListView( child: ListView(
children: snapshot.data children: snapshot.data!
.map((u) => CartonListRow( .map((u) => CartonListRow(
key: ValueKey(u.id), key: ValueKey(u.id),
carton: u, carton: u,
@@ -158,20 +158,20 @@ class PartSearchDelegate extends SearchDelegate<Carton> {
} }
_scan(BuildContext context) async { _scan(BuildContext context) async {
PermissionStatus permission = // PermissionStatus permission =
await PermissionHandler().checkPermissionStatus(PermissionGroup.camera); // await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
if (permission != PermissionStatus.granted) { // if (permission != PermissionStatus.granted) {
Map<PermissionGroup, PermissionStatus> permissions = // Map<PermissionGroup, PermissionStatus> permissions =
await PermissionHandler() // await PermissionHandler()
.requestPermissions([PermissionGroup.camera]); // .requestPermissions([PermissionGroup.camera]);
if (permissions[PermissionGroup.camera] != PermissionStatus.granted) { // if (permissions[PermissionGroup.camera] != PermissionStatus.granted) {
showMsgDialog(context, "Error", "Camera permission is not granted"); // showMsgDialog(context, "Error", "Camera permission is not granted");
return null; // return null;
} // }
} // }
try { try {
String barcode = await scanBarcode(); String? barcode = await scanBarcode();
if (barcode != null) { if (barcode != null) {
query = barcode; query = barcode;
showResults(context); showResults(context);

View File

@@ -7,13 +7,13 @@ 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/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'model/carton_size_model.dart'; import 'model/carton_size_model.dart';
class CartonSizeEditor extends StatefulWidget { class CartonSizeEditor extends StatefulWidget {
final CartonSize cartonSize; final CartonSize? cartonSize;
CartonSizeEditor({this.cartonSize}); CartonSizeEditor({this.cartonSize});
@override @override
@@ -27,8 +27,8 @@ class _CartonSizeEditorState extends State<CartonSizeEditor> {
TextEditingController _lengthController = new TextEditingController(); TextEditingController _lengthController = new TextEditingController();
bool _isLoading = false; bool _isLoading = false;
CartonSize _cartonSize; CartonSize? _cartonSize;
bool _isNew; bool _isNew = false;
@override @override
void initState() { void initState() {
@@ -36,10 +36,10 @@ class _CartonSizeEditorState extends State<CartonSizeEditor> {
if (widget.cartonSize != null) { if (widget.cartonSize != null) {
_cartonSize = widget.cartonSize; _cartonSize = widget.cartonSize;
_isNew = false; _isNew = false;
_nameController.text = _cartonSize.name; _nameController.text = _cartonSize!.name ?? "";
_widthController.text = _cartonSize.width.toString(); _widthController.text = _cartonSize!.width.toString();
_heightController.text = _cartonSize.height.toString(); _heightController.text = _cartonSize!.height.toString();
_lengthController.text = _cartonSize.length.toString(); _lengthController.text = _cartonSize!.length.toString();
} else { } else {
_lengthController.text = "12"; _lengthController.text = "12";
_widthController.text = "12"; _widthController.text = "12";
@@ -110,7 +110,7 @@ class _CartonSizeEditorState extends State<CartonSizeEditor> {
await cartonSizeModel.addCartonSize(_cartonSize); await cartonSizeModel.addCartonSize(_cartonSize);
} else { } else {
CartonSize _cartonSize = CartonSize( CartonSize _cartonSize = CartonSize(
id: widget.cartonSize.id, id: widget.cartonSize!.id,
name: _nameController.text, name: _nameController.text,
length: l, length: l,
width: w, width: w,
@@ -184,7 +184,7 @@ class _CartonSizeEditorState extends State<CartonSizeEditor> {
CartonSize _cartonSize = CartonSize( CartonSize _cartonSize = CartonSize(
name: _nameController.text, length: l, width: w, height: h); name: _nameController.text, length: l, width: w, height: h);
return widget.cartonSize.isChangedForEdit(_cartonSize); return widget.cartonSize!.isChangedForEdit(_cartonSize);
} }
} }
} }

View File

@@ -40,7 +40,7 @@ class _CartonSizeListState extends State<CartonSizeList> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
new Text( new Text(
p.name, p.name ?? "",
style: TextStyle(fontSize: 15.0), style: TextStyle(fontSize: 15.0),
), ),
Padding( Padding(
@@ -135,7 +135,7 @@ class _CartonSizeListState extends State<CartonSizeList> {
CartonSizeModel cartonSizeModel = CartonSizeModel cartonSizeModel =
Provider.of<CartonSizeModel>(context, listen: false); Provider.of<CartonSizeModel>(context, listen: false);
try { try {
await cartonSizeModel.deleteCartonSize(cartonSize.id); await cartonSizeModel.deleteCartonSize(cartonSize.id!);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
} finally { } finally {

View File

@@ -13,7 +13,7 @@ class CartonSizeModel extends BaseModel {
List<CartonSize> cartonSizes = []; List<CartonSize> cartonSizes = [];
final log = Logger('CartonSizeModel'); final log = Logger('CartonSizeModel');
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot>? listener;
List<CartonSize> get getCartonSizes { List<CartonSize> get getCartonSizes {
var _cartonSizes = new List<CartonSize>.from(cartonSizes); var _cartonSizes = new List<CartonSize>.from(cartonSizes);
@@ -27,17 +27,18 @@ class CartonSizeModel extends BaseModel {
Future<void> _loadCartonSizes() async { Future<void> _loadCartonSizes() async {
try { try {
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection( .collection(
"/$config_collection/$setting_doc_id/$carton_sizes_collection") "/$config_collection/$setting_doc_id/$carton_sizes_collection")
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
cartonSizes.clear(); cartonSizes.clear();
cartonSizes = snapshot.documents.map((documentSnapshot) { cartonSizes = snapshot.docs.map((documentSnapshot) {
var c = CartonSize.fromMap( var c = CartonSize.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return c; return c;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -49,7 +50,7 @@ class CartonSizeModel extends BaseModel {
@override @override
logout() async { logout() async {
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
cartonSizes = []; cartonSizes = [];
} }

View File

@@ -2,7 +2,6 @@ import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/package/package_info.dart'; import 'package:fcs/pages/package/package_info.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/fcs_id_icon.dart'; import 'package:fcs/pages/widgets/fcs_id_icon.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
@@ -14,18 +13,18 @@ typedef CallbackOnViewDetail();
class Bubble extends StatelessWidget { class Bubble extends StatelessWidget {
Bubble( Bubble(
{this.message, {this.message,
this.date, required this.date,
this.delivered, required this.delivered,
this.isMine, required this.isMine,
this.sender, this.sender,
this.isSystem, required this.isSystem,
this.isCustomer, required this.isCustomer,
this.showDate, required this.showDate,
this.callbackOnViewDetail}); this.callbackOnViewDetail});
final CallbackOnViewDetail callbackOnViewDetail; final CallbackOnViewDetail? callbackOnViewDetail;
final DateTime date; final DateTime date;
final String message, sender; final String? message, sender;
final bool delivered, isMine, isSystem, isCustomer, showDate; final bool delivered, isMine, isSystem, isCustomer, showDate;
@override @override
@@ -84,7 +83,7 @@ class Bubble extends StatelessWidget {
fontWeight: FontWeight.bold))) fontWeight: FontWeight.bold)))
] ]
: [ : [
Text(isCustomer ? "FCS Team" : sender, Text(isCustomer ? "FCS Team" : sender ?? "",
style: TextStyle( style: TextStyle(
color: Colors.black38, color: Colors.black38,
fontSize: 10.0, fontSize: 10.0,
@@ -102,8 +101,8 @@ class Bubble extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: EdgeInsets.only(right: 48.0), padding: EdgeInsets.only(right: 48.0),
child: Text(message, child: Text(message ?? "",
style: hasUnicode(message) style: hasUnicode(message ?? "")
? newLabelStyleMM(color: primaryColor) ? newLabelStyleMM(color: primaryColor)
: newLabelStyle(color: primaryColor))), : newLabelStyle(color: primaryColor))),
Positioned( Positioned(
@@ -130,6 +129,6 @@ class Bubble extends StatelessWidget {
} }
_viewDetail() { _viewDetail() {
if (callbackOnViewDetail != null) callbackOnViewDetail(); if (callbackOnViewDetail != null) callbackOnViewDetail!();
} }
} }

View File

@@ -21,14 +21,17 @@ import 'package:provider/provider.dart';
import 'bubble.dart'; import 'bubble.dart';
class MessageDetail extends StatelessWidget { class MessageDetail extends StatelessWidget {
final String receiverName; final String? receiverName;
final String receiverID; final String? receiverID;
final MessageModel messageModel; final MessageModel messageModel;
final TextEditingController textEditingController = TextEditingController(); final TextEditingController textEditingController = TextEditingController();
final ScrollController listScrollController = ScrollController(); final ScrollController listScrollController = ScrollController();
MessageDetail( MessageDetail(
{Key key, this.messageModel, this.receiverName, this.receiverID}) {Key? key,
required this.messageModel,
this.receiverName,
this.receiverID})
: super(key: key) { : super(key: key) {
listScrollController.addListener(() { listScrollController.addListener(() {
if (listScrollController.offset >= if (listScrollController.offset >=
@@ -44,7 +47,7 @@ class MessageDetail extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
String userID = Provider.of<MessageModel>(context).user.id; String userID = Provider.of<MessageModel>(context).user?.id ?? "";
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@@ -96,8 +99,8 @@ class MessageDetail extends StatelessWidget {
Widget buildBubble(Message msg, String userID, bool showDate, Widget buildBubble(Message msg, String userID, bool showDate,
CallbackOnViewDetail callback) { CallbackOnViewDetail callback) {
return Bubble( return Bubble(
message: msg.message, message: msg.message ?? "",
date: msg.date, date: msg.date!,
delivered: true, delivered: true,
sender: msg.senderName, sender: msg.senderName,
isMine: msg.senderID == userID || msg.receiverID == receiverID, isMine: msg.senderID == userID || msg.receiverID == receiverID,
@@ -117,8 +120,8 @@ class MessageDetail extends StatelessWidget {
child: Container( child: Container(
child: TextField( child: TextField(
onSubmitted: (value) { onSubmitted: (value) {
Provider.of<MessageModel>(context, listen: false) Provider.of<MessageModel>(context, listen: false).sendMessage(
.sendMessage(textEditingController.text, receiverID); textEditingController.text, receiverID ?? "");
textEditingController.text = ""; textEditingController.text = "";
}, },
style: TextStyle(color: primaryColor, fontSize: 15.0), style: TextStyle(color: primaryColor, fontSize: 15.0),
@@ -152,8 +155,8 @@ class MessageDetail extends StatelessWidget {
child: IconButton( child: IconButton(
icon: Icon(Icons.send), icon: Icon(Icons.send),
onPressed: () { onPressed: () {
Provider.of<MessageModel>(context, listen: false) Provider.of<MessageModel>(context, listen: false).sendMessage(
.sendMessage(textEditingController.text, receiverID); textEditingController.text, receiverID ?? "");
textEditingController.text = ""; textEditingController.text = "";
}, },
color: primaryColor, color: primaryColor,
@@ -165,7 +168,8 @@ class MessageDetail extends StatelessWidget {
), ),
width: double.infinity, width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border(top: BorderSide(color: Colors.grey[700], width: 0.5)), border:
Border(top: BorderSide(color: Colors.grey.shade700, width: 0.5)),
color: Colors.white), color: Colors.white),
); );
} }
@@ -176,7 +180,7 @@ class MessageDetail extends StatelessWidget {
message.messageID != "") { message.messageID != "") {
PackageModel packageModel = PackageModel packageModel =
Provider.of<PackageModel>(context, listen: false); Provider.of<PackageModel>(context, listen: false);
Package p = await packageModel.getPackage(message.messageID); Package p = await packageModel.getPackage(message.messageID!);
if (p == null) return; if (p == null) return;
Navigator.push<bool>(context, Navigator.push<bool>(context,
CupertinoPageRoute(builder: (context) => PackageInfo(package: p))); CupertinoPageRoute(builder: (context) => PackageInfo(package: p)));
@@ -186,7 +190,7 @@ class MessageDetail extends StatelessWidget {
message.messageID != "") { message.messageID != "") {
MainModel mainModel = Provider.of<MainModel>(context, listen: false); MainModel mainModel = Provider.of<MainModel>(context, listen: false);
if (mainModel.user.isCustomer()) { if (mainModel.user?.isCustomer() ?? false) {
Navigator.push<bool>( Navigator.push<bool>(
context, CupertinoPageRoute(builder: (context) => Profile())); context, CupertinoPageRoute(builder: (context) => Profile()));
} else { } else {
@@ -202,7 +206,7 @@ class MessageDetail extends StatelessWidget {
message.messageID != "") { message.messageID != "") {
ShipmentModel shipmentModel = ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false); Provider.of<ShipmentModel>(context, listen: false);
Shipment s = await shipmentModel.getShipment(message.messageID); Shipment s = await shipmentModel.getShipment(message.messageID!);
if (s == null) return; if (s == null) return;
await Navigator.push<bool>( await Navigator.push<bool>(
context, context,

View File

@@ -10,44 +10,46 @@ import 'package:logging/logging.dart';
class MessageModel extends BaseModel { class MessageModel extends BaseModel {
final log = Logger('MessageModel'); final log = Logger('MessageModel');
List<Message> messages; List<Message> messages = [];
@override @override
logout() async { logout() async {
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
messages = []; messages = [];
} }
Query query; late Query query;
DocumentSnapshot prevSnap; DocumentSnapshot? prevSnap;
bool isEnded; late bool isEnded;
bool isLoading; late bool isLoading;
String userID; String? userID;
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot>? listener;
static const int rowPerLoad = 20; static const int rowPerLoad = 20;
void initQuery(String userID) { void initQuery(String? userID) {
if (userID == null) return;
this.messages = []; this.messages = [];
this.userID = userID; this.userID = userID;
this.prevSnap = null; this.prevSnap = null;
query = Firestore.instance query = FirebaseFirestore.instance
.collection("$user_collection/$userID/$messages_collection") .collection("$user_collection/$userID/$messages_collection")
.orderBy('date', descending: true); .orderBy('date', descending: true);
load(); load();
} }
Future<void> load() async { Future<void> load() async {
if (prevSnap == null) return;
Query _query = Query _query =
prevSnap != null ? query.startAfterDocument(prevSnap) : query; prevSnap != null ? query.startAfterDocument(prevSnap!) : query;
QuerySnapshot snapshot = QuerySnapshot snapshot =
await _query.limit(rowPerLoad).getDocuments(source: Source.server); await _query.limit(rowPerLoad).get(GetOptions(source: Source.server));
int count = snapshot.documents.length; int count = snapshot.docs.length;
isEnded = count < rowPerLoad; isEnded = count < rowPerLoad;
prevSnap = count > 0 ? snapshot.documents[count - 1] : prevSnap; prevSnap = count > 0 ? snapshot.docs[count - 1] : prevSnap;
snapshot.documents.forEach((e) { snapshot.docs.forEach((e) {
messages.add(Message.fromMap(e.data, e.documentID)); messages.add(Message.fromMap(e.data() as Map<String, dynamic>, e.id));
if (messages.length == 1) { if (messages.length == 1) {
_initListener(e); _initListener(e);
} }
@@ -56,20 +58,22 @@ class MessageModel extends BaseModel {
} }
void _initListener(DocumentSnapshot snap) { void _initListener(DocumentSnapshot snap) {
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection("$user_collection/$userID/$messages_collection") .collection("$user_collection/$userID/$messages_collection")
.endBeforeDocument(snap) .endBeforeDocument(snap)
.orderBy('date', descending: true) .orderBy('date', descending: true)
.snapshots(includeMetadataChanges: true) .snapshots(includeMetadataChanges: true)
.listen((qs) { .listen((qs) {
qs.documentChanges.forEach((c) { qs.docChanges.forEach((c) {
switch (c.type) { switch (c.type) {
case DocumentChangeType.added: case DocumentChangeType.added:
log.info("added!! $c"); log.info("added!! $c");
messages.insert( messages.insert(
0, Message.fromMap(c.document.data, c.document.documentID)); 0,
Message.fromMap(
c.doc.data() as Map<String, dynamic>, c.doc.id));
notifyListeners(); notifyListeners();
break; break;
case DocumentChangeType.modified: case DocumentChangeType.modified:

View File

@@ -1,6 +1,5 @@
import 'package:fcs/domain/vo/contact.dart'; import 'package:fcs/domain/vo/contact.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/contact/model/contact_model.dart'; import 'package:fcs/pages/contact/model/contact_model.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/input_text.dart';
@@ -14,7 +13,7 @@ import 'package:provider/provider.dart';
import 'widgets.dart'; import 'widgets.dart';
class ContactEditor extends StatefulWidget { class ContactEditor extends StatefulWidget {
final Contact contact; final Contact? contact;
const ContactEditor({this.contact}); const ContactEditor({this.contact});
@override @override
_ContactEditorState createState() => _ContactEditorState(); _ContactEditorState createState() => _ContactEditorState();
@@ -29,22 +28,23 @@ class _ContactEditorState extends State<ContactEditor> {
TextEditingController _facebook = new TextEditingController(); TextEditingController _facebook = new TextEditingController();
bool _isLoading = false; bool _isLoading = false;
bool isNew; bool isNew = false;
Contact? _contact;
@override @override
void initState() { void initState() {
if (widget.contact != null) _contact = widget.contact!;
super.initState(); super.initState();
if (widget.contact != null) { isNew = widget.contact == null;
isNew = false; }
_usaPhone.text = widget.contact.usaContactNumber;
_mmPhone.text = widget.contact.mmContactNumber; initContact() {
_usaAddress.text = widget.contact.usaAddress; _usaPhone.text = _contact?.usaContactNumber ?? '';
_mmAddress.text = widget.contact.mmAddress; _mmPhone.text = _contact?.mmContactNumber ?? '';
_email.text = widget.contact.emailAddress; _usaAddress.text = _contact?.usaAddress ?? '';
_facebook.text = widget.contact.facebookLink; _mmAddress.text = _contact?.mmAddress ?? '';
} else { _email.text = _contact?.emailAddress ?? '';
isNew = true; _facebook.text = _contact?.facebookLink ?? '';
}
} }
@override @override
@@ -136,14 +136,17 @@ class _ContactEditorState extends State<ContactEditor> {
_isLoading = true; _isLoading = true;
}); });
try { try {
widget.contact.usaContactNumber = _usaPhone.text; _contact?.usaContactNumber = _usaPhone.text;
widget.contact.mmContactNumber = _mmPhone.text; _contact?.mmContactNumber = _mmPhone.text;
widget.contact.usaAddress = _usaAddress.text; _contact?.usaAddress = _usaAddress.text;
widget.contact.mmAddress = _mmAddress.text; _contact?.mmAddress = _mmAddress.text;
widget.contact.emailAddress = _email.text; _contact?.emailAddress = _email.text;
widget.contact.facebookLink = _facebook.text; _contact?.facebookLink = _facebook.text;
var contactModel = Provider.of<ContactModel>(context, listen: false); if (this._contact != null) {
await contactModel.saveContact(widget.contact); var contactModel = Provider.of<ContactModel>(context, listen: false);
await contactModel.saveContact(_contact!);
}
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());

View File

@@ -1,7 +1,6 @@
import 'package:fcs/domain/entities/setting.dart'; import 'package:fcs/domain/entities/setting.dart';
import 'package:fcs/domain/vo/contact.dart'; import 'package:fcs/domain/vo/contact.dart';
import 'package:fcs/helpers/theme.dart'; import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/contact/contact_editor.dart'; import 'package:fcs/pages/contact/contact_editor.dart';
import 'package:fcs/pages/main/model/main_model.dart'; import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
@@ -22,7 +21,8 @@ class ContactPage extends StatefulWidget {
class _ContactPageState extends State<ContactPage> { class _ContactPageState extends State<ContactPage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Setting setting = Provider.of<MainModel>(context).setting; Setting? setting = Provider.of<MainModel>(context).setting;
if (setting == null) return Container();
bool isEditable = context.select((MainModel m) => m.contactEditable()); bool isEditable = context.select((MainModel m) => m.contactEditable());
return Scaffold( return Scaffold(
@@ -62,14 +62,14 @@ class _ContactPageState extends State<ContactPage> {
children: [ children: [
itemTitle(context, "contact.callus"), itemTitle(context, "contact.callus"),
contactItem(context, setting.usaContactNumber, CupertinoIcons.phone, contactItem(context, setting.usaContactNumber, CupertinoIcons.phone,
onTap: () => _call(setting.usaContactNumber), onTap: () => _call(setting.usaContactNumber ?? ""),
labelKey: "contact.usa.phone"), labelKey: "contact.usa.phone"),
contactItem( contactItem(
context, context,
setting.mmContactNumber, setting.mmContactNumber,
CupertinoIcons.phone, CupertinoIcons.phone,
onTap: () => _call( onTap: () => _call(
setting.mmContactNumber, setting.mmContactNumber ?? "",
), ),
labelKey: "contact.mm.phone", labelKey: "contact.mm.phone",
), ),
@@ -91,7 +91,7 @@ class _ContactPageState extends State<ContactPage> {
context, context,
setting.emailAddress, setting.emailAddress,
CupertinoIcons.mail, CupertinoIcons.mail,
onTap: () => _email(setting.emailAddress), onTap: () => _email(setting.emailAddress ?? ""),
labelKey: "contact.fcs.email", labelKey: "contact.fcs.email",
), ),
itemTitle(context, "contact.visitus"), itemTitle(context, "contact.visitus"),
@@ -99,7 +99,7 @@ class _ContactPageState extends State<ContactPage> {
context, context,
setting.facebookLink, setting.facebookLink,
FontAwesomeIcons.facebook, FontAwesomeIcons.facebook,
onTap: () => _opencontactItem(setting.facebookLink), onTap: () => _opencontactItem(setting.facebookLink ?? ""),
labelKey: "contact.facebook", labelKey: "contact.facebook",
), ),
], ],

View File

@@ -7,14 +7,14 @@ Widget itemTitle(BuildContext context, String textKey) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 18.0, top: 25, bottom: 5), padding: const EdgeInsets.only(left: 18.0, top: 25, bottom: 5),
child: Text( child: Text(
AppTranslations.of(context).text(textKey), AppTranslations.of(context)!.text(textKey),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black), fontWeight: FontWeight.bold, fontSize: 18, color: Colors.black),
), ),
); );
} }
Widget subItemTitle(BuildContext context, String textKey, {IconData iconData}) { Widget subItemTitle(BuildContext context, String textKey, {IconData? iconData}) {
return Padding( return Padding(
padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0), padding: const EdgeInsets.only(left: 0, top: 0, bottom: 0),
child: Row( child: Row(
@@ -25,7 +25,7 @@ Widget subItemTitle(BuildContext context, String textKey, {IconData iconData}) {
), ),
SizedBox(width: 10), SizedBox(width: 10),
Text( Text(
AppTranslations.of(context).text(textKey), AppTranslations.of(context)!.text(textKey),
style: TextStyle( style: TextStyle(
fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor), fontWeight: FontWeight.w700, fontSize: 15, color: primaryColor),
), ),
@@ -34,8 +34,8 @@ Widget subItemTitle(BuildContext context, String textKey, {IconData iconData}) {
); );
} }
Widget contactItem(BuildContext context, String text, IconData iconData, Widget contactItem(BuildContext context, String? text, IconData iconData,
{Function() onTap, String labelKey}) { {Function()? onTap, String? labelKey}) {
return Material( return Material(
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18), padding: const EdgeInsets.only(left: 18.0, bottom: 10, right: 18),

View File

@@ -14,7 +14,7 @@ import 'package:provider/provider.dart';
typedef void FindCallBack(); typedef void FindCallBack();
class CustomerEditor extends StatefulWidget { class CustomerEditor extends StatefulWidget {
final User customer; final User? customer;
const CustomerEditor({this.customer}); const CustomerEditor({this.customer});
@override @override
_CustomerEditorState createState() => _CustomerEditorState(); _CustomerEditorState createState() => _CustomerEditorState();
@@ -34,17 +34,17 @@ class _CustomerEditorState extends State<CustomerEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: widget.customer.phoneNumber, text: widget.customer!.phoneNumber,
labelTextKey: "customer.phone", labelTextKey: "customer.phone",
iconData: Icons.phone, iconData: Icons.phone,
)), )),
IconButton( IconButton(
icon: Icon(Icons.open_in_new, color: primaryColor), icon: Icon(Icons.open_in_new, color: primaryColor),
onPressed: () => call(context, widget.customer.phoneNumber)), onPressed: () => call(context, widget.customer?.phoneNumber ?? "")),
], ],
); );
final enabled = widget.customer.status != user_disabled_status; final enabled = widget.customer!.status != user_disabled_status;
final enableBox = LocalButton( final enableBox = LocalButton(
textKey: enabled ? "customer.disable.btn" : "customer.enable.btn", textKey: enabled ? "customer.disable.btn" : "customer.enable.btn",
iconData: enabled ? Icons.lock : Icons.lock_open, iconData: enabled ? Icons.lock : Icons.lock_open,
@@ -68,7 +68,7 @@ class _CustomerEditorState extends State<CustomerEditor> {
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
title: Text( title: Text(
widget.customer.name, widget.customer?.name ?? "",
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: 20,
color: primaryColor, color: primaryColor,
@@ -81,26 +81,26 @@ class _CustomerEditorState extends State<CustomerEditor> {
children: <Widget>[ children: <Widget>[
phoneNumberBox, phoneNumberBox,
DisplayText( DisplayText(
text: widget.customer.fcsID, text: widget.customer!.fcsID,
labelTextKey: "customer.fcs.id", labelTextKey: "customer.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
), ),
DisplayText( DisplayText(
text: widget.customer.status, text: widget.customer!.status,
labelTextKey: "customer.status", labelTextKey: "customer.status",
iconData: Icons.add_alarm, iconData: Icons.add_alarm,
), ),
SizedBox( SizedBox(
height: 20, height: 20,
), ),
widget.customer.requested widget.customer!.requested
? fcsButton( ? fcsButton(
context, context,
getLocalString( getLocalString(
context, "customer.invitation.request.confirm"), context, "customer.invitation.request.confirm"),
callack: _add) callack: _add)
: Container(), : Container(),
widget.customer.joined || widget.customer.disabled widget.customer!.joined || widget.customer!.disabled
? enableBox ? enableBox
: Container() : Container()
], ],
@@ -119,7 +119,7 @@ class _CustomerEditorState extends State<CustomerEditor> {
CustomerModel customerModel = CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false); Provider.of<CustomerModel>(context, listen: false);
try { try {
await customerModel.acceptRequest(widget.customer.id); await customerModel.acceptRequest(widget.customer?.id ?? "");
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -139,7 +139,7 @@ class _CustomerEditorState extends State<CustomerEditor> {
CustomerModel customerModel = CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false); Provider.of<CustomerModel>(context, listen: false);
try { try {
await customerModel.enableUser(widget.customer, enabled); await customerModel.enableUser(widget.customer!, enabled);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());

View File

@@ -125,7 +125,7 @@ class _CustomerListState extends State<CustomerList> {
Padding( Padding(
padding: const EdgeInsets.only(top: 2.0), padding: const EdgeInsets.only(top: 2.0),
child: new Text( child: new Text(
customer.name, customer.name ?? "",
style: new TextStyle( style: new TextStyle(
fontSize: 20.0, color: primaryColor), fontSize: 20.0, color: primaryColor),
), ),
@@ -171,7 +171,7 @@ class _CustomerListState extends State<CustomerList> {
children: [ children: [
Padding( Padding(
padding: const EdgeInsets.only(right: 5), padding: const EdgeInsets.only(right: 5),
child: _status(customer.status), child: _status(customer.status ?? ""),
), ),
Padding( Padding(
padding: const EdgeInsets.only(right: 5), padding: const EdgeInsets.only(right: 5),
@@ -222,22 +222,22 @@ class _CustomerListState extends State<CustomerList> {
))) )))
.then((value) { .then((value) {
if (customer.fcsUnseenCount > 0) { if (customer.fcsUnseenCount > 0) {
messageModel.seenMessages(customer.id, false); messageModel.seenMessages(customer.id ?? "", false);
} }
}); });
if (customer.fcsUnseenCount > 0) { if (customer.fcsUnseenCount > 0) {
messageModel.seenMessages(customer.id, false); messageModel.seenMessages(customer.id ?? "", false);
} }
} }
_share(User user) async { _share(User user) async {
MainModel mainModel = Provider.of<MainModel>(context, listen: false); MainModel mainModel = Provider.of<MainModel>(context, listen: false);
String appUrl = mainModel.setting.appUrl; String appUrl = mainModel.setting?.appUrl ?? "";
final RenderBox box = context.findRenderObject(); final RenderBox? box = context.findRenderObject() as RenderBox;
await Share.share( await Share.share(
"Join us on FCS Logistics App. Here is the link:\n $appUrl\n" + "Join us on FCS Logistics App. Here is the link:\n $appUrl\n" +
user.share, user.share,
subject: "Invitation to FCS Logistics App", subject: "Invitation to FCS Logistics App",
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size); sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
} }
} }

View File

@@ -19,7 +19,7 @@ class _InvitationCreateState extends State<InvitationCreate> {
TextEditingController _phoneController = new TextEditingController(); TextEditingController _phoneController = new TextEditingController();
bool _isLoading = false; bool _isLoading = false;
String dialCode; late String dialCode;
@override @override
void initState() { void initState() {
@@ -85,7 +85,7 @@ class _InvitationCreateState extends State<InvitationCreate> {
), ),
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all(color: Colors.grey[400], width: 1), border: Border.all(color: Colors.grey.shade400, width: 1),
borderRadius: BorderRadius.all(Radius.circular(12.0))), borderRadius: BorderRadius.all(Radius.circular(12.0))),
child: CountryCodePicker( child: CountryCodePicker(
onChanged: _countryChange, onChanged: _countryChange,
@@ -140,7 +140,7 @@ class _InvitationCreateState extends State<InvitationCreate> {
_countryChange(CountryCode countryCode) { _countryChange(CountryCode countryCode) {
setState(() { setState(() {
dialCode = countryCode.dialCode; dialCode = countryCode.dialCode!;
}); });
} }

View File

@@ -11,7 +11,7 @@ import 'package:provider/provider.dart';
typedef void FindCallBack(); typedef void FindCallBack();
class InvitationEditor extends StatefulWidget { class InvitationEditor extends StatefulWidget {
final User customer; final User? customer;
const InvitationEditor({this.customer}); const InvitationEditor({this.customer});
@override @override
_InvitationEditorState createState() => _InvitationEditorState(); _InvitationEditorState createState() => _InvitationEditorState();
@@ -31,13 +31,13 @@ class _InvitationEditorState extends State<InvitationEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: widget.customer.phoneNumber, text: widget.customer!.phoneNumber,
labelTextKey: getLocalString(context, "customer.phone"), labelTextKey: getLocalString(context, "customer.phone"),
iconData: Icons.phone, iconData: Icons.phone,
)), )),
IconButton( IconButton(
icon: Icon(Icons.open_in_new, color: primaryColor), icon: Icon(Icons.open_in_new, color: primaryColor),
onPressed: () => call(context, widget.customer.phoneNumber)), onPressed: () => call(context, widget.customer?.phoneNumber ?? "")),
], ],
); );
@@ -57,7 +57,7 @@ class _InvitationEditorState extends State<InvitationEditor> {
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
title: Text( title: Text(
widget.customer.name, widget.customer?.name ?? "",
style: TextStyle(fontSize: 20, color: primaryColor), style: TextStyle(fontSize: 20, color: primaryColor),
), ),
), ),
@@ -87,7 +87,7 @@ class _InvitationEditorState extends State<InvitationEditor> {
CustomerModel customerModel = CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false); Provider.of<CustomerModel>(context, listen: false);
try { try {
await customerModel.deleteInvite(widget.customer.phoneNumber); await customerModel.deleteInvite(widget.customer?.phoneNumber ?? "");
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());

View File

@@ -12,8 +12,8 @@ class CustomerModel extends BaseModel {
List<User> customers = []; List<User> customers = [];
List<User> invitations = []; List<User> invitations = [];
StreamSubscription<QuerySnapshot> customerListener; late StreamSubscription<QuerySnapshot>? customerListener;
StreamSubscription<QuerySnapshot> invitationListener; late StreamSubscription<QuerySnapshot>? invitationListener;
@override @override
void privilegeChanged() { void privilegeChanged() {
@@ -24,8 +24,8 @@ class CustomerModel extends BaseModel {
@override @override
logout() async { logout() async {
if (customerListener != null) customerListener.cancel(); if (customerListener != null) customerListener!.cancel();
if (invitationListener != null) invitationListener.cancel(); if (invitationListener != null) invitationListener!.cancel();
customers = []; customers = [];
invitations = []; invitations = [];
} }
@@ -43,21 +43,22 @@ class CustomerModel extends BaseModel {
} }
Future<void> _loadCustomer() async { Future<void> _loadCustomer() async {
if (user == null || !user.hasCustomers()) return; if (user == null && !user!.hasCustomers()) return;
try { try {
if (customerListener != null) customerListener.cancel(); if (customerListener != null) customerListener!.cancel();
customerListener = Firestore.instance customerListener = FirebaseFirestore.instance
.collection("/$user_collection") .collection("/$user_collection")
.where("is_sys_admin", isEqualTo: false) .where("is_sys_admin", isEqualTo: false)
.orderBy("message_time", descending: true) .orderBy("message_time", descending: true)
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
customers.clear(); customers.clear();
customers = snapshot.documents.map((documentSnapshot) { customers = snapshot.docs.map((documentSnapshot) {
var user = var user = User.fromMap(
User.fromMap(documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return user; return user;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -68,19 +69,20 @@ class CustomerModel extends BaseModel {
} }
Future<void> _loadInvitations() async { Future<void> _loadInvitations() async {
if (user == null || !user.hasCustomers()) return; if (user == null && !user!.hasCustomers()) return;
try { try {
if (invitationListener != null) invitationListener.cancel(); if (invitationListener != null) invitationListener!.cancel();
invitationListener = Firestore.instance invitationListener = FirebaseFirestore.instance
.collection("/$invitations_collection") .collection("/$invitations_collection")
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
invitations.clear(); invitations.clear();
invitations = snapshot.documents.map((documentSnapshot) { invitations = snapshot.docs.map((documentSnapshot) {
var user = var user = User.fromMap(
User.fromMap(documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data() as Map<String, dynamic>,
documentSnapshot.id);
return user; return user;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -90,23 +92,22 @@ class CustomerModel extends BaseModel {
} }
} }
Future<User> getUser(String id) async { Future<User> getUser(String? id) async {
String path = "/$user_collection"; String path = "/$user_collection";
var snap = await Firestore.instance.collection(path).document(id).get(); var snap = await FirebaseFirestore.instance.collection(path).doc(id).get();
return User.fromMap(snap.data, snap.documentID); return User.fromMap(snap.data() as Map<String, dynamic>, snap.id);
} }
Future<List<User>> getInvoiceUsers(String fcsShipmentID) async { Future<List<User>> getInvoiceUsers(String fcsShipmentID) async {
List<User> users = []; List<User> users = [];
try { try {
var snaps = await Firestore.instance var snaps = await FirebaseFirestore.instance
.collection( .collection(
"/$fcs_shipment_collection/$fcsShipmentID/$user_collection") "/$fcs_shipment_collection/$fcsShipmentID/$user_collection")
.where("pending_invoice_carton_count", isGreaterThan: 0) .where("pending_invoice_carton_count", isGreaterThan: 0)
.getDocuments(source: Source.server); .get(GetOptions(source: Source.server));
users = snaps.documents.map((documentSnapshot) { users = snaps.docs.map((documentSnapshot) {
var user = var user = User.fromMap(documentSnapshot.data(), documentSnapshot.id);
User.fromMap(documentSnapshot.data, documentSnapshot.documentID);
return user; return user;
}).toList(); }).toList();
} catch (e) { } catch (e) {
@@ -116,6 +117,6 @@ class CustomerModel extends BaseModel {
} }
Future<void> enableUser(User user, bool enabled) { Future<void> enableUser(User user, bool enabled) {
return Services.instance.userService.enableUser(user.id, enabled); return Services.instance.userService.enableUser(user.id ?? "", enabled);
} }
} }

View File

@@ -22,14 +22,14 @@ import 'package:fcs/pages/widgets/local_title.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
final DateFormat dateFormat = DateFormat("d MMM yyyy"); final DateFormat dateFormat = DateFormat("d MMM yyyy");
class DeliveryInfo extends StatefulWidget { class DeliveryInfo extends StatefulWidget {
final Carton box; final Carton? box;
DeliveryInfo({this.box}); DeliveryInfo({this.box});
@override @override
@@ -38,8 +38,8 @@ class DeliveryInfo extends StatefulWidget {
class _DeliveryInfoState extends State<DeliveryInfo> { class _DeliveryInfoState extends State<DeliveryInfo> {
bool _isLoading = false; bool _isLoading = false;
Carton _box; late Carton _box;
String _selectedCartonType; late String _selectedCartonType;
List<Package> _packages = []; List<Package> _packages = [];
List<Carton> _mixBoxes = []; List<Carton> _mixBoxes = [];
Carton _selectedShipmentBox = new Carton(); Carton _selectedShipmentBox = new Carton();
@@ -51,17 +51,17 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
double volumetricRatio = 0; double volumetricRatio = 0;
double shipmentWeight = 0; double shipmentWeight = 0;
bool isMixBox; late bool isMixBox;
bool isFromShipments; late bool isFromShipments;
bool isFromPackages; late bool isFromPackages;
bool isSmallBag; late bool isSmallBag;
bool isEdiable; late bool isEdiable;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_box = widget.box; if (widget.box != null) _box = widget.box!;
_selectedCartonType = _box.cartonType; _selectedCartonType = _box.cartonType ?? '';
//for shipment weight //for shipment weight
volumetricRatio = Provider.of<ShipmentRateModel>(context, listen: false) volumetricRatio = Provider.of<ShipmentRateModel>(context, listen: false)
@@ -80,7 +80,7 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
_heightController.text = _box.height.toString(); _heightController.text = _box.height.toString();
_lengthController.text = _box.length.toString(); _lengthController.text = _box.length.toString();
_cargoTypes = _box.cargoTypes; _cargoTypes = _box.cargoTypes;
_deliveryAddress = _box.deliveryAddress; _deliveryAddress = _box.deliveryAddress!;
isMixBox = _box.cartonType == carton_mix_box; isMixBox = _box.cartonType == carton_mix_box;
isFromShipments = _box.cartonType == carton_from_shipments; isFromShipments = _box.cartonType == carton_from_shipments;
isFromPackages = _box.cartonType == carton_from_packages; isFromPackages = _box.cartonType == carton_from_packages;
@@ -96,7 +96,7 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
if (_box.cartonType == carton_from_packages && _box.userID == null) return; if (_box.cartonType == carton_from_packages && _box.userID == 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.userID!, [
package_processed_status, package_processed_status,
package_packed_status, package_packed_status,
package_shipped_status, package_shipped_status,
@@ -135,21 +135,22 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
final cartonTypeBox = LocalRadioButtons( final cartonTypeBox = LocalRadioButtons(
readOnly: true, readOnly: true,
values: cartonModel.cartonTypesInfo, values: cartonModel.cartonTypesInfo,
selectedValue: selectedValue: (_box.isShipmentCarton ?? false)
_box.isShipmentCarton ? carton_from_shipments : _box.cartonType); ? carton_from_shipments
: _box.cartonType);
final shipmentBox = DisplayText( final shipmentBox = DisplayText(
text: _box.fcsShipmentNumber, text: _box.fcsShipmentNumber,
labelTextKey: "box.fcs_shipment_num", labelTextKey: "box.fcs_shipment_num",
iconData: Ionicons.ios_airplane, iconData: Ionicons.ios_airplane,
); );
final fcsIDBox = DisplayText( final fcsIDBox = DisplayText(
text: _box.fcsID == null ? "" : _box.fcsID, text: _box.fcsID,
labelTextKey: "box.fcs.id", labelTextKey: "box.fcs.id",
icon: FcsIDIcon(), icon: FcsIDIcon(),
); );
final customerNameBox = DisplayText( final customerNameBox = DisplayText(
text: _box.userName == null ? "" : _box.userName, text: _box.userName,
labelTextKey: "box.name", labelTextKey: "box.name",
iconData: Icons.person, iconData: Icons.person,
); );
@@ -173,13 +174,11 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Text( child: new Text(
_selectedShipmentBox.shipmentNumber == null _selectedShipmentBox.shipmentNumber ?? "",
? ""
: _selectedShipmentBox.shipmentNumber,
style: textStyle, style: textStyle,
)), )),
new Text( new Text(
_selectedShipmentBox.desc == null ? "" : _selectedShipmentBox.desc, _selectedShipmentBox.desc ?? "",
style: textStyle, style: textStyle,
), ),
], ],
@@ -216,7 +215,7 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
); );
final shipmentWeightBox = DisplayText( final shipmentWeightBox = DisplayText(
text: shipmentWeight != null ? shipmentWeight.toStringAsFixed(0) : "", text: shipmentWeight.toStringAsFixed(0),
labelTextKey: "box.shipment_weight", labelTextKey: "box.shipment_weight",
iconData: MaterialCommunityIcons.weight, iconData: MaterialCommunityIcons.weight,
); );
@@ -302,7 +301,7 @@ class _DeliveryInfoState extends State<DeliveryInfo> {
}); });
try { try {
var deliveryModel = Provider.of<DeliveryModel>(context, listen: false); var deliveryModel = Provider.of<DeliveryModel>(context, listen: false);
await deliveryModel.deliver(widget.box); await deliveryModel.deliver(this._box);
Navigator.pop(context, true); Navigator.pop(context, true);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());

View File

@@ -3,14 +3,14 @@ import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'delivery_info.dart'; import 'delivery_info.dart';
class DeliveryListRow extends StatelessWidget { class DeliveryListRow extends StatelessWidget {
final Carton box; final Carton? box;
DeliveryListRow({Key key, this.box}) : super(key: key); DeliveryListRow({Key? key, this.box}) : super(key: key);
final double dotSize = 15.0; final double dotSize = 15.0;
final DateFormat dateFormat = new DateFormat("dd MMM yyyy"); final DateFormat dateFormat = new DateFormat("dd MMM yyyy");
@@ -19,10 +19,11 @@ class DeliveryListRow extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return InkWell( return InkWell(
onTap: () { onTap: () {
Navigator.push( if (box != null)
context, Navigator.push(
CupertinoPageRoute(builder: (context) => DeliveryInfo(box: box)), context,
); CupertinoPageRoute(builder: (context) => DeliveryInfo(box: box!)),
);
}, },
child: Container( child: Container(
padding: EdgeInsets.only(left: 15, right: 15), padding: EdgeInsets.only(left: 15, right: 15),
@@ -48,7 +49,7 @@ class DeliveryListRow extends StatelessWidget {
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: new Text( child: new Text(
box.cartonNumber ?? "", box?.cartonNumber ?? "",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
@@ -56,7 +57,7 @@ class DeliveryListRow extends StatelessWidget {
Padding( Padding(
padding: const EdgeInsets.only(left: 10.0, top: 10), padding: const EdgeInsets.only(left: 10.0, top: 10),
child: new Text( child: new Text(
box.userName ?? "", box?.userName ?? "",
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),
@@ -72,14 +73,14 @@ class DeliveryListRow extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Padding( Padding(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: getStatus(box.status == null ? "" : box.status), child: getStatus(box?.status ?? ''),
), ),
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5), padding: const EdgeInsets.only(left: 8.0, top: 5, bottom: 5),
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
new Text( new Text(
"${box.actualWeight?.toString() ?? ''} lb", "${box?.actualWeight.toString() ?? ''} lb",
style: style:
new TextStyle(fontSize: 15.0, color: Colors.grey), new TextStyle(fontSize: 15.0, color: Colors.grey),
), ),

View File

@@ -14,18 +14,18 @@ class DeliveryModel extends BaseModel {
List<Carton> get cartons => List<Carton> get cartons =>
_selectedIndex == 1 ? _cartons : List<Carton>.from(_delivered.values); _selectedIndex == 1 ? _cartons : List<Carton>.from(_delivered.values);
Paginator _delivered; late Paginator _delivered;
int _selectedIndex = 1; int _selectedIndex = 1;
bool isLoading = false; bool isLoading = false;
List<Carton> _cartons = []; List<Carton> _cartons = [];
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot>? listener;
set selectedIndex(int index) { set selectedIndex(int index) {
_selectedIndex = index; _selectedIndex = index;
notifyListeners(); notifyListeners();
} }
get selectedIndex => _selectedIndex; int get selectedIndex => _selectedIndex;
initData() { initData() {
_selectedIndex = 1; _selectedIndex = 1;
@@ -37,12 +37,12 @@ class DeliveryModel extends BaseModel {
} }
Future<void> _loadCartons() async { Future<void> _loadCartons() async {
if (user == null || !user.hasDeliveries()) return; if (user == null || !user!.hasDeliveries()) return;
String path = "/$cartons_collection/"; String path = "/$cartons_collection/";
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
_cartons = []; _cartons = [];
try { try {
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("status", isEqualTo: carton_shipped_status) .where("status", isEqualTo: carton_shipped_status)
.where("carton_type", whereIn: [ .where("carton_type", whereIn: [
@@ -55,9 +55,9 @@ class DeliveryModel extends BaseModel {
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
_cartons.clear(); _cartons.clear();
_cartons = snapshot.documents.map((documentSnapshot) { _cartons = snapshot.docs.map((documentSnapshot) {
var s = Carton.fromMap( var s = Carton.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data as Map<String, dynamic>, documentSnapshot.id);
return s; return s;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -68,9 +68,9 @@ class DeliveryModel extends BaseModel {
} }
Paginator _getDelivered() { Paginator _getDelivered() {
if (user == null || !user.hasDeliveries()) return null; if (user == null || !user!.hasDeliveries()) throw "No Privilege";
var pageQuery = Firestore.instance var pageQuery = FirebaseFirestore.instance
.collection("/$cartons_collection") .collection("/$cartons_collection")
.where("is_delivered", isEqualTo: true) .where("is_delivered", isEqualTo: true)
.where("status", whereIn: [carton_delivered_status]).where("is_deleted", .where("status", whereIn: [carton_delivered_status]).where("is_deleted",
@@ -105,7 +105,7 @@ class DeliveryModel extends BaseModel {
@override @override
logout() async { logout() async {
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
if (_delivered != null) _delivered.close(); if (_delivered != null) _delivered.close();
_cartons = []; _cartons = [];
} }

View File

@@ -7,13 +7,13 @@ import 'package:fcs/pages/widgets/input_text.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/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class DeliveryAddressEditor extends StatefulWidget { class DeliveryAddressEditor extends StatefulWidget {
final DeliveryAddress deliveryAddress; final DeliveryAddress? deliveryAddress;
final User user; final User? user;
DeliveryAddressEditor({this.deliveryAddress, this.user}); DeliveryAddressEditor({this.deliveryAddress, this.user});
@override @override
@@ -38,13 +38,13 @@ class _DeliveryAddressEditorState extends State<DeliveryAddressEditor> {
super.initState(); super.initState();
if (widget.deliveryAddress != null) { if (widget.deliveryAddress != null) {
_isNew = false; _isNew = false;
_deliveryAddress = widget.deliveryAddress; _deliveryAddress = widget.deliveryAddress!;
_nameController.text = _deliveryAddress.fullName; _nameController.text = _deliveryAddress.fullName ?? "";
_address1Controller.text = _deliveryAddress.addressLine1; _address1Controller.text = _deliveryAddress.addressLine1 ?? "";
_address2Controller.text = _deliveryAddress.addressLine2; _address2Controller.text = _deliveryAddress.addressLine2 ?? "";
_cityController.text = _deliveryAddress.city; _cityController.text = _deliveryAddress.city ?? "";
_stateController.text = _deliveryAddress.state; _stateController.text = _deliveryAddress.state ?? "";
_phoneController.text = _deliveryAddress.phoneNumber; _phoneController.text = _deliveryAddress.phoneNumber?? "";
} else { } else {
_cityController.text = "Yangon"; _cityController.text = "Yangon";
_stateController.text = "Yangon"; _stateController.text = "Yangon";
@@ -198,7 +198,7 @@ class _DeliveryAddressEditorState extends State<DeliveryAddressEditor> {
return; return;
} }
if (widget.user != null) { if (widget.user != null) {
deliveryAddress.userID = widget.user.id; deliveryAddress.userID = widget.user!.id;
} }
setState(() { setState(() {
_isLoading = true; _isLoading = true;
@@ -224,7 +224,7 @@ class _DeliveryAddressEditorState extends State<DeliveryAddressEditor> {
return; return;
} }
if (widget.user != null) { if (widget.user != null) {
deliveryAddress.userID = widget.user.id; deliveryAddress.userID = widget.user!.id;
} }
setState(() { setState(() {
_isLoading = true; _isLoading = true;
@@ -255,7 +255,7 @@ class _DeliveryAddressEditorState extends State<DeliveryAddressEditor> {
DeliveryAddressModel deliveryAddressModel = DeliveryAddressModel deliveryAddressModel =
Provider.of<DeliveryAddressModel>(context, listen: false); Provider.of<DeliveryAddressModel>(context, listen: false);
if (widget.user != null) { if (widget.user != null) {
_deliveryAddress.userID = widget.user.id; _deliveryAddress.userID = widget.user!.id;
} }
await deliveryAddressModel.deleteDeliveryAddress(_deliveryAddress); await deliveryAddressModel.deleteDeliveryAddress(_deliveryAddress);
Navigator.pop(context, true); Navigator.pop(context, true);
@@ -278,7 +278,7 @@ class _DeliveryAddressEditorState extends State<DeliveryAddressEditor> {
_stateController.text != "Yangon"; _stateController.text != "Yangon";
} else { } else {
DeliveryAddress deliveryAddress = _getPayload(); DeliveryAddress deliveryAddress = _getPayload();
return widget.deliveryAddress.isChangedForEdit(deliveryAddress); return this._deliveryAddress.isChangedForEdit(deliveryAddress);
} }
} }
} }

View File

@@ -13,9 +13,9 @@ import 'model/delivery_address_model.dart';
class DeliveryAddressList extends StatefulWidget { class DeliveryAddressList extends StatefulWidget {
final bool isAdminCreation; final bool isAdminCreation;
final DeliveryAddress deliveryAddress; final DeliveryAddress? deliveryAddress;
const DeliveryAddressList( const DeliveryAddressList(
{Key key, this.isAdminCreation = false, this.deliveryAddress}) {Key? key, this.isAdminCreation = false, this.deliveryAddress})
: super(key: key); : super(key: key);
@override @override
_DeliveryAddressListState createState() => _DeliveryAddressListState(); _DeliveryAddressListState createState() => _DeliveryAddressListState();
@@ -85,7 +85,7 @@ class _DeliveryAddressListState extends State<DeliveryAddressList> {
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
child: Icon(Icons.check, child: Icon(Icons.check,
color: widget.isAdminCreation color: widget.isAdminCreation
? widget.deliveryAddress.id == deliveryAddress.id ? widget.deliveryAddress?.id == deliveryAddress.id
? primaryColor ? primaryColor
: Colors.black26 : Colors.black26
: deliveryAddress.isDefault : deliveryAddress.isDefault

View File

@@ -3,15 +3,15 @@ import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/widgets/local_text.dart'; import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
typedef SelectionCallback(DeliveryAddress deliveryAddress); typedef SelectionCallback(DeliveryAddress deliveryAddress);
class DeliveryAddressRow extends StatelessWidget { class DeliveryAddressRow extends StatelessWidget {
final DeliveryAddress deliveryAddress; final DeliveryAddress deliveryAddress;
final SelectionCallback selectionCallback; final SelectionCallback? selectionCallback;
const DeliveryAddressRow( const DeliveryAddressRow(
{Key key, this.deliveryAddress, this.selectionCallback}) {Key? key, required this.deliveryAddress, this.selectionCallback})
: super(key: key); : super(key: key);
@override @override
@@ -19,7 +19,7 @@ class DeliveryAddressRow extends StatelessWidget {
return InkWell( return InkWell(
onTap: selectionCallback == null onTap: selectionCallback == null
? null ? null
: () => this.selectionCallback(deliveryAddress), : () => this.selectionCallback!(deliveryAddress),
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
@@ -54,8 +54,8 @@ class DeliveryAddressRow extends StatelessWidget {
); );
} }
Widget line(BuildContext context, String text, Widget line(BuildContext context, String? text,
{IconData iconData, Color color, double fontSize}) { {IconData? iconData, Color? color, double? fontSize}) {
return Row( return Row(
children: [ children: [
iconData == null iconData == null
@@ -69,7 +69,7 @@ class DeliveryAddressRow extends StatelessWidget {
context, context,
text ?? "", text ?? "",
fontSize: fontSize ?? 14, fontSize: fontSize ?? 14,
color: color, color: color ?? Colors.grey,
), ),
), ),
], ],

View File

@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:barcode_scan2/gen/protos/protos.pb.dart';
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:fcs/data/services/services.dart'; import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/vo/delivery_address.dart'; import 'package:fcs/domain/vo/delivery_address.dart';
@@ -10,13 +11,13 @@ class DeliveryAddressModel extends BaseModel {
final log = Logger('FcsShipmentModel'); final log = Logger('FcsShipmentModel');
List<DeliveryAddress> deliveryAddresses = []; List<DeliveryAddress> deliveryAddresses = [];
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot>? listener;
DeliveryAddress get defalutAddress => DeliveryAddress get defalutAddress =>
deliveryAddresses.firstWhere((e) => e.isDefault, orElse: () => null); deliveryAddresses.firstWhere((e) => e.isDefault, orElse: () => DeliveryAddress());
DeliveryAddress getLocalDeliveryAddress(String id) => DeliveryAddress getLocalDeliveryAddress(String id) =>
deliveryAddresses.firstWhere((e) => e.id == id, orElse: () => null); deliveryAddresses.firstWhere((e) => e.id == id, orElse: () => DeliveryAddress());
@override @override
void privilegeChanged() { void privilegeChanged() {
@@ -26,26 +27,26 @@ class DeliveryAddressModel extends BaseModel {
@override @override
logout() async { logout() async {
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
deliveryAddresses = []; deliveryAddresses = [];
} }
Future<void> _loadDeliveryAddresses() async { Future<void> _loadDeliveryAddresses() async {
if (user == null) return; if (user == null) return;
String path = "$delivery_address_collection/"; String path = "$delivery_address_collection/";
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
deliveryAddresses = []; deliveryAddresses = [];
try { try {
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection('users') .collection('users')
.document("${user.id}") .doc("${user!.id}")
.collection("$path") .collection("$path")
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
deliveryAddresses.clear(); deliveryAddresses.clear();
deliveryAddresses = snapshot.documents.map((documentSnapshot) { deliveryAddresses = snapshot.docs.map((documentSnapshot) {
var s = DeliveryAddress.fromMap( var s = DeliveryAddress.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data as Map<String,dynamic>, documentSnapshot.id);
return s; return s;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -56,9 +57,9 @@ class DeliveryAddressModel extends BaseModel {
} }
Future<DeliveryAddress> getDeliveryAddress(String id) async { Future<DeliveryAddress> getDeliveryAddress(String id) async {
String path = "/$user_collection/${user.id}/$delivery_address_collection"; String path = "/$user_collection/${user!.id}/$delivery_address_collection";
var snap = await Firestore.instance.collection(path).document(id).get(); var snap = await FirebaseFirestore.instance.collection(path).doc(id).get();
return DeliveryAddress.fromMap(snap.data, snap.documentID); return DeliveryAddress.fromMap(snap.data as Map<String,dynamic>, snap.id);
} }
void initUser(user) { void initUser(user) {
@@ -87,14 +88,14 @@ class DeliveryAddressModel extends BaseModel {
Future<List<DeliveryAddress>> getDeliveryAddresses(String userID) async { Future<List<DeliveryAddress>> getDeliveryAddresses(String userID) async {
String path = "$delivery_address_collection/"; String path = "$delivery_address_collection/";
var querySnap = await Firestore.instance var querySnap = await FirebaseFirestore.instance
.collection('users') .collection('users')
.document("$userID") .doc("$userID")
.collection("$path") .collection("$path")
.orderBy("full_name") .orderBy("full_name")
.getDocuments(); .get();
return querySnap.documents return querySnap.docs
.map((e) => DeliveryAddress.fromMap(e.data, e.documentID)) .map((e) => DeliveryAddress.fromMap(e.data as Map<String,dynamic>, e.id))
.toList(); .toList();
} }
} }

View File

@@ -1,24 +1,22 @@
import 'package:fcs/domain/entities/discount.dart'; import 'package:fcs/domain/entities/discount.dart';
import 'package:fcs/domain/entities/user.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/discount/model/discount_model.dart'; import 'package:fcs/pages/discount/model/discount_model.dart';
import 'package:fcs/pages/main/util.dart'; import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/rates/model/shipment_rate_model.dart';
import 'package:fcs/pages/user_search/user_serach.dart'; import 'package:fcs/pages/user_search/user_serach.dart';
import 'package:fcs/pages/widgets/display_text.dart'; import 'package:fcs/pages/widgets/display_text.dart';
import 'package:fcs/pages/widgets/input_text.dart'; import 'package:fcs/pages/widgets/input_text.dart';
import 'package:fcs/pages/widgets/progress.dart'; import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart'; import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
class DiscountEditor extends StatefulWidget { class DiscountEditor extends StatefulWidget {
final Discount discount; final Discount? discount;
const DiscountEditor({Key key, this.discount}) : super(key: key); const DiscountEditor({Key? key, this.discount}) : super(key: key);
@override @override
_DiscountEditorState createState() => _DiscountEditorState(); _DiscountEditorState createState() => _DiscountEditorState();
} }
@@ -38,12 +36,12 @@ class _DiscountEditorState extends State<DiscountEditor> {
void initState() { void initState() {
super.initState(); super.initState();
if (widget.discount != null) { if (widget.discount != null) {
_discount = widget.discount; _discount = widget.discount!;
_codeController.text = _discount.code; _codeController.text = _discount.code ?? "";
_amountController.text = _discount.amount.toStringAsFixed(2); _amountController.text = _discount.amount.toStringAsFixed(2);
_statusController.text = _discount.status; _statusController.text = _discount.status ?? '';
customerName = widget.discount.customerName; customerName = _discount.customerName ?? "";
customerId = widget.discount.customerId; customerId = _discount.customerId ?? "";
} else { } else {
_isNew = true; _isNew = true;
} }
@@ -71,7 +69,7 @@ class _DiscountEditorState extends State<DiscountEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: DisplayText( child: DisplayText(
text: customerName != null ? customerName : "", text: customerName,
labelTextKey: "discount.name", labelTextKey: "discount.name",
iconData: Feather.user, iconData: Feather.user,
)), )),
@@ -79,8 +77,8 @@ class _DiscountEditorState extends State<DiscountEditor> {
icon: Icon(Icons.search, color: primaryColor), icon: Icon(Icons.search, color: primaryColor),
onPressed: () => searchUser(context, onUserSelect: (u) { onPressed: () => searchUser(context, onUserSelect: (u) {
setState(() { setState(() {
customerId = u.id; customerId = u.id ?? "";
customerName = u.name; customerName = u.name ?? "";
}); });
},popPage: true)), },popPage: true)),
], ],
@@ -93,7 +91,7 @@ class _DiscountEditorState extends State<DiscountEditor> {
appBar: AppBar( appBar: AppBar(
centerTitle: true, centerTitle: true,
title: Text( title: Text(
AppTranslations.of(context).text("discount.form"), AppTranslations.of(context)!.text("discount.form"),
), ),
leading: new IconButton( leading: new IconButton(
icon: new Icon(CupertinoIcons.back), icon: new Icon(CupertinoIcons.back),
@@ -162,7 +160,7 @@ class _DiscountEditorState extends State<DiscountEditor> {
if (_isNew) { if (_isNew) {
await discountModel.addDiscount(_discount); await discountModel.addDiscount(_discount);
} else { } else {
_discount.id = widget.discount.id; _discount.id = this._discount.id;
await discountModel.updateDiscount(_discount); await discountModel.updateDiscount(_discount);
} }
Navigator.pop(context); Navigator.pop(context);
@@ -186,7 +184,7 @@ class _DiscountEditorState extends State<DiscountEditor> {
}); });
try { try {
var discountModel = Provider.of<DiscountModel>(context, listen: false); var discountModel = Provider.of<DiscountModel>(context, listen: false);
await discountModel.deleteDiscount(widget.discount); await discountModel.deleteDiscount(_discount);
Navigator.pop(context); Navigator.pop(context);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
@@ -208,7 +206,7 @@ class _DiscountEditorState extends State<DiscountEditor> {
customerName: customerName, customerName: customerName,
customerId: customerId, customerId: customerId,
amount: double.parse(_amountController.text)); amount: double.parse(_amountController.text));
return widget.discount.isChangedForEdit(_discount); return widget.discount!.isChangedForEdit(_discount);
} }
} }
} }

Some files were not shown because too many files have changed in this diff Show More