Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Phaung Phaung
2021-09-10 15:23:22 +06:30
35 changed files with 261 additions and 262 deletions

View File

@@ -9,7 +9,7 @@ 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;
@@ -27,7 +27,7 @@ class Setting {
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,

View File

@@ -16,8 +16,8 @@ class User {
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 => String get initial =>
@@ -42,12 +42,12 @@ class User {
} }
String get getUserUnseenCount => userUnseenCount != null String get getUserUnseenCount => userUnseenCount != null
? userUnseenCount! > 100 ? userUnseenCount > 100
? "99+" ? "99+"
: userUnseenCount.toString() : userUnseenCount.toString()
: "0"; : "0";
String get getFcsUnseenCount => fcsUnseenCount != null String get getFcsUnseenCount => fcsUnseenCount != null
? fcsUnseenCount! > 100 ? fcsUnseenCount > 100
? "99+" ? "99+"
: fcsUnseenCount.toString() : fcsUnseenCount.toString()
: "0"; : "0";
@@ -72,8 +72,8 @@ class User {
this.privileges = const [], 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,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';
@@ -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

@@ -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,13 +12,14 @@ import 'package:logging/logging.dart';
class CartonModel extends BaseModel { class CartonModel extends BaseModel {
List<Carton> _boxes = []; List<Carton> _boxes = [];
PaginatorListener cartonsByFilter; PaginatorListener? 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;
@@ -87,17 +86,17 @@ 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

View File

@@ -26,7 +26,8 @@ class MessageModel extends BaseModel {
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;

View File

@@ -90,7 +90,7 @@ 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 Firestore.instance.collection(path).document(id).get();
return User.fromMap(snap.data, snap.documentID); return User.fromMap(snap.data, snap.documentID);

View File

@@ -45,7 +45,7 @@ class _BoxAdditionState extends State<BoxAddition> {
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
backgroundColor: primaryColor, backgroundColor: primaryColor,
title: Text(AppTranslations.of(context).text("box.edit.title")), title: Text(AppTranslations.of(context)!.text("box.edit.title")),
), ),
body: Card( body: Card(
child: Column( child: Column(

View File

@@ -38,7 +38,7 @@ class InvoiceCartonTable extends StatelessWidget {
? [Container()] ? [Container()]
: cartons!.asMap().entries.map((p) { : cartons!.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.shade50.withOpacity(0.2), : Colors.grey.shade50.withOpacity(0.2),
child: Container( child: Container(
@@ -56,7 +56,7 @@ class InvoiceCartonTable extends StatelessWidget {
child: Row( child: Row(
children: <Widget>[ children: <Widget>[
onSelect == null onSelect == null
? p.value.isChecked ? p.value.isChecked!
? SizedBox( ? SizedBox(
child: Icon(Icons.check, color: primaryColor), child: Icon(Icons.check, color: primaryColor),
width: 30) width: 30)
@@ -72,7 +72,7 @@ class InvoiceCartonTable extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
p.value.cartonNumber, p.value.cartonNumber!,
style: textStyle, style: textStyle,
), ),
], ],

View File

@@ -68,7 +68,7 @@ class InvoiceDiscountList extends StatelessWidget {
onSelectChanged: (value) => Navigator.pop(context, c), onSelectChanged: (value) => Navigator.pop(context, c),
cells: [ cells: [
MyDataCell(new Text( MyDataCell(new Text(
c.code, c.code!,
style: textStyle, style: textStyle,
)), )),
MyDataCell( MyDataCell(

View File

@@ -91,7 +91,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
_loadCartons() async { _loadCartons() async {
CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false); CartonModel cartonModel = Provider.of<CartonModel>(context, listen: false);
List<Carton> cartons = await cartonModel.getCartonsForInvoice( List<Carton> cartons = await cartonModel.getCartonsForInvoice(
widget.fcsShipment!.id, widget.customer!.id); widget.fcsShipment!.id!, widget.customer!.id!);
cartons.forEach((c) { cartons.forEach((c) {
c.isChecked = true; c.isChecked = true;
}); });
@@ -104,7 +104,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
ShipmentModel shipmentModel = ShipmentModel shipmentModel =
Provider.of<ShipmentModel>(context, listen: false); Provider.of<ShipmentModel>(context, listen: false);
List<Shipment> shipments = await shipmentModel.getShipmentWithHandlingFee( List<Shipment> shipments = await shipmentModel.getShipmentWithHandlingFee(
widget.fcsShipment!.id, widget.customer!.id); widget.fcsShipment!.id!, widget.customer!.id!);
shipments.forEach((s) { shipments.forEach((s) {
s.isSelected = true; s.isSelected = true;
}); });
@@ -117,7 +117,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
_loadDiscount() async { _loadDiscount() async {
DiscountModel discountModel = DiscountModel discountModel =
Provider.of<DiscountModel>(context, listen: false); Provider.of<DiscountModel>(context, listen: false);
discounts = await discountModel.getDiscount(widget.customer!.id); discounts = (await discountModel.getDiscount(widget.customer!.id!))!;
if (discounts != null && discounts.length > 0) { if (discounts != null && discounts.length > 0) {
setState(() { setState(() {
_invoice!.discount = discounts.first; _invoice!.discount = discounts.first;
@@ -281,7 +281,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(dateFormatter.format(_invoice!.invoiceDate)), Text(dateFormatter.format(_invoice!.invoiceDate!)),
SizedBox( SizedBox(
height: 10, height: 10,
), ),
@@ -429,7 +429,7 @@ class _InvoiceEditorState extends State<InvoiceEditor> {
invoice.cargoTypes = cargoTypes; invoice.cargoTypes = cargoTypes;
invoice.amount = amount; invoice.amount = amount;
invoice.handlingFee = _invoice!.getHandlingFee(); invoice.handlingFee = _invoice!.getHandlingFee();
invoice.cartons = _invoice!.cartons.where((c) => c.isChecked).toList(); invoice.cartons = _invoice!.cartons.where((c) => c.isChecked!).toList();
invoice.shipments = invoice.shipments =
_invoice!.shipments.where((s) => s.isSelected).toList(); _invoice!.shipments.where((s) => s.isSelected).toList();
invoice.discount = _invoice!.discount; invoice.discount = _invoice!.discount;

View File

@@ -72,7 +72,7 @@ class InvoiceHandlingFeeList extends StatelessWidget {
onSelectChanged: (value) => Navigator.pop(context, c), onSelectChanged: (value) => Navigator.pop(context, c),
cells: [ cells: [
MyDataCell(new Text( MyDataCell(new Text(
c.shipmentNumber, c.shipmentNumber!,
style: textStyle, style: textStyle,
)), )),
MyDataCell( MyDataCell(

View File

@@ -33,7 +33,7 @@ class _InvoiceCustomerListState extends State<InvoiceCustomerList> {
_load() async { _load() async {
CustomerModel customerModel = CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false); Provider.of<CustomerModel>(context, listen: false);
var users = await customerModel.getInvoiceUsers(widget.fcsShipment!.id); var users = await customerModel.getInvoiceUsers(widget.fcsShipment!.id!);
setState(() { setState(() {
_users = users; _users = users;
}); });
@@ -125,7 +125,7 @@ class _InvoiceCustomerListState extends State<InvoiceCustomerList> {
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),
), ),
@@ -133,7 +133,7 @@ class _InvoiceCustomerListState extends State<InvoiceCustomerList> {
Padding( Padding(
padding: const EdgeInsets.only(top: 2.0), padding: const EdgeInsets.only(top: 2.0),
child: new Text( child: new Text(
customer.phoneNumber, customer.phoneNumber!,
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),

View File

@@ -118,7 +118,7 @@ class _InvoiceInfoState extends State<InvoiceInfo> {
Column( Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(dateFormatter.format(_invoice!.invoiceDate)), Text(dateFormatter.format(_invoice!.invoiceDate!)),
SizedBox( SizedBox(
height: 5, height: 5,
), ),
@@ -140,7 +140,7 @@ class _InvoiceInfoState extends State<InvoiceInfo> {
); );
final paymentMethodBox = DisplayText( final paymentMethodBox = DisplayText(
labelTextKey: "invoice.payment_method", labelTextKey: "invoice.payment_method",
text: _invoice!.paymentMethod.name, text: _invoice!.paymentMethod!.name,
); );
final cancelBtn = LocalButton( final cancelBtn = LocalButton(

View File

@@ -58,7 +58,7 @@ class InvoiceListRow extends StatelessWidget {
fontSize: 13.0, color: primaryColor), fontSize: 13.0, color: primaryColor),
), ),
new Text( new Text(
dateFormatter.format(invoice!.invoiceDate), dateFormatter.format(invoice!.invoiceDate!),
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
) )

View File

@@ -64,7 +64,7 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
child: new Text( child: new Text(
_fcsShipment.shipmentNumber == null _fcsShipment.shipmentNumber == null
? '' ? ''
: _fcsShipment.shipmentNumber, : _fcsShipment.shipmentNumber!,
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.black), fontSize: 15.0, color: Colors.black),
), ),
@@ -72,7 +72,7 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
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(
dateFormatter.format(_fcsShipment.cutoffDate), dateFormatter.format(_fcsShipment.cutoffDate!),
style: new TextStyle( style: new TextStyle(
fontSize: 15.0, color: Colors.grey), fontSize: 15.0, color: Colors.grey),
), ),
@@ -86,7 +86,7 @@ class _InvoiceShipmentListRowState extends State<InvoiceShipmentListRow> {
), ),
Padding( Padding(
padding: const EdgeInsets.all(0), padding: const EdgeInsets.all(0),
child: getStatus(_fcsShipment.status), child: getStatus(_fcsShipment.status!),
), ),
], ],
), ),

View File

@@ -61,16 +61,16 @@ class InvoiceTable extends StatelessWidget {
List<InvoiceTableRow> getTableRows() { List<InvoiceTableRow> getTableRows() {
List<InvoiceTableRow> tableRows = []; List<InvoiceTableRow> tableRows = [];
// add cargo types // add cargo types
List<CargoType> _cargoTypes = invoice!.getCargoTypes(rate!) ?? []; List<CargoType> _cargoTypes = invoice!.getCargoTypes(rate!);
_cargoTypes.forEach((c) { _cargoTypes.forEach((c) {
tableRows.add(InvoiceTableRow( tableRows.add(InvoiceTableRow(
invoiceDataType: InvoiceDataType.CargoDataType, invoiceDataType: InvoiceDataType.CargoDataType,
desc: c.name, desc: c.name,
rate: rate:
"${c.calWeight!.toStringAsFixed(2)} x ${c.calRate!.toStringAsFixed(2)}", "${c.calWeight.toStringAsFixed(2)} x ${c.calRate.toStringAsFixed(2)}",
amount: "${c.calAmount.toStringAsFixed(2)}")); amount: "${c.calAmount.toStringAsFixed(2)}"));
}); });
invoice!.shipments.where((ss) => (ss.isSelected ?? false)).forEach((s) { invoice!.shipments.where((ss) => (ss.isSelected )).forEach((s) {
tableRows.add(InvoiceTableRow( tableRows.add(InvoiceTableRow(
data: s, data: s,
invoiceDataType: InvoiceDataType.HandlingFeeType, invoiceDataType: InvoiceDataType.HandlingFeeType,
@@ -95,7 +95,7 @@ class InvoiceTable extends StatelessWidget {
invoiceDataType: InvoiceDataType.DeliveryFeeType, invoiceDataType: InvoiceDataType.DeliveryFeeType,
desc: "Delivery fee", desc: "Delivery fee",
rate: "", rate: "",
amount: "${invoice?.deliveryFee?.toStringAsFixed(2) ?? '0'}")); amount: "${invoice?.deliveryFee.toStringAsFixed(2) ?? '0'}"));
// // add discounts // // add discounts
if (invoice!.discount != null) { if (invoice!.discount != null) {
@@ -104,7 +104,7 @@ class InvoiceTable extends StatelessWidget {
invoiceDataType: InvoiceDataType.DiscountDataType, invoiceDataType: InvoiceDataType.DiscountDataType,
desc: "Discount\n${invoice?.discount?.code ?? ""}", desc: "Discount\n${invoice?.discount?.code ?? ""}",
rate: "", rate: "",
amount: "(${invoice?.discount?.amount?.toStringAsFixed(2) ?? ''})")); amount: "(${invoice?.discount?.amount.toStringAsFixed(2) ?? ''})"));
} }
return tableRows; return tableRows;

View File

@@ -15,14 +15,14 @@ import 'package:path/path.dart' as Path;
class InvoiceModel extends BaseModel { class InvoiceModel extends BaseModel {
final log = Logger('InvoiceModel'); final log = Logger('InvoiceModel');
StreamSubscription<QuerySnapshot> listener; StreamSubscription<QuerySnapshot<Map<String, dynamic>>>? listener;
List<Invoice> _invoices = []; List<Invoice> _invoices = [];
List<Invoice> get invoices => List<Invoice> get invoices =>
_selectedIndex == 1 ? _invoices : List<Invoice>.from(_paginator.values); _selectedIndex == 1 ? _invoices : List<Invoice>.from(_paginator.values);
Paginator _paginator; late Paginator _paginator;
bool endOfPaidInvoices = false; bool endOfPaidInvoices = false;
bool isLoading = false; bool isLoading = false;
@@ -33,7 +33,7 @@ class InvoiceModel extends BaseModel {
notifyListeners(); notifyListeners();
} }
get selectedIndex => _selectedIndex; int get selectedIndex => _selectedIndex;
@override @override
void privilegeChanged() { void privilegeChanged() {
@@ -54,11 +54,11 @@ class InvoiceModel extends BaseModel {
if (user == null) return; if (user == null) return;
if (!forCustomer && !user.hasInvoices()) return; if (!forCustomer && !user.hasInvoices()) return;
String path = "/$invoices_collection"; String path = "/$invoices_collection";
if (listener != null) listener.cancel(); if (listener != null) listener!.cancel();
_invoices = []; _invoices = [];
try { try {
var q = Firestore.instance var q = FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("status", isEqualTo: invoice_issued_status) .where("status", isEqualTo: invoice_issued_status)
.where("is_deleted", isEqualTo: false); .where("is_deleted", isEqualTo: false);
@@ -69,9 +69,9 @@ class InvoiceModel extends BaseModel {
listener = q.snapshots().listen((QuerySnapshot snapshot) { listener = q.snapshots().listen((QuerySnapshot snapshot) {
_invoices.clear(); _invoices.clear();
_invoices = snapshot.documents.map((documentSnapshot) { _invoices = snapshot.docs.map((documentSnapshot) {
var s = Invoice.fromMap( var s = Invoice.fromMap(documentSnapshot.data as Map<String, dynamic>,
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.id);
return s; return s;
}).toList(); }).toList();
notifyListeners(); notifyListeners();
@@ -85,7 +85,7 @@ class InvoiceModel extends BaseModel {
if (!isCustomer) { if (!isCustomer) {
if (user == null || !(user.hasInvoices())) throw "No privilege"; if (user == null || !(user.hasInvoices())) throw "No privilege";
} }
var pageQuery = Firestore.instance var pageQuery = FirebaseFirestore.instance
.collection("/$invoices_collection") .collection("/$invoices_collection")
.where("is_deleted", isEqualTo: false); .where("is_deleted", isEqualTo: false);
if (isCustomer) { if (isCustomer) {
@@ -105,7 +105,7 @@ class InvoiceModel extends BaseModel {
return paginator; return paginator;
} }
Future<void> loadMore({bool isCustomer}) async { Future<void> loadMore({bool? isCustomer}) async {
if (_paginator.ended || _selectedIndex == 1) if (_paginator.ended || _selectedIndex == 1)
return; // when paid menu is not selected return return; // when paid menu is not selected return
isLoading = true; isLoading = true;
@@ -116,7 +116,7 @@ class InvoiceModel extends BaseModel {
}); });
} }
Future<void> refresh({bool isCustomer}) async { Future<void> refresh({bool? isCustomer}) async {
if (_selectedIndex == 1) return; // when paid menu is not selected return if (_selectedIndex == 1) return; // when paid menu is not selected return
await _paginator.refresh(onFinished: () { await _paginator.refresh(onFinished: () {
notifyListeners(); notifyListeners();
@@ -129,17 +129,17 @@ class InvoiceModel extends BaseModel {
logout() async { logout() async {
if (_paginator != null) _paginator.close(); if (_paginator != null) _paginator.close();
if (listener != null) await listener.cancel(); if (listener != null) await listener!.cancel();
_invoices = []; _invoices = [];
} }
Future<Invoice> getInvoice(String id) async { Future<Invoice?> getInvoice(String id) async {
String path = "/$invoices_collection"; String path = "/$invoices_collection";
try { try {
var ref = Firestore.instance.collection("$path").document(id); var ref = FirebaseFirestore.instance.collection("$path").doc(id);
var snap = await ref.get(source: Source.server); var snap = await ref.get(const GetOptions(source: Source.server));
if (snap.exists) { if (snap.exists) {
var s = Invoice.fromMap(snap.data, snap.documentID); var s = Invoice.fromMap(snap.data as Map<String, dynamic>, snap.id);
return s; return s;
} }
} catch (e) { } catch (e) {

View File

@@ -50,9 +50,9 @@ class _PaymentPageState extends State<PaymentPage> {
_loadInvoice() async { _loadInvoice() async {
InvoiceModel invoiceModel = InvoiceModel invoiceModel =
Provider.of<InvoiceModel>(context, listen: false); Provider.of<InvoiceModel>(context, listen: false);
Invoice i = await invoiceModel.getInvoice(_invoice.id); Invoice? i = await invoiceModel.getInvoice(_invoice.id!);
setState(() { setState(() {
_invoice = i; _invoice = i!;
}); });
} }
@@ -97,7 +97,7 @@ class _PaymentPageState extends State<PaymentPage> {
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
backgroundColor: primaryColor, backgroundColor: primaryColor,
title: Text(AppTranslations.of(context).text("pm_.title")), title: Text(AppTranslations.of(context)!.text("pm_.title")),
), ),
body: ListView( body: ListView(
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
@@ -133,8 +133,8 @@ class _PaymentPageState extends State<PaymentPage> {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.grey))), border: Border(bottom: BorderSide(color: Colors.grey))),
padding: const EdgeInsets.only( padding:
left: 5.0, right: 5.0, top: 5.0, bottom: 5.0), const EdgeInsets.only(left: 5.0, right: 5.0, top: 5.0, bottom: 5.0),
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
@@ -145,7 +145,7 @@ class _PaymentPageState extends State<PaymentPage> {
Padding( Padding(
padding: const EdgeInsets.only(left: 8.0), padding: const EdgeInsets.only(left: 8.0),
child: Text( child: Text(
'${p.paymentDate != null ? dateFormatter.format(p.paymentDate) : ""}'), '${p.paymentDate != null ? dateFormatter.format(p.paymentDate!) : ""}'),
), ),
SizedBox( SizedBox(
height: 5, height: 5,
@@ -153,7 +153,7 @@ class _PaymentPageState extends State<PaymentPage> {
LocalImagePicker( LocalImagePicker(
key: ValueKey(p.id), key: ValueKey(p.id),
enabled: false, enabled: false,
initialImgUrl: p.paymentReceiptURL, initialImgUrl: p.paymentReceiptURL!,
title: "Receipt", title: "Receipt",
color: primaryColor, color: primaryColor,
) )
@@ -187,8 +187,7 @@ class _PaymentPageState extends State<PaymentPage> {
onTap: () => _cancel(p), onTap: () => _cancel(p),
child: Padding( child: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Icon(Icons.close, child: Icon(Icons.close, color: primaryColor),
color: primaryColor),
), ),
), ),
] ]

View File

@@ -154,7 +154,7 @@ class _PaymentPageEditState extends State<PaymentPageEdit> {
onPressed: () => Navigator.of(context).pop(), onPressed: () => Navigator.of(context).pop(),
), ),
backgroundColor: primaryColor, backgroundColor: primaryColor,
title: Text(AppTranslations.of(context).text("pm_.title")), title: Text(AppTranslations.of(context)!.text("pm_.title")),
), ),
body: Padding( body: Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
@@ -189,7 +189,7 @@ class _PaymentPageEditState extends State<PaymentPageEdit> {
_widget = initialImage(); _widget = initialImage();
} else { } else {
_widget = InkWell( _widget = InkWell(
child: Image.asset(widget.receipt!.fileUrl, fit: BoxFit.cover), child: Image.asset(widget.receipt!.fileUrl!, fit: BoxFit.cover),
onTap: () {}, onTap: () {},
); );
} }

View File

@@ -84,7 +84,7 @@ class _HomePageState extends State<HomePage> {
} }
_loadStaffMode(bool isCustomer) async { _loadStaffMode(bool isCustomer) async {
bool staffMode = await SharedPref.getStaffMode(); bool? staffMode = await SharedPref.getStaffMode();
setState(() { setState(() {
if (isCustomer) { if (isCustomer) {
isFcs[0] = false; isFcs[0] = false;
@@ -117,12 +117,12 @@ class _HomePageState extends State<HomePage> {
if (mainModel.isLogin()) { if (mainModel.isLogin()) {
timer.cancel(); timer.cancel();
bool isCustomer = mainModel.isCustomer(); bool isCustomer = mainModel.isCustomer();
String receiverID = isCustomer ? mainModel.user.id : notiUserID; String? receiverID = isCustomer ? mainModel.user?.id : notiUserID;
String receiverName = isCustomer ? mainModel.user.name : notiUserName; String? receiverName = isCustomer ? mainModel.user?.name : notiUserName;
MessageModel messageModel = MessageModel messageModel =
Provider.of<MessageModel>(context, listen: false); Provider.of<MessageModel>(context, listen: false);
messageModel.initQuery(receiverID); messageModel.initQuery(receiverID);
User user = mainModel.user; User user = mainModel.user!;
if (!isCustomer) { if (!isCustomer) {
CustomerModel customerModel = CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false); Provider.of<CustomerModel>(context, listen: false);
@@ -133,15 +133,15 @@ class _HomePageState extends State<HomePage> {
MaterialPageRoute( MaterialPageRoute(
builder: (context) => MessageDetail( builder: (context) => MessageDetail(
messageModel: messageModel, messageModel: messageModel,
receiverID: receiverID, receiverID: receiverID ?? "",
receiverName: receiverName, receiverName: receiverName ?? "",
))).then((value) { ))).then((value) {
if (user.userUnseenCount > 0) { if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true); messageModel.seenMessages(user.id ?? "", true);
} }
}); });
if (user.userUnseenCount > 0) { if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true); messageModel.seenMessages(user.id ?? "", true);
} }
} }
} }
@@ -204,7 +204,7 @@ class _HomePageState extends State<HomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
User user = Provider.of<MainModel>(context).user; User? user = Provider.of<MainModel>(context).user;
if (user == null) { if (user == null) {
Future.microtask( Future.microtask(
@@ -280,11 +280,11 @@ class _HomePageState extends State<HomePage> {
)) ))
.then((value) { .then((value) {
if (user.userUnseenCount > 0) { if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true); messageModel.seenMessages(user.id ?? "", true);
} }
}); });
if (user.userUnseenCount > 0) { if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true); messageModel.seenMessages(user.id ?? "", true);
} }
}); });
final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount); final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount);

View File

@@ -101,8 +101,8 @@ class _InitialLanguageSelectionPageState
? BoxDecoration() ? BoxDecoration()
: BoxDecoration( : BoxDecoration(
border: Border( border: Border(
bottom: bottom: BorderSide(
BorderSide(color: Colors.grey.shade300), color: Colors.grey.shade300),
), ),
), ),
child: ListTile( child: ListTile(

View File

@@ -6,9 +6,9 @@ import 'package:fcs/helpers/api_helper.dart';
import 'main_model.dart'; import 'main_model.dart';
abstract class BaseModel extends ChangeNotifier { abstract class BaseModel extends ChangeNotifier {
User user; User? user;
Setting setting; Setting? setting;
MainModel mainModel; MainModel? mainModel;
void initUser(User user) async { void initUser(User user) async {
this.user = user; this.user = user;
@@ -16,7 +16,7 @@ abstract class BaseModel extends ChangeNotifier {
void privilegeChanged() {} void privilegeChanged() {}
void initSetting(Setting setting) async { void initSetting(Setting? setting) async {
this.setting = setting; this.setting = setting;
} }
@@ -32,8 +32,8 @@ abstract class BaseModel extends ChangeNotifier {
String path, String path,
method, { method, {
dynamic payload, dynamic payload,
String token, required String token,
String url, String? url,
}) async { }) async {
return await requestAPI(path, method, return await requestAPI(path, method,
payload: payload, token: token, url: url); payload: payload, token: token, url: url);

View File

@@ -5,7 +5,7 @@ import 'package:flutter/painting.dart';
import 'base_model.dart'; import 'base_model.dart';
class LanguageModel extends BaseModel { class LanguageModel extends BaseModel {
String language; late String language;
bool get isEng => this.language == "English"; bool get isEng => this.language == "English";
List<bool> get currentState => isEng ? [true, false] : [false, true]; List<bool> get currentState => isEng ? [true, false] : [false, true];

View File

@@ -15,16 +15,16 @@ class MainModel extends ChangeNotifier {
final log = Logger('MainModel'); final log = Logger('MainModel');
List<BaseModel> models = []; List<BaseModel> models = [];
String messagingToken; String? messagingToken;
User user; User? user;
PackageInfo packageInfo; PackageInfo? packageInfo;
set setMessaginToken(token) { set setMessaginToken(token) {
this.messagingToken = token; this.messagingToken = token;
uploadMsgToken(); uploadMsgToken();
} }
Setting setting; Setting? setting;
bool isLoaded = false; bool isLoaded = false;
bool isOnline = false; bool isOnline = false;
@@ -42,23 +42,23 @@ class MainModel extends ChangeNotifier {
} }
bool faqEditable() { bool faqEditable() {
return this.user != null && this.user.hasSupport(); return this.user != null && this.user!.hasSupport();
} }
bool rateEditable() { bool rateEditable() {
return this.user != null && this.user.hasSupport(); return this.user != null && this.user!.hasSupport();
} }
bool paymentMethodsEditable() { bool paymentMethodsEditable() {
return this.user != null && this.user.hasSupport(); return this.user != null && this.user!.hasSupport();
} }
bool termEditable() { bool termEditable() {
return this.user != null && this.user.hasSupport(); return this.user != null && this.user!.hasSupport();
} }
bool contactEditable() { bool contactEditable() {
return this.user != null && this.user.hasSupport(); return this.user != null && this.user!.hasSupport();
} }
bool isLogin() { bool isLogin() {
@@ -66,32 +66,31 @@ class MainModel extends ChangeNotifier {
} }
bool isCustomer() { bool isCustomer() {
return user != null && user.isCustomer(); return user != null && user!.isCustomer();
} }
bool isSysAdmin() { bool isSysAdmin() {
return this.user != null && this.user.hasSysAdmin(); return this.user != null && this.user!.hasSysAdmin();
} }
bool isAdmin() { bool isAdmin() {
return this.user != null && this.user.hasAdmin(); return this.user != null && this.user!.hasAdmin();
} }
// userListener should never be closed // userListener should never be closed
StreamSubscription<User> userListener; StreamSubscription<User?>? userListener;
_init() async { _init() async {
await _listenSetting(); await _listenSetting();
this.isFirstLaunch = await SharedPref.isFirstLaunch(); this.isFirstLaunch = await SharedPref.isFirstLaunch() ?? true;
this.isFirstLaunch = this.isFirstLaunch ?? true;
this.packageInfo = await PackageInfo.fromPlatform(); this.packageInfo = await PackageInfo.fromPlatform();
if (userListener != null) userListener.cancel(); if (userListener != null) userListener!.cancel();
userListener = userListener =
Services.instance.authService.getUserStream().listen((_user) { Services.instance.authService.getUserStream().listen((_user) {
if (_user != null) { if (_user != null) {
models.forEach((m) => m.initUser(_user)); models.forEach((m) => m.initUser(_user));
// call diffPrivileges if privilege changed or first time login // call diffPrivileges if privilege changed or first time login
if (this.user == null || _user.diffPrivileges(this.user)) { if (this.user == null || _user.diffPrivileges(this.user!)) {
models.forEach((m) => m.privilegeChanged()); models.forEach((m) => m.privilegeChanged());
} }
if (this.user == null) { if (this.user == null) {
@@ -124,7 +123,7 @@ class MainModel extends ChangeNotifier {
bool isSupport() { bool isSupport() {
if (packageInfo == null || setting == null) return false; if (packageInfo == null || setting == null) return false;
return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum; return int.parse(packageInfo!.buildNumber) >= setting!.supportBuildNum;
} }
Future<AuthResult> sendSms(String phoneNumber) { Future<AuthResult> sendSms(String phoneNumber) {
@@ -137,14 +136,14 @@ class MainModel extends ChangeNotifier {
return authResult; return authResult;
} }
Future<void> uploadMsgToken() { Future<void>? uploadMsgToken() {
if (messagingToken == null || user == null) return null; if (messagingToken == null || user == null) return null;
return Services.instance.userService.uploadMsgToken(messagingToken); return Services.instance.userService.uploadMsgToken(messagingToken!);
} }
Future<void> removeMsgToken() { Future<void>? removeMsgToken() {
if (messagingToken == null || user == null) return null; if (messagingToken == null || user == null) return null;
return Services.instance.userService.removeMsgToken(messagingToken); return Services.instance.userService.removeMsgToken(messagingToken!);
} }
Future<void> signout() async { Future<void> signout() async {

View File

@@ -35,7 +35,7 @@ class _MarketEditorState extends State<MarketEditor> {
children: <Widget>[ children: <Widget>[
Expanded( Expanded(
child: new Text( child: new Text(
p.name, p.name ?? "",
style: TextStyle( style: TextStyle(
fontSize: 15.0, fontSize: 15.0,
), ),
@@ -117,7 +117,7 @@ class _MarketEditorState extends State<MarketEditor> {
}); });
MarketModel marketModel = Provider.of<MarketModel>(context, listen: false); MarketModel marketModel = Provider.of<MarketModel>(context, listen: false);
try { try {
await marketModel.deleteMarket(market.id); await marketModel.deleteMarket(market.id!);
} catch (e) { } catch (e) {
showMsgDialog(context, "Error", e.toString()); showMsgDialog(context, "Error", e.toString());
} finally { } finally {

View File

@@ -20,14 +20,14 @@ class MarketModel extends BaseModel {
try { try {
if (listener != null) listener.cancel(); if (listener != null) listener.cancel();
listener = Firestore.instance listener = FirebaseFirestore.instance
.collection("/$config_collection/$setting_doc_id/$markets_collection") .collection("/$config_collection/$setting_doc_id/$markets_collection")
.snapshots() .snapshots()
.listen((QuerySnapshot snapshot) { .listen((QuerySnapshot snapshot) {
markets.clear(); markets.clear();
markets = snapshot.documents.map((documentSnapshot) { markets = snapshot.docs.map((documentSnapshot) {
var user = Market.fromMap( var user = Market.fromMap(
documentSnapshot.data, documentSnapshot.documentID); documentSnapshot.data as Map<String, dynamic>, documentSnapshot.id);
return user; return user;
}).toList(); }).toList();
notifyListeners(); notifyListeners();

View File

@@ -16,9 +16,9 @@ import 'package:path/path.dart' as Path;
class PackageModel extends BaseModel { class PackageModel extends BaseModel {
final log = Logger('PackageModel'); final log = Logger('PackageModel');
PaginatorListener packages; PaginatorListener? packages;
PaginatorListener customerPackages; PaginatorListener? customerPackages;
PaginatorListener activePackages; PaginatorListener? activePackages;
bool isLoading = false; bool isLoading = false;
int _menuSelectedIndex = 1; int _menuSelectedIndex = 1;
@@ -32,7 +32,7 @@ class PackageModel extends BaseModel {
notifyListeners(); notifyListeners();
} }
get menuSelectedIndex => _menuSelectedIndex; int get menuSelectedIndex => _menuSelectedIndex;
void privilegeChanged() { void privilegeChanged() {
if (user != null) { if (user != null) {
@@ -63,9 +63,9 @@ class PackageModel extends BaseModel {
@override @override
logout() async { logout() async {
if (customerPackages != null) customerPackages.close(); if (customerPackages != null) customerPackages!.close();
if (packages != null) packages.close(); if (packages != null) packages!.close();
if (activePackages != null) activePackages.close(); if (activePackages != null) activePackages!.close();
} }
Future<void> _loadPackages(bool isDelivered) async { Future<void> _loadPackages(bool isDelivered) async {
@@ -75,15 +75,15 @@ class PackageModel extends BaseModel {
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
Query listenerQuery = Firestore.instance Query listenerQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: isDelivered); .where("is_delivered", isEqualTo: isDelivered);
Query pageQuery = Firestore.instance Query pageQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: isDelivered); .where("is_delivered", isEqualTo: isDelivered);
pageQuery = pageQuery.orderBy("update_time", descending: true); pageQuery = pageQuery.orderBy("update_time", descending: true);
packages.refresh(listeningQuery: listenerQuery, pageQuery: pageQuery); packages!.refresh(listeningQuery: listenerQuery, pageQuery: pageQuery);
} catch (e) { } catch (e) {
log.warning("Error!! $e"); log.warning("Error!! $e");
} }
@@ -94,17 +94,17 @@ class PackageModel extends BaseModel {
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
Query listenerQuery = Firestore.instance Query listenerQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: isDelivered) .where("is_delivered", isEqualTo: isDelivered)
.where("user_id", isEqualTo: user.id); .where("user_id", isEqualTo: user.id);
Query pageQuery = Firestore.instance Query pageQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: isDelivered) .where("is_delivered", isEqualTo: isDelivered)
.where("user_id", isEqualTo: user.id) .where("user_id", isEqualTo: user.id)
.orderBy("update_time", descending: true); .orderBy("update_time", descending: true);
customerPackages.refresh( customerPackages!.refresh(
listeningQuery: listenerQuery, pageQuery: pageQuery); listeningQuery: listenerQuery, pageQuery: pageQuery);
} catch (e) { } catch (e) {
log.warning("Error!! $e"); log.warning("Error!! $e");
@@ -118,29 +118,30 @@ class PackageModel extends BaseModel {
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
Query listenerQuery = Firestore.instance Query listenerQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: false); .where("is_delivered", isEqualTo: false);
Query pageQuery = Firestore.instance Query pageQuery = FirebaseFirestore.instance
.collection(path) .collection(path)
.where("is_delivered", isEqualTo: false); .where("is_delivered", isEqualTo: false);
pageQuery = pageQuery.orderBy("update_time", descending: true); pageQuery = pageQuery.orderBy("update_time", descending: true);
activePackages.refresh( activePackages!.refresh(
listeningQuery: listenerQuery, pageQuery: pageQuery); listeningQuery: listenerQuery, pageQuery: pageQuery);
} catch (e) { } catch (e) {
log.warning("Error!! $e"); log.warning("Error!! $e");
} }
} }
Future<Package> getPackage(String id) async { Future<Package?> getPackage(String id) async {
if (user == null) return null; if (user == null) return null;
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
DocumentSnapshot snap = DocumentSnapshot snap =
await Firestore.instance.collection("$path").document(id).get(); await FirebaseFirestore.instance.collection("$path").doc(id).get();
if (snap.exists) { if (snap.exists) {
var package = Package.fromMap(snap.data, snap.documentID); var package =
Package.fromMap(snap.data as Map<String, dynamic>, snap.id);
return package; return package;
} }
} catch (e) { } catch (e) {
@@ -149,18 +150,18 @@ class PackageModel extends BaseModel {
return null; return null;
} }
Future<Package> getPackageByTrackingID(String trackingID) async { Future<Package?> getPackageByTrackingID(String trackingID) async {
if (user == null) return null; if (user == null) return null;
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
var snaps = await Firestore.instance var snaps = await FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("tracking_id", isEqualTo: trackingID) .where("tracking_id", isEqualTo: trackingID)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(source: Source.server); .get(const GetOptions(source: Source.server));
if (snaps.documents.length == 1) { if (snaps.docs.length == 1) {
var snap = snaps.documents[0]; var snap = snaps.docs[0];
var package = Package.fromMap(snap.data, snap.documentID); var package = Package.fromMap(snap.data as Map<String, dynamic>, snap.id);
return package; return package;
} }
} catch (e) { } catch (e) {
@@ -169,35 +170,35 @@ class PackageModel extends BaseModel {
return null; return null;
} }
Future<Package> lookupPackage(String trackingID) async { Future<Package?> lookupPackage(String trackingID) async {
if (user == null) return null; if (user == null) return null;
String path = "/$packages_collection"; String path = "/$packages_collection";
try { try {
var qsnap = await Firestore.instance var qsnap = await FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("tracking_id", isEqualTo: trackingID) .where("tracking_id", isEqualTo: trackingID)
.where("has_user_id", isEqualTo: false) .where("has_user_id", isEqualTo: false)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(source: Source.server); .get(const GetOptions(source: Source.server));
if (qsnap.documents.length > 0) { if (qsnap.docs.length > 0) {
var snap = qsnap.documents[0]; var snap = qsnap.docs[0];
if (snap.exists) { if (snap.exists) {
var package = Package.fromMap(snap.data, snap.documentID); var package = Package.fromMap(snap.data as Map<String, dynamic>, snap.id);
return package; return package;
} }
} }
qsnap = await Firestore.instance qsnap = await FirebaseFirestore.instance
.collection("$path") .collection("$path")
.where("tracking_id", isEqualTo: trackingID) .where("tracking_id", isEqualTo: trackingID)
.where("user_id", isEqualTo: user.id) .where("user_id", isEqualTo: user.id)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(source: Source.server); .get(const GetOptions(source: Source.server));
if (qsnap.documents.length > 0) { if (qsnap.docs.length > 0) {
var snap = qsnap.documents[0]; var snap = qsnap.docs[0];
if (snap.exists) { if (snap.exists) {
var package = Package.fromMap(snap.data, snap.documentID); var package = Package.fromMap(snap.data as Map<String, dynamic>, snap.id);
return package; return package;
} }
} }
@@ -210,15 +211,15 @@ class PackageModel extends BaseModel {
Future<List<Package>> getPackages(String userID, List<String> status) async { Future<List<Package>> getPackages(String userID, List<String> status) async {
List<Package> packages = []; List<Package> packages = [];
try { try {
var snaps = await Firestore.instance var snaps = await FirebaseFirestore.instance
.collection("/$packages_collection") .collection("/$packages_collection")
.where("status", whereIn: status) .where("status", whereIn: status)
.where("user_id", isEqualTo: userID) .where("user_id", isEqualTo: userID)
.where("is_deleted", isEqualTo: false) .where("is_deleted", isEqualTo: false)
.getDocuments(source: Source.server); .get(const GetOptions(source: Source.server));
packages = snaps.documents.map((documentSnapshot) { packages = snaps.docs.map((documentSnapshot) {
var p = var p =
Package.fromMap(documentSnapshot.data, documentSnapshot.documentID); Package.fromMap(documentSnapshot.data as Map<String, dynamic>, documentSnapshot.id);
return p; return p;
}).toList(); }).toList();
} catch (e) { } catch (e) {
@@ -235,22 +236,22 @@ class PackageModel extends BaseModel {
Future<List<Package>> packages = Future<List<Package>> packages =
Services.instance.packageService.searchPackage(term); Services.instance.packageService.searchPackage(term);
Future<List<Package>> packagesFTS = Future<List<Package>?> packagesFTS =
Services.instance.packageService.ftsSearchPackage(term); Services.instance.packageService.ftsSearchPackage(term);
// Package pkg = await getPackageByTrackingID(term); // Package pkg = await getPackageByTrackingID(term);
// if (pkg != null && !packages.contains(pkg)) { // if (pkg != null && !packages.contains(pkg)) {
// packages.insert(0, pkg); // packages.insert(0, pkg);
// } // }
List<Package> pkgs = await packages; List<Package> pkgs = await packages;
List<Package> ftsPkgs = await packagesFTS; List<Package>? ftsPkgs = await packagesFTS;
pkgs.addAll(ftsPkgs); pkgs.addAll(ftsPkgs!);
final seen = Set<Package>(); final seen = Set<Package>();
return pkgs.where((e) => seen.add(e)).toList(); return pkgs.where((e) => seen.add(e)).toList();
} }
Future<void> createPackages(User user, List<Package> packages) { Future<void> createPackages(User user, List<Package> packages) {
return Services.instance.packageService return Services.instance.packageService
.createPackages(packages, user.fcsID); .createPackages(packages, user.fcsID!);
} }
Future<void> createReceiving( Future<void> createReceiving(
@@ -370,10 +371,10 @@ class PackageModel extends BaseModel {
Future<void> changeDeliveryAddress( Future<void> changeDeliveryAddress(
Package package, DeliveryAddress deliveryAddress) { Package package, DeliveryAddress deliveryAddress) {
return Services.instance.packageService return Services.instance.packageService
.changeDeliveryAddress(package.id, deliveryAddress.id); .changeDeliveryAddress(package.id!, deliveryAddress.id!);
} }
Future<void> packageReturn(Package package) { Future<void> packageReturn(Package package) {
return Services.instance.packageService.packageReturn(package.id); return Services.instance.packageService.packageReturn(package.id!);
} }
} }

View File

@@ -38,7 +38,7 @@ class _DeliveryAddressSelectionState extends State<DeliveryAddressSelection> {
Provider.of<DeliveryAddressModel>(context, listen: false); Provider.of<DeliveryAddressModel>(context, listen: false);
var deliveryAddresses = var deliveryAddresses =
await addressModel.getDeliveryAddresses(widget.user!.id); await addressModel.getDeliveryAddresses(widget.user!.id!);
setState(() { setState(() {
this._deliveryAddresses = deliveryAddresses; this._deliveryAddresses = deliveryAddresses;
}); });
@@ -64,7 +64,7 @@ class _DeliveryAddressSelectionState extends State<DeliveryAddressSelection> {
bool updated = await Navigator.of(context).push(CupertinoPageRoute( bool updated = await Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => builder: (context) =>
DeliveryAddressEditor(user: widget.user))); DeliveryAddressEditor(user: widget.user)));
if (updated ?? false) { if (updated) {
_getDeliverAddresses(); _getDeliverAddresses();
} }
}, },
@@ -117,7 +117,7 @@ class _DeliveryAddressSelectionState extends State<DeliveryAddressSelection> {
bool updated = await Navigator.of(context).push(CupertinoPageRoute( bool updated = await Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => DeliveryAddressEditor( builder: (context) => DeliveryAddressEditor(
user: widget.user, deliveryAddress: deliveryAddress))); user: widget.user, deliveryAddress: deliveryAddress)));
if (updated ?? false) { if (updated) {
_getDeliverAddresses(); _getDeliverAddresses();
} }
} }

View File

@@ -53,7 +53,8 @@ class DiscountDropdown<T> extends StatelessWidget {
items: values!.map<DropdownMenuItem<T>>((T value) { items: values!.map<DropdownMenuItem<T>>((T value) {
return DropdownMenuItem<T>( return DropdownMenuItem<T>(
value: value, value: value,
child: Text(value == null ? "" : (value as Discount).code, child: Text(
value == null ? "" : (value as Discount).code!,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: TextStyle(color: primaryColor)), style: TextStyle(color: primaryColor)),
); );

View File

@@ -20,7 +20,7 @@ class MyDataColumn {
/// ///
/// The [label] argument must not be null. /// The [label] argument must not be null.
const MyDataColumn({ const MyDataColumn({
@required this.label, required this.label,
this.tooltip, this.tooltip,
this.numeric = false, this.numeric = false,
this.onSort, this.onSort,
@@ -40,7 +40,7 @@ class MyDataColumn {
/// This is a longer description of the column heading, for cases /// This is a longer description of the column heading, for cases
/// where the heading might have been abbreviated to keep the column /// where the heading might have been abbreviated to keep the column
/// width to a reasonable size. /// width to a reasonable size.
final String tooltip; final String? tooltip;
/// Whether this column represents numeric data or not. /// Whether this column represents numeric data or not.
/// ///
@@ -53,7 +53,7 @@ class MyDataColumn {
/// If null, the column will not be considered sortable. /// If null, the column will not be considered sortable.
/// ///
/// See [MyDataTable.sortColumnIndex] and [MyDataTable.sortAscending]. /// See [MyDataTable.sortColumnIndex] and [MyDataTable.sortAscending].
final MyDataColumnSortCallback onSort; final MyDataColumnSortCallback? onSort;
bool get _debugInteractive => onSort != null; bool get _debugInteractive => onSort != null;
} }

View File

@@ -8,14 +8,14 @@ class ShowMultiImage extends StatefulWidget {
final List<DisplayImageSource> displayImageSources; final List<DisplayImageSource> displayImageSources;
final int initialPage; final int initialPage;
const ShowMultiImage( const ShowMultiImage(
{Key key, this.displayImageSources, this.initialPage = 0}) {Key? key, required this.displayImageSources, this.initialPage = 0})
: super(key: key); : super(key: key);
@override @override
_ShowMultiImageState createState() => _ShowMultiImageState(); _ShowMultiImageState createState() => _ShowMultiImageState();
} }
class _ShowMultiImageState extends State<ShowMultiImage> { class _ShowMultiImageState extends State<ShowMultiImage> {
PageController pageController; late PageController pageController;
@override @override
void initState() { void initState() {
pageController = PageController(initialPage: widget.initialPage); pageController = PageController(initialPage: widget.initialPage);
@@ -58,7 +58,7 @@ class _ShowMultiImageState extends State<ShowMultiImage> {
value: event == null value: event == null
? 0 ? 0
: event.cumulativeBytesLoaded / : event.cumulativeBytesLoaded /
event.expectedTotalBytes, event.expectedTotalBytes!,
), ),
), ),
), ),

View File

@@ -4,7 +4,7 @@ import 'package:fcs/domain/vo/shipment_status.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';
import 'package:timeline_list/timeline.dart'; import 'package:timeline_list/timeline.dart';
import 'package:timeline_list/timeline_model.dart'; import 'package:timeline_list/timeline_model.dart';
@@ -12,10 +12,10 @@ import 'package:timeline_list/timeline_model.dart';
var dateFormatter = new DateFormat('dd MMM yyyy'); var dateFormatter = new DateFormat('dd MMM yyyy');
class StatusTree extends StatelessWidget { class StatusTree extends StatelessWidget {
final List<ShipmentStatus> shipmentHistory; final List<ShipmentStatus>? shipmentHistory;
final String currentStatus; final String? currentStatus;
const StatusTree({Key key, this.shipmentHistory, this.currentStatus}) const StatusTree({Key? key, this.shipmentHistory, this.currentStatus})
: super(key: key); : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -39,7 +39,7 @@ class StatusTree extends StatelessWidget {
if (shipmentHistory == null || currentStatus == null) return []; if (shipmentHistory == null || currentStatus == null) return [];
bool isPacked = currentStatus != package_received_status && bool isPacked = currentStatus != package_received_status &&
currentStatus != package_processed_status; currentStatus != package_processed_status;
return shipmentHistory return shipmentHistory!
.map((e) => TimelineModel( .map((e) => TimelineModel(
Padding( Padding(
padding: const EdgeInsets.all(18.0), padding: const EdgeInsets.all(18.0),
@@ -48,17 +48,17 @@ class StatusTree extends StatelessWidget {
children: <Widget>[ children: <Widget>[
Text(e.status, Text(e.status,
style: TextStyle( style: TextStyle(
color: e.done ? primaryColor : Colors.grey, color: e.done! ? primaryColor : Colors.grey,
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold)), fontWeight: FontWeight.bold)),
e.done || isPacked e.done! || isPacked
? Text(dateFormatter.format(e.date)) ? Text(dateFormatter.format(e.date))
: Container(), : Container(),
e.staffName == null ? Container() : Text(e.staffName) e.staffName == null ? Container() : Text(e.staffName!)
], ],
), ),
), ),
iconBackground: e.done ? primaryColor : Colors.grey, iconBackground: e.done! ? primaryColor : Colors.grey,
icon: Icon( icon: Icon(
e.status == "shipped" e.status == "shipped"
? Ionicons.ios_airplane ? Ionicons.ios_airplane

View File

@@ -9,11 +9,11 @@ typedef BtnCallback();
/// TaskButton is used to navigate to eash task /// TaskButton is used to navigate to eash task
class TaskButton extends StatelessWidget { class TaskButton extends StatelessWidget {
final String titleKey; final String? titleKey;
final IconData icon; final IconData? icon;
final BtnCallback btnCallback; final BtnCallback? btnCallback;
const TaskButton(this.titleKey, {Key key, this.icon, this.btnCallback}) const TaskButton(this.titleKey, {Key? key, this.icon, this.btnCallback})
: super(key: key); : super(key: key);
@override @override
@@ -45,7 +45,7 @@ class TaskButton extends StatelessWidget {
Container( Container(
height: 45, height: 45,
alignment: Alignment.topCenter, alignment: Alignment.topCenter,
child: Text(AppTranslations.of(context).text(titleKey), child: Text(AppTranslations.of(context)!.text(titleKey!),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: languageModel.isEng style: languageModel.isEng
? TextStyle( ? TextStyle(

View File

@@ -6,11 +6,11 @@ import 'package:flutter/material.dart';
import 'callbacks.dart'; import 'callbacks.dart';
class TitleWithAddButton extends StatelessWidget { class TitleWithAddButton extends StatelessWidget {
final IconData iconData; final IconData? iconData;
final String titleKey; final String? titleKey;
final OnTap onTap; final OnTap? onTap;
const TitleWithAddButton({Key key, this.iconData, this.titleKey, this.onTap}) const TitleWithAddButton({Key? key, this.iconData, this.titleKey, this.onTap})
: super(key: key); : super(key: key);
@override @override
@@ -28,7 +28,7 @@ class TitleWithAddButton extends StatelessWidget {
), ),
LocalText( LocalText(
context, context,
titleKey, titleKey!,
color: Colors.black54, color: Colors.black54,
fontSize: 20, fontSize: 20,
) )
@@ -40,7 +40,7 @@ class TitleWithAddButton extends StatelessWidget {
: Padding( : Padding(
padding: const EdgeInsets.only(right: 0), padding: const EdgeInsets.only(right: 0),
child: IconButton( child: IconButton(
onPressed: () => onTap(), onPressed: () => onTap!(),
icon: Icon( icon: Icon(
Icons.add_circle, Icons.add_circle,
color: primaryColor, color: primaryColor,

View File

@@ -14,7 +14,7 @@ dependencies:
cupertino_icons: ^1.0.3 cupertino_icons: ^1.0.3
firebase_core: ^1.5.0 firebase_core: ^1.5.0
cloud_firestore: ^2.5.0 cloud_firestore: ^2.5.2
firebase_storage: ^10.0.2 firebase_storage: ^10.0.2
firebase_auth: "^3.0.2" firebase_auth: "^3.0.2"
# firebase_messaging: ^6.0.15 # firebase_messaging: ^6.0.15