This commit is contained in:
Sai Naw Wun
2020-10-07 02:33:06 +06:30
parent 01a2798a74
commit 65dda16fe6
475 changed files with 1543 additions and 90780 deletions

View File

@@ -0,0 +1,404 @@
import 'dart:async';
import 'dart:io';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/transalation.dart';
import 'package:fcs/pages/box/box_list.dart';
import 'package:fcs/pages/chat/message_detail.dart';
import 'package:fcs/pages/chat/model/message_model.dart';
import 'package:fcs/pages/customer/customer_list.dart';
import 'package:fcs/pages/customer/model/customer_model.dart';
import 'package:fcs/pages/delivery/delivery_list.dart';
import 'package:fcs/pages/discount/discount_list.dart';
import 'package:fcs/pages/faq/faq_list_page.dart';
import 'package:fcs/pages/fcs_shipment/fcs_shipment_list.dart';
import 'package:fcs/pages/invoice/invoce_list.dart';
import 'package:fcs/pages/main/model/language_model.dart';
import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/package/package_list.dart';
import 'package:fcs/pages/rates/shipment_rates.dart';
import 'package:fcs/pages/shipment/pickup_list.dart';
import 'package:fcs/pages/staff/staff_list.dart';
import 'package:fcs/pages/widgets/task_button.dart';
import 'package:fcs/pages/widgets/badge.dart';
import 'package:fcs/pages/widgets/bottom_up_page_route.dart';
import 'package:fcs/pages/widgets/bottom_widgets.dart';
import 'package:fcs/pages/widgets/right_left_page_rout.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_icons/flutter_icons.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:intl/intl.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import '../profile/profile_page.dart';
import '../signin/signin_page.dart';
import '../widgets/banner.dart';
import '../widgets/offline_redirect.dart';
final msgLog = Logger('backgroundMessageHandler');
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
final log = Logger('_HomePageState');
bool login = false;
bool customer = true;
List<bool> isSelected = [true, false];
static FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
@override
void initState() {
super.initState();
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
Services.instance.messagingService.init(
(message) {
print("Message from FCM:$message");
_showNotification(message);
},
onLaunch: (m) => _showNotiContent(m),
onResume: (m) => _showNotiContent(m),
onSetupComplete: (token) {
mainModel.setMessaginToken = token;
});
_initLocalNotifications();
}
String notiUserID, notiUserName;
_showNotiContent(Map<String, dynamic> message) {
try {
Map<String, dynamic> map = Map<String, dynamic>.from(message["data"]);
notiUserID = map['user_id'];
notiUserName = map['user_name'];
_startNotiTimer();
print("Notification:$map");
} catch (e) {
print("Error:$e");
}
}
_startNotiTimer() async {
var _duration = new Duration(milliseconds: 500);
new Timer.periodic(_duration, (t) => displayNoti(t));
}
void displayNoti(Timer timer) async {
MainModel mainModel = Provider.of<MainModel>(context, listen: false);
if (mainModel.isLogin()) {
timer.cancel();
bool isCustomer = mainModel.isCustomer();
String receiverID = isCustomer ? mainModel.user.id : notiUserID;
String receiverName = isCustomer ? mainModel.user.name : notiUserName;
MessageModel messageModel =
Provider.of<MessageModel>(context, listen: false);
messageModel.initQuery(receiverID);
User user = mainModel.user;
if (!isCustomer) {
CustomerModel customerModel =
Provider.of<CustomerModel>(context, listen: false);
user = await customerModel.getUser(receiverID);
}
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MessageDetail(
messageModel: messageModel,
receiverID: receiverID,
receiverName: receiverName,
))).then((value) {
if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true);
}
});
if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true);
}
}
}
_initLocalNotifications() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('@mipmap/ic_launcher');
var initializationSettingsIOS = new IOSInitializationSettings();
var initializationSettings = new InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
_flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
static Future _showNotification(Map<String, dynamic> message) async {
var pushTitle;
var pushText;
var action;
if (Platform.isAndroid) {
var nodeData = message['notification'];
pushTitle = nodeData['title'];
pushText = nodeData['body'];
action = nodeData['action'];
} else {
pushTitle = message['title'];
pushText = message['body'];
action = message['action'];
}
print("AppPushs params pushTitle : $pushTitle");
print("AppPushs params pushText : $pushText");
print("AppPushs params pushAction : $action");
// @formatter:off
var platformChannelSpecificsAndroid = new AndroidNotificationDetails(
'your channel id', 'your channel name', 'your channel description',
playSound: true,
enableVibration: true,
importance: Importance.Max,
priority: Priority.High);
// @formatter:on
var platformChannelSpecificsIos =
new IOSNotificationDetails(presentSound: true);
var platformChannelSpecifics = new NotificationDetails(
platformChannelSpecificsAndroid, platformChannelSpecificsIos);
new Future.delayed(Duration.zero, () {
_flutterLocalNotificationsPlugin.show(
0,
pushTitle,
pushText,
platformChannelSpecifics,
payload: 'No_Sound',
);
});
}
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
User user = Provider.of<MainModel>(context).user;
if (user == null) {
return Container();
}
customer = Provider.of<MainModel>(context).isCustomer();
login = Provider.of<MainModel>(context).isLogin();
LanguageModel languageModel = Provider.of<LanguageModel>(context);
final faqBtn = TaskButton("faq.btn",
icon: MaterialCommunityIcons.frequently_asked_questions,
btnCallback: () => Navigator.of(context).push(CupertinoPageRoute(
builder: (context) => FAQListPage(),
)));
final packagesBtn = TaskButton("package.btn.name",
icon: Octicons.package,
btnCallback: () => Navigator.of(context).push<void>(
CupertinoPageRoute(builder: (context) => PackageList())));
final boxesBtn = TaskButton("boxes.name",
icon: MaterialCommunityIcons.package,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(BoxList())));
final pickUpBtn = TaskButton("pickup",
icon: SimpleLineIcons.direction,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(PickUpList())));
final shipmentCostBtn = TaskButton("rate",
icon: FontAwesomeIcons.calculator,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(ShipmentRates())));
final fcsShipmentBtn = TaskButton("shipment.title",
icon: Ionicons.ios_airplane,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(FcsShipmentList())));
final notiBtnOrg =
TaskButton("message.btn", icon: Icons.message, btnCallback: () {
MessageModel messageModel =
Provider.of<MessageModel>(context, listen: false);
messageModel.initQuery(user.id);
Navigator.push(
context,
BottomUpPageRoute(MessageDetail(
messageModel: messageModel,
)),
).then((value) {
if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true);
}
});
if (user.userUnseenCount > 0) {
messageModel.seenMessages(user.id, true);
}
});
final notiBtn = badgeCounter(notiBtnOrg, user.userUnseenCount);
final staffBtn = TaskButton(
"staff.title",
icon: MaterialCommunityIcons.worker,
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
builder: (context) => StaffList(),
)),
);
final customersBtn = TaskButton("customers.btn",
icon: Feather.users,
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
builder: (context) => CustomerList(),
)));
final invoicesBtn = TaskButton("invoices.btn",
icon: FontAwesomeIcons.fileInvoice,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(InvoiceList())));
final discountBtn = TaskButton("discount.btn",
icon: Entypo.price_ribbon,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(DiscountList())));
final deliveryBtn = TaskButton("delivery.title",
icon: MaterialCommunityIcons.truck_fast,
btnCallback: () =>
Navigator.of(context).push(BottomUpPageRoute(DeliverList())));
List<Widget> widgets = [];
widgets.add(faqBtn);
if (user != null) {
true ? widgets.add(pickUpBtn) : "";
!customer ? widgets.add(fcsShipmentBtn) : "";
customer ? widgets.add(notiBtn) : "";
user.hasStaffs() ? widgets.add(staffBtn) : "";
widgets.add(shipmentCostBtn);
user.hasPackages() ? widgets.add(packagesBtn) : "";
true ? widgets.add(boxesBtn) : "";
true ? widgets.add(deliveryBtn) : "";
user.hasCustomers() ? widgets.add(customersBtn) : "";
true ? widgets.add(invoicesBtn) : "";
true ? widgets.add(discountBtn) : "";
}
return OfflineRedirect(
child: FlavorBanner(
child: Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: primaryColor,
title: ClipRRect(
child: Image.asset("assets/logo.jpg", height: 40),
borderRadius: new BorderRadius.circular(30.0),
),
actions: login
? <Widget>[
ToggleButtons(
children: <Widget>[
Image.asset(
'icons/flags/png/us.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
),
Image.asset(
'icons/flags/png/mm.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
)
],
onPressed: _langChange,
isSelected: languageModel.currentState,
selectedBorderColor: Colors.white24,
),
IconButton(
onPressed: () {
Navigator.of(context)
.push(RightLeftPageRoute(Profile()));
},
iconSize: 30,
icon: Icon(Icons.account_circle),
),
]
: <Widget>[
ToggleButtons(
children: <Widget>[
Image.asset(
'icons/flags/png/us.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
),
Image.asset(
'icons/flags/png/mm.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
)
],
onPressed: _langChange,
isSelected: languageModel.currentState,
),
FlatButton(
onPressed: () {
Navigator.of(context)
.push(BottomUpPageRoute(SigninPage()));
},
child: Text(
"Sign In",
style: siginButtonStyle,
),
),
]),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Color(0xd0272262),
Color(0xfa272262),
],
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Expanded(
child: ListView(children: [
Wrap(
alignment: WrapAlignment.center,
children: widgets,
),
]),
),
BottomWidgets(),
],
))),
),
);
}
_langChange(index) {
var languageModel = Provider.of<LanguageModel>(context, listen: false);
languageModel.saveLanguage(Translation().supportedLanguages[index]);
setState(() {
isSelected.asMap().forEach((i, e) {
isSelected[i] = false;
});
isSelected[index] = !isSelected[index];
});
}
// Widget _buildBtn(String title, {IconData icon, BtnCallback btnCallback}) {
// return TaskButton(titleKey: title, icon: icon, btnCallback: btnCallback);
// }
}

View File

@@ -0,0 +1,202 @@
import 'package:fcs/helpers/shared_pref.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/transalation.dart';
import 'package:fcs/pages/main/model/language_model.dart';
import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/pages/signin/signin_page.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:fcs/pages/widgets/progress.dart';
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
class InitialLanguageSelectionPage extends StatefulWidget {
@override
_InitialLanguageSelectionPageState createState() =>
_InitialLanguageSelectionPageState();
}
class _InitialLanguageSelectionPageState
extends State<InitialLanguageSelectionPage> {
static final List<String> languagesList = Translation().supportedLanguages;
static final List<String> languageCodesList =
Translation().supportedLanguagesCodes;
final Map<dynamic, dynamic> languagesMap = {
languagesList[0]: languageCodesList[0],
languagesList[1]: languageCodesList[1],
};
String selectedLanguage;
int selectedIndex;
bool _isLoading;
@override
void initState() {
super.initState();
_isLoading = false;
var languageModel = Provider.of<LanguageModel>(context, listen: false);
this.selectedIndex = languageModel.isEng ? 0 : 1;
loadLaunguage(languageModel);
}
loadLaunguage(LanguageModel languageModel) async {
var lan = await languageModel.load();
if (this.selectedLanguage != lan) {
setState(() {
this.selectedLanguage = lan;
});
}
}
@override
Widget build(BuildContext context) {
return LocalProgress(
inAsyncCall: _isLoading,
child: Material(
type: MaterialType.transparency,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xff272282), primaryColor],
begin: const FractionalOffset(0.8, 0.9),
end: const FractionalOffset(0.9, 0.0),
stops: [0.0, 1.0],
),
),
child: Align(
alignment: Alignment.center,
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
children: [
Container(
height: 40,
child: LocalText(context, "language.selection.title",
fontSize: 20,
fontWeight: FontWeight.w200,
color: Colors.white),
),
Container(
padding: EdgeInsets.only(top: 0),
child: Card(
color: Color(0xfff4edec),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
child: Container(
padding: EdgeInsets.only(top: 20),
width: 300,
height: 160,
child: Column(
children: languagesList.asMap().entries.map((e) {
var language = e.value;
var key = e.key;
return InkWell(
onTap: () {
_select(key, language);
},
child: Container(
padding: EdgeInsets.all(2),
decoration: key == languagesList.length - 1
? BoxDecoration()
: BoxDecoration(
border: Border(
bottom:
BorderSide(color: Colors.grey[300]),
),
),
child: ListTile(
leading: language == 'English'
? Container(
child: CircleAvatar(
radius: 20,
backgroundImage: AssetImage(
"icons/flags/png/gb.png",
package: 'country_icons',
),
),
)
: Container(
child: CircleAvatar(
radius: 20,
backgroundImage: AssetImage(
"icons/flags/png/mm.png",
package: 'country_icons',
),
),
),
title: Text("$language"),
trailing: Theme(
data: Theme.of(context).copyWith(
unselectedWidgetColor: Colors.grey[400],
),
child: Radio(
value: key,
groupValue: selectedIndex,
onChanged: (int i) =>
_select(key, language),
activeColor: primaryColor,
),
)),
),
);
}).toList()),
),
),
),
SizedBox(height: 20.0),
Container(
padding: EdgeInsets.only(left: 230, top: 20),
child: Container(
width: 50,
height: 50,
child: InkWell(
onTap: () {
_next();
},
child: CircleAvatar(
radius: 25,
backgroundColor: Colors.white,
child: Center(
child: Icon(FontAwesomeIcons.arrowRight,
color: Colors.black87)),
),
),
),
)
],
),
),
),
),
),
);
}
_select(int index, String lang) {
setState(() {
selectedIndex = index;
selectedLanguage = lang;
Translation().onLocaleChanged(Locale(languagesMap[lang]));
Provider.of<LanguageModel>(context, listen: false)
.saveLanguage(selectedLanguage);
});
}
_next() {
setState(() {
_isLoading = true;
});
try {
SharedPref.finishFirstLaunch();
bool isLogin = Provider.of<MainModel>(context, listen: false).isLogin();
String page = isLogin ? "/home" : "/welcome";
Navigator.of(context).pushReplacementNamed(page);
} catch (e) {} finally {
setState(() {
_isLoading = false;
});
}
}
}

View File

@@ -0,0 +1,37 @@
import 'package:fcs/domain/entities/setting.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:flutter/foundation.dart';
import 'package:fcs/helpers/api_helper.dart';
import 'main_model.dart';
abstract class BaseModel extends ChangeNotifier {
User user;
Setting setting;
MainModel mainModel;
void initUser(User user) async {
this.user = user;
}
void privilegeChanged() {}
void initSetting(Setting setting) async {
this.setting = setting;
}
void logout() {}
// request makes http request
// if token is null
dynamic request(
String path,
method, {
dynamic payload,
String token,
String url,
}) async {
return await requestAPI(path, method,
payload: payload, token: token, url: url);
}
}

View File

@@ -0,0 +1,45 @@
import 'package:fcs/localization/transalation.dart';
import 'package:fcs/helpers/shared_pref.dart';
import 'package:flutter/painting.dart';
import 'base_model.dart';
class LanguageModel extends BaseModel {
String language;
bool get isEng => this.language == "English";
List<bool> get currentState => isEng ? [true, false] : [false, true];
static final List<String> languageCodesList =
Translation().supportedLanguagesCodes;
static final List<String> languagesList = Translation().supportedLanguages;
final Map<dynamic, dynamic> languagesMap = {
languagesList[0]: languageCodesList[0],
languagesList[1]: languageCodesList[1],
};
LanguageModel() {
load();
}
@override
logout() async {}
Future<String> load() async {
var data = await SharedPref.getLang();
String result = languagesList[1]; // defalut to english
if (data != null) {
result = data;
}
this.language = result;
Translation().onLocaleChanged(Locale(languagesMap[this.language]));
notifyListeners();
return result;
}
void saveLanguage(String language) async {
Translation().onLocaleChanged(Locale(languagesMap[language]));
SharedPref.saveLang(language);
this.language = language;
notifyListeners();
}
}

View File

@@ -0,0 +1,169 @@
import 'dart:async';
import 'package:fcs/data/services/services.dart';
import 'package:fcs/domain/entities/auth_result.dart';
import 'package:fcs/domain/entities/setting.dart';
import 'package:fcs/domain/entities/user.dart';
import 'package:fcs/helpers/network_connectivity.dart';
import 'package:fcs/helpers/shared_pref.dart';
import 'package:fcs/pages/main/model/base_model.dart';
import 'package:flutter/foundation.dart';
import 'package:logging/logging.dart';
import 'package:package_info/package_info.dart';
class MainModel extends ChangeNotifier {
final log = Logger('MainModel');
List<BaseModel> models = [];
String messagingToken;
User user;
PackageInfo packageInfo;
set setMessaginToken(token) {
this.messagingToken = token;
uploadMsgToken();
}
Setting setting;
bool isLoaded = false;
bool isOnline = false;
bool isFirstLaunch = false;
MainModel() {
NetworkConnectivity.instance.statusStream.listen((data) {
bool _isOnline = data["isOnline"];
if (_isOnline && !this.isOnline) {
_init();
}
this.isOnline = _isOnline;
notifyListeners();
});
}
bool faqEditable() {
return this.user != null && this.user.hasSupport();
}
bool paymentMethodsEditable() {
return this.user != null && this.user.hasSupport();
}
bool termEditable() {
return this.user != null && this.user.hasSupport();
}
bool contactEditable() {
return this.user != null && this.user.hasSupport();
}
bool isLogin() {
return this.user != null;
}
bool isCustomer() {
return user != null && user.isCustomer();
}
bool isSysAdmin() {
return this.user != null && this.user.hasSysAdmin();
}
bool isAdmin() {
return this.user != null && this.user.hasAdmin();
}
// userListener should never be closed
StreamSubscription<User> userListener;
_init() async {
await _listenSetting();
this.isFirstLaunch = await SharedPref.isFirstLaunch();
this.isFirstLaunch = this.isFirstLaunch ?? true;
this.packageInfo = await PackageInfo.fromPlatform();
if (userListener != null) userListener.cancel();
userListener =
Services.instance.authService.getUserStream().listen((_user) {
if (_user != null) {
models.forEach((m) => m.initUser(_user));
// call diffPrivileges if privilege changed or first time login
if (this.user == null || _user.diffPrivileges(this.user)) {
models.forEach((m) => m.privilegeChanged());
}
if (this.user == null) {
uploadMsgToken();
}
} else {
if (this.user != null) {
models.forEach((m) => m.logout());
}
}
this.user = _user;
isLoaded = true;
notifyListeners();
});
}
void addModel(BaseModel model) {
models.add(model);
}
Future<void> _listenSetting() async {
try {
Services.instance.authService.getSetting().listen((event) {
this.setting = event;
models.forEach((m) => m.initSetting(setting));
notifyListeners();
});
} finally {}
}
bool isSupport() {
if (packageInfo == null || setting == null) return false;
return int.parse(packageInfo.buildNumber) >= setting.supportBuildNum;
}
Future<AuthResult> sendSms(String phoneNumber) {
return Services.instance.authService.sendSmsCodeToPhoneNumber(phoneNumber);
}
Future<AuthResult> signin(String smsCode) async {
AuthResult authResult =
await Services.instance.authService.signInWithSmsCode(smsCode);
return authResult;
}
Future<void> uploadMsgToken() {
if (messagingToken == null || user == null) return null;
return Services.instance.userService.uploadMsgToken(messagingToken);
}
Future<void> removeMsgToken() {
if (messagingToken == null || user == null) return null;
return Services.instance.userService.removeMsgToken(messagingToken);
}
Future<void> signout() async {
await removeMsgToken();
await Services.instance.authService.signout();
models.forEach((m) => m.logout());
}
Future<bool> hasInvite() async {
return Services.instance.authService.hasInvite();
}
Future<void> signup(String userName) async {
await Services.instance.authService.signup(userName);
}
Future<void> joinInvite(String userName) async {
await Services.instance.authService.joinInvite(userName);
notifyListeners();
}
Future<void> updateProfile(String newUserName) async {
await Services.instance.authService.updateProfile(newUserName);
notifyListeners();
}
}

View File

@@ -0,0 +1,101 @@
import 'dart:async';
import 'package:fcs/pages/main/model/main_model.dart';
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
class SplashScreen extends StatefulWidget {
@override
_SplashScreenState createState() => new _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
final log = Logger('_SplashScreenState');
String page = "/language_selection";
bool _loaded = false;
bool _isSupport = false;
bool _isOnline = true;
Timer timer;
startTime() async {
var _duration = new Duration(milliseconds: 3000);
this.timer = new Timer.periodic(_duration, navigationPage);
}
void navigationPage(Timer timer) async {
if (_loaded && _isOnline && _isSupport) {
timer.cancel();
Navigator.of(context).pushReplacementNamed(page);
}
}
@override
void initState() {
super.initState();
startTime();
}
void dispose() {
super.dispose();
if (timer.isActive) timer.cancel();
}
@override
Widget build(BuildContext context) {
MainModel mainModel = Provider.of<MainModel>(context);
this._isSupport = mainModel.isSupport();
this._isOnline = mainModel.isOnline;
if (mainModel.isLoaded) {
if (mainModel.isFirstLaunch) {
page = "/language_selection";
} else if (mainModel.isLogin()) {
page = "/home";
} else {
page = "/welcome";
}
this._loaded = mainModel.isLoaded;
}
return new Scaffold(
backgroundColor: Colors.white,
body: new Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Image.asset(
"assets/logo.jpg",
width: 180,
),
SizedBox(height: 50),
Column(
children: <Widget>[
Text(
"FCS Logistics",
style: welcomeSubLabelStyle,
),
],
),
SizedBox(height: 30),
_loaded && !_isOnline
? Column(
children: <Widget>[
LocalText(context, "offline.status"),
],
)
: Container(),
Text(
_loaded && !_isSupport
? "Version outdated, please update your app!"
: "",
style: TextStyle(
color: primaryColor, fontWeight: FontWeight.bold)),
],
),
),
);
}
}

452
lib/pages/main/util.dart Normal file
View File

@@ -0,0 +1,452 @@
import 'package:fcs/helpers/theme.dart';
import 'package:fcs/localization/app_translations.dart';
import 'package:fcs/pages/main/model/language_model.dart';
import 'package:fcs/pages/widgets/local_text.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../widgets/label_widgets.dart';
final log = Logger('Util');
Future showMsgDialog(BuildContext context, String title, String msg) {
return showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: new Text(title),
content: new Text(msg),
actions: <Widget>[
new FlatButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
Future<void> showConfirmDialog(
BuildContext context, String translationKey, ok(),
{List<String> translationVariables}) async {
await showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: Center(
child: LocalText(
context,
translationKey,
translationVariables: translationVariables,
color: primaryColor,
),
),
content: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
FlatButton(
color: Colors.grey[300],
child: Text(
AppTranslations.of(context).text('Cancel'),
style: Provider.of<LanguageModel>(context).isEng
? TextStyle()
: TextStyle(fontFamily: 'Myanmar3'),
),
onPressed: () {
Navigator.of(context).pop();
}),
SizedBox(
width: 0,
),
FlatButton(
color: primaryColor,
child: Text(AppTranslations.of(context).text('Ok'),
style: Provider.of<LanguageModel>(context).isEng
? TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold)
: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: 'Myanmar3')),
onPressed: () async {
Navigator.of(context).pop();
await ok();
})
],
),
),
);
});
}
void showCommentDialog(BuildContext context, commentCallback(comment)) {
TextEditingController _comment = new TextEditingController();
showDialog(
context: context,
builder: (_) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(32.0))),
content: Container(
width: 300.0,
height: 80.0,
child: Container(
child: TextFormField(
controller: _comment,
autofocus: false,
cursorColor: primaryColor,
maxLines: 3,
style: textStyle,
decoration: new InputDecoration(
labelText: "Comment",
labelStyle: labelStyle,
icon: Icon(
Icons.add_comment,
color: primaryColor,
),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: primaryColor, width: 1.0)),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: primaryColor, width: 1.0)),
),
validator: (value) {
if (value.isEmpty) {
return "Please enter comment";
}
return null;
},
),
),
),
actions: <Widget>[
FlatButton(
child: Text(
"Cancel",
style: labelStyle,
),
onPressed: () {
_comment.clear();
Navigator.of(context).pop();
}),
FlatButton(
color: primaryColor,
child: Text("Submit",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold)),
onPressed: () {
commentCallback(_comment.text);
Navigator.of(context).pop();
})
],
);
});
}
Widget getStatus(String status) {
return status == "Delivered"
? Text(status,
style: TextStyle(
color: primaryColor, fontSize: 18, fontWeight: FontWeight.bold))
: status == "rejected"
? Chip(
backgroundColor: Colors.red,
avatar: Icon(
Icons.remove,
color: Colors.white,
size: 14,
),
label: Text(
status,
style: TextStyle(color: Colors.white, fontSize: 12),
))
: status == "In progress"
? Text(
status,
style: TextStyle(color: Colors.white, fontSize: 12),
)
: status == "Pickuped"
? Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold),
)
: status == "Pending" || status == "Rescheduled"
? Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.schedule),
),
Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold),
)
],
)
: status == "Assigned"
? Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.check),
),
Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold),
)
],
)
: status == "Canceled"
? Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold),
)
: status == "Delivered" || status == "Avaliable"
? Text(
status,
style: TextStyle(
color: Colors.green, fontSize: 18),
)
: status == "Used"
? Text(
status,
style: TextStyle(
color: Colors.red, fontSize: 18),
)
: status == "Paid"
? Row(
children: <Widget>[
Padding(
padding:
const EdgeInsets.all(8.0),
child: Icon(Icons.check),
),
Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight:
FontWeight.bold),
)
],
)
: Text(
status,
style: TextStyle(
color: primaryColor,
fontSize: 18,
fontWeight: FontWeight.bold),
);
}
call(BuildContext context, String phone) {
showConfirmDialog(context, "contact.phone.confim", () => launch("tel:$phone"),
translationVariables: ["$phone"]);
}
Widget nameWidget(String name) {
return Center(
child: Padding(
padding: const EdgeInsets.only(left: 10.0, top: 8),
child: Text(
name,
style: TextStyle(
color: Colors.black87, fontSize: 18, fontWeight: FontWeight.bold),
),
),
);
}
Widget phoneWidget(BuildContext context, String phone) {
return Container(
padding: EdgeInsets.only(top: 10),
child: Row(
children: <Widget>[
Icon(Icons.phone),
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: labeledText(context, phone, "user.phone"),
),
],
),
);
}
Widget fcsInput(String label, IconData iconData,
{TextEditingController controller,
String value,
bool autoFocus = false,
TextInputType textInputType}) {
return TextFormField(
initialValue: value,
controller: controller,
cursorColor: primaryColor,
maxLines: null,
minLines: 1,
autofocus: autoFocus,
keyboardType: textInputType,
decoration: InputDecoration(
fillColor: Colors.white,
labelText: label,
labelStyle: TextStyle(fontSize: 16, color: Colors.grey),
filled: true,
icon: Icon(
iconData,
color: primaryColor,
),
focusedBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.grey, width: 1.0)),
));
}
Widget fcsInputReadOnly(String label, IconData iconData,
{TextEditingController controller, String value}) {
return TextFormField(
initialValue: value,
controller: controller,
cursorColor: primaryColor,
maxLines: null,
minLines: 1,
readOnly: true,
decoration: InputDecoration(
fillColor: Colors.white,
border: InputBorder.none,
labelText: label,
labelStyle: TextStyle(fontSize: 16, color: Colors.grey),
filled: true,
icon: Icon(
iconData,
color: primaryColor,
),
));
}
Widget fcsDropDown(String label, IconData iconData,
{TextEditingController controller}) {
return Row(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Icon(iconData),
),
Expanded(
child: Container(
height: 50.0,
child: Row(children: <Widget>[
Expanded(child: _dropDown()),
]),
)),
],
);
}
Widget _dropDown() {
return DropdownButton<String>(
value: "Ko Nge",
icon: Icon(Icons.arrow_downward),
iconSize: 24,
elevation: 16,
// style: TextStyle(color: Colors.deepPurple),
underline: Container(
height: 2,
color: primaryColor,
),
onChanged: (String newValue) {},
items: <String>['Ko Nge', 'Two', 'Free', 'Four']
.map<DropdownMenuItem<String>>((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(value),
);
}).toList(),
);
}
Widget fcsButton(BuildContext context, String text,
{Function callack, IconData iconData}) {
var languageModel = Provider.of<LanguageModel>(context);
var style = languageModel.isEng
? TextStyle(
fontSize: 16.0, color: Colors.white, fontWeight: FontWeight.bold)
: TextStyle(
fontSize: 16.0,
color: Colors.white,
fontWeight: FontWeight.bold,
fontFamily: "Myanmar3");
return Container(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: Container(
height: 45.0,
decoration: BoxDecoration(
color: primaryColor,
shape: BoxShape.rectangle,
),
child: ButtonTheme(
minWidth: 900.0,
height: 100.0,
child: FlatButton(
onPressed: callack,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
iconData == null
? Container()
: Icon(
iconData,
color: Colors.white,
),
SizedBox(
width: 15,
),
Text(text, style: style),
],
),
),
),
),
);
}
String getLocalString(BuildContext context, String key) {
return AppTranslations.of(context).text(key);
}
void showToast(GlobalKey key, String text) {
final ScaffoldState scaffold = key.currentState;
scaffold.showSnackBar(
SnackBar(
content: Text(text),
backgroundColor: secondaryColor,
duration: Duration(seconds: 1),
),
);
}
bool hasUnicode(String text) {
final int maxBits = 128;
List<int> unicodeSymbols =
text.codeUnits.where((ch) => ch > maxBits).toList();
return unicodeSymbols.length > 0;
}

View File

@@ -0,0 +1,156 @@
import 'package:fcs/localization/transalation.dart';
import 'package:fcs/pages/main/model/language_model.dart';
import 'package:fcs/pages/main/util.dart';
import 'package:fcs/pages/widgets/bottom_widgets.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:provider/provider.dart';
import '../../helpers/theme.dart';
import '../signin/signin_page.dart';
import '../widgets/banner.dart';
import '../widgets/bottom_up_page_route.dart';
import '../widgets/offline_redirect.dart';
final msgLog = Logger('backgroundMessageHandler');
class WelcomePage extends StatefulWidget {
@override
_WelcomePageState createState() => _WelcomePageState();
}
typedef BtnCallback();
class _WelcomePageState extends State<WelcomePage> {
final log = Logger('_HomePageWelcomeState');
String pin;
List<bool> isSelected = [true, false];
@override
void initState() {
super.initState();
_loadLang();
}
void _loadLang() {
isSelected =
Provider.of<LanguageModel>(context, listen: false).currentState;
}
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return OfflineRedirect(
child: FlavorBanner(
child: Scaffold(
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment
.bottomCenter, // 10% of the width, so there are ten blinds.
colors: [
Color(0xd0272262),
Color(0xfa272262),
], // whitish to gray
)),
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ToggleButtons(
children: <Widget>[
Image.asset(
'icons/flags/png/us.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
),
Image.asset(
'icons/flags/png/mm.png',
package: 'country_icons',
fit: BoxFit.fitWidth,
width: 25,
)
],
selectedBorderColor: Colors.white12,
borderColor: Colors.transparent,
onPressed: _langChange,
isSelected: isSelected,
),
FlatButton(
onPressed: () {
Navigator.of(context)
.push(BottomUpPageRoute(SigninPage()));
},
child: Text(
getLocalString(context, "welcome.signin"),
style: siginButtonStyle,
),
),
],
),
Expanded(
child: Column(
children: <Widget>[
Expanded(
child: Center(
child: Text(
getLocalString(context, "welcome.msg"),
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontFamily: "Roboto"),
),
),
),
Container(
padding: EdgeInsets.only(top: 0),
child: CircleAvatar(
radius: (25),
backgroundColor: Colors.white,
child: ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.asset("assets/logo.jpg"),
)),
),
Padding(
padding:
const EdgeInsets.only(bottom: 10.0, top: 5),
child: Text(
"by FCS Logistics",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 11,
fontFamily: "Roboto"),
),
),
],
),
),
BottomWidgets(),
],
))),
),
);
}
_langChange(index) {
var languageModel = Provider.of<LanguageModel>(context, listen: false);
languageModel.saveLanguage(Translation().supportedLanguages[index]);
setState(() {
isSelected.asMap().forEach((i, e) {
isSelected[i] = false;
});
isSelected[index] = !isSelected[index];
});
}
}